Class: StatsD::Instrument::CompiledMetric
- Inherits:
-
Object
- Object
- StatsD::Instrument::CompiledMetric
- Defined in:
- lib/statsd/instrument/compiled_metric.rb
Overview
A compiled metric pre-builds the datagram template at definition time to minimize allocations during metric emission. This is particularly beneficial for high-frequency metrics with consistent tag patterns.
Example: class CheckoutMetric < StatsD::Instrument::CompiledMetric::Counter define( name: "checkout.completed", static_tags: { service: "web" }, tags: { shop_id: Integer, user_id: Integer } ) end
# Later, emit with minimal allocations: CheckoutMetric.increment(shop_id: 123, user_id: 456, value: 1)
Direct Known Subclasses
Defined Under Namespace
Classes: Counter, DatagramBlueprintBuilder, DefinitionError, Distribution, Gauge, PrecompiledDatagram
Constant Summary collapse
- DEFAULT_MAX_TAG_COMBINATION_CACHE_SIZE =
Default maximum number of unique tag combinations to cache before clearing the cache to prevent unbounded memory growth
5000
Class Method Summary collapse
-
.allow_measuring_latency ⇒ Boolean
The
valuekwarg will be ignored and instead the execution time of the block in milliseconds will be used. -
.default_value ⇒ Numeric?
Returning nil makes value a required argument.
-
.define(name:, static_tags: {}, tags: {}, no_prefix: false, sample_rate: nil, max_cache_size: DEFAULT_MAX_TAG_COMBINATION_CACHE_SIZE) ⇒ Class
Defines a new compiled metric class with the given configuration.
-
.define_metric_method(tags) ⇒ Object
Defines the metric emission method - must be implemented by subclasses.
-
.method_name ⇒ Symbol
The method name to define (e.g., :increment).
-
.metric_name ⇒ String?
The normalized metric name for this compiled metric class (
nilif not yet defined). - .sample?(sample_rate) ⇒ Boolean
-
.sample_rate ⇒ Float
Will raise when
definehas not yet been called on the class. -
.type ⇒ String
The metric type character (e.g., "c" for counter).
Class Method Details
.allow_measuring_latency ⇒ Boolean
The value kwarg will be ignored and instead the execution time of the block in milliseconds will be used.
The return value of the block will be passed through.
105 106 107 |
# File 'lib/statsd/instrument/compiled_metric.rb', line 105 def allow_measuring_latency false end |
.default_value ⇒ Numeric?
Returning nil makes value a required argument.
98 99 100 |
# File 'lib/statsd/instrument/compiled_metric.rb', line 98 def default_value raise NotImplementedError, "Subclasses must implement #default_value" end |
.define(name:, static_tags: {}, tags: {}, no_prefix: false, sample_rate: nil, max_cache_size: DEFAULT_MAX_TAG_COMBINATION_CACHE_SIZE) ⇒ Class
Defines a new compiled metric class with the given configuration.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/statsd/instrument/compiled_metric.rb', line 41 def define(name:, static_tags: {}, tags: {}, no_prefix: false, sample_rate: nil, max_cache_size: DEFAULT_MAX_TAG_COMBINATION_CACHE_SIZE) if equal?(CompiledMetric) || superclass.equal?(CompiledMetric) raise DefinitionError, "`define` must be called on a subclass, not on #{self.name} directly. " \ "Use `Class.new(#{self.name}) { define(...) }` or " \ "`class MyMetric < #{self.name}; define(...); end` instead." end if defined?(@datagram_blueprint) raise DefinitionError, "`define` has already been called on #{self.name}. " \ "Each CompiledMetric subclass can only be defined once." end client = StatsD.singleton_client # Build the datagram blueprint using the builder # The builder handles prefix, tags compilation, and blueprint construction datagram_blueprint = DatagramBlueprintBuilder.build( name: name, type: type, client_prefix: client.prefix, no_prefix: no_prefix, default_tags: client., static_tags: , dynamic_tags: , sample_rate: sample_rate || client.default_sample_rate, ) # Create a new class for this specific metric # Using classes instead of instances for better YJIT optimization metric_class = tap do @name = DatagramBlueprintBuilder.normalize_name(name).freeze @datagram_blueprint = datagram_blueprint @tag_combination_cache = {} @max_cache_size = max_cache_size @singleton_client = client @sample_rate = sample_rate || client.default_sample_rate define_metric_method() end metric_class end |
.define_metric_method(tags) ⇒ Object
Defines the metric emission method - must be implemented by subclasses
111 112 113 114 115 116 117 |
# File 'lib/statsd/instrument/compiled_metric.rb', line 111 def define_metric_method() if .any? define_dynamic_method() else define_static_method end end |
.method_name ⇒ Symbol
Returns The method name to define (e.g., :increment).
92 93 94 |
# File 'lib/statsd/instrument/compiled_metric.rb', line 92 def method_name raise NotImplementedError, "Subclasses must implement #method_name" end |
.metric_name ⇒ String?
Returns The normalized metric name for this compiled metric class (nil if not yet defined).
124 125 126 |
# File 'lib/statsd/instrument/compiled_metric.rb', line 124 def metric_name @name end |
.sample?(sample_rate) ⇒ Boolean
119 120 121 |
# File 'lib/statsd/instrument/compiled_metric.rb', line 119 def sample?(sample_rate) @singleton_client.sink.sample?(sample_rate) end |
.sample_rate ⇒ Float
Will raise when define has not yet been called on the class.
130 131 132 133 134 |
# File 'lib/statsd/instrument/compiled_metric.rb', line 130 def sample_rate raise DefinitionError, "Every CompiledMetric subclass needs to call `define` before accessing its sample_rate." unless defined?(@sample_rate) @sample_rate end |
.type ⇒ String
Returns The metric type character (e.g., "c" for counter).
87 88 89 |
# File 'lib/statsd/instrument/compiled_metric.rb', line 87 def type raise NotImplementedError, "Subclasses must implement #type" end |