Repository: vespa-engine/vespa
File: vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/resource/StreamingJsonLinesResponseTest.java (Java)

Code before:
        f.jsonlResponse.writeDocumentValue(f.doc1, null);
        String expected = """
                {"put":"id:ns:music::one","fields":{"embedding":{"type":"tensor(x[3])","values":[1.0,2.0,3.0]}}}
                """;
        verify(f.writer).write(expected, null);

        f = new Fixture(new JsonFormat.EncodeOptions(true, false, true)); // hex form
        f.doc1.setFieldValue("embedding", new TensorFieldValue(Tensor.from("tensor(x[3]):[4,5,6]")));
        f.jsonlResponse.writeDocumentValue(f.doc1, null);
        expected = """
                {"put":"id:ns:music::one","fields":{"embedding":{"type":"tensor(x[3])","values":"401000000000000040140000000000004018000000000000"}}}
                """;
        verify(f.writer).write(expected, null);
    }

    @Test
    void request_trace_is_rendered_as_own_line() throws IOException {
        var f = new Fixture();
        var trace = new Trace(9);
        trace.trace(7, "Poirot's deductions", false);
        trace.getRoot().addChild(new TraceNode().setStrict(false)
                .addChild("The butler did it")
                .addChild("Weapon was a garden gnome"));
        f.jsonlResponse.writeRequestTrace(trace);
        String expected = """
                {"requestTrace":{"trace":[{"message":"Poirot's deductions"},{"fork":[{"message":"The butler did it"},{"message":"Weapon was a garden gnome"}]}]}}
                """;
        verify(f.writer).write(expected, null);
    }

    @Test
    void null_request_trace_is_not_rendered() throws Exception {
        var f = new Fixture();
        f.jsonlResponse.writeRequestTrace(null);
        verify(f.writer, never()).write(anyString(), any());
    }

    @Test
    void empty_request_trace_is_not_rendered() throws Exception {
        var f = new Fixture();
        var trace = new Trace(9);
        // Not rendering traces without a root node is the behavior of the legacy
        // JSON renderer, so we carry the torch of that particular tradition.
        f.jsonlResponse.writeRequestTrace(trace);
        verify(f.writer, never()).write(anyString(), any());
    }

    @Test
    void message_is_rendered_as_own_line() throws IOException {
        var f = new Fixture();
        f.jsonlResponse.writeMessage("'ello, 'ello, this is London", StreamableJsonResponse.MessageSeverity.INFO);

Review comment (suggestion):
My suggestions (in random order): `operationTrace`, `documentApiTrace`, `documentTrace`.
The naming `requestTrace` could indicate that it's specific to HTTP.

Code after:
        f.jsonlResponse.writeDocumentValue(f.doc1, null);
        String expected = """
                {"put":"id:ns:music::one","fields":{"embedding":{"type":"tensor(x[3])","values":[1.0,2.0,3.0]}}}
                """;
        verify(f.writer).write(expected, null);

        f = new Fixture(new JsonFormat.EncodeOptions(true, false, true)); // hex form
        f.doc1.setFieldValue("embedding", new TensorFieldValue(Tensor.from("tensor(x[3]):[4,5,6]")));
        f.jsonlResponse.writeDocumentValue(f.doc1, null);
        expected = """
                {"put":"id:ns:music::one","fields":{"embedding":{"type":"tensor(x[3])","values":"401000000000000040140000000000004018000000000000"}}}
                """;
        verify(f.writer).write(expected, null);
    }

    @Test
    void session_trace_is_rendered_as_own_line() throws IOException {
        var f = new Fixture();
        var trace = new Trace(9);
        trace.trace(7, "Poirot's deductions", false);
        trace.getRoot().addChild(new TraceNode().setStrict(false)
                .addChild("The butler did it")
                .addChild("Weapon was a garden gnome"));
        f.jsonlResponse.writeTrace(trace);
        String expected = """
                {"sessionTrace":{"trace":[{"message":"Poirot's deductions"},{"fork":[{"message":"The butler did it"},{"message":"Weapon was a garden gnome"}]}]}}
                """;
        verify(f.writer).write(expected, null);
    }

    @Test
    void null_session_trace_is_not_rendered() throws Exception {
        var f = new Fixture();
        f.jsonlResponse.writeTrace(null);
        verify(f.writer, never()).write(anyString(), any());
    }

    @Test
    void empty_session_trace_is_not_rendered() throws Exception {
        var f = new Fixture();
        var trace = new Trace(9);
        // Not rendering traces without a root node is the behavior of the legacy
        // JSON renderer, so we carry the torch of that particular tradition.
        f.jsonlResponse.writeTrace(trace);
        verify(f.writer, never()).write(anyString(), any());
    }

    @Test
    void message_is_rendered_as_own_line() throws IOException {
        var f = new Fixture();
        f.jsonlResponse.writeMessage("'ello, 'ello, this is London", StreamableJsonResponse.MessageSeverity.INFO);