Performance monitoring via Cloudflare Workers

My team had an idea about using Cloudflare Workers to help monitor our site performance. The idea is to capture various metrics related to page load time as the user experiences it, including an approximation of time to first paint and time to interactive. We would start the measurement at the time Cloudflare receives the request, and then use some JS code (which we can add to our pages on our end) to capture the remaining time to first-paint and time-to-interactive (both for CF cache hits and misses). Obviously this wouldn’t be a complete end-to-end test since there’s still the time it takes for the request to reach CF servers, but hopefully that’s generally pretty minimal, and it seems like relative comparisons of the metrics recorded with this solution would still provide valuable insights.

I’m rather new to performance testing and monitoring, so first of all I just wanted to ask: does this sound like a good use case for CF workers? Has anyone else done something like this?

I realize that CF already tracks some performance stats like origin response time, but starting the measurement in a CF worker and sending the data in the same way we’ll do it from the browser (e.g. with Google Tag Manager, or we might be calling some other endpoint that would talk to Prometheus), seemed like it would be simpler than combining stats from multiple sources. I was thinking that this would also give a more accurate calculation of the amount of time elapsed from the time the request is received by CF to the first paint in the browser…if we go with a custom API monitoring endpoint, we could rely on it to calculate the time difference between the two requests it would receive for a given page (the first from the CF worker and the second from the browser). Does this sound like a good plan to any veteran performance experts here?

1 Like

Workers would be good to inject the JS used to do various timings on the client browser once they have the response… if you can’t get in the payload otherwise.

You could actually get some backend metrics if you send them over in the Server-Timing response header. If you used Logflare, origin_time and the Server-Timing headers would be available for you to search, make dashboards from in Data Studio and query directly in BigQuery.

You could actually log the client side timings to Logflare too, and if you send the Cloudflare request ID with that event, it would tie the whole chain together.

Thanks for the feedback! I don’t think we would need to inject any scripts via workers; we are rebuilding our site so we can easily change the source code on our end. (Well, with the possible exception of injecting something like window.CloudflareRequestId = ... if using workers for this.)

Will look into Logflare…just wondering, is Logflare the only way (other than rolling our own solution or CF app) to have the Server-Timing header populated for us as measured from CF?

You would populate the server timings header from your backend. Then anything on the client should be able to see it.

You can pick up the Cloudflare request ID from the headers on the client too, no need for workers to add that.

Logflare just gives you an easy way to get that data into something you can see, search, dynamically query and build charts from.

You could actually just log all that to Logflare from the client (without the CF app) … but I haven’t had anyone do that yet so if you’re interested I can work with you to make that happen. Oh … I built Logflare…

When you say the Cloudflare request ID is in the headers, do you mean the CF-RAY header? After writing my previous comment, I just realized that something like window.CloudflareRequestId = ... would probably be unnecessary in any case, assuming that CF-RAY is a unique identifier for the request and not just the data center (the docs aren’t crystal clear on this). So yeah, we would just use that header then.

I suppose populating server timings on our backend could provide some additional useful metrics (including database response time), but it would be good to know how long it took the backend to respond including the time to reach our Kubernetes cluster in the first place. It’s cool that we could send whatever metrics we want to Logflare, so this seems like something we could easily add via our own CF worker.

However, I just read a little more about the HTML5 Navigation Timing API, and I realized that this whole idea of measuring server response time ourselves is probably unnecessary (given that measuring page loading experience for users with JS disabled isn’t a priority for us). It looks like that API includes the total request time out of the box, including the time it takes to reach CF’s servers and the time it takes the browser to parse the HTML. So if I understand correctly, we could use that and send the metrics via AJAX to Logflare or any other metrics database/tool.

Yeah cf-ray is the Cloudflare request ID. You’ll probably want to use the response cf-ray as it includes the Cloudflare colo at the end. edit: if you’re in the Cloudflare Worker … if you’re on the client it would naturally be the response cf-ray.

From the sound of it, I think you’ve got a good handle on everything :slight_smile:

Thanks again!

2 Likes

Got a question regarding the cf-ray and if to use it as a request ID:
To me it seems to be reused for the same client assuming Cloudflare can pin a cookie to the client? So in that case it would rather be a client ID than a request ID… Might be safer to set a X-Request-Id header on the request either in the client or in the worker.

Got a test-endpoint at https://router.ahlstrand.es/headers that prints the headers if you wanna try it out.

It’s refreshing for me? Just the letters in the middle though, I thought it wasn’t for a second.

Just to be sure, and since we have the logs and tools here :slight_smile: …

See: Are Cloudflare CF Ray Response Headers Unique?

We’ve only ever seen unique cf ray IDs on our requests. That is just a subset of requests for us. Basically everything not hitting api.logflare.app. But enough to say pretty confidently that they are unique.

If you wanted to generate your own ID you can. If you ever have an issue where you want Cloudflare to look into it, they’ll ask for the ray ID.

Wow, totally missed that :slight_smile: Got fooled by that the start and end always are the same.

1 Like