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

Add the MeterProvider and related packages for review LS-29752 #172

Merged
merged 5 commits into from
Jun 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 17 additions & 6 deletions examples/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,29 @@ func main() {
ctx := context.Background()
meter := metricglobal.Meter("testing")

// This example shows 1 instrument each for (UpDown)?(SumObserver|Counter)
// The two monotonic instruments of these have a fixed rate of +1.
// The two non-monotonic instruments of these have a fixed rate of -1.
// There are 2 example ValueObserver instruments (one a Gaussian, one a Sine wave).
//
// TODO: ValueRecorder examples.
// This example shows 1 instrument each for synchronous and
// asynchronous Counter and UpDownCounter. The two monotonic
// instruments of these have a fixed rate of +1. The two
// non-monotonic instruments of these have a fixed rate of -1.
// There are 2 example Gauge instruments (one a Gaussian, one
// a Sine wave), and one Histogram.

c1, _ := meter.SyncInt64().Counter(prefix + "counter")
c2, _ := meter.SyncInt64().UpDownCounter(prefix + "updowncounter")
hist, _ := meter.SyncFloat64().Histogram(prefix + "histogram")
go func() {
for {
c1.Add(ctx, 1)
c2.Add(ctx, -1)

secs := float64(time.Now().UnixNano()) / float64(time.Second)
mult := math.Sin(secs / (40 * math.Pi))
mult *= mult

for i := 0; i < 10000; i++ {
hist.Record(ctx, mult*(100+rand.NormFloat64()*100))
}

time.Sleep(time.Second)
}
}()
Expand Down Expand Up @@ -114,6 +124,7 @@ func main() {
func(ctx context.Context) {
secs := float64(time.Now().UnixNano()) / float64(time.Second)

sineWave.Observe(ctx, math.Sin(secs/(50*math.Pi)), attribute.String("period", "fastest"))
sineWave.Observe(ctx, math.Sin(secs/(200*math.Pi)), attribute.String("period", "fast"))
sineWave.Observe(ctx, math.Sin(secs/(1000*math.Pi)), attribute.String("period", "regular"))
sineWave.Observe(ctx, math.Sin(secs/(5000*math.Pi)), attribute.String("period", "slow"))
Expand Down
21 changes: 16 additions & 5 deletions launcher/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,15 @@ func WithMetricReportingPeriod(p time.Duration) Option {
}
}

// WithMetricTemporalityPreference controls the temporality preference
// used for Counter and Histogram (only not for UpDownCounter, which
// ignores this preference for specified reasons).
func WithMetricTemporalityPreference(prefName string) Option {
return func(c *Config) {
c.MetricTemporalityPreference = prefName
}
}

// WithMetricEnabled configures whether metrics should be enabled
func WithMetricsEnabled(enabled bool) Option {
return func(c *Config) {
Expand Down Expand Up @@ -199,6 +208,7 @@ type Config struct {
LogLevel string `env:"OTEL_LOG_LEVEL,default=info"`
Propagators []string `env:"OTEL_PROPAGATORS,default=b3"`
MetricReportingPeriod string `env:"OTEL_EXPORTER_OTLP_METRIC_PERIOD,default=30s"`
MetricTemporalityPreference string `env:"OTEL_EXPORTER_OTLP_METRIC_TEMPORALITY_PREFERENCE,default=cumulative"`
ResourceAttributes map[string]string
Resource *resource.Resource
logger Logger
Expand Down Expand Up @@ -361,11 +371,12 @@ func setupMetrics(c Config) (func() error, error) {
return nil, nil
}
return pipelines.NewMetricsPipeline(pipelines.PipelineConfig{
Endpoint: c.MetricExporterEndpoint,
Insecure: c.MetricExporterEndpointInsecure,
Headers: c.Headers,
Resource: c.Resource,
ReportingPeriod: c.MetricReportingPeriod,
Endpoint: c.MetricExporterEndpoint,
Insecure: c.MetricExporterEndpointInsecure,
Headers: c.Headers,
Resource: c.Resource,
ReportingPeriod: c.MetricReportingPeriod,
TemporalityPreference: c.MetricTemporalityPreference,
})
}

Expand Down
6 changes: 6 additions & 0 deletions launcher/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ func TestDefaultConfig(t *testing.T) {
MetricExporterEndpointInsecure: false,
MetricReportingPeriod: "30s",
MetricsEnabled: true,
MetricTemporalityPreference: "cumulative",
LogLevel: "info",
Propagators: []string{"b3"},
Resource: resource.NewWithAttributes(semconv.SchemaURL, attributes...),
Expand Down Expand Up @@ -349,6 +350,7 @@ func TestEnvironmentVariables(t *testing.T) {
MetricExporterEndpoint: "metrics-url",
MetricExporterEndpointInsecure: true,
MetricReportingPeriod: "30s",
MetricTemporalityPreference: "delta",
LogLevel: "debug",
Propagators: []string{"b3", "w3c"},
Resource: resource.NewWithAttributes(semconv.SchemaURL, attributes...),
Expand All @@ -372,6 +374,7 @@ func TestConfigurationOverrides(t *testing.T) {
WithSpanExporterInsecure(false),
WithMetricExporterEndpoint("override-metrics-url"),
WithMetricExporterInsecure(false),
WithMetricTemporalityPreference("stateless"),
WithLogLevel("info"),
WithLogger(logger),
WithErrorHandler(handler),
Expand All @@ -395,6 +398,7 @@ func TestConfigurationOverrides(t *testing.T) {
MetricExporterEndpoint: "override-metrics-url",
MetricExporterEndpointInsecure: false,
MetricReportingPeriod: "30s",
MetricTemporalityPreference: "stateless",
Headers: map[string]string{"lightstep-access-token": "override-access-token"},
LogLevel: "info",
Propagators: []string{"b3"},
Expand Down Expand Up @@ -600,6 +604,7 @@ func setEnvironment() {
os.Setenv("OTEL_LOG_LEVEL", "debug")
os.Setenv("OTEL_PROPAGATORS", "b3,w3c")
os.Setenv("OTEL_RESOURCE_ATTRIBUTES", "service.name=test-service-name-b")
os.Setenv("OTEL_EXPORTER_OTLP_METRIC_TEMPORALITY_PREFERENCE", "delta")
os.Setenv("LS_METRICS_ENABLED", "false")
}

Expand All @@ -616,6 +621,7 @@ func unsetEnvironment() {
"OTEL_PROPAGATORS",
"OTEL_RESOURCE_ATTRIBUTES",
"OTEL_EXPORTER_OTLP_METRIC_PERIOD",
"OTEL_EXPORTER_OTLP_METRIC_TEMPORALITY_PREFERENCE",
"LS_METRICS_ENABLED",
}
for _, envvar := range vars {
Expand Down
59 changes: 59 additions & 0 deletions lightstep/sdk/metric/asyncinst.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright The OpenTelemetry Authors
njvrzm marked this conversation as resolved.
Show resolved Hide resolved
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package metric // import "github.com/lightstep/otel-launcher-go/lightstep/sdk/metric"

import (
"go.opentelemetry.io/otel/metric/instrument"
"go.opentelemetry.io/otel/metric/instrument/asyncfloat64"
"go.opentelemetry.io/otel/metric/instrument/asyncint64"
"github.com/lightstep/otel-launcher-go/lightstep/sdk/metric/internal/asyncstate"
"github.com/lightstep/otel-launcher-go/lightstep/sdk/metric/number"
"github.com/lightstep/otel-launcher-go/lightstep/sdk/metric/sdkinstrument"
)

type (
asyncint64Instruments struct{ *meter }
asyncfloat64Instruments struct{ *meter }
)

func (i asyncint64Instruments) Counter(name string, opts ...instrument.Option) (asyncint64.Counter, error) {
jmacd marked this conversation as resolved.
Show resolved Hide resolved
inst, err := i.asynchronousInstrument(name, opts, number.Int64Kind, sdkinstrument.CounterObserverKind)
return asyncstate.NewObserver[int64, number.Int64Traits](inst), err
}

func (i asyncint64Instruments) UpDownCounter(name string, opts ...instrument.Option) (asyncint64.UpDownCounter, error) {
inst, err := i.asynchronousInstrument(name, opts, number.Int64Kind, sdkinstrument.UpDownCounterObserverKind)
return asyncstate.NewObserver[int64, number.Int64Traits](inst), err
}

func (i asyncint64Instruments) Gauge(name string, opts ...instrument.Option) (asyncint64.Gauge, error) {
inst, err := i.asynchronousInstrument(name, opts, number.Int64Kind, sdkinstrument.GaugeObserverKind)
return asyncstate.NewObserver[int64, number.Int64Traits](inst), err
}

func (f asyncfloat64Instruments) Counter(name string, opts ...instrument.Option) (asyncfloat64.Counter, error) {
inst, err := f.asynchronousInstrument(name, opts, number.Float64Kind, sdkinstrument.CounterObserverKind)
return asyncstate.NewObserver[float64, number.Float64Traits](inst), err
}

func (f asyncfloat64Instruments) UpDownCounter(name string, opts ...instrument.Option) (asyncfloat64.UpDownCounter, error) {
inst, err := f.asynchronousInstrument(name, opts, number.Float64Kind, sdkinstrument.UpDownCounterObserverKind)
return asyncstate.NewObserver[float64, number.Float64Traits](inst), err
}

func (f asyncfloat64Instruments) Gauge(name string, opts ...instrument.Option) (asyncfloat64.Gauge, error) {
inst, err := f.asynchronousInstrument(name, opts, number.Float64Kind, sdkinstrument.GaugeObserverKind)
return asyncstate.NewObserver[float64, number.Float64Traits](inst), err
}
92 changes: 92 additions & 0 deletions lightstep/sdk/metric/asyncinst_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package metric

import (
"context"
"testing"
"time"

"github.com/lightstep/otel-launcher-go/lightstep/sdk/metric/aggregator/aggregation"
"github.com/lightstep/otel-launcher-go/lightstep/sdk/metric/aggregator/gauge"
"github.com/lightstep/otel-launcher-go/lightstep/sdk/metric/aggregator/sum"
"github.com/lightstep/otel-launcher-go/lightstep/sdk/metric/internal/test"
"github.com/lightstep/otel-launcher-go/lightstep/sdk/metric/number"
"github.com/lightstep/otel-launcher-go/lightstep/sdk/metric/sdkinstrument"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric/instrument"
"go.opentelemetry.io/otel/sdk/resource"
)

func TestAsyncInsts(t *testing.T) {
rdr := NewManualReader("test")
res := resource.Empty()
provider := NewMeterProvider(WithReader(rdr), WithResource(res))

ci := must(provider.Meter("test").AsyncInt64().Counter("icount"))
cf := must(provider.Meter("test").AsyncFloat64().Counter("fcount"))
ui := must(provider.Meter("test").AsyncInt64().UpDownCounter("iupcount"))
uf := must(provider.Meter("test").AsyncFloat64().UpDownCounter("fupcount"))
gi := must(provider.Meter("test").AsyncInt64().Gauge("igauge"))
gf := must(provider.Meter("test").AsyncFloat64().Gauge("fgauge"))

attr := attribute.String("a", "B")

_ = provider.Meter("test").RegisterCallback([]instrument.Asynchronous{
ci, cf, ui, uf, gi, gf,
}, func(ctx context.Context) {
ci.Observe(ctx, 2, attr)
cf.Observe(ctx, 3, attr)
ui.Observe(ctx, 4, attr)
uf.Observe(ctx, 5, attr)
gi.Observe(ctx, 6, attr)
gf.Observe(ctx, 7, attr)
})

data := rdr.Produce(nil)
notime := time.Time{}
cumulative := aggregation.CumulativeTemporality

test.RequireEqualResourceMetrics(
t, data, res,
test.Scope(
test.Library("test"),
test.Instrument(
test.Descriptor("icount", sdkinstrument.CounterObserverKind, number.Int64Kind),
test.Point(notime, notime, sum.NewMonotonicInt64(2), cumulative, attr),
),
test.Instrument(
test.Descriptor("fcount", sdkinstrument.CounterObserverKind, number.Float64Kind),
test.Point(notime, notime, sum.NewMonotonicFloat64(3), cumulative, attr),
),
test.Instrument(
test.Descriptor("iupcount", sdkinstrument.UpDownCounterObserverKind, number.Int64Kind),
test.Point(notime, notime, sum.NewNonMonotonicInt64(4), cumulative, attr),
),
test.Instrument(
test.Descriptor("fupcount", sdkinstrument.UpDownCounterObserverKind, number.Float64Kind),
test.Point(notime, notime, sum.NewNonMonotonicFloat64(5), cumulative, attr),
),
test.Instrument(
test.Descriptor("igauge", sdkinstrument.GaugeObserverKind, number.Int64Kind),
test.Point(notime, notime, gauge.NewInt64(6), cumulative, attr),
),
test.Instrument(
test.Descriptor("fgauge", sdkinstrument.GaugeObserverKind, number.Float64Kind),
test.Point(notime, notime, gauge.NewFloat64(7), cumulative, attr),
),
),
)
}
Loading