Metrics API
API reference for the metrics subsystem: the service/emitter type and its methods, the
MetricBuilder, the Metric and Measure value types, the target abstraction with its concrete
target names, and the dimension-cap constant. Signatures below are taken from source and reflect each
SDK’s exact names.
For conceptual explanation — how a target is chosen, the Prometheus pull lifecycle, the durable CloudWatch buffer, and EMF timestamp units — see the Metrics guide. This page is the signature reference.
Obtaining the service
Section titled “Obtaining the service”The accessor name and the returned type differ per language.
// getMetrics() returns a MetricEmitter instance.MetricEmitter metrics = gg.getMetrics();# get_metrics() returns the MetricEmitter CLASS itself — every method is a# @staticmethod backed by process-global state. There is no per-instance emitter.metrics = gg.get_metrics()// metrics() returns an Arc<dyn MetricService>.let metrics = gg.metrics();// metrics() returns a MetricService.const metrics = gg.metrics();The type names map across SDKs as follows: Java MetricEmitter (concrete class), Python
MetricEmitter (returned as the class, static methods), Rust MetricService trait behind
Arc<dyn MetricService>, TypeScript MetricService interface (the concrete impl is also named
MetricEmitter).
MetricService / MetricEmitter
Section titled “MetricService / MetricEmitter”The emitting surface. defineMetric registers a metric definition by name; emitMetric records
measure values through the target’s buffer; emitMetricNow bypasses batching and delivers
immediately; isMetricDefined reports whether a name is registered; flush/shutdown drain and release
the target.
The measure-value container type is language-specific: Map<String, Float> (Java — note Float, not
double), a dict of str -> float (Python), HashMap<String, f64> (Rust), and
Record<string, number> (TypeScript, aliased as MeasureValues).
void defineMetric(Metric metric);boolean isMetricDefined(String name);void emitMetric(String name, Map<String, Float> measureValues); // bufferedvoid emitMetricNow(String name, Map<String, Float> measureValues); // immediatevoid flushMetrics(); // force-drain the buffervoid close(); // release the target on shutdown (call flushMetrics() first to drain)MetricConfiguration getMetricConfig();String getThingName();String getComponentName();# All methods are @staticmethod on the MetricEmitter class.init(config_manager) # wired by GGCommons during startupdefine_metric(metric)is_metric_defined(name) -> boolemit_metric(name, measure_values) # buffered; measure_values: dict[str, float]emit_metric_now(name, measure_values) # immediateshutdown() # closes the active targetget_metric_config()get_thing_name()get_component_name()# NOTE: there is NO public flush method on the Python emitter — targets own batching/close.// trait MetricService (implemented by MetricEmitter)fn define_metric(&self, metric: Metric);fn is_metric_defined(&self, name: &str) -> bool;async fn emit_metric(&self, name: &str, values: HashMap<String, f64>) -> Result<()>; // bufferedasync fn emit_metric_now(&self, name: &str, values: HashMap<String, f64>) -> Result<()>; // immediateasync fn flush_metrics(&self) -> Result<()>;async fn shutdown(&self);// interface MetricService (type MeasureValues = Record<string, number>)defineMetric(metric: Metric): void;isMetricDefined(name: string): boolean;emitMetric(name: string, values: MeasureValues): Promise<void>; // bufferedemitMetricNow(name: string, values: MeasureValues): Promise<void>; // immediateflushMetrics(): Promise<void>;shutdown(): Promise<void>;MetricBuilder
Section titled “MetricBuilder”Defines a metric: a name, one or more measures (each with a unit and a storage resolution), and
optional dimensions. withConfig/with_config populates identity fields from the active config.
Storage resolution is 1 (high resolution, 1-second) or 60 (standard, 1-minute).
static MetricBuilder create(String name);MetricBuilder withNamespace(String namespace);MetricBuilder withThingName(String thingName); // -> coreName dimensionMetricBuilder withComponentName(String componentName); // -> component dimensionMetricBuilder withConfig(ConfigManager config); // fills thing + component + namespaceMetricBuilder addMeasure(String name, String unit, int storageResolution);MetricBuilder addMeasure(Measure measure);MetricBuilder addDimension(String key, String value); // throws if > 10 dimensionsMetric build(); // throws IllegalStateException if namespace unset / no measuresMetric build(MetricEmitter emitter); // fills namespace/thing/component from the emitterMetricBuilder(name) # or: MetricBuilder.create(name) (static)with_namespace(namespace) # raises ValueError if emptywith_thing_name(thing_name)with_component_name(component_name)with_config(config_service) # fills thing + component ONLY (not namespace)add_measure(name, unit, storage_resolution=60) # ValueError if storage_resolution not in [1, 60]add_dimension(key, value) # ValueError if key OR value emptybuild() -> Metric # ValueError if assembled dims > Metric.MAX_DIMENSIONS# build() has NO emitter overload; if thing/component/namespace are unset it substitutes the# placeholders "test-thing" / "test-component" / "GGCommons/Metrics".// MetricBuilder — build() is infallible (no Result)pub fn create(name: impl Into<String>) -> MetricBuilder;pub fn with_namespace(self, namespace: impl Into<String>) -> MetricBuilder;pub fn with_thing_name(self, thing_name: impl Into<String>) -> MetricBuilder;pub fn with_component_name(self, component_name: impl Into<String>) -> MetricBuilder;pub fn with_config(self, config: &Config) -> MetricBuilder; // fills thing + component + namespacepub fn add_measure(self, name: impl Into<String>, unit: impl Into<String>, storage_resolution: u32) -> MetricBuilder;pub fn add_dimension(self, key: impl Into<String>, value: impl Into<String>) -> MetricBuilder;pub fn build(self) -> Metric; // > 10 dims: TRIMS excess custom dims + tracing::warn! (never errors)static create(name: string): MetricBuilder;withNamespace(namespace: string): MetricBuilder;withThingName(thingName: string): MetricBuilder;withComponentName(componentName: string): MetricBuilder;withConfig(config: ConfigManager): MetricBuilder; // fills thing + component + namespaceaddMeasure(name: string, unit: string, storageResolution: number): MetricBuilder;addDimension(key: string, value: string): MetricBuilder;build(): Metric; // throws Error if dimensions > Metric.MAX_DIMENSIONSBuilder behavior divergences
Section titled “Builder behavior divergences”These differences are load-bearing — they change what valid code looks like per language:
withConfigand namespace. Java, Rust, and TypeScript fill thing + component + namespace. Pythonwith_configfills thing + component only — setwith_namespace(...)yourself orbuild()substitutesGGCommons/Metrics.- Storage resolution. Java, Rust, and TypeScript silently coerce (
< 60becomes1, otherwise60). Python’sadd_measurerejects anything not exactly1or60with aValueError. (TheMeasurevalue object still coerces if constructed directly — see below.) build()overloads. Java has bothbuild()(requires namespace, else throws) andbuild(MetricEmitter). Python, Rust, and TypeScript have a singlebuild().- Dimension-cap behavior. Java, Python, and TypeScript throw when more than 10 dimensions are
present; Rust trims the excess custom dimensions and logs a
tracing::warn!(itsbuild()is infallible). - Empty dimension value. Python raises
ValueErrorfor an empty value; Java, Rust, and TypeScript accept it.
Metric and Measure
Section titled “Metric and Measure”A Measure is a named value type within a metric (its name, unit, and storageResolution). The
Measure value object itself coerces storage resolution to 1 or 60 (< 60 becomes 1) in every
language.
// record Measure(String name, String unit, int storageResolution)Measure(String name, String unit, int storageResolution); // coerces: storageResolution < 60 ? 1 : 60Measure(String name, String unit); // convenience — defaults to 60String name();String unit();int storageResolution();# @dataclass MeasureMeasure(name, unit, storage_resolution=60) # __post_init__ coerces: 1 if < 60 else 60get_name() # also exposed as public attrs: name / unit / storage_resolutionget_unit()get_storage_resolution()pub fn new(name: impl Into<String>, unit: impl Into<String>, storage_resolution: u32) -> Measure; // coerces: if < 60 { 1 } else { 60 }pub fn get_name(&self) -> &str;pub fn get_unit(&self) -> &str;pub fn get_storage_resolution(&self) -> u32;// class Measure — readonly fields name / unit / storageResolutionnew Measure(name: string, unit: string, storageResolution: number); // coerces: storageResolution < 60 ? 1 : 60A Metric is what MetricBuilder.build() returns and what defineMetric registers. You normally
build it rather than construct it directly. Its read accessors:
String getName();String getNamespace();Map<String, Measure> getMeasures();Measure getMeasure(String name);Map<String, String> getDimensions();void addMeasure(...); // adds (or replaces) a measurevoid addDimension(String key, String value); // enforces the 10-dimension capMAX_DIMENSIONS = 10 # public class attribute on Metricget_name()get_namespace()get_measures()get_measure(name)get_dimensions()add_dimension(key, value) # raises ValueError when the 10-dimension cap is exceededpub fn get_name(&self) -> &str;pub fn get_namespace(&self) -> Option<&str>; // namespace is optionalpub fn get_measures(&self) -> &BTreeMap<String, Measure>;pub fn get_measure(&self, name: &str) -> Option<&Measure>;pub fn get_dimensions(&self) -> &BTreeMap<String, String>;pub fn add_measure(&mut self, measure: Measure);pub fn add_dimension(&mut self, name: impl Into<String>, value: impl Into<String>);static readonly MAX_DIMENSIONS = 10; // public static on MetricgetName(): string;getNamespace(): string | undefined; // namespace is optionalgetMeasures(): Map<string, Measure>;getMeasure(name: string): Measure | undefined;getDimensions(): Map<string, string>;Auto-injected dimensions
Section titled “Auto-injected dimensions”Three dimensions are injected automatically at build() time (they count toward the 10-dimension
cap):
| Dimension | Value | Source |
|---|---|---|
category |
the metric’s name | set by the Metric constructor |
coreName |
the IoT Thing name | from withThingName / config |
component |
the component name | from withComponentName / config |
Constants
Section titled “Constants”| Constant | Value | Meaning |
|---|---|---|
MAX_DIMENSIONS |
10 |
CloudWatch’s per-metric dimension cap (incl. the 3 injected). |
| Prometheus port | 9090 |
Default listener port for the prometheus target. |
| Prometheus path | /metrics |
Default scrape path for the prometheus target. |
MAX_DIMENSIONS is exposed as a named public constant only in Python (Metric.MAX_DIMENSIONS)
and TypeScript (Metric.MAX_DIMENSIONS). In Java the cap is a hard-coded literal 10 in
Metric.addDimension and MetricBuilder.addDimension; in Rust it is a module-private
const MAX_DIMENSIONS: usize = 10 (not part of the public API). The value is 10 in all four.
Targets
Section titled “Targets”A target is the destination metrics are written to. Each SDK has a target abstraction that the
concrete targets implement; the active target is selected by config (metricEmission.target) and the
three-tier precedence described in the Metrics guide.
The abstraction:
// abstract class MetricTargetabstract void emitMetric(Metric metric, Map<String, Float> measureValues);abstract void emitMetricNow(Metric metric, Map<String, Float> measureValues);abstract boolean onConfigurationChanged();void flush(); // default no-opvoid close(); // default no-op# class MetricTarget(ConfigurationChangeListener, ABC)emit_metric(metric, measure_values: dict[str, float])emit_metric_now(metric, measure_values: dict[str, float])on_configuration_change(configuration) -> boolclose() -> None// trait MetricTarget: Send + Syncasync fn emit(&self, metric: &Metric, values: &HashMap<String, f64>) -> Result<()>;async fn emit_now(&self, metric: &Metric, values: &HashMap<String, f64>) -> Result<()>;async fn flush(&self) -> Result<()>; // default no-opasync fn shutdown(&self); // default no-op// interface MetricTargetemit(metric: Metric, values: MeasureValues): Promise<void>;emitNow(metric: Metric, values: MeasureValues): Promise<void>;flush(): Promise<void>; // default no-opshutdown(): Promise<void>; // default no-opConcrete targets
Section titled “Concrete targets”The selectable metricEmission.target values, and the source file that implements each:
target value |
Java | Python | Rust (feature) | TypeScript |
|---|---|---|---|---|
log |
Log.java |
metric_log.py |
target/log.rs |
target/log.ts |
messaging |
Messaging.java |
messaging.py |
target/messaging.rs |
target/messaging.ts |
cloudwatch |
CloudWatch.java |
cloudwatch.py |
target/cloudwatch.rs (cloudwatch) |
target/cloudwatch.ts |
cloudwatchcomponent |
CloudWatchComponent.java |
cloudwatch_component.py |
target/cloudwatch_component.rs |
target/cloudwatch_component.ts |
prometheus |
Prometheus.java |
prometheus.py |
target/prometheus.rs (metrics-prometheus) |
target/prometheus.ts |
Define and emit
Section titled “Define and emit”A complete define-then-emit cycle in all four languages.
MetricEmitter metrics = gg.getMetrics();
metrics.defineMetric( MetricBuilder.create("performance") .withConfig(config) // fills thing / component / namespace .addMeasure("replyLatency", "Milliseconds", 1) .build());
Map<String, Float> values = new HashMap<>();values.put("replyLatency", 12.5f); // Map<String, Float>metrics.emitMetric("performance", values); // bufferedmetrics = gg.get_metrics() # the MetricEmitter class (static methods)
metric = (MetricBuilder.create("performance") .with_config(config) .with_namespace("MyApp/Metrics") # set explicitly: with_config skips namespace .add_measure("reply_latency", "Milliseconds", 1) .build())metrics.define_metric(metric)
metrics.emit_metric_now("performance", {"reply_latency": 12.5})let metrics = gg.metrics(); // Arc<dyn MetricService>
metrics.define_metric( MetricBuilder::create("performance") .with_config(&config) // fills thing / component / namespace .add_measure("replyLatency", "Milliseconds", 1) .build(),);
let mut values = HashMap::new();values.insert("replyLatency".to_string(), 12.5_f64); // HashMap<String, f64>metrics.emit_metric("performance", values).await?;const metrics = gg.metrics(); // MetricService
const metric = MetricBuilder.create("performance") .withConfig(config) // fills thing / component / namespace .addMeasure("replyLatency", "Milliseconds", 1) .build();metrics.defineMetric(metric);
await metrics.emitMetric("performance", { replyLatency: 12.5 }); // Record<string, number>