1
0
mirror of https://github.com/open-telemetry/opentelemetry-go.git synced 2025-01-18 03:22:12 +02:00
Joshua MacDonald 3c8e1853f0
Separate InstrumentationLibrary from metric.Descriptor (#2197)
* factor instrumentation library out of the instrument descriptor

* SDK tests pass

* checkpoint work

* otlp and opencensus tests passing

* prometheus

* tests pass, working on lint

* lint applied: MetricReader->Reader

* comments

* Changelog

* Apply suggestions from code review

Co-authored-by: alrex <alrex.boten@gmail.com>

* remove an interdependency

* fix build

* re-indent one

* Apply suggestions from code review

Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com>

* Lint&feedback

* update after rename

* comment fix

* style fix for meter options

* remove libraryReader, let Controller implement the reader API directly

* rename 'impl' field to 'provider'

* remove a type assertion

* move metric/registry into internal; move registry.MeterProvider into metric controller

* add test for controller registry function

* CheckpointSet->Reader everywhere

* lint

* remove two unnecessary accessor methods; Controller implements MeterProvider and InstrumentationLibraryReader directly, no need to get these

* use a sync.Map

* ensure the initOnce is always called; handle multiple errors

* Apply suggestions from code review

Co-authored-by: Anthony Mirabella <a9@aneurysm9.com>

* cleanup locking in metrictest

* Revert "ensure the initOnce is always called; handle multiple errors"

This reverts commit 3356eb5ed0c288ac3edcc2bc2e853aecda7f29b3.

* Revert "use a sync.Map"

This reverts commit ea7bc599bd3a24c4acb4cd9facd13f08cd702237.

* restore the TODO about sync.Map

Co-authored-by: alrex <alrex.boten@gmail.com>
Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com>
Co-authored-by: Anthony Mirabella <a9@aneurysm9.com>
2021-09-27 08:51:47 -07:00
..

OpenCensus Bridge

The OpenCensus Bridge helps facilitate the migration of an application from OpenCensus to OpenTelemetry.

Caveat about OpenCensus

Installing a metric or tracing bridge will cause OpenCensus telemetry to be exported by OpenTelemetry exporters. Since OpenCensus telemetry uses globals, installing a bridge will result in telemetry collection from all libraries that use OpenCensus, including some you may not expect. For example (#1928), if a client library generates traces with OpenCensus, installing the bridge will cause those traces to be exported by OpenTelemetry.

Tracing

The Problem: Mixing OpenCensus and OpenTelemetry libraries

In a perfect world, one would simply migrate their entire go application --including custom instrumentation, libraries, and exporters-- from OpenCensus to OpenTelemetry all at once. In the real world, dependency constraints, third-party ownership of libraries, or other reasons may require mixing OpenCensus and OpenTelemetry libraries in a single application.

However, if you create the following spans in a go application:

ctx, ocSpan := opencensus.StartSpan(context.Background(), "OuterSpan")
defer ocSpan.End()
ctx, otSpan := opentelemetryTracer.Start(ctx, "MiddleSpan")
defer otSpan.End()
ctx, ocSpan := opencensus.StartSpan(ctx, "InnerSpan")
defer ocSpan.End()

OpenCensus reports (to OpenCensus exporters):

[--------OuterSpan------------]
    [----InnerSpan------]

OpenTelemetry reports (to OpenTelemetry exporters):

   [-----MiddleSpan--------]

Instead, I would prefer (to a single set of exporters):

[--------OuterSpan------------]
   [-----MiddleSpan--------]
    [----InnerSpan------]

The bridge solution

The bridge implements the OpenCensus trace API using OpenTelemetry. This would cause, for example, a span recorded with OpenCensus' StartSpan() method to be equivalent to recording a span using OpenTelemetry's tracer.Start() method. Funneling all tracing API calls to OpenTelemetry APIs results in the desired unified span hierarchy.

User Journey

Starting from an application using entirely OpenCensus APIs:

  1. Instantiate OpenTelemetry SDK and Exporters
  2. Override OpenCensus' DefaultTracer with the bridge
  3. Migrate libraries individually from OpenCensus to OpenTelemetry
  4. Remove OpenCensus exporters and configuration

To override OpenCensus' DefaultTracer with the bridge:

import (
	octrace "go.opencensus.io/trace"
	"go.opentelemetry.io/otel/bridge/opencensus"
	"go.opentelemetry.io/otel"
)

tracer := otel.GetTracerProvider().Tracer("bridge")
octrace.DefaultTracer = opencensus.NewTracer(tracer)

Be sure to set the Tracer name to your instrumentation package name instead of "bridge".

Incompatibilities

OpenCensus and OpenTelemetry APIs are not entirely compatible. If the bridge finds any incompatibilities, it will log them. Incompatibilities include:

  • Custom OpenCensus Samplers specified during StartSpan are ignored.
  • Links cannot be added to OpenCensus spans.
  • OpenTelemetry Debug or Deferred trace flags are dropped after an OpenCensus span is created.

Metrics

The problem: mixing libraries without mixing pipelines

The problem for monitoring is simpler than the problem for tracing, since there are no context propagation issues to deal with. However, it still is difficult for users to migrate an entire applications' monitoring at once. It should be possible to send metrics generated by OpenCensus libraries to an OpenTelemetry pipeline so that migrating a metric does not require maintaining separate export pipelines for OpenCensus and OpenTelemetry.

The Exporter "wrapper" solution

The solution we use here is to allow wrapping an OpenTelemetry exporter such that it implements the OpenCensus exporter interfaces. This allows a single exporter to be used for metrics from both OpenCensus and OpenTelemetry.

User Journey

Starting from an application using entirely OpenCensus APIs:

  1. Instantiate OpenTelemetry SDK and Exporters.
  2. Replace OpenCensus exporters with a wrapped OpenTelemetry exporter from step 1.
  3. Migrate libraries individually from OpenCensus to OpenTelemetry
  4. Remove OpenCensus Exporters and configuration.

For example, to swap out the OpenCensus logging exporter for the OpenTelemetry stdout exporter:

import (
	"go.opencensus.io/metric/metricexport"
	"go.opentelemetry.io/otel/bridge/opencensus"
	"go.opentelemetry.io/otel/exporters/stdout"
	"go.opentelemetry.io/otel"
)
// With OpenCensus, you could have previously configured the logging exporter like this:
//       import logexporter "go.opencensus.io/examples/exporter"
//       exporter, _ := logexporter.NewLogExporter(logexporter.Options{})
// Instead, we can create an equivalent using the OpenTelemetry stdout exporter:
openTelemetryExporter, _ := stdout.New(stdout.WithPrettyPrint())
exporter := opencensus.NewMetricExporter(openTelemetryExporter)

// Use the wrapped OpenTelemetry exporter like you normally would with OpenCensus
intervalReader, _ := metricexport.NewIntervalReader(&metricexport.Reader{}, exporter)
intervalReader.Start()