pkg/metrics/stats_reporter.go (50 lines of code) (raw):
package metrics
import (
"context"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/metric/global"
)
const (
instrumentationName = "keyvaultkms"
errorMessageKey = "error_message"
statusTypeKey = "status"
operationTypeKey = "operation"
kmsRequestMetricName = "kms_request"
// ErrorStatusTypeValue sets status tag to "error".
ErrorStatusTypeValue = "error"
// SuccessStatusTypeValue sets status tag to "success".
SuccessStatusTypeValue = "success"
// EncryptOperationTypeValue sets operation tag to "encrypt".
EncryptOperationTypeValue = "encrypt"
// DecryptOperationTypeValue sets operation tag to "decrypt".
DecryptOperationTypeValue = "decrypt"
// GrpcOperationTypeValue sets operation tag to "grpc".
GrpcOperationTypeValue = "grpc"
)
type reporter struct {
histogram metric.Float64Histogram
}
// StatsReporter reports metrics.
type StatsReporter interface {
ReportRequest(ctx context.Context, operationType, status string, duration float64, errors ...string)
}
// NewStatsReporter instantiates otel reporter.
func NewStatsReporter() (StatsReporter, error) {
meter := global.Meter(instrumentationName)
metricCounter, err := meter.Float64Histogram(
kmsRequestMetricName,
metric.WithDescription("Distribution of how long it took for an operation"),
)
if err != nil {
return nil, err
}
return &reporter{
histogram: metricCounter,
}, nil
}
func (r *reporter) ReportRequest(ctx context.Context, operationType, status string, duration float64, errors ...string) {
labels := []attribute.KeyValue{
attribute.String(operationTypeKey, operationType),
attribute.String(statusTypeKey, status),
}
// Add errors
if (status == ErrorStatusTypeValue) && len(errors) > 0 {
for _, err := range errors {
labels = append(labels, attribute.String(errorMessageKey, err))
}
}
r.histogram.Record(ctx, duration, metric.WithAttributes(labels...))
}