223 lines
7.2 KiB
Go
223 lines
7.2 KiB
Go
package telemetry
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"sync"
|
|
|
|
"go.opentelemetry.io/otel"
|
|
"go.opentelemetry.io/otel/attribute"
|
|
"go.opentelemetry.io/otel/metric"
|
|
)
|
|
|
|
// Metrics exposes strongly typed metric instruments used across the adapter.
|
|
type Metrics struct {
|
|
HTTPRequestsTotal metric.Int64Counter
|
|
HTTPRequestDuration metric.Float64Histogram
|
|
HTTPRequestsInFlight metric.Int64UpDownCounter
|
|
HTTPRequestSize metric.Int64Histogram
|
|
HTTPResponseSize metric.Int64Histogram
|
|
|
|
StepExecutionDuration metric.Float64Histogram
|
|
StepExecutionTotal metric.Int64Counter
|
|
StepErrorsTotal metric.Int64Counter
|
|
|
|
PluginExecutionDuration metric.Float64Histogram
|
|
PluginErrorsTotal metric.Int64Counter
|
|
|
|
BecknMessagesTotal metric.Int64Counter
|
|
SignatureValidationsTotal metric.Int64Counter
|
|
SchemaValidationsTotal metric.Int64Counter
|
|
CacheOperationsTotal metric.Int64Counter
|
|
CacheHitsTotal metric.Int64Counter
|
|
CacheMissesTotal metric.Int64Counter
|
|
RoutingDecisionsTotal metric.Int64Counter
|
|
}
|
|
|
|
var (
|
|
metricsInstance *Metrics
|
|
metricsOnce sync.Once
|
|
metricsErr error
|
|
)
|
|
|
|
// Attribute keys shared across instruments.
|
|
var (
|
|
AttrModule = attribute.Key("module")
|
|
AttrSubsystem = attribute.Key("subsystem")
|
|
AttrName = attribute.Key("name")
|
|
AttrStep = attribute.Key("step")
|
|
AttrRole = attribute.Key("role")
|
|
AttrAction = attribute.Key("action")
|
|
AttrHTTPMethod = attribute.Key("http_method")
|
|
AttrHTTPStatus = attribute.Key("http_status_code")
|
|
AttrStatus = attribute.Key("status")
|
|
AttrErrorType = attribute.Key("error_type")
|
|
AttrPluginID = attribute.Key("plugin_id")
|
|
AttrPluginType = attribute.Key("plugin_type")
|
|
AttrOperation = attribute.Key("operation")
|
|
AttrRouteType = attribute.Key("route_type")
|
|
AttrTargetType = attribute.Key("target_type")
|
|
AttrSchemaVersion = attribute.Key("schema_version")
|
|
)
|
|
|
|
// GetMetrics lazily initializes instruments and returns a cached reference.
|
|
func GetMetrics(ctx context.Context) (*Metrics, error) {
|
|
metricsOnce.Do(func() {
|
|
metricsInstance, metricsErr = newMetrics()
|
|
})
|
|
return metricsInstance, metricsErr
|
|
}
|
|
|
|
func newMetrics() (*Metrics, error) {
|
|
meter := otel.GetMeterProvider().Meter(
|
|
"github.com/beckn-one/beckn-onix/telemetry",
|
|
metric.WithInstrumentationVersion("1.0.0"),
|
|
)
|
|
|
|
m := &Metrics{}
|
|
var err error
|
|
|
|
if m.HTTPRequestsTotal, err = meter.Int64Counter(
|
|
"http_server_requests_total",
|
|
metric.WithDescription("Total number of HTTP requests processed"),
|
|
metric.WithUnit("{request}"),
|
|
); err != nil {
|
|
return nil, fmt.Errorf("http_server_requests_total: %w", err)
|
|
}
|
|
|
|
if m.HTTPRequestDuration, err = meter.Float64Histogram(
|
|
"http_server_request_duration_seconds",
|
|
metric.WithDescription("HTTP request duration in seconds"),
|
|
metric.WithUnit("s"),
|
|
metric.WithExplicitBucketBoundaries(0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10),
|
|
); err != nil {
|
|
return nil, fmt.Errorf("http_server_request_duration_seconds: %w", err)
|
|
}
|
|
|
|
if m.HTTPRequestsInFlight, err = meter.Int64UpDownCounter(
|
|
"http_server_requests_in_flight",
|
|
metric.WithDescription("Number of HTTP requests currently being processed"),
|
|
metric.WithUnit("{request}"),
|
|
); err != nil {
|
|
return nil, fmt.Errorf("http_server_requests_in_flight: %w", err)
|
|
}
|
|
|
|
if m.HTTPRequestSize, err = meter.Int64Histogram(
|
|
"http_server_request_size_bytes",
|
|
metric.WithDescription("Size of HTTP request payloads"),
|
|
metric.WithUnit("By"),
|
|
metric.WithExplicitBucketBoundaries(100, 1000, 10000, 100000, 1000000),
|
|
); err != nil {
|
|
return nil, fmt.Errorf("http_server_request_size_bytes: %w", err)
|
|
}
|
|
|
|
if m.HTTPResponseSize, err = meter.Int64Histogram(
|
|
"http_server_response_size_bytes",
|
|
metric.WithDescription("Size of HTTP responses"),
|
|
metric.WithUnit("By"),
|
|
metric.WithExplicitBucketBoundaries(100, 1000, 10000, 100000, 1000000),
|
|
); err != nil {
|
|
return nil, fmt.Errorf("http_server_response_size_bytes: %w", err)
|
|
}
|
|
|
|
if m.StepExecutionDuration, err = meter.Float64Histogram(
|
|
"onix_step_execution_duration_seconds",
|
|
metric.WithDescription("Duration of individual processing steps"),
|
|
metric.WithUnit("s"),
|
|
metric.WithExplicitBucketBoundaries(0.0005, 0.001, 0.005, 0.01, 0.05, 0.1, 0.25, 0.5),
|
|
); err != nil {
|
|
return nil, fmt.Errorf("onix_step_execution_duration_seconds: %w", err)
|
|
}
|
|
|
|
if m.StepExecutionTotal, err = meter.Int64Counter(
|
|
"onix_step_executions_total",
|
|
metric.WithDescription("Total processing step executions"),
|
|
metric.WithUnit("{execution}"),
|
|
); err != nil {
|
|
return nil, fmt.Errorf("onix_step_executions_total: %w", err)
|
|
}
|
|
|
|
if m.StepErrorsTotal, err = meter.Int64Counter(
|
|
"onix_step_errors_total",
|
|
metric.WithDescription("Processing step errors"),
|
|
metric.WithUnit("{error}"),
|
|
); err != nil {
|
|
return nil, fmt.Errorf("onix_step_errors_total: %w", err)
|
|
}
|
|
|
|
if m.PluginExecutionDuration, err = meter.Float64Histogram(
|
|
"onix_plugin_execution_duration_seconds",
|
|
metric.WithDescription("Plugin execution time"),
|
|
metric.WithUnit("s"),
|
|
metric.WithExplicitBucketBoundaries(0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1),
|
|
); err != nil {
|
|
return nil, fmt.Errorf("onix_plugin_execution_duration_seconds: %w", err)
|
|
}
|
|
|
|
if m.PluginErrorsTotal, err = meter.Int64Counter(
|
|
"onix_plugin_errors_total",
|
|
metric.WithDescription("Plugin level errors"),
|
|
metric.WithUnit("{error}"),
|
|
); err != nil {
|
|
return nil, fmt.Errorf("onix_plugin_errors_total: %w", err)
|
|
}
|
|
|
|
if m.BecknMessagesTotal, err = meter.Int64Counter(
|
|
"beckn_messages_total",
|
|
metric.WithDescription("Total Beckn protocol messages processed"),
|
|
metric.WithUnit("{message}"),
|
|
); err != nil {
|
|
return nil, fmt.Errorf("beckn_messages_total: %w", err)
|
|
}
|
|
|
|
if m.SignatureValidationsTotal, err = meter.Int64Counter(
|
|
"beckn_signature_validations_total",
|
|
metric.WithDescription("Signature validation attempts"),
|
|
metric.WithUnit("{validation}"),
|
|
); err != nil {
|
|
return nil, fmt.Errorf("beckn_signature_validations_total: %w", err)
|
|
}
|
|
|
|
if m.SchemaValidationsTotal, err = meter.Int64Counter(
|
|
"beckn_schema_validations_total",
|
|
metric.WithDescription("Schema validation attempts"),
|
|
metric.WithUnit("{validation}"),
|
|
); err != nil {
|
|
return nil, fmt.Errorf("beckn_schema_validations_total: %w", err)
|
|
}
|
|
|
|
if m.CacheOperationsTotal, err = meter.Int64Counter(
|
|
"onix_cache_operations_total",
|
|
metric.WithDescription("Redis cache operations"),
|
|
metric.WithUnit("{operation}"),
|
|
); err != nil {
|
|
return nil, fmt.Errorf("onix_cache_operations_total: %w", err)
|
|
}
|
|
|
|
if m.CacheHitsTotal, err = meter.Int64Counter(
|
|
"onix_cache_hits_total",
|
|
metric.WithDescription("Redis cache hits"),
|
|
metric.WithUnit("{hit}"),
|
|
); err != nil {
|
|
return nil, fmt.Errorf("onix_cache_hits_total: %w", err)
|
|
}
|
|
|
|
if m.CacheMissesTotal, err = meter.Int64Counter(
|
|
"onix_cache_misses_total",
|
|
metric.WithDescription("Redis cache misses"),
|
|
metric.WithUnit("{miss}"),
|
|
); err != nil {
|
|
return nil, fmt.Errorf("onix_cache_misses_total: %w", err)
|
|
}
|
|
|
|
if m.RoutingDecisionsTotal, err = meter.Int64Counter(
|
|
"onix_routing_decisions_total",
|
|
metric.WithDescription("Routing decisions taken by handler"),
|
|
metric.WithUnit("{decision}"),
|
|
); err != nil {
|
|
return nil, fmt.Errorf("onix_routing_decisions_total: %w", err)
|
|
}
|
|
|
|
return m, nil
|
|
}
|