Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create metrics.Factory adapter for OTEL Metrics #5661

Merged
merged 52 commits into from
Jun 30, 2024
Merged
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
f1f9b7a
Instantiated OTEL Metrics
Wise-Wizard Jun 19, 2024
12403b1
Ran make fmt
Wise-Wizard Jun 19, 2024
175efa3
Merge branch 'main' into OTEL_Metrics
Wise-Wizard Jun 20, 2024
443858f
Merge branch 'main' into OTEL_Metrics
Wise-Wizard Jun 20, 2024
0a073b6
Create otelmetrics package
Wise-Wizard Jun 21, 2024
aa92107
Merge branch 'main' into OTEL_Metrics
Wise-Wizard Jun 21, 2024
7efd9b9
Update pkg/metrics/otelmetrics/factory.go
Wise-Wizard Jun 21, 2024
a70d64a
Created benchmark to compare metric implementation
Wise-Wizard Jun 22, 2024
2ab543b
Merge branch 'OTEL_Metrics' of https://github.com/Wise-Wizard/jaeger …
Wise-Wizard Jun 22, 2024
dc2a9ed
Resolved conflicts
Wise-Wizard Jun 22, 2024
f508b8a
Merge branch 'main' into OTEL_Metrics
Wise-Wizard Jun 22, 2024
4a99291
avoid allocations
yurishkuro Jun 22, 2024
099ba05
Implemented changes
Wise-Wizard Jun 22, 2024
21c14b4
Merge branch 'main' into OTEL_Metrics
Wise-Wizard Jun 23, 2024
8b47b12
Used metrics.NullCounter as return type
Wise-Wizard Jun 23, 2024
8032ce2
Created rough implementation of OTEL SDK
Wise-Wizard Jun 23, 2024
6ec5ec4
Fixed initialization errors
Wise-Wizard Jun 24, 2024
33d5855
Merge branch 'main' into OTEL_Metrics
Wise-Wizard Jun 24, 2024
4e7dcbb
Made suggested changes
Wise-Wizard Jun 24, 2024
f29cad5
Created Prometheus Exporter
Wise-Wizard Jun 24, 2024
67e23e2
Implemented OTEL Metrics for other Instruments
Wise-Wizard Jun 25, 2024
b434c20
Merge branch 'main' into OTEL_Metrics
Wise-Wizard Jun 25, 2024
598c39f
Update internal/metrics/otelmetrics/factory.go
Wise-Wizard Jun 25, 2024
29f6382
Update internal/metrics/benchmark_test.go
Wise-Wizard Jun 25, 2024
51bd2f0
Update internal/metrics/benchmark_test.go
Wise-Wizard Jun 25, 2024
22fe680
Update internal/metrics/otelmetrics/factory.go
Wise-Wizard Jun 25, 2024
6f41a52
Refactored Code
Wise-Wizard Jun 25, 2024
a6212bb
Added Unit
Wise-Wizard Jun 25, 2024
8594dc2
Merge branch 'main' into OTEL_Metrics
Wise-Wizard Jun 26, 2024
d6347c4
Added Namespace Configuration
Wise-Wizard Jun 26, 2024
1c667f2
Added Factory Test File
Wise-Wizard Jun 26, 2024
61df6b0
Merge branch 'main' into OTEL_Metrics
Wise-Wizard Jun 26, 2024
f6fce72
Added missing value
Wise-Wizard Jun 26, 2024
a42e1fe
Added missing value
Wise-Wizard Jun 26, 2024
3594d80
Made changes to Test Suites
Wise-Wizard Jun 27, 2024
0a24e87
Made Required changes in Test
Wise-Wizard Jun 27, 2024
362ea74
Removed No-Op Test
Wise-Wizard Jun 27, 2024
7deeb6b
Added Go Leak Test
Wise-Wizard Jun 27, 2024
92ea1bb
Fixed Alias Error
Wise-Wizard Jun 27, 2024
47c2aed
Update internal/metrics/otelmetrics/factory_test.go
Wise-Wizard Jun 27, 2024
36dda89
Implemented missing Tests
Wise-Wizard Jun 27, 2024
d4ee6e0
Created Table Driven Test
Wise-Wizard Jun 27, 2024
5e7c624
Added invalid test for all metrics
Wise-Wizard Jun 28, 2024
965ad84
Added check for Empty Namespace
Wise-Wizard Jun 28, 2024
43de5d1
Disabled OTEL Scope Info
Wise-Wizard Jun 28, 2024
878e5f4
Test Nested Namespace
Wise-Wizard Jun 28, 2024
864acde
Ran make Lint
Wise-Wizard Jun 28, 2024
0054c5c
Ran make fmt
Wise-Wizard Jun 28, 2024
7188cc8
Update internal/metrics/otelmetrics/factory_test.go
Wise-Wizard Jun 30, 2024
7916122
Merge branch 'main' into OTEL_Metrics
Wise-Wizard Jun 30, 2024
e0d7fdb
Added Empty Namespace Test
Wise-Wizard Jun 30, 2024
3265bc0
Refactored Test
Wise-Wizard Jun 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions internal/metrics/benchmark_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Copyright (c) 2024 The Jaeger Authors.
// SPDX-License-Identifier: Apache-2.0

package benchmark_test

import (
"testing"

"github.com/prometheus/client_golang/prometheus"
"github.com/stretchr/testify/require"
promExporter "go.opentelemetry.io/otel/exporters/prometheus"
"go.opentelemetry.io/otel/sdk/metric"

"github.com/jaegertracing/jaeger/internal/metrics/otelmetrics"
prom "github.com/jaegertracing/jaeger/internal/metrics/prometheus"
"github.com/jaegertracing/jaeger/pkg/metrics"
"github.com/jaegertracing/jaeger/pkg/testutils"
)

func TestMain(m *testing.M) {
testutils.VerifyGoLeaks(m)
}

func setupPrometheusFactory() metrics.Factory {
reg := prometheus.NewRegistry()
return prom.New(prom.WithRegisterer(reg))
}

func setupOTELFactory(b *testing.B) metrics.Factory {
registry := prometheus.NewRegistry()
exporter, err := promExporter.New(promExporter.WithRegisterer(registry))
require.NoError(b, err)
meterProvider := metric.NewMeterProvider(
metric.WithReader(exporter),
)
return otelmetrics.NewFactory(meterProvider)
}

func benchmarkCounter(b *testing.B, factory metrics.Factory) {
counter := factory.Counter(metrics.Options{
Name: "test_counter",
Tags: map[string]string{"tag1": "value1"},
})

for i := 0; i < b.N; i++ {
counter.Inc(1)
}
}

func benchmarkGauge(b *testing.B, factory metrics.Factory) {
gauge := factory.Gauge(metrics.Options{
Name: "test_gauge",
Tags: map[string]string{"tag1": "value1"},
})

for i := 0; i < b.N; i++ {
gauge.Update(1)
}
}

func benchmarkTimer(b *testing.B, factory metrics.Factory) {
timer := factory.Timer(metrics.TimerOptions{
Name: "test_timer",
Tags: map[string]string{"tag1": "value1"},
})

for i := 0; i < b.N; i++ {
timer.Record(100)
}
}

func benchmarkHistogram(b *testing.B, factory metrics.Factory) {
histogram := factory.Histogram(metrics.HistogramOptions{
Name: "test_histogram",
Tags: map[string]string{"tag1": "value1"},
})

for i := 0; i < b.N; i++ {
histogram.Record(1.0)
}
}

func BenchmarkPrometheusCounter(b *testing.B) {
benchmarkCounter(b, setupPrometheusFactory())
}

func BenchmarkOTELCounter(b *testing.B) {
benchmarkCounter(b, setupOTELFactory(b))
}

func BenchmarkPrometheusGauge(b *testing.B) {
benchmarkGauge(b, setupPrometheusFactory())
}

func BenchmarkOTELGauge(b *testing.B) {
benchmarkGauge(b, setupOTELFactory(b))
}

func BenchmarkPrometheusTimer(b *testing.B) {
benchmarkTimer(b, setupPrometheusFactory())
}

func BenchmarkOTELTimer(b *testing.B) {
benchmarkTimer(b, setupOTELFactory(b))
}

func BenchmarkPrometheusHistogram(b *testing.B) {
benchmarkHistogram(b, setupPrometheusFactory())
}

func BenchmarkOTELHistogram(b *testing.B) {
benchmarkHistogram(b, setupOTELFactory(b))
}
Wise-Wizard marked this conversation as resolved.
Show resolved Hide resolved
20 changes: 20 additions & 0 deletions internal/metrics/otelmetrics/counter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) 2024 The Jaeger Authors.
// SPDX-License-Identifier: Apache-2.0

package otelmetrics

import (
"context"

"go.opentelemetry.io/otel/metric"
)

type otelCounter struct {
counter metric.Int64Counter
fixedCtx context.Context
option metric.AddOption
}

func (c *otelCounter) Inc(value int64) {
c.counter.Add(c.fixedCtx, value, c.option)
Wise-Wizard marked this conversation as resolved.
Show resolved Hide resolved
}
133 changes: 133 additions & 0 deletions internal/metrics/otelmetrics/factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// Copyright (c) 2024 The Jaeger Authors.
// SPDX-License-Identifier: Apache-2.0

package otelmetrics

import (
"context"
"log"
"strings"

"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric"

"github.com/jaegertracing/jaeger/pkg/metrics"
)

type otelFactory struct {
meter metric.Meter
scope string
separator string
normalizer *strings.Replacer
tags map[string]string
}

func NewFactory(meterProvider metric.MeterProvider) metrics.Factory {
return &otelFactory{
meter: meterProvider.Meter("jaeger-v2"),
separator: ".",
normalizer: strings.NewReplacer(" ", "_", ".", "_", "-", "_"),
tags: make(map[string]string),
}
}

func (f *otelFactory) Counter(opts metrics.Options) metrics.Counter {
name := f.subScope(opts.Name)
counter, err := f.meter.Int64Counter(name)
if err != nil {
log.Printf("Error creating OTEL counter: %v", err)
return metrics.NullCounter
}
return &otelCounter{
counter: counter,
fixedCtx: context.Background(),
option: attributeSetOption(f.mergeTags(opts.Tags)),
}
}

func (f *otelFactory) Gauge(opts metrics.Options) metrics.Gauge {
name := f.subScope(opts.Name)
gauge, err := f.meter.Int64Gauge(name)
if err != nil {
log.Printf("Error creating OTEL gauge: %v", err)
Wise-Wizard marked this conversation as resolved.
Show resolved Hide resolved
return metrics.NullGauge

Check warning on line 53 in internal/metrics/otelmetrics/factory.go

View check run for this annotation

Codecov / codecov/patch

internal/metrics/otelmetrics/factory.go#L52-L53

Added lines #L52 - L53 were not covered by tests
}

return &otelGauge{
gauge: gauge,
fixedCtx: context.Background(),
option: attributeSetOption(f.mergeTags(opts.Tags)),
}
}

func (f *otelFactory) Histogram(opts metrics.HistogramOptions) metrics.Histogram {
name := f.subScope(opts.Name)
histogram, err := f.meter.Float64Histogram(name)
if err != nil {
log.Printf("Error creating OTEL histogram: %v", err)
return metrics.NullHistogram

Check warning on line 68 in internal/metrics/otelmetrics/factory.go

View check run for this annotation

Codecov / codecov/patch

internal/metrics/otelmetrics/factory.go#L67-L68

Added lines #L67 - L68 were not covered by tests
}

return &otelHistogram{
histogram: histogram,
fixedCtx: context.Background(),
option: attributeSetOption(f.mergeTags(opts.Tags)),
}
}

func (f *otelFactory) Timer(opts metrics.TimerOptions) metrics.Timer {
name := f.subScope(opts.Name)
timer, err := f.meter.Float64Histogram(name, metric.WithUnit("s"))
if err != nil {
log.Printf("Error creating OTEL timer: %v", err)
return metrics.NullTimer

Check warning on line 83 in internal/metrics/otelmetrics/factory.go

View check run for this annotation

Codecov / codecov/patch

internal/metrics/otelmetrics/factory.go#L82-L83

Added lines #L82 - L83 were not covered by tests
}
return &otelTimer{
histogram: timer,
fixedCtx: context.Background(),
option: attributeSetOption(f.mergeTags(opts.Tags)),
}
}

func (f *otelFactory) Namespace(opts metrics.NSOptions) metrics.Factory {
return &otelFactory{
meter: f.meter,
scope: f.subScope(opts.Name),
separator: f.separator,
normalizer: f.normalizer,
tags: f.mergeTags(opts.Tags),
}
}

func (f *otelFactory) subScope(name string) string {
if f.scope == "" {
return f.normalize(name)
}
if name == "" {
return f.normalize(f.scope)

Check warning on line 107 in internal/metrics/otelmetrics/factory.go

View check run for this annotation

Codecov / codecov/patch

internal/metrics/otelmetrics/factory.go#L107

Added line #L107 was not covered by tests
Wise-Wizard marked this conversation as resolved.
Show resolved Hide resolved
}
return f.normalize(f.scope + f.separator + name)
}

func (f *otelFactory) normalize(v string) string {
return f.normalizer.Replace(v)
}

func (f *otelFactory) mergeTags(tags map[string]string) map[string]string {
merged := make(map[string]string)
for k, v := range f.tags {
merged[k] = v
}
for k, v := range tags {
merged[k] = v
}
return merged
}

func attributeSetOption(tags map[string]string) metric.MeasurementOption {
attributes := make([]attribute.KeyValue, 0, len(tags))
for k, v := range tags {
attributes = append(attributes, attribute.String(k, v))
}
return metric.WithAttributes(attributes...)
}
Loading
Loading