Efficiently Track Bytes Sent

I am setting up a pay by usage model and I’ve tried a global response filter but am not able to get at the length of the response (FrameResponseStream.get_Length not supported in dotnet core 2.1) so I’m left with serializing the dto and getting length but hoping for a more efficient method?

                GlobalResponseFilters.Add((httpReq, res, responseDto) =>
                {

                    var sess = res.Request.SessionAs<UserSession>();
                    sess.bytesUsed += ServiceStack.Text.JsonSerializer.SerializeToString(responseDto).Length;


                });

I don’t know of an efficient way, serialized Service responses are written directly to the Response OutputStream so their length isn’t known.

Perhaps you can calculate it from Reverse Proxy / load balancer logs if it’s being hosted behind an nginx/HA Proxy.

Ok, thanks. AWS API gateway seems to have something analogous but I’m not sure its going to be “more efficient” (that is… cost to serve) https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-usage-plans-with-console.html

PS: {ServiceStack.Api.OpenApi.OpenApiSpecification} has a circular reference and cannot be serialized :wink:

What do you mean, serialized by what? Do you have a StackTrace and how can I repro the issue?

Can’t get a stack trace on a stack overflow easily, but if you put the response filter above in and then hit swagger-ui using the openapi plugin, you should get a repro. that response type does get a true on TypeSerializer.HasCircularReferences… Took me a long time to track down… work around is as follows:

            // sliding session & bytes used
            GlobalResponseFilters.Add((httpReq, res, responseDto) =>
            {

                var sess = res.Request.SessionAs<UserSession>();
                if (!ServiceStack.Text.TypeSerializer.HasCircularReferences(responseDto))
                {
                    sess.bytesUsed += ServiceStack.Text.JsonSerializer.SerializeToString(responseDto).Length;


                }

                res.Request.SaveSession(sess, TimeSpan.FromHours(hours));




            });

PS: did repro both on core 2.1 mac as well as AWS ECS.

That’s because it’s returning the response wrapped in a HttpResult which should never be serialized.

You can unwrap response DTOs with:

var dto = responseDto is IHttpResult httpResult ? httpResult.Response : responseDto;

ah… got it thanks.