pedestal 2025-02-19

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

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)}

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.

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.

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

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?

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.

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.

that makes sense, thanks!