Applying Temporal Aggregation Functions


Control how Honeycomb aggregates your metrics over time by applying temporal aggregation functions directly in your queries.

Important

This feature is in beta, and we would love your feedback!

To opt in, join our Pollinators Community Slack and ping us in the #discuss-metrics channel. Pro and Enterprise users can also contact Honeycomb Support or email support@honeycomb.io.

Introduction 

Honeycomb automatically applies the appropriate temporal aggregation function for each metric based on its metadata, so most queries work out of the box without manual setup.

When the defaults do not match your expectations or you need more control, you can override them using Honeycomb’s supported temporal aggregation functions.

Default Behavior 

OpenTelemetry defines several core metric types:

  • Gauge: A single numeric value at a point in time, such as memory usage or temperature. Gauges represent a snapshot of a value at a single point in time. They are not counting up or down, so monotonicity does not apply. Similarly, gauges are not tracking change over time, so temporality is also not meaningful.

  • Sum: A continuously increasing or fluctuating counter. Used to track totals like bytes sent or messages processed. Can be monotonic (only increases) or non-monotonic (can go up or down), and use either delta (change since last measurement) or cumulative (total since start) temporality.

  • Histogram: A distribution of values collected over a time range, grouped into buckets. Useful for measuring things like request sizes or durations. Histogram buckets are counters under the hood, but they are not monotonic. This is because each bucket represents the count of values that fall within a specific range, so negative values do not make sense in this context. Histograms can be either delta or cumulative.

  • Exponential Histogram: Like a histogram, but uses exponential bucket sizes for more efficient encoding of large ranges. Treated the same as histograms for querying purposes.

Because each metric type behaves differently over time, Honeycomb automatically selects the appropriate temporal aggregation function based on metadata:

Data Type Monotonic? Temporality Default Aggregation
Gauge N/A N/A LAST()
Sum Yes Cumulative INCREASE()
Sum No Cumulative LAST()
Sum Any Delta SUMMARIZE()
Histogram N/A Cumulative INCREASE()
Histogram N/A Delta SUMMARIZE()

These defaults are our best guess at what you will typically want to see when you query that metric. For example, gauges represent point-in-time values, so it makes sense to return the latest sample per time step. Sums and histograms usually track change over time, so Honeycomb computes increases or totals.

For a detailed look at aggregation functions and metric types, visit Temporal Aggregation Concepts.

When to Override Default Behavior 

Although Honeycomb chooses an aggregation function based on the structure of the metric by default, you might want to manually apply a temporal aggregation function if:

  • You want to control how data is bucketed across step boundaries
  • You are debugging and want to see raw or step-aligned data
  • You need a specific range for calculating RATE() or INCREASE()
  • The automatic default is not suitable for your use case

For example, you may want to:

  • Normalize counters by time to view a rate instead of a raw increase.
  • Show the latest value in a gauge instead of an average.
  • Total values across time steps to understand burst behavior.

Manually Applying Temporal Aggregation Functions 

To override default temporal aggregation behavior, create a query-scoped calculated field, wrapping the target metric name inside a supported temporal aggregation function. For example, you can define a calculated field like RATE(http.server.request.count) to override the default and apply RATE() explicitly.

You can use this syntax in the VISUALIZE clause or anywhere you reference a metric.

To learn more about the supported temporal aggregation functions, visit Temporal Aggregation Concepts.

Query Clauses and Temporal Aggregation 

When you build a metrics query that includes temporal aggregation functions, you can use the full power of Honeycomb’s query clauses, including VISUALIZE, WHERE, GROUP BY, ORDER BY, LIMIT, and HAVING.

Here is how each clause fits in:

  • VISUALIZE is where you apply aggregate functions to define what gets plotted on your chart.
  • GROUP BY and WHERE can target both metric attributes (like k8s.node.name or http.route) and metric values. Filtering on metric values, such as WHERE INCREASE(http.server.request.duration) > 10000, is fully supported and often useful. Grouping by raw metric values is more limited. For example, grouping by buckets of values requires wrapping metrics in calculated field expressions, which is not yet supported.
  • HAVING lets you filter results after aggregation based on the aggregated values themselves. For example, you can exclude any group where the RATE() of a metric falls below a certain threshold.
  • ORDER BY and LIMIT behave just as they do in other Honeycomb queries, letting you sort and trim the aggregated results.

To get aggregated trends over time, your query must include at least one aggregate function in the VISUALIZE clause. Without an aggregation, we default to COUNT, so the chart will return results that do not reflect anything meaningful for metrics.

Using Temporal Aggregation Functions in Queries 

To use temporal aggregation functions in queries, define a query-scoped calculated field in the Query Builder or include them in your API request.

To create a query with a temporal aggregation function:

  1. Select Query (Query Menu icon) from the navigation menu.

  2. Select the Metrics dataset.

  3. Select the VISUALIZE clause field, and choose Define Calculated Field.

  4. Enter a name for your calculated field, such as my_rate.

  5. In the editor, enter a formula that includes a temporal aggregation function, and select Use in query:

    RATE($http.server.requests, 300)
    

    Use the $ prefix to reference a raw metric.

    The second argument (300) is optional and sets the time window (in seconds) used to calculate the rate. To learn more, visit Temporal Aggregation Concepts: Understanding the range_interval_seconds argument.

  6. In the VISUALIZE clause section, add your new field, and use HEATMAP() on the calculated field to produce a visualization:

    HEATMAP(my_rate)
    
  7. Select Run Query.

This will return a time-aligned heatmap showing how the rate of http.server.requests varies across series (such as hosts or pods) over 5-minute windows.

To define a metrics-based query via the Honeycomb API, include your calculated field in the calculated_fields section, and then reference it in calculations using a supported operator like HEATMAP().

Use Metrics as your datasetSlug.

{
  "time_range": 3600,
  "granularity": 60,
  "calculated_fields": [
    {
      "name": "my_rate",
      "expression": "RATE($http.server.requests, 300)"
    }
  ],
  "calculations": [
    {
      "op": "HEATMAP", 
      "column": "my_rate"
    }
  ]
}

Example Queries 

These examples show how to override Honeycomb’s default temporal aggregation behavior by applying temporal aggregation functions directly in a query-scoped calculated field.

Each example uses the Honeycomb Query Language to define queries and assumes you are working in the Query Builder or sending queries via the API.

Track Requests Per Second with RATE() 

Calculate the per-second rate of http.requests.total, using a 60-second time window. This smooths out spikes and normalizes throughput over time, regardless of the query’s granularity.

Use this when you are interested in how frequently something happens rather than the total count.

  • Calculated Field: RATE($http.requests.total, 60)

  • Query: VISUALIZE AVG(custom_rate)

Combine RATE() with a Percentile Aggregation 

Track the 99th percentile of the rate of http.server.request.body.size, using a 60-second time window. Use the RATE()temporal aggregation function in a calculated field, and then apply P99 in the aggregate clause.

Use this when you want to monitor high-percentile throughput of request body sizes, which is helpful for catching unusually large payloads.

  • Calculated Field: RATE($http.server.request.body.size, 60)

  • Query: VISUALIZE P99(rate_body)

Compare Request Sizes by Node 

Compute the 99th percentile of request body size per Kubernetes node.

Use this when you want to compare the distribution of request sizes across the nodes or other dimensions.

  • Calculated field: No calculated field is necessary because Honeycomb applies the appropriate default temporal aggregation function for this histogram field.

  • Query:

    • VISUALIZE P99(http.server.request.body.size)
    • GROUP BY k8s.node.name

Get Total Requests for Delta Metrics 

Use SUMMARIZE() to compute the total value of a delta metric in each time step. Delta-style sums represent change between reports. This function adds those values to get per-step totals.

  • Calculated Field: SUMMARIZE($http.requests.delta_count)

  • Query: VISUALIZE SUM(total_requests)

Tips for Querying 

  • Always include an aggregate clause to trigger temporal aggregation.
  • Use GROUP BY attributes, not raw metric fields.
  • Use range_interval_seconds in RATE() and INCREASE() for smoother results.
  • Validate results visually to confirm expected behavior.

What’s Not Supported 

Keep the following constraints in mind when working with temporal aggregation functions:

  • Only use them in query-scoped calculated fields. Temporal aggregation functions are not supported in saved calculated fields or SLOs.
  • Nesting one temporal aggregation function inside another temporal aggregation function is not supported.
  • Querying metrics data and non-metrics data in a single query is not supported.