NGINX: calculating total req_time per client

Hi,

I have some NGINX JSON logs coming into Grafana cloud and I’d like to count up the total “request_time” per client in a 2 minute period. However I’m having trouble coming up with the right query.

I extract the client ID from the JSON request string using regexp “regexp /static/client/(*?<client>.{36})” and the request_time is also available in the json log (see example below).

I have promtail delivering logs into Grafana cloud from NGINX, in the following (lightly trimmed for clarity/privacy) JSON format:

{“msec”: “1756711886.826”, “time_iso8601”: “2025-09-01T07:31:26+00:00”, “request_uri”: “/static/client/12345678-abcd-123a-1234-1234567890ab/resouce?page=1&limit=10”, “status”: “200”, “request_time”: “0.116”, “request_method”: “GET”, (ETC…) }

So, for a simplified example, if over a 2 minute period ‘client A’ connected 100 times at a request time of 1s per request and ‘client B’ was logged connecting three times at a request time of 20, I’d like it to sum of the request time, within a 2 minute block, grouped by client:

Client_1: 100
Client_2: 60

I’ve spent the afternoon noodling around in the explorer, but as a Grafana novice I’m not able to make any progress.

Can anyone give me a hint as to how you might go about this?

Thank you.

Great description for Grot (AI): Grot AI helper | Grafana Labs

AI response:
To achieve your goal—summing the total request_time per client (where client ID is extracted from the request_uri) over a 2-minute period in Grafana Cloud Loki—you can use LogQL’s parsing and aggregation features.

Here’s how you can construct your query:

  1. Extract the client ID from request_uri using regexp.
  2. Parse the JSON to extract request_time.
  3. Unwrap request_time as a numeric value.
  4. Sum the unwrapped values, grouped by client, over a 2-minute window.

A query that accomplishes this would look like:

sum by (client) (
  sum_over_time(
    {your_label_selectors}
      | json
      | regexp client="request_uri:/static/client/(?P<client>.{36})"
      | unwrap request_time [2m]
  )
)

Explanation:

  • {your_label_selectors}: Replace this with your actual log stream selectors (e.g., {job="nginx"}).
  • | json: Parses the log line as JSON and extracts all fields.
  • | regexp client="request_uri:/static/client/(?P<client>.{36})": Extracts the client ID from the request_uri field using a named capture group.
  • | unwrap request_time [2m]: Unwraps the request_time field as a value for aggregation over a 2-minute window.
  • sum by (client) (...): Sums the total request time per client.

Important notes:

  • The unwrap stage expects request_time to be a numeric value. If it’s a string, Loki will attempt to convert it.
  • If your client ID format is always a UUID, you may want to use a more specific regex, e.g., (?P<client>[0-9a-fA-F-]{36}).

It may need some polishing, but it makes sense as a starting point.

Thanks, I was unaware of this functionality.
That looks pretty close to what I’m after, I’ll just need to get a test sorted to verify those numbers manually to make sure it’s on track. I’ll report back once I’ve given it a try!

Cheers.

That worked. Thank you.