Class: LambdaLoadout::Metrics
- Inherits:
-
Object
- Object
- LambdaLoadout::Metrics
- Defined in:
- lib/lambda_loadout/metrics.rb
Overview
CloudWatch Metrics using Embedded Metric Format (EMF)
Creates custom metrics asynchronously by outputting metrics to stdout following Amazon CloudWatch Embedded Metric Format (EMF).
Constant Summary collapse
- UNITS =
CloudWatch metric units
%w[ Seconds Microseconds Milliseconds Bytes Kilobytes Megabytes Gigabytes Terabytes Bits Kilobits Megabits Gigabits Terabits Percent Count Bytes/Second Kilobytes/Second Megabytes/Second Gigabytes/Second Terabytes/Second Bits/Second Kilobits/Second Megabits/Second Gigabits/Second Terabits/Second Count/Second None ].freeze
- RESOLUTIONS =
Metric resolutions in seconds
[1, 60].freeze
- MAX_DIMENSIONS =
29- MAX_METRICS =
100
Instance Attribute Summary collapse
-
#namespace ⇒ Object
readonly
Returns the value of attribute namespace.
-
#output ⇒ Object
readonly
Returns the value of attribute output.
-
#service ⇒ Object
readonly
Returns the value of attribute service.
Instance Method Summary collapse
-
#add_cold_start_metric(context) ⇒ void
Add cold start metric.
-
#add_dimension(name:, value:) ⇒ void
Add a dimension to all metrics.
-
#add_metadata(key:, value:) ⇒ void
Add metadata (searchable in CloudWatch Logs but not as a metric dimension).
-
#add_metric(name:, unit:, value:, resolution: 60) ⇒ void
Add a metric.
-
#clear ⇒ void
Clear all metrics, dimensions, and metadata.
-
#flush(raise_on_empty: false) ⇒ void
Serialize and flush all metrics.
-
#initialize(namespace: nil, service: nil, output: $stdout) ⇒ Metrics
constructor
Initialize metrics.
-
#set_default_dimensions(**dimensions) ⇒ void
Set default dimensions that persist across flushes.
-
#set_timestamp(timestamp) ⇒ void
Set custom timestamp for metrics.
Constructor Details
#initialize(namespace: nil, service: nil, output: $stdout) ⇒ Metrics
Initialize metrics
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/lambda_loadout/metrics.rb', line 54 def initialize(namespace: nil, service: nil, output: $stdout) @namespace = namespace || ENV.fetch('POWERTOOLS_METRICS_NAMESPACE', nil) @service = service || ENV.fetch('POWERTOOLS_SERVICE_NAME', nil) @output = output raise ArgumentError, 'Namespace is required' if @namespace.nil? || @namespace.empty? @metrics = {} @dimensions = {} @metadata = {} @default_dimensions = {} @timestamp = nil @cold_start_captured = false # Add service as default dimension if provided add_dimension(name: 'service', value: @service) if @service end |
Instance Attribute Details
#namespace ⇒ Object (readonly)
Returns the value of attribute namespace.
47 48 49 |
# File 'lib/lambda_loadout/metrics.rb', line 47 def namespace @namespace end |
#output ⇒ Object (readonly)
Returns the value of attribute output.
47 48 49 |
# File 'lib/lambda_loadout/metrics.rb', line 47 def output @output end |
#service ⇒ Object (readonly)
Returns the value of attribute service.
47 48 49 |
# File 'lib/lambda_loadout/metrics.rb', line 47 def service @service end |
Instance Method Details
#add_cold_start_metric(context) ⇒ void
This method returns an undefined value.
Add cold start metric
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/lambda_loadout/metrics.rb', line 152 def add_cold_start_metric(context) return if @cold_start_captured return unless LambdaLoadout.cold_start? @cold_start_captured = true # Create a separate EMF blob for cold start metric cold_start_metrics = self.class.new(namespace: @namespace, output: @output) cold_start_metrics.add_metric(name: 'ColdStart', unit: 'Count', value: 1) cold_start_metrics.add_dimension(name: 'function_name', value: context.function_name) cold_start_metrics.add_dimension(name: 'service', value: @service) if @service cold_start_metrics.flush rescue StandardError => e warn "[LambdaLoadout::Metrics] Failed to add cold start metric: #{e.}" end |
#add_dimension(name:, value:) ⇒ void
This method returns an undefined value.
Add a dimension to all metrics
100 101 102 103 104 |
# File 'lib/lambda_loadout/metrics.rb', line 100 def add_dimension(name:, value:) raise ArgumentError, "Maximum number of dimensions (#{MAX_DIMENSIONS}) exceeded" if @dimensions.size >= MAX_DIMENSIONS @dimensions[name.to_s] = value.to_s end |
#add_metadata(key:, value:) ⇒ void
This method returns an undefined value.
Add metadata (searchable in CloudWatch Logs but not as a metric dimension)
111 112 113 |
# File 'lib/lambda_loadout/metrics.rb', line 111 def (key:, value:) @metadata[key.to_s] = value end |
#add_metric(name:, unit:, value:, resolution: 60) ⇒ void
This method returns an undefined value.
Add a metric
80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/lambda_loadout/metrics.rb', line 80 def add_metric(name:, unit:, value:, resolution: 60) validate_metric_name!(name) validate_metric_unit!(unit) validate_metric_value!(value) validate_metric_resolution!(resolution) # Auto-flush if we've hit the max metrics limit flush_metrics if @metrics.size >= MAX_METRICS metric_key = name.to_s @metrics[metric_key] ||= { 'Unit' => unit.to_s, 'StorageResolution' => resolution, 'Values' => [] } @metrics[metric_key]['Values'] << value.to_f end |
#clear ⇒ void
This method returns an undefined value.
Clear all metrics, dimensions, and metadata
189 190 191 192 193 194 195 |
# File 'lib/lambda_loadout/metrics.rb', line 189 def clear @metrics.clear @dimensions.clear @metadata.clear @dimensions.merge!(@default_dimensions) @timestamp = nil end |
#flush(raise_on_empty: false) ⇒ void
This method returns an undefined value.
Serialize and flush all metrics
Outputs metrics in CloudWatch Embedded Metric Format (EMF) to stdout. Metrics are automatically ingested by CloudWatch when running in Lambda.
175 176 177 178 179 180 181 182 183 184 |
# File 'lib/lambda_loadout/metrics.rb', line 175 def flush(raise_on_empty: false) if @metrics.empty? warn '[LambdaLoadout::Metrics] No metrics to flush' unless raise_on_empty raise 'No metrics to flush' if raise_on_empty return end flush_metrics end |
#set_default_dimensions(**dimensions) ⇒ void
This method returns an undefined value.
Set default dimensions that persist across flushes
119 120 121 122 |
# File 'lib/lambda_loadout/metrics.rb', line 119 def set_default_dimensions(**dimensions) @default_dimensions.merge!(dimensions.transform_keys(&:to_s)) @dimensions.merge!(@default_dimensions) end |
#set_timestamp(timestamp) ⇒ void
This method returns an undefined value.
Set custom timestamp for metrics
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/lambda_loadout/metrics.rb', line 128 def () @timestamp = case when Time (.to_f * 1000).to_i when Integer else raise ArgumentError, 'Timestamp must be Time object or Integer (epoch ms)' end # Validate timestamp is within CloudWatch limits (14 days past, 2 hours future) now = (Time.now.to_f * 1000).to_i min_time = now - (14 * 24 * 60 * 60 * 1000) max_time = now + (2 * 60 * 60 * 1000) return unless @timestamp < min_time || @timestamp > max_time warn '[LambdaLoadout::Metrics] Timestamp outside CloudWatch limits (14 days past, 2 hours future)' end |