This guide explains how to send custom metrics to Metoro using OpenTelemetry. Metoro supports the OpenTelemetry Protocol (OTLP) for metric ingestion, allowing you to send metrics from any application or service that can export OpenTelemetry metrics.
Prerequisites
- A Metoro account
- An application configured with OpenTelemetry
High Level Overview
The Metoro exporter running in each cluster is a fully compliant OpenTelemetry collector. This means that you can send metrics to Metoro using any OpenTelemetry compatible metrics library.
Endpoint Configuration
Configure your OpenTelemetry exporter to send metrics to:
http://metoro-exporter.metoro.svc.cluster.local/api/v1/custom/otel/v1/metrics
This endpoint is available within your Kubernetes cluster where the Metoro exporter is installed.
Authentication
No additional authentication is required when sending metrics from within the cluster to the Metoro exporter.
Language-Specific Examples
Python
Here’s an example Python script that publishes deployment metrics to Metoro:
import sys
from kubernetes import client, config
from opentelemetry import metrics
from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import (
PeriodicExportingMetricReader,
)
# Main
if __name__ == "__main__":
metric_reader = PeriodicExportingMetricReader(
OTLPMetricExporter(endpoint="http://metoro-exporter.metoro.svc.cluster.local/api/v1/custom/otel/v1/metrics")
)
provider = MeterProvider(metric_readers=[metric_reader])
# Sets the global default meter provider
metrics.set_meter_provider(provider)
# Creates a meter from the global meter provider
meter = metrics.get_meter(__name__)
config.load_kube_config()
namespace = sys.argv[1]
app = client.AppsV1Api()
deployment_data = app.list_namespaced_deployment(namespace)
desired_replicas = meter.create_gauge("custom_metrics.desired_replicas")
available_replicas = meter.create_gauge("custom_metrics.available_replicas")
for item in deployment_data.items:
desired_replicas.set(item.status.replicas, {"deployment": item.metadata.name})
available_replicas.set(item.status.available_replicas, {"deployment": item.metadata.name})
# Make sure that all the metrics are exported before the application exits
provider.force_flush()
This script:
- Creates two gauge metrics:
custom_metrics.desired_replicas
- The desired number of replicas for a deployment
custom_metrics.available_replicas
- The number of available replicas for a deployment
- Includes a
deployment
attribute with the name of the deployment
- Uses the OpenTelemetry SDK to export metrics to Metoro
package main
import (
"context"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp"
"go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/resource"
semconv "go.opentelemetry.io/otel/semconv/v1.24.0"
)
func initMetrics() (*metric.MeterProvider, error) {
ctx := context.Background()
exporter, err := otlpmetrichttp.New(ctx,
otlpmetrichttp.WithEndpoint("metoro-exporter.metoro.svc.cluster.local"),
otlpmetrichttp.WithURLPath("/api/v1/custom/otel/v1/metrics"),
otlpmetrichttp.WithInsecure(), // Since we're in-cluster
)
if err != nil {
return nil, err
}
resource := resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceName("your-service-name"),
)
meterProvider := metric.NewMeterProvider(
metric.WithReader(metric.NewPeriodicReader(exporter)),
metric.WithResource(resource),
)
return meterProvider, nil
}
Node.js
const { MeterProvider } = require('@opentelemetry/sdk-metrics');
const { OTLPMetricExporter } = require('@opentelemetry/exporter-metrics-otlp-http');
const { Resource } = require('@opentelemetry/resources');
const { SemanticResourceAttributes } = require('@opentelemetry/semantic-conventions');
const resource = new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: 'your-service-name',
});
const metricExporter = new OTLPMetricExporter({
url: 'http://metoro-exporter.metoro.svc.cluster.local/api/v1/custom/otel/v1/metrics',
headers: {},
});
const meterProvider = new MeterProvider({
resource: resource,
});
meterProvider.addMetricReader(new PeriodicExportingMetricReader({
exporter: metricExporter,
exportIntervalMillis: 1000,
}));
Metric Types
OpenTelemetry supports several metric types that you can use:
- Counter - A value that can only increase or be reset to zero
- Gauge - A value that can arbitrarily go up and down
- Histogram - Tracks the distribution of values over time
Attributes and Context
When sending metrics via OpenTelemetry, you can include additional attributes that will be indexed and searchable in Metoro:
- Use resource attributes to define static information about the service
- Use metric attributes to include dynamic information with each metric value
- Link metrics with traces using trace context propagation
Troubleshooting
If you encounter issues with OpenTelemetry metric ingestion:
- Verify your endpoint URL is correct
- Check your network connectivity to the Metoro OTLP endpoint
- Enable debug logging in your OpenTelemetry SDK
- Verify your metrics appear in the Metoro metrics view
- Contact support if issues persist
Additional Resources