relay_server/
statsd.rs

1use relay_statsd::{CounterMetric, DistributionMetric, GaugeMetric, TimerMetric};
2#[cfg(doc)]
3use relay_system::RuntimeMetrics;
4
5/// Gauge metrics used by Relay
6pub enum RelayGauges {
7    /// Tracks the number of futures waiting to be executed in the pool's queue.
8    ///
9    /// Useful for understanding the backlog of work and identifying potential bottlenecks.
10    ///
11    /// This metric is tagged with:
12    /// - `pool`: the name of the pool.
13    AsyncPoolQueueSize,
14    /// Tracks the utilization of the async pool.
15    ///
16    /// The utilization is a value between 0.0 and 100.0 which determines how busy the pool is doing
17    /// CPU-bound work.
18    ///
19    /// This metric is tagged with:
20    /// - `pool`: the name of the pool.
21    AsyncPoolUtilization,
22    /// Tracks the activity of the async pool.
23    ///
24    /// The activity is a value between 0.0 and 100.0 which determines how busy is the pool
25    /// w.r.t. to its provisioned capacity.
26    ///
27    /// This metric is tagged with:
28    /// - `pool`: the name of the pool.
29    AsyncPoolActivity,
30    /// The state of Relay with respect to the upstream connection.
31    /// Possible values are `0` for normal operations and `1` for a network outage.
32    NetworkOutage,
33    /// Number of elements in the envelope buffer across all the stacks.
34    ///
35    /// This metric is tagged with:
36    /// - `storage_type`: The type of storage used in the envelope buffer.
37    BufferEnvelopesCount,
38    /// The number of individual stacks in the priority queue.
39    ///
40    /// Per combination of `(own_key, sampling_key)`, a new stack is created.
41    BufferStackCount,
42    /// The used disk for the buffer.
43    BufferDiskUsed,
44    /// The currently used memory by the entire system.
45    ///
46    /// Relay uses the same value for its memory health check.
47    SystemMemoryUsed,
48    /// The total system memory.
49    ///
50    /// Relay uses the same value for its memory health check.
51    SystemMemoryTotal,
52    /// The number of connections currently being managed by the Redis Pool.
53    #[cfg(feature = "processing")]
54    RedisPoolConnections,
55    /// The number of idle connections in the Redis Pool.
56    #[cfg(feature = "processing")]
57    RedisPoolIdleConnections,
58    /// The maximum number of connections in the Redis pool.
59    #[cfg(feature = "processing")]
60    RedisPoolMaxConnections,
61    /// The number of futures waiting to grab a connection.
62    #[cfg(feature = "processing")]
63    RedisPoolWaitingForConnection,
64    /// The number of notifications in the broadcast channel of the project cache.
65    ProjectCacheNotificationChannel,
66    /// The number of scheduled and in progress fetches in the project cache.
67    ProjectCacheScheduledFetches,
68    /// Exposes the amount of currently open and handled connections by the server.
69    ServerActiveConnections,
70    /// Maximum delay of a metric bucket in seconds.
71    ///
72    /// The maximum is measured from initial creation of the bucket in an internal Relay
73    /// until it is produced to Kafka.
74    ///
75    /// This metric is tagged with:
76    /// - `namespace`: the metric namespace.
77    #[cfg(feature = "processing")]
78    MetricDelayMax,
79    /// Estimated percentage [0-100] of how busy Relay's internal services are.
80    ///
81    /// This metric is tagged with:
82    /// - `service`: the service name.
83    /// - `instance_id`: a for the service name unique identifier for the running service
84    ServiceUtilization,
85    /// Number of attachment uploads currently in flight.
86    #[cfg(feature = "processing")]
87    ConcurrentAttachmentUploads,
88}
89
90impl GaugeMetric for RelayGauges {
91    fn name(&self) -> &'static str {
92        match self {
93            Self::AsyncPoolQueueSize => "async_pool.queue_size",
94            Self::AsyncPoolUtilization => "async_pool.utilization",
95            Self::AsyncPoolActivity => "async_pool.activity",
96            Self::NetworkOutage => "upstream.network_outage",
97            Self::BufferEnvelopesCount => "buffer.envelopes_count",
98            Self::BufferStackCount => "buffer.stack_count",
99            Self::BufferDiskUsed => "buffer.disk_used",
100            Self::SystemMemoryUsed => "health.system_memory.used",
101            Self::SystemMemoryTotal => "health.system_memory.total",
102            #[cfg(feature = "processing")]
103            Self::RedisPoolConnections => "redis.pool.connections",
104            #[cfg(feature = "processing")]
105            Self::RedisPoolIdleConnections => "redis.pool.idle_connections",
106            #[cfg(feature = "processing")]
107            Self::RedisPoolMaxConnections => "redis.pool.max_connections",
108            #[cfg(feature = "processing")]
109            Self::RedisPoolWaitingForConnection => "redis.pool.waiting_for_connection",
110            Self::ProjectCacheNotificationChannel => "project_cache.notification_channel.size",
111            Self::ProjectCacheScheduledFetches => "project_cache.fetches.size",
112            Self::ServerActiveConnections => "server.http.connections",
113            #[cfg(feature = "processing")]
114            Self::MetricDelayMax => "metrics.delay.max",
115            Self::ServiceUtilization => "service.utilization",
116            #[cfg(feature = "processing")]
117            Self::ConcurrentAttachmentUploads => "attachment.upload.concurrent",
118        }
119    }
120}
121
122/// Gauge metrics collected from the Runtime.
123pub enum RuntimeGauges {
124    /// Exposes [`RuntimeMetrics::num_idle_threads`].
125    NumIdleThreads,
126    /// Exposes [`RuntimeMetrics::num_alive_tasks`].
127    NumAliveTasks,
128    /// Exposes [`RuntimeMetrics::blocking_queue_depth`].
129    BlockingQueueDepth,
130    /// Exposes [`RuntimeMetrics::num_blocking_threads`].
131    NumBlockingThreads,
132    /// Exposes [`RuntimeMetrics::num_idle_blocking_threads`].
133    NumIdleBlockingThreads,
134    /// Exposes [`RuntimeMetrics::num_workers`].
135    NumWorkers,
136    /// Exposes [`RuntimeMetrics::worker_local_queue_depth`].
137    ///
138    /// This metric is tagged with:
139    /// - `worker`: the worker id.
140    WorkerLocalQueueDepth,
141    /// Exposes [`RuntimeMetrics::worker_mean_poll_time`].
142    ///
143    /// This metric is tagged with:
144    /// - `worker`: the worker id.
145    WorkerMeanPollTime,
146}
147
148impl GaugeMetric for RuntimeGauges {
149    fn name(&self) -> &'static str {
150        match self {
151            RuntimeGauges::NumIdleThreads => "runtime.idle_threads",
152            RuntimeGauges::NumAliveTasks => "runtime.alive_tasks",
153            RuntimeGauges::BlockingQueueDepth => "runtime.blocking_queue_depth",
154            RuntimeGauges::NumBlockingThreads => "runtime.num_blocking_threads",
155            RuntimeGauges::NumIdleBlockingThreads => "runtime.num_idle_blocking_threads",
156            RuntimeGauges::NumWorkers => "runtime.num_workers",
157            RuntimeGauges::WorkerLocalQueueDepth => "runtime.worker_local_queue_depth",
158            RuntimeGauges::WorkerMeanPollTime => "runtime.worker_mean_poll_time",
159        }
160    }
161}
162
163/// Counter metrics collected from the Runtime.
164pub enum RuntimeCounters {
165    /// Exposes [`RuntimeMetrics::budget_forced_yield_count`].
166    BudgetForcedYieldCount,
167    /// Exposes [`RuntimeMetrics::worker_local_schedule_count`].
168    ///
169    /// This metric is tagged with:
170    /// - `worker`: the worker id.
171    WorkerLocalScheduleCount,
172    /// Exposes [`RuntimeMetrics::worker_noop_count`].
173    ///
174    /// This metric is tagged with:
175    /// - `worker`: the worker id.
176    WorkerNoopCount,
177    /// Exposes [`RuntimeMetrics::worker_overflow_count`].
178    ///
179    /// This metric is tagged with:
180    /// - `worker`: the worker id.
181    WorkerOverflowCount,
182    /// Exposes [`RuntimeMetrics::worker_park_count`].
183    ///
184    /// This metric is tagged with:
185    /// - `worker`: the worker id.
186    WorkerParkCount,
187    /// Exposes [`RuntimeMetrics::worker_poll_count`].
188    ///
189    /// This metric is tagged with:
190    /// - `worker`: the worker id.
191    WorkerPollCount,
192    /// Exposes [`RuntimeMetrics::worker_steal_count`].
193    ///
194    /// This metric is tagged with:
195    /// - `worker`: the worker id.
196    WorkerStealCount,
197    /// Exposes [`RuntimeMetrics::worker_steal_operations`].
198    ///
199    /// This metric is tagged with:
200    /// - `worker`: the worker id.
201    WorkerStealOperations,
202    /// Exposes [`RuntimeMetrics::worker_total_busy_duration`].
203    ///
204    /// This metric is tagged with:
205    /// - `worker`: the worker id.
206    WorkerTotalBusyDuration,
207}
208
209impl CounterMetric for RuntimeCounters {
210    fn name(&self) -> &'static str {
211        match self {
212            RuntimeCounters::BudgetForcedYieldCount => "runtime.budget_forced_yield_count",
213            RuntimeCounters::WorkerLocalScheduleCount => "runtime.worker_local_schedule_count",
214            RuntimeCounters::WorkerNoopCount => "runtime.worker_noop_count",
215            RuntimeCounters::WorkerOverflowCount => "runtime.worker_overflow_count",
216            RuntimeCounters::WorkerParkCount => "runtime.worker_park_count",
217            RuntimeCounters::WorkerPollCount => "runtime.worker_poll_count",
218            RuntimeCounters::WorkerStealCount => "runtime.worker_steal_count",
219            RuntimeCounters::WorkerStealOperations => "runtime.worker_steal_operations",
220            RuntimeCounters::WorkerTotalBusyDuration => "runtime.worker_total_busy_duration",
221        }
222    }
223}
224
225/// Histogram metrics used by Relay.
226pub enum RelayDistributions {
227    /// The number of bytes received by Relay for each individual envelope item type.
228    ///
229    /// This metric is tagged with:
230    ///  - `item_type`: The type of the items being counted.
231    ///  - `is_container`: Whether this item is a container holding multiple items.
232    EnvelopeItemSize,
233    /// The amount of bytes in the item payloads of an envelope pushed to the envelope buffer.
234    ///
235    /// This is not quite the same as the actual size of a serialized envelope, because it ignores
236    /// the envelope header and item headers.
237    BufferEnvelopeBodySize,
238    /// Size of a serialized envelope pushed to the envelope buffer.
239    BufferEnvelopeSize,
240    /// Size of a compressed envelope pushed to the envelope buffer.
241    BufferEnvelopeSizeCompressed,
242    /// The number of batches emitted per partition.
243    BatchesPerPartition,
244    /// The number of buckets in a batch emitted.
245    ///
246    /// This corresponds to the number of buckets that will end up in an envelope.
247    BucketsPerBatch,
248    /// The number of spans per processed transaction event.
249    ///
250    /// This metric is tagged with:
251    ///  - `platform`: The event's platform, such as `"javascript"`.
252    ///  - `sdk`: The name of the Sentry SDK sending the transaction. This tag is only set for
253    ///    Sentry's SDKs and defaults to "proprietary".
254    EventSpans,
255    /// Number of projects in the in-memory project cache that are waiting for their state to be
256    /// updated.
257    ///
258    /// See `project_cache.size` for more description of the project cache.
259    ProjectStatePending,
260    /// Number of project states **requested** from the upstream for each batch request.
261    ///
262    /// If multiple batches are updated concurrently, this metric is reported multiple times.
263    ///
264    /// The batch size can be configured with `cache.batch_size`. See `project_cache.size` for more
265    /// description of the project cache.
266    ProjectStateRequestBatchSize,
267    /// Number of project states **returned** from the upstream for each batch request.
268    ///
269    /// If multiple batches are updated concurrently, this metric is reported multiple times.
270    ///
271    /// See `project_cache.size` for more description of the project cache.
272    ProjectStateReceived,
273    /// Number of attempts required to fetch the config for a given project key.
274    ProjectStateAttempts,
275    /// Number of project states currently held in the in-memory project cache.
276    ///
277    /// The cache duration for project states can be configured with the following options:
278    ///
279    ///  - `cache.project_expiry`: The time after which a project state counts as expired. It is
280    ///    automatically refreshed if a request references the project after it has expired.
281    ///  - `cache.project_grace_period`: The time after expiry at which the project state will still
282    ///    be used to ingest events. Once the grace period expires, the cache is evicted and new
283    ///    requests wait for an update.
284    ///
285    /// There is no limit to the number of cached projects.
286    ProjectStateCacheSize,
287    /// The size of the compressed project config in the redis cache, in bytes.
288    #[cfg(feature = "processing")]
289    ProjectStateSizeBytesCompressed,
290    /// The size of the uncompressed project config in the redis cache, in bytes.
291    #[cfg(feature = "processing")]
292    ProjectStateSizeBytesDecompressed,
293    /// The number of upstream requests queued up for sending.
294    ///
295    /// Relay employs connection keep-alive whenever possible. Connections are kept open for _15_
296    /// seconds of inactivity or _75_ seconds of activity. If all connections are busy, they are
297    /// queued, which is reflected in this metric.
298    ///
299    /// This metric is tagged with:
300    ///  - `priority`: The queueing priority of the request, either `"high"` or `"low"`. The
301    ///    priority determines precedence in executing requests.
302    ///
303    /// The number of concurrent connections can be configured with:
304    ///  - `limits.max_concurrent_requests` for the overall number of connections
305    ///  - `limits.max_concurrent_queries` for the number of concurrent high-priority requests
306    UpstreamMessageQueueSize,
307    /// Counts the number of retries for each upstream http request.
308    ///
309    /// This metric is tagged with:
310    ///
311    ///   - `result`: What happened to the request, an enumeration with the following values:
312    ///     * `success`: The request was sent and returned a success code `HTTP 2xx`
313    ///     * `response_error`: The request was sent and it returned an HTTP error.
314    ///     * `payload_failed`: The request was sent but there was an error in interpreting the response.
315    ///     * `send_failed`: Failed to send the request due to a network error.
316    ///     * `rate_limited`: The request was rate limited.
317    ///     * `invalid_json`: The response could not be parsed back into JSON.
318    ///   - `route`: The endpoint that was called on the upstream.
319    ///   - `status-code`: The status code of the request when available, otherwise "-".
320    UpstreamRetries,
321    /// Size of envelopes sent over HTTP in bytes.
322    UpstreamQueryBodySize,
323    /// Size of queries (projectconfig queries, i.e. the request payload, not the response) sent by
324    /// Relay over HTTP in bytes.
325    UpstreamEnvelopeBodySize,
326    /// Size of batched global metrics requests sent by Relay over HTTP in bytes.
327    UpstreamMetricsBodySize,
328    /// Distribution of flush buckets over partition keys.
329    ///
330    /// The distribution of buckets should be even.
331    /// If it is not, this metric should expose it.
332    PartitionKeys,
333    /// Measures how many splits were performed when sending out a partition.
334    PartitionSplits,
335    /// Canonical size of a Trace Item.
336    ///
337    /// This is not the size in bytes, this is using the same algorithm we're using for the logs
338    /// billing category.
339    ///
340    /// This metric is tagged with:
341    ///  - `item`: the trace item type.
342    ///  - `too_large`: `true` or `false`, whether the item is bigger than the allowed size limit.
343    TraceItemCanonicalSize,
344    /// The Content-Length of incoming HTTP requests in bytes.
345    ///
346    /// This metric is tagged with:
347    ///  - `has_content_length`: Whether the Content-Length header was present ("true"/"false").
348    ///  - `route`: The matched route pattern.
349    ///  - `status_code`: The HTTP response status code.
350    ContentLength,
351}
352
353impl DistributionMetric for RelayDistributions {
354    fn name(&self) -> &'static str {
355        match self {
356            Self::EnvelopeItemSize => "event.item_size",
357            Self::EventSpans => "event.spans",
358            Self::BatchesPerPartition => "metrics.buckets.batches_per_partition",
359            Self::BucketsPerBatch => "metrics.buckets.per_batch",
360            Self::BufferEnvelopeBodySize => "buffer.envelope_body_size",
361            Self::BufferEnvelopeSize => "buffer.envelope_size",
362            Self::BufferEnvelopeSizeCompressed => "buffer.envelope_size.compressed",
363            Self::ProjectStatePending => "project_state.pending",
364            Self::ProjectStateAttempts => "project_state.attempts",
365            Self::ProjectStateRequestBatchSize => "project_state.request.batch_size",
366            Self::ProjectStateReceived => "project_state.received",
367            Self::ProjectStateCacheSize => "project_cache.size",
368            #[cfg(feature = "processing")]
369            Self::ProjectStateSizeBytesCompressed => "project_state.size_bytes.compressed",
370            #[cfg(feature = "processing")]
371            Self::ProjectStateSizeBytesDecompressed => "project_state.size_bytes.decompressed",
372            Self::UpstreamMessageQueueSize => "http_queue.size",
373            Self::UpstreamRetries => "upstream.retries",
374            Self::UpstreamQueryBodySize => "upstream.query.body_size",
375            Self::UpstreamEnvelopeBodySize => "upstream.envelope.body_size",
376            Self::UpstreamMetricsBodySize => "upstream.metrics.body_size",
377            Self::PartitionKeys => "metrics.buckets.partition_keys",
378            Self::PartitionSplits => "partition_splits",
379            Self::TraceItemCanonicalSize => "trace_item.canonical_size",
380            Self::ContentLength => "requests.content_length",
381        }
382    }
383}
384
385/// Timer metrics used by Relay
386pub enum RelayTimers {
387    /// Time in milliseconds spent deserializing an event from JSON bytes into the native data
388    /// structure on which Relay operates.
389    EventProcessingDeserialize,
390    /// Time in milliseconds spent running normalization on an event. Normalization
391    /// happens before envelope filtering and metric extraction.
392    EventProcessingNormalization,
393    /// Time in milliseconds spent running inbound data filters on an event.
394    EventProcessingFiltering,
395    /// Time in milliseconds spent checking for organization, project, and DSN rate limits.
396    ///
397    /// Not all events reach this point. After an event is rate limited for the first time, the rate
398    /// limit is cached. Events coming in after this will be discarded earlier in the request queue
399    /// and do not reach the processing queue.
400    ///
401    /// This metric is tagged with:
402    ///  - `type`: The type of limiter executed, `cached` or `consistent`.
403    ///  - `unit`: The item/unit of work which is being rate limited, only available for new
404    ///    processing pipelines.
405    EventProcessingRateLimiting,
406    /// Time in milliseconds spent in data scrubbing for the current event. Data scrubbing happens
407    /// last before serializing the event back to JSON.
408    EventProcessingPii,
409    /// Time spent converting the event from its in-memory reprsentation into a JSON string.
410    EventProcessingSerialization,
411    /// Time used to extract span metrics from an event.
412    EventProcessingSpanMetricsExtraction,
413    /// Time spent between the start of request handling and processing of the envelope.
414    ///
415    /// This includes streaming the request body, scheduling overheads, project config fetching,
416    /// batched requests and congestions in the internal processor. This does not include delays in
417    /// the incoming request (body upload) and skips all envelopes that are fast-rejected.
418    EnvelopeWaitTime,
419    /// Time in milliseconds spent in synchronous processing of envelopes.
420    ///
421    /// This timing covers the end-to-end processing in the CPU pool and comprises:
422    ///
423    ///  - `event_processing.deserialize`
424    ///  - `event_processing.pii`
425    ///  - `event_processing.serialization`
426    ///
427    /// With Relay in processing mode, this also includes the following timings:
428    ///
429    ///  - `event_processing.process`
430    ///  - `event_processing.filtering`
431    ///  - `event_processing.rate_limiting`
432    EnvelopeProcessingTime,
433    /// Total time in milliseconds an envelope spends in Relay from the time it is received until it
434    /// finishes processing and has been submitted to the upstream.
435    EnvelopeTotalTime,
436    /// Latency of project config updates until they reach Relay.
437    ///
438    /// The metric is calculated by using the creation timestamp of the project config
439    /// and when Relay updates its local cache with the new project config.
440    ///
441    /// No metric is emitted when Relay fetches a project config for the first time.
442    ///
443    /// This metric is tagged with:
444    ///  - `delay`: Bucketed amount of seconds passed between fetches.
445    ProjectCacheUpdateLatency,
446    /// Total time spent from starting to fetch a project config update to completing the fetch.
447    ProjectCacheFetchDuration,
448    /// Total time in milliseconds spent fetching queued project configuration updates requests to
449    /// resolve.
450    ///
451    /// Relay updates projects in batches. Every update cycle, Relay requests
452    /// `limits.max_concurrent_queries * cache.batch_size` projects from the upstream. This metric
453    /// measures the wall clock time for all concurrent requests in this loop.
454    ///
455    /// Note that after an update loop has completed, there may be more projects pending updates.
456    /// This is indicated by `project_state.pending`.
457    ProjectStateRequestDuration,
458    /// Time in milliseconds required to decompress a project config from redis.
459    ///
460    /// Note that this also times the cases where project config is uncompressed,
461    /// in which case the timer should be very close to zero.
462    #[cfg(feature = "processing")]
463    ProjectStateDecompression,
464    /// Total duration in milliseconds for handling inbound web requests until the HTTP response is
465    /// returned to the client.
466    ///
467    /// This does **not** correspond to the full event ingestion time. Requests for events that are
468    /// not immediately rejected due to bad data or cached rate limits always return `200 OK`. Full
469    /// validation and normalization occur asynchronously, which is reported by
470    /// `event.processing_time`.
471    ///
472    /// This metric is tagged with:
473    ///  - `method`: The HTTP method of the request.
474    ///  - `route`: Unique dashed identifier of the endpoint.
475    RequestsDuration,
476    /// Time spent on minidump scrubbing.
477    ///
478    /// This is the total time spent on parsing and scrubbing the minidump.  Even if no PII
479    /// scrubbing rules applied the minidump will still be parsed and the rules evaluated on
480    /// the parsed minidump, this duration is reported here with status of "n/a".
481    ///
482    /// This metric is tagged with:
483    ///
484    /// - `status`: Scrubbing status: "ok" means successful scrubbed, "error" means there
485    ///   was an error during scrubbing and finally "n/a" means scrubbing was successful
486    ///   but no scurbbing rules applied.
487    MinidumpScrubbing,
488    /// Time spent on view hierarchy scrubbing.
489    ///
490    /// This is the total time spent on parsing and scrubbing the view hierarchy json file.
491    ///
492    /// This metric is tagged with:
493    ///
494    /// - `status`: "ok" means successful scrubbed, "error" means there was an error during
495    ///   scrubbing
496    ViewHierarchyScrubbing,
497    /// Time spend on attachment scrubbing.
498    ///
499    /// This represents the total time spent on evaluating the scrubbing rules for an
500    /// attachment and the attachment scrubbing itself, regardless of whether any rules were
501    /// applied.  Note that minidumps which failed to be parsed (status="error" in
502    /// scrubbing.minidumps.duration) will be scrubbed as plain attachments and count
503    /// towards this.
504    ///
505    /// This metric is tagged with:
506    ///
507    ///   - `attachment_type`: The type of attachment, e.g. "minidump".
508    AttachmentScrubbing,
509    /// Total time spent to send request to upstream Relay and handle the response.
510    ///
511    /// This metric is tagged with:
512    ///
513    ///   - `result`: What happened to the request, an enumeration with the following values:
514    ///     * `success`: The request was sent and returned a success code `HTTP 2xx`
515    ///     * `response_error`: The request was sent and it returned an HTTP error.
516    ///     * `payload_failed`: The request was sent but there was an error in interpreting the response.
517    ///     * `send_failed`: Failed to send the request due to a network error.
518    ///     * `rate_limited`: The request was rate limited.
519    ///     * `invalid_json`: The response could not be parsed back into JSON.
520    ///   - `route`: The endpoint that was called on the upstream.
521    ///   - `status-code`: The status code of the request when available, otherwise "-".
522    ///   - `retries`: Number of retries bucket 0, 1, 2, few (3 - 10), many (more than 10).
523    UpstreamRequestsDuration,
524    /// The delay between the timestamp stated in a payload and the receive time.
525    ///
526    /// SDKs cannot transmit payloads immediately in all cases. Sometimes, crashes require that
527    /// events are sent after restarting the application. Similarly, SDKs buffer events during
528    /// network downtimes for later transmission. This metric measures the delay between the time of
529    /// the event and the time it arrives in Relay. The delay is measured after clock drift
530    /// correction is applied.
531    ///
532    /// Only payloads with a delay of more than 1 minute are captured.
533    ///
534    /// This metric is tagged with:
535    ///
536    ///  - `category`: The data category of the payload. Can be one of: `event`, `transaction`,
537    ///    `security`, or `session`.
538    TimestampDelay,
539    /// The time it takes the outcome aggregator to flush aggregated outcomes.
540    OutcomeAggregatorFlushTime,
541    /// Time in milliseconds spent on parsing, normalizing and scrubbing replay recordings.
542    ReplayRecordingProcessing,
543    /// Total time spent to send a request and receive the response from upstream.
544    GlobalConfigRequestDuration,
545    /// Timing in milliseconds for processing a message in the internal CPU pool.
546    ///
547    /// This metric is tagged with:
548    ///
549    ///  - `message`: The type of message that was processed.
550    ProcessMessageDuration,
551    /// Timing in milliseconds for processing a task in the project cache service.
552    ///
553    /// This metric is tagged with:
554    /// - `task`: The type of the task the project cache does.
555    ProjectCacheTaskDuration,
556    /// Timing in milliseconds for handling and responding to a health check request.
557    ///
558    /// This metric is tagged with:
559    ///  - `type`: The type of the health check, `liveness` or `readiness`.
560    HealthCheckDuration,
561    /// Temporary timing metric for how much time was spent evaluating span and transaction
562    /// rate limits using the `RateLimitBuckets` message in the processor.
563    ///
564    /// This metric is tagged with:
565    ///  - `category`: The data category evaluated.
566    ///  - `limited`: Whether the batch is rate limited.
567    ///  - `count`: How many items matching the data category are contained in the batch.
568    #[cfg(feature = "processing")]
569    RateLimitBucketsDuration,
570    /// Timing in milliseconds for processing a task in the aggregator service.
571    ///
572    /// This metric is tagged with:
573    ///  - `task`: The task being executed by the aggregator.
574    ///  - `aggregator`: The name of the aggregator.
575    AggregatorServiceDuration,
576    /// Timing in milliseconds for processing a message in the metric router service.
577    ///
578    /// This metric is tagged with:
579    ///  - `message`: The type of message that was processed.
580    MetricRouterServiceDuration,
581    /// Timing in milliseconds for processing a message in the metric store service.
582    ///
583    /// This metric is tagged with:
584    ///  - `message`: The type of message that was processed.
585    #[cfg(feature = "processing")]
586    StoreServiceDuration,
587    /// Timing in milliseconds for the time it takes for initialize the buffer.
588    BufferInitialization,
589    /// Timing in milliseconds for the time it takes for the buffer to pack & spool a batch.
590    ///
591    /// Contains the time it takes to pack multiple envelopes into a single memory blob.
592    BufferSpool,
593    /// Timing in milliseconds for the time it takes for the buffer to spool data to SQLite.
594    BufferSqlWrite,
595    /// Timing in milliseconds for the time it takes for the buffer to unspool data from disk.
596    BufferUnspool,
597    /// Timing in milliseconds for the time it takes for the buffer to push.
598    BufferPush,
599    /// Timing in milliseconds for the time it takes for the buffer to peek.
600    BufferPeek,
601    /// Timing in milliseconds for the time it takes for the buffer to pop.
602    BufferPop,
603    /// Timing in milliseconds for the time it takes for the buffer to drain its envelopes.
604    BufferDrain,
605    /// Timing in milliseconds for the time it takes for an envelope to be serialized.
606    BufferEnvelopesSerialization,
607    /// Timing in milliseconds for the time it takes for an envelope to be compressed.
608    BufferEnvelopeCompression,
609    /// Timing in milliseconds for the time it takes for an envelope to be decompressed.
610    BufferEnvelopeDecompression,
611    /// Timing in milliseconds to count spans in a serialized transaction payload.
612    CheckNestedSpans,
613    /// The time it needs to create a signature. Includes both the signature used for
614    /// trusted relays and for register challenges.
615    SignatureCreationDuration,
616    /// Time needed to upload an attachment to objectstore.
617    ///
618    /// Tagged by:
619    /// - `type`: "envelope" or "attachment_v2".
620    #[cfg(feature = "processing")]
621    AttachmentUploadDuration,
622}
623
624impl TimerMetric for RelayTimers {
625    fn name(&self) -> &'static str {
626        match self {
627            RelayTimers::EventProcessingDeserialize => "event_processing.deserialize",
628            RelayTimers::EventProcessingNormalization => "event_processing.normalization",
629            RelayTimers::EventProcessingFiltering => "event_processing.filtering",
630            RelayTimers::EventProcessingRateLimiting => "event_processing.rate_limiting",
631            RelayTimers::EventProcessingPii => "event_processing.pii",
632            RelayTimers::EventProcessingSpanMetricsExtraction => {
633                "event_processing.span_metrics_extraction"
634            }
635            RelayTimers::EventProcessingSerialization => "event_processing.serialization",
636            RelayTimers::EnvelopeWaitTime => "event.wait_time",
637            RelayTimers::EnvelopeProcessingTime => "event.processing_time",
638            RelayTimers::EnvelopeTotalTime => "event.total_time",
639            RelayTimers::ProjectStateRequestDuration => "project_state.request.duration",
640            #[cfg(feature = "processing")]
641            RelayTimers::ProjectStateDecompression => "project_state.decompression",
642            RelayTimers::ProjectCacheUpdateLatency => "project_cache.latency",
643            RelayTimers::ProjectCacheFetchDuration => "project_cache.fetch.duration",
644            RelayTimers::RequestsDuration => "requests.duration",
645            RelayTimers::MinidumpScrubbing => "scrubbing.minidumps.duration",
646            RelayTimers::ViewHierarchyScrubbing => "scrubbing.view_hierarchy_scrubbing.duration",
647            RelayTimers::AttachmentScrubbing => "scrubbing.attachments.duration",
648            RelayTimers::UpstreamRequestsDuration => "upstream.requests.duration",
649            RelayTimers::TimestampDelay => "requests.timestamp_delay",
650            RelayTimers::OutcomeAggregatorFlushTime => "outcomes.aggregator.flush_time",
651            RelayTimers::ReplayRecordingProcessing => "replay.recording.process",
652            RelayTimers::GlobalConfigRequestDuration => "global_config.requests.duration",
653            RelayTimers::ProcessMessageDuration => "processor.message.duration",
654            RelayTimers::ProjectCacheTaskDuration => "project_cache.task.duration",
655            RelayTimers::HealthCheckDuration => "health.message.duration",
656            #[cfg(feature = "processing")]
657            RelayTimers::RateLimitBucketsDuration => "processor.rate_limit_buckets",
658            RelayTimers::AggregatorServiceDuration => "metrics.aggregator.message.duration",
659            RelayTimers::MetricRouterServiceDuration => "metrics.router.message.duration",
660            #[cfg(feature = "processing")]
661            RelayTimers::StoreServiceDuration => "store.message.duration",
662            RelayTimers::BufferInitialization => "buffer.initialization.duration",
663            RelayTimers::BufferSpool => "buffer.spool.duration",
664            RelayTimers::BufferSqlWrite => "buffer.write.duration",
665            RelayTimers::BufferUnspool => "buffer.unspool.duration",
666            RelayTimers::BufferPush => "buffer.push.duration",
667            RelayTimers::BufferPeek => "buffer.peek.duration",
668            RelayTimers::BufferPop => "buffer.pop.duration",
669            RelayTimers::BufferDrain => "buffer.drain.duration",
670            RelayTimers::BufferEnvelopesSerialization => "buffer.envelopes_serialization",
671            RelayTimers::BufferEnvelopeCompression => "buffer.envelopes_compression",
672            RelayTimers::BufferEnvelopeDecompression => "buffer.envelopes_decompression",
673            RelayTimers::CheckNestedSpans => "envelope.check_nested_spans",
674            RelayTimers::SignatureCreationDuration => "signature.create.duration",
675            #[cfg(feature = "processing")]
676            RelayTimers::AttachmentUploadDuration => "attachment.upload.duration",
677        }
678    }
679}
680
681/// Counter metrics used by Relay
682pub enum RelayCounters {
683    /// Tracks the number of tasks driven to completion by the async pool.
684    ///
685    /// This metric is tagged with:
686    /// - `pool`: the name of the pool.
687    AsyncPoolFinishedTasks,
688    /// Number of Events that had corrupted (unprintable) event attributes.
689    ///
690    /// This currently checks for `environment` and `release`, for which we know that
691    /// some SDKs may send corrupted values.
692    EventCorrupted,
693    /// Number of envelopes accepted in the current time slot.
694    ///
695    /// This represents requests that have successfully passed rate limits and filters, and have
696    /// been sent to the upstream.
697    ///
698    /// This metric is tagged with:
699    ///  - `handling`: Either `"success"` if the envelope was handled correctly, or `"failure"` if
700    ///    there was an error or bug.
701    EnvelopeAccepted,
702    /// Number of envelopes rejected in the current time slot.
703    ///
704    /// This includes envelopes being rejected because they are malformed or any other errors during
705    /// processing (including filtered events, invalid payloads, and rate limits).
706    ///
707    /// To check the rejection reason, check `events.outcomes`, instead.
708    ///
709    /// This metric is tagged with:
710    ///  - `handling`: Either `"success"` if the envelope was handled correctly, or `"failure"` if
711    ///    there was an error or bug.
712    EnvelopeRejected,
713    /// Number of total envelope items we received.
714    ///
715    /// Note: This does not count raw items, it counts the logical amount of items,
716    /// e.g. a single item container counts all its contained items.
717    ///
718    /// This metric is tagged with:
719    ///  - `item_type`: The type of the items being counted.
720    ///  - `is_container`: Whether this item is a container holding multiple items.
721    ///  - `sdk`: The name of the Sentry SDK sending the envelope. This tag is only set for
722    ///    Sentry's SDKs and defaults to "proprietary".
723    EnvelopeItems,
724    /// Number of bytes we processed per envelope item.
725    ///
726    /// This metric is tagged with:
727    ///  - `item_type`: The type of the items being counted.
728    ///  - `is_container`: Whether this item is a container holding multiple items.
729    ///  - `sdk`: The name of the Sentry SDK sending the envelope. This tag is only set for
730    ///    Sentry's SDKs and defaults to "proprietary".
731    EnvelopeItemBytes,
732    /// Number of times an envelope from the buffer is trying to be popped.
733    BufferTryPop,
734    /// Number of envelopes spool to disk.
735    BufferSpooledEnvelopes,
736    /// Number of envelopes unspooled from disk.
737    BufferUnspooledEnvelopes,
738    /// Number of project changed updates received by the buffer.
739    BufferProjectChangedEvent,
740    /// Number of times one or more projects of an envelope were pending when trying to pop
741    /// their envelope.
742    BufferProjectPending,
743    /// Number of iterations of the envelope buffer service loop.
744    BufferServiceLoopIteration,
745    /// Number of outcomes and reasons for rejected Envelopes.
746    ///
747    /// This metric is tagged with:
748    ///  - `outcome`: The basic cause for rejecting the event.
749    ///  - `reason`: A more detailed identifier describing the rule or mechanism leading to the
750    ///    outcome.
751    ///  - `to`: Describes the destination of the outcome. Can be either 'kafka' (when in
752    ///    processing mode) or 'http' (when outcomes are enabled in an external relay).
753    ///
754    /// Possible outcomes are:
755    ///  - `filtered`: Dropped by inbound data filters. The reason specifies the filter that
756    ///    matched.
757    ///  - `rate_limited`: Dropped by organization, project, or DSN rate limit, as well as exceeding
758    ///    the Sentry plan quota. The reason contains the rate limit or quota that was exceeded.
759    ///  - `invalid`: Data was considered invalid and could not be recovered. The reason indicates
760    ///    the validation that failed.
761    Outcomes,
762    /// The number of individual outcomes including their quantity.
763    ///
764    /// While [`RelayCounters::Outcomes`] tracks the number of times aggregated outcomes
765    /// have been emitted, this counter tracks the total quantity of individual outcomes.
766    OutcomeQuantity,
767    /// Number of project state HTTP requests.
768    ///
769    /// Relay updates projects in batches. Every update cycle, Relay requests
770    /// `limits.max_concurrent_queries` batches of `cache.batch_size` projects from the upstream.
771    /// The duration of these requests is reported via `project_state.request.duration`.
772    ///
773    /// Note that after an update loop has completed, there may be more projects pending updates.
774    /// This is indicated by `project_state.pending`.
775    ProjectStateRequest,
776    /// Number of times a project state is requested from the central Redis cache.
777    ///
778    /// This metric is tagged with:
779    ///  - `hit`: One of:
780    ///     - `revision`: the cached version was validated to be up to date using its revision.
781    ///     - `project_config`: the request was handled by the cache.
782    ///     - `project_config_revision`: the request was handled by the cache and the revision did
783    ///       not change.
784    ///     - `false`: the request will be sent to the sentry endpoint.
785    #[cfg(feature = "processing")]
786    ProjectStateRedis,
787    /// Number of times a project had a fetch scheduled.
788    ProjectCacheSchedule,
789    /// Number of times an upstream request for a project config is completed.
790    ///
791    /// Completion can be because a result was returned or because the config request was
792    /// dropped after there still was no response after a timeout.  This metrics has tags
793    /// for `result` and `attempts` indicating whether it was succesful or a timeout and how
794    /// many attempts were made respectively.
795    ProjectUpstreamCompleted,
796    /// Number of times an upstream request for a project config failed.
797    ///
798    /// Failure can happen, for example, when there's a network error. Refer to
799    /// [`UpstreamRequestError`](crate::services::upstream::UpstreamRequestError) for all cases.
800    ProjectUpstreamFailed,
801    /// Number of Relay server starts.
802    ///
803    /// This can be used to track unwanted restarts due to crashes or termination.
804    ServerStarting,
805    /// Number of messages placed on the Kafka queues.
806    ///
807    /// When Relay operates as Sentry service and an Envelope item is successfully processed, each
808    /// Envelope item results in a dedicated message on one of the ingestion topics on Kafka.
809    ///
810    /// This metric is tagged with:
811    ///  - `event_type`: The kind of message produced to Kafka.
812    ///  - `namespace` (only for metrics): The namespace that the metric belongs to.
813    ///  - `is_segment` (only for event_type span): `true` the span is the root of a segment.
814    ///  - `has_parent` (only for event_type span): `false` if the span is the root of a trace.
815    ///  - `platform` (only for event_type span): The platform from which the span was spent.
816    ///  - `metric_type` (only for event_type metric): The metric type, counter, distribution,
817    ///    gauge or set.
818    ///  - `metric_encoding` (only for event_type metric): The encoding used for distribution and
819    ///    set metrics.
820    ///
821    /// The message types can be:
822    ///
823    ///  - `event`: An error or transaction event. Error events are sent to `ingest-events`,
824    ///    transactions to `ingest-transactions`, and errors with attachments are sent to
825    ///    `ingest-attachments`.
826    ///  - `attachment`: An attachment file associated with an error event, sent to
827    ///    `ingest-attachments`.
828    ///  - `user_report`: A message from the user feedback dialog, sent to `ingest-events`.
829    ///  - `session`: A release health session update, sent to `ingest-sessions`.
830    #[cfg(feature = "processing")]
831    ProcessingMessageProduced,
832    /// Number of spans produced in the new format.
833    #[cfg(feature = "processing")]
834    SpanV2Produced,
835    /// Number of events that hit any of the store-like endpoints: Envelope, Store, Security,
836    /// Minidump, Unreal.
837    ///
838    /// The events are counted before they are rate limited, filtered, or processed in any way.
839    ///
840    /// This metric is tagged with:
841    ///  - `version`: The event protocol version number defaulting to `7`.
842    EventProtocol,
843    /// The number of transaction events processed by the source of the transaction name.
844    ///
845    /// This metric is tagged with:
846    ///  - `platform`: The event's platform, such as `"javascript"`.
847    ///  - `source`: The source of the transaction name on the client. See the [transaction source
848    ///    documentation](https://develop.sentry.dev/sdk/event-payloads/properties/transaction_info/)
849    ///    for all valid values.
850    ///  - `contains_slashes`: Whether the transaction name contains `/`. We use this as a heuristic
851    ///    to represent URL transactions.
852    EventTransaction,
853    /// The number of transaction events processed grouped by transaction name modifications.
854    /// This metric is tagged with:
855    ///  - `source_in`: The source of the transaction name before normalization.
856    ///    See the [transaction source
857    ///    documentation](https://develop.sentry.dev/sdk/event-payloads/properties/transaction_info/)
858    ///    for all valid values.
859    ///  - `change`: The mechanism that changed the transaction name.
860    ///    Either `"none"`, `"pattern"`, `"rule"`, or `"both"`.
861    ///  - `source_out`: The source of the transaction name after normalization.
862    TransactionNameChanges,
863    /// Number of HTTP requests reaching Relay.
864    Requests,
865    /// Number of completed HTTP requests.
866    ///
867    /// This metric is tagged with:
868    ///
869    ///  - `status_code`: The HTTP status code number.
870    ///  - `method`: The HTTP method used in the request in uppercase.
871    ///  - `route`: Unique dashed identifier of the endpoint.
872    ResponsesStatusCodes,
873    /// Number of evicted stale projects from the cache.
874    ///
875    /// Relay scans the in-memory project cache for stale entries in a regular interval configured
876    /// by `cache.eviction_interval`.
877    ///
878    /// The cache duration for project states can be configured with the following options:
879    ///
880    ///  - `cache.project_expiry`: The time after which a project state counts as expired. It is
881    ///    automatically refreshed if a request references the project after it has expired.
882    ///  - `cache.project_grace_period`: The time after expiry at which the project state will still
883    ///    be used to ingest events. Once the grace period expires, the cache is evicted and new
884    ///    requests wait for an update.
885    EvictingStaleProjectCaches,
886    /// Number of refreshes for stale projects in the cache.
887    RefreshStaleProjectCaches,
888    /// Number of times that parsing a metrics bucket item from an envelope failed.
889    MetricBucketsParsingFailed,
890    /// Count extraction of transaction names. Tag with the decision to drop / replace / use original.
891    MetricsTransactionNameExtracted,
892    /// Number of Events with an OpenTelemetry Context
893    ///
894    /// This metric is tagged with:
895    ///  - `platform`: The event's platform, such as `"javascript"`.
896    ///  - `sdk`: The name of the Sentry SDK sending the transaction. This tag is only set for
897    ///    Sentry's SDKs and defaults to "proprietary".
898    OpenTelemetryEvent,
899    /// Number of global config fetches from upstream. Only 2XX responses are
900    /// considered and ignores send errors (e.g. auth or network errors).
901    ///
902    /// This metric is tagged with:
903    ///  - `success`: whether deserializing the global config succeeded.
904    GlobalConfigFetched,
905    /// The number of attachments processed in the same envelope as a user_report_v2 event.
906    FeedbackAttachments,
907    /// All COGS tracked values.
908    ///
909    /// This metric is tagged with:
910    /// - `resource_id`: The COGS resource id.
911    /// - `app_feature`: The COGS app feature.
912    CogsUsage,
913    /// The amount of times metrics of a project have been flushed without the project being
914    /// fetched/available.
915    ProjectStateFlushMetricsNoProject,
916    /// Incremented every time a bucket is dropped.
917    ///
918    /// This should only happen when a project state is invalid during graceful shutdown.
919    ///
920    /// This metric is tagged with:
921    ///  - `aggregator`: The name of the metrics aggregator (usually `"default"`).
922    BucketsDropped,
923    /// Incremented every time a segment exceeds the expected limit.
924    ReplayExceededSegmentLimit,
925    /// Incremented every time the server accepts a new connection.
926    ServerSocketAccept,
927    /// Incremented every time the server aborts a connection because of an idle timeout.
928    ServerConnectionIdleTimeout,
929    /// The total delay of metric buckets in seconds.
930    ///
931    /// The delay is measured from initial creation of the bucket in an internal Relay
932    /// until it is produced to Kafka.
933    ///
934    /// Use [`Self::MetricDelayCount`] to calculate the average delay.
935    ///
936    /// This metric is tagged with:
937    /// - `namespace`: the metric namespace.
938    #[cfg(feature = "processing")]
939    MetricDelaySum,
940    /// The amount of buckets counted for the [`Self::MetricDelaySum`] metric.
941    ///
942    /// This metric is tagged with:
943    /// - `namespace`: the metric namespace.
944    #[cfg(feature = "processing")]
945    MetricDelayCount,
946    /// The amount of times PlayStation processing was attempted.
947    #[cfg(all(sentry, feature = "processing"))]
948    PlaystationProcessing,
949    /// The number of times a sampling decision was made.
950    ///
951    /// This metric is tagged with:
952    /// - `item`: what item the decision is taken for (transaction vs span).
953    SamplingDecision,
954    /// The number of times an upload of an attachment occurs.
955    ///
956    /// This metric is tagged with:
957    /// - `result`: `success` or the failure reason.
958    /// - `type`: `envelope` or `attachment_v2`
959    #[cfg(feature = "processing")]
960    AttachmentUpload,
961    /// Whether a logs envelope has a trace context header or not
962    ///
963    /// This metric is tagged with:
964    /// - `dsc`: yes or no
965    /// - `sdk`: low-cardinality client name
966    EnvelopeWithLogs,
967    /// Amount of profile chunks without a platform item header.
968    ///
969    /// The metric is emitted when processing profile chunks, profile chunks which are fast path
970    /// rate limited are not counted in this metric.
971    ProfileChunksWithoutPlatform,
972}
973
974impl CounterMetric for RelayCounters {
975    fn name(&self) -> &'static str {
976        match self {
977            RelayCounters::AsyncPoolFinishedTasks => "async_pool.finished_tasks",
978            RelayCounters::EventCorrupted => "event.corrupted",
979            RelayCounters::EnvelopeAccepted => "event.accepted",
980            RelayCounters::EnvelopeRejected => "event.rejected",
981            RelayCounters::EnvelopeItems => "event.items",
982            RelayCounters::EnvelopeItemBytes => "event.item_bytes",
983            RelayCounters::BufferTryPop => "buffer.try_pop",
984            RelayCounters::BufferSpooledEnvelopes => "buffer.spooled_envelopes",
985            RelayCounters::BufferUnspooledEnvelopes => "buffer.unspooled_envelopes",
986            RelayCounters::BufferProjectChangedEvent => "buffer.project_changed_event",
987            RelayCounters::BufferProjectPending => "buffer.project_pending",
988            RelayCounters::BufferServiceLoopIteration => "buffer.service_loop_iteration",
989            RelayCounters::Outcomes => "events.outcomes",
990            RelayCounters::OutcomeQuantity => "events.outcome_quantity",
991            RelayCounters::ProjectStateRequest => "project_state.request",
992            #[cfg(feature = "processing")]
993            RelayCounters::ProjectStateRedis => "project_state.redis.requests",
994            RelayCounters::ProjectUpstreamCompleted => "project_upstream.completed",
995            RelayCounters::ProjectUpstreamFailed => "project_upstream.failed",
996            RelayCounters::ProjectCacheSchedule => "project_cache.schedule",
997            RelayCounters::ServerStarting => "server.starting",
998            #[cfg(feature = "processing")]
999            RelayCounters::ProcessingMessageProduced => "processing.event.produced",
1000            #[cfg(feature = "processing")]
1001            RelayCounters::SpanV2Produced => "store.produced.span_v2",
1002            RelayCounters::EventProtocol => "event.protocol",
1003            RelayCounters::EventTransaction => "event.transaction",
1004            RelayCounters::TransactionNameChanges => "event.transaction_name_changes",
1005            RelayCounters::Requests => "requests",
1006            RelayCounters::ResponsesStatusCodes => "responses.status_codes",
1007            RelayCounters::EvictingStaleProjectCaches => "project_cache.eviction",
1008            RelayCounters::RefreshStaleProjectCaches => "project_cache.refresh",
1009            RelayCounters::MetricBucketsParsingFailed => "metrics.buckets.parsing_failed",
1010            RelayCounters::MetricsTransactionNameExtracted => "metrics.transaction_name",
1011            RelayCounters::OpenTelemetryEvent => "event.opentelemetry",
1012            RelayCounters::GlobalConfigFetched => "global_config.fetch",
1013            RelayCounters::FeedbackAttachments => "processing.feedback_attachments",
1014            RelayCounters::CogsUsage => "cogs.usage",
1015            RelayCounters::ProjectStateFlushMetricsNoProject => "project_state.metrics.no_project",
1016            RelayCounters::BucketsDropped => "metrics.buckets.dropped",
1017            RelayCounters::ReplayExceededSegmentLimit => "replay.segment_limit_exceeded",
1018            RelayCounters::ServerSocketAccept => "server.http.accepted",
1019            RelayCounters::ServerConnectionIdleTimeout => "server.http.idle_timeout",
1020            #[cfg(feature = "processing")]
1021            RelayCounters::MetricDelaySum => "metrics.delay.sum",
1022            #[cfg(feature = "processing")]
1023            RelayCounters::MetricDelayCount => "metrics.delay.count",
1024            #[cfg(all(sentry, feature = "processing"))]
1025            RelayCounters::PlaystationProcessing => "processing.playstation",
1026            RelayCounters::SamplingDecision => "sampling.decision",
1027            #[cfg(feature = "processing")]
1028            RelayCounters::AttachmentUpload => "attachment.upload",
1029            RelayCounters::EnvelopeWithLogs => "logs.envelope",
1030            RelayCounters::ProfileChunksWithoutPlatform => "profile_chunk.no_platform",
1031        }
1032    }
1033}