Collected Metrics

Relay collects the following metrics:

event.accepted (Counter)

Number of envelopes accepted in the current time slot.

This represents requests that have successfully passed rate limits and filters, and have been sent to the upstream.

This metric is tagged with:

  • handling: Either "success" if the envelope was handled correctly, or "failure" if there was an error or bug.
event.corrupted (Counter)

Number of Events that had corrupted (unprintable) event attributes.

This currently checks for environment and release, for which we know that some SDKs may send corrupted values.

event.opentelemetry (Counter)

Number of Events with an OpenTelemetry Context

This metric is tagged with:

  • platform: The event's platform, such as "javascript".
  • sdk: The name of the Sentry SDK sending the transaction. This tag is only set for Sentry's SDKs and defaults to "proprietary".
event.processing_time (Timer)

Time in milliseconds spent in synchronous processing of envelopes.

This timing covers the end-to-end processing in the CPU pool and comprises:

  • event_processing.deserialize
  • event_processing.pii
  • event_processing.serialization

With Relay in processing mode, this also includes the following timings:

  • event_processing.process
  • event_processing.filtering
  • event_processing.rate_limiting
event.protocol (Counter)

Number of events that hit any of the store-like endpoints: Envelope, Store, Security, Minidump, Unreal.

The events are counted before they are rate limited, filtered, or processed in any way.

This metric is tagged with:

  • version: The event protocol version number defaulting to 7.
event.queue_size (Histogram)

The number of envelopes in the queue.

The queue holds all envelopes that are being processed at a particular time in Relay:

  • When Relay receives a Request, it ensures the submitted data is wrapped in a single envelope.
  • The envelope receives some preliminary processing to determine if it can be processed or if it must be rejected.
  • Once this determination has been made, the HTTP request that created the envelope terminates and, if the request is to be further processed, the envelope enters a queue.
  • After the envelope finishes processing and is sent upstream, the envelope is considered handled and it leaves the queue.

The queue size can be configured with cache.event_buffer_size.

event.queue_size.pct (Histogram)

The number of envelopes in the queue as a percentage of the maximum number of envelopes that can be stored in the queue.

The value ranges from 0 when the queue is empty to 1 when the queue is full and no additional events can be added. The queue size can be configured using event.queue_size.

event.rejected (Counter)

Number of envelopes rejected in the current time slot.

This includes envelopes being rejected because they are malformed or any other errors during processing (including filtered events, invalid payloads, and rate limits).

To check the rejection reason, check events.outcomes, instead.

This metric is tagged with:

  • handling: Either "success" if the envelope was handled correctly, or "failure" if there was an error or bug.
event.size_bytes.raw (Histogram)

The size of the HTTP request body as seen by Relay after it is extracted from a request in bytes.

  • For envelope requests, this is the full size of the envelope.
  • For JSON store requests, this is the size of the JSON body.
  • For multipart uploads of crash reports and attachments, this is the size of the multipart body including boundaries.

If this request contains a base64 zlib compressed payload without a proper content-encoding header, then this is the size before decompression.

The maximum request body size can be configured with limits.max_envelope_size.

event.size_bytes.uncompressed (Histogram)

The size of the request body as seen by Relay after decompression and decoding in bytes.

JSON store requests may contain a base64 zlib compressed payload without proper content-encoding header. In this case, this metric contains the size after decoding. Otherwise, it is always equal to event.size_bytes.raw.

event.total_time (Timer)

Total time in milliseconds an envelope spends in Relay from the time it is received until it finishes processing and has been submitted to the upstream.

event.transaction_source (Counter)

The number of transaction events processed by the source of the transaction name.

This metric is tagged with:

  • platform: The event's platform, such as "javascript".
  • sdk: The name of the Sentry SDK sending the transaction. This tag is only set for Sentry's SDKs and defaults to "proprietary".
  • source: The source of the transaction name on the client. See the transaction source documentation for all valid values.
event.wait_time (Timer)

Time spent between the start of request handling and processing of the envelope.

This includes streaming the request body, scheduling overheads, project config fetching, batched requests and congestions in the internal processor. This does not include delays in the incoming request (body upload) and skips all envelopes that are fast-rejected.

event_processing.deserialize (Timer)

Time in milliseconds spent deserializing an event from JSON bytes into the native data structure on which Relay operates.

event_processing.filtering (Timer)

Time in milliseconds spent running inbound data filters on an event.

event_processing.pii (Timer)

Time in milliseconds spent in data scrubbing for the current event. Data scrubbing happens last before serializing the event back to JSON.

event_processing.process (Timer)

Time in milliseconds spent running event processors on an event for normalization. Event processing happens before filtering.

event_processing.rate_limiting (Timer)

Time in milliseconds spent checking for organization, project, and DSN rate limits.

Not all events reach this point. After an event is rate limited for the first time, the rate limit is cached. Events coming in after this will be discarded earlier in the request queue and do not reach the processing queue.

event_processing.serialization (Timer)

Time spent converting the event from its in-memory reprsentation into a JSON string.

events.outcomes (Counter)

Number of outcomes and reasons for rejected Envelopes.

This metric is tagged with:

  • outcome: The basic cause for rejecting the event.
  • reason: A more detailed identifier describing the rule or mechanism leading to the outcome.
  • to: Describes the destination of the outcome. Can be either 'kafka' (when in processing mode) or 'http' (when outcomes are enabled in an external relay).

Possible outcomes are:

  • filtered: Dropped by inbound data filters. The reason specifies the filter that matched.
  • rate_limited: Dropped by organization, project, or DSN rate limit, as well as exceeding the Sentry plan
    quotaThe monthly number of events that you pay Sentry to track.
    . The reason contains the rate limit or quota that was exceeded.
  • invalid: Data was considered invalid and could not be recovered. The reason indicates the validation that failed.
http_queue.size (Histogram)

The number of upstream requests queued up for sending.

Relay employs connection keep-alive whenever possible. Connections are kept open for 15 seconds of inactivity or 75 seconds of activity. If all connections are busy, they are queued, which is reflected in this metric.

This metric is tagged with:

  • priority: The queueing priority of the request, either "high" or "low". The priority determines precedence in executing requests.

The number of concurrent connections can be configured with:

  • limits.max_concurrent_requests for the overall number of connections
  • limits.max_concurrent_queries for the number of concurrent high-priority requests
kafka.message_size (Histogram)

Size of emitted kafka message in bytes, tagged by message type.

metrics.buckets (Gauge)

The total number of metric buckets in Relay's metrics aggregator.

metrics.buckets.batches_per_partition (Histogram)

The number of batches emitted per partition by [crate::aggregation::Aggregator].

metrics.buckets.cost (Gauge)

The total storage cost of metric buckets in Relay's metrics aggregator.

metrics.buckets.created.unique (Set)

Count the number of unique buckets created.

This is a set of bucketing keys. The metric is basically equivalent to metrics.buckets.merge.miss for a single Relay, but could be useful to determine how much duplicate buckets there are when multiple instances are running.

The hashing is platform-dependent at the moment, so all your relays that send this metric should run on the same CPU architecture, otherwise this metric is not reliable.

metrics.buckets.delay (Histogram)

The reporting delay at which a bucket arrives in Relay.

A positive delay indicates the bucket arrives after its stated timestamp. Large delays indicate backdating, particularly all delays larger than bucket_interval + initial_delay. Negative delays indicate that the bucket is dated into the future, likely due to clock drift on the client.

This metric is tagged with:

  • backdated: A flag indicating whether the metric was reported within the initial_delay time period (false) or after the initial delay has expired (true).
metrics.buckets.dropped (Counter)

Incremented every time a bucket is dropped.

This should only happen when a project state is invalid during graceful shutdown.

metrics.buckets.flushed (Histogram)

The total number of metric buckets flushed in a cycle across all projects.

metrics.buckets.flushed_per_project (Histogram)

The number of metric buckets flushed in a cycle for each project.

Relay scans metric buckets in regular intervals and flushes expired buckets. This histogram is logged for each project that is being flushed. The count of the histogram values is equivalent to the number of projects being flushed.

metrics.buckets.invalid_timestamp (Histogram)

Distribution of invalid bucket timestamps observed, relative to the time of observation.

This is a temporary metric to better understand why we see so many invalid timestamp errors.

metrics.buckets.merge.hit (Counter)

Incremented every time two buckets or two metrics are merged.

Tagged by metric type and name.

metrics.buckets.merge.miss (Counter)

Incremented every time a bucket is created.

Tagged by metric type and name.

metrics.buckets.parsing_failed (Counter)

Number of times that parsing a metrics bucket item from an envelope failed.

metrics.buckets.partition_keys (Histogram)

Distribution of flush buckets over partition keys.

The distribution of buckets should be even. If it is not, this metric should expose it.

metrics.buckets.per_batch (Histogram)

The number of buckets in a batch emitted by [crate::aggregation::Aggregator].

This corresponds to the number of buckets that will end up in an envelope.

metrics.buckets.scan_duration (Timer)

Time in milliseconds spent scanning metric buckets to flush.

Relay scans metric buckets in regular intervals and flushes expired buckets. This timer shows the time it takes to perform this scan and remove the buckets from the internal cache. Sending the metric buckets to upstream is outside of this timer.

metrics.extraction.transactions (Timer)

Time in milliseconds spent on converting a transaction event into a metric.

metrics.insert (Counter)

Incremented for every metric that is inserted.

Tagged by metric type and name.

metrics.transaction_name (Counter)

Count extraction of transaction names. Tag with the decision to drop / replace / use original.

outcomes.aggregator.flush_time (Timer)

The time it takes the outcome aggregator to flush aggregated outcomes.

processing.event.produced (Counter)

Number of messages placed on the Kafka queues.

When Relay operates as Sentry service and an Envelope item is successfully processed, each Envelope item results in a dedicated message on one of the ingestion topics on Kafka.

This metric is tagged with:

  • event_type: The kind of message produced to Kafka.

The message types can be:

  • event: An error or transaction event. Error events are sent to ingest-events, transactions to ingest-transactions, and errors with attachments are sent to ingest-attachments.
  • attachment: An attachment file associated with an error event, sent to ingest-attachments.
  • user_report: A message from the user feedback dialog, sent to ingest-events.
  • session: A release health session update, sent to ingest-sessions.
processing.produce.error (Counter)

Number of producer errors occurred after an envelope was already enqueued for sending to Kafka.

These errors include, for example, "MessageTooLarge" errors when the broker does not accept the requests over a certain size, which is usually due to invalid or inconsistent broker/producer configurations.

project_cache.eviction (Counter)

Number of evicted stale projects from the cache.

Relay scans the in-memory project cache for stale entries in a regular interval configured by cache.eviction_interval.

The cache duration for project states can be configured with the following options:

  • cache.project_expiry: The time after which a project state counts as expired. It is automatically refreshed if a request references the project after it has expired.
  • cache.project_grace_period: The time after expiry at which the project state will still be used to ingest events. Once the grace period expires, the cache is evicted and new requests wait for an update.
project_cache.garbage.queue_size (Gauge)

The number of items currently in the garbage disposal queue.

project_cache.hit (Counter)

Number of times a project is looked up from the cache.

The cache may contain and outdated or expired project state. In that case, the project state is updated even after a cache hit.

project_cache.miss (Counter)

Number of times a project lookup failed.

A cache entry is created immediately and the project state requested from the upstream.

project_cache.size (Histogram)

Number of project states currently held in the in-memory project cache.

The cache duration for project states can be configured with the following options:

  • cache.project_expiry: The time after which a project state counts as expired. It is automatically refreshed if a request references the project after it has expired.
  • cache.project_grace_period: The time after expiry at which the project state will still be used to ingest events. Once the grace period expires, the cache is evicted and new requests wait for an update.

There is no limit to the number of cached projects.

project_state.attempts (Histogram)

Number of attempts required to fetch the config for a given project key.

project_state.decompression (Timer)

Time in milliseconds required to decompress a project config from redis.

Note that this also times the cases where project config is uncompressed, in which case the timer should be very close to zero.

project_state.eviction.duration (Timer)

Total time in milliseconds spent evicting outdated and unused projects happens.

project_state.get (Counter)

Number of times a project state is looked up from the cache.

This includes lookups for both cached and new projects. As part of this, updates for outdated or expired project caches are triggered.

Related metrics:

  • project_cache.hit: For successful cache lookups, even for outdated projects.
  • project_cache.miss: For failed lookups resulting in an update.
project_state.no_cache (Counter)

Number of times a project config was requested with .no-cache.

This effectively counts the number of envelopes or events that have been sent with a corresponding DSN. Actual queries to the upstream may still be deduplicated for these project state requests.

A maximum of 1 such requests per second is allowed per project key. This metric counts only permitted requests.

project_state.pending (Histogram)

Number of projects in the in-memory project cache that are waiting for their state to be updated.

See project_cache.size for more description of the project cache.

project_state.received (Histogram)

Number of project states returned from the upstream for each batch request.

If multiple batches are updated concurrently, this metric is reported multiple times.

See project_cache.size for more description of the project cache.

project_state.redis.requests (Counter)

Number of times a project state is requested from the central Redis cache.

This has a tag hit with values true or false. If false the request will be sent to the sentry endpoint.

project_state.request (Counter)

Number of project state HTTP requests.

Relay updates projects in batches. Every update cycle, Relay requests limits.max_concurrent_queries batches of cache.batch_size projects from the upstream. The duration of these requests is reported via project_state.request.duration.

Note that after an update loop has completed, there may be more projects pending updates. This is indicated by project_state.pending.

project_state.request.batch_size (Histogram)

Number of project states requested from the upstream for each batch request.

If multiple batches are updated concurrently, this metric is reported multiple times.

The batch size can be configured with cache.batch_size. See project_cache.size for more description of the project cache.

project_state.request.duration (Timer)

Total time in milliseconds spent fetching queued project configuration updates requests to resolve.

Relay updates projects in batches. Every update cycle, Relay requests limits.max_concurrent_queries * cache.batch_size projects from the upstream. This metric measures the wall clock time for all concurrent requests in this loop.

Note that after an update loop has completed, there may be more projects pending updates. This is indicated by project_state.pending.

project_upstream.completed (Counter)

Number of times an upstream request for a project config is completed.

Completion can be because a result was returned or because the config request was dropped after there still was no response after a timeout. This metrics has tags for result and attempts indicating whether it was succesful or a timeout and how many attempts were made respectively.

replay.recording.process (Timer)

Time in milliseconds spent on parsing, normalizing and scrubbing replay recordings.

requests (Counter)

Number of HTTP requests reaching Relay.

requests.duration (Timer)

Total duration in milliseconds for handling inbound web requests until the HTTP response is returned to the client.

This does not correspond to the full event ingestion time. Requests for events that are not immediately rejected due to bad data or cached rate limits always return 200 OK. Full validation and normalization occur asynchronously, which is reported by event.processing_time.

This metric is tagged with:

  • method: The HTTP method of the request.
  • route: Unique dashed identifier of the endpoint.
requests.timestamp_delay (Timer)

The delay between the timestamp stated in a payload and the receive time.

SDKs cannot transmit payloads immediately in all cases. Sometimes, crashes require that events are sent after restarting the application. Similarly, SDKs buffer events during network downtimes for later transmission. This metric measures the delay between the time of the event and the time it arrives in Relay. The delay is measured after clock drift correction is applied.

Only payloads with a delay of more than 1 minute are captured.

This metric is tagged with:

  • category: The data category of the payload. Can be one of: event, transaction, security, or session.
responses.status_codes (Counter)

Number of completed HTTP requests.

This metric is tagged with:

  • status_code: The HTTP status code number.
  • method: The HTTP method used in the request in uppercase.
  • route: Unique dashed identifier of the endpoint.
scrubbing.attachments.duration (Timer)

Time spend on attachment scrubbing.

This represents the total time spent on evaluating the scrubbing rules for an attachment and the attachment scrubbing itself, regardless of whether any rules were applied. Note that minidumps which failed to be parsed (status="error" in scrubbing.minidumps.duration) will be scrubbed as plain attachments and count towards this.

scrubbing.minidumps.duration (Timer)

Time spent on minidump scrubbing.

This is the total time spent on parsing and scrubbing the minidump. Even if no PII scrubbing rules applied the minidump will still be parsed and the rules evaluated on the parsed minidump, this duration is reported here with status of "n/a".

This metric is tagged with:

  • status: Scrubbing status: "ok" means successful scrubbed, "error" means there was an error during scrubbing and finally "n/a" means scrubbing was successful but no scurbbing rules applied.
server.starting (Counter)

Number of Relay server starts.

This can be used to track unwanted restarts due to crashes or termination.

service.back_pressure (Gauge)

A number of messages queued in a services inbound message channel.

This metric is emitted once per second for every running service. Without backlogs, this number should be close to 0. If this number is monotonically increasing, the service is not able to process the inbound message volume.

This metric is tagged with:

  • service: The fully qualified type name of the service implementation.
upstream.envelope.body_size (Histogram)

Size of queries (projectconfig queries, i.e. the request payload, not the response) sent by Relay over HTTP in bytes.

upstream.network_outage (Gauge)

The state of Relay with respect to the upstream connection. Possible values are 0 for normal operations and 1 for a network outage.

upstream.query.body_size (Histogram)

Size of envelopes sent over HTTP in bytes.

upstream.requests.duration (Timer)

Total time spent to send request to upstream Relay and handle the response.

This metric is tagged with:

  • result: What happened to the request, an enumeration with the following values:
  • success: The request was sent and returned a success code HTTP 2xx
  • response_error: The request was sent and it returned an HTTP error.
  • payload_failed: The request was sent but there was an error in interpreting the response.
  • send_failed: Failed to send the request due to a network error.
  • rate_limited: The request was rate limited.
  • invalid_json: The response could not be parsed back into JSON.
  • route: The endpoint that was called on the upstream.
  • status-code: The status code of the request when available, otherwise "-".
  • retries: Number of retries bucket 0, 1, 2, few (3 - 10), many (more than 10).
upstream.retries (Histogram)

Counts the number of retries for each upstream http request.

This metric is tagged with:

  • result: What happened to the request, an enumeration with the following values:
  • success: The request was sent and returned a success code HTTP 2xx
  • response_error: The request was sent and it returned an HTTP error.
  • payload_failed: The request was sent but there was an error in interpreting the response.
  • send_failed: Failed to send the request due to a network error.
  • rate_limited: The request was rate limited.
  • invalid_json: The response could not be parsed back into JSON.
  • route: The endpoint that was called on the upstream.
  • status-code: The status code of the request when available, otherwise "-".
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) to suggesting an update ("yeah, this would be better").