pedestal

jmv 2025-02-19T23:01:52.952379Z

hello! curious what's the best approach to attach the size of the response body to our telemetry data for an issue i'm trying to debug. i see as 39cc924 that the body is this function io.pedestal.http.response/stream-xform

jmv 2025-02-19T23:18:21.769259Z

this was what i originally tried

{:name  ::custom-trace-metrics   
 :leave (fn [context]            
            (when-let [body (get-in context [:response :body])]                            
              (when-let [len (cond
                               (bytes? body)  (alength body)
                               (string? body) (alength (String/.getBytes body)))]                
                (span/add-span-data! {:attributes {:http.response.bytes len}})))
            context)}

hlship 2025-02-19T23:39:20.085579Z

One of the types of response body is a function; this function is passed an OutputStream, and is responsible for writing the actual response to it. That's very opaque, of course. The stream-form (really, stream-xform/fn) is a wrapper that converts a result collection to an output format, typically JSON, and writes the JSON stream out.

hlship 2025-02-19T23:40:09.950339Z

So it would be better if whatever attached the body, set the Content-Length header as well, if it knows ahead of time how big the content stream is going to be.

hlship 2025-02-19T23:41:44.578059Z

http://pedestal.io/pedestal/0.8/reference/response-bodies.html -- there's a lot of possible returns types.

hlship 2025-02-19T23:47:01.663009Z

I've had to touch on all of these in my latest rounds of refactoring.

jmv 2025-02-20T00:15:54.685509Z

we are using io.pedestal.http/json-body to format the response. are you saying that it would be ideal for this function to set Content-Length in addition to Content-Type?

hlship 2025-02-20T00:18:07.253109Z

That would be ideal for your use case, but could be costly otherwise ... it would be necessary to run the entire streaming operation twice; once to determine the length, and again to generate the content. Alternately, it could be changed to simply create a String or ByteBuffer of the content ... but that requires potentially more memory than writing to an OuputStream. There's always trade-offs.

hlship 2025-02-20T00:19:37.651269Z

When I say "it could be changed" I mean your could swap out the default Pedestal interceptor for this, with one of your own that could, perhaps, do the encoding to a String and (if this makes sense) emit the metric in one go.

jmv 2025-02-20T00:26:28.103929Z

that makes sense, thanks!