// 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 opentracing implements a bridge that forwards OpenTracing API
// calls to the OpenTelemetry SDK.
//
// To use the bridge, first create an OpenTelemetry tracer of
// choice. Then use the NewTracerPair() function to create two tracers
// - one implementing OpenTracing API (BridgeTracer) and one that
// implements the OpenTelemetry API (WrapperTracer) and mostly
// forwards the calls to the OpenTelemetry tracer of choice, but does
// some extra steps to make the interaction between both APIs
// working. If the OpenTelemetry tracer of choice already knows how to
// cooperate with OpenTracing API through the OpenTracing bridge
// (explained in detail below), then it is fine to skip the
// WrapperTracer by calling the NewBridgeTracer() function to get the
// bridge tracer and then passing the chosen OpenTelemetry tracer to
// the SetOpenTelemetryTracer() function of the bridge tracer.
//
// To use an OpenTelemetry span as the parent of an OpenTracing span,
// create a context using the ContextWithBridgeSpan() function of
// the bridge tracer, and then use the StartSpanFromContext function
// of the OpenTracing API.
//
// Bridge tracer also allows the user to install a warning handler
// through the SetWarningHandler() function. The warning handler will
// be called when there is some misbehavior of the OpenTelemetry
// tracer with regard to the cooperation with the OpenTracing API.
//
// For an OpenTelemetry tracer to cooperate with OpenTracing API
// through the BridgeTracer, the OpenTelemetry tracer needs to
// (reasoning is below the list):
//
// 1. Return the same context it received in the Start() function if
// migration.SkipContextSetup() returns true.
//
// 2. Implement the migration.DeferredContextSetupTracerExtension
// interface. The implementation should setup the context it would
// normally do in the Start() function if the
// migration.SkipContextSetup() function returned false. Calling
// ContextWithBridgeSpan() is not necessary.
//
// 3. Have an access to the BridgeTracer instance.
//
// 4. If the migration.SkipContextSetup() function returned false, the
// tracer should use the ContextWithBridgeSpan() function to install the
// created span as an active OpenTracing span.
//
// There are some differences between OpenTracing and OpenTelemetry
// APIs, especially with regard to Go context handling. When a span is
// created with an OpenTracing API (through the StartSpan() function)
// the Go context is not available. BridgeTracer has access to the
// OpenTelemetry tracer of choice, so in the StartSpan() function
// BridgeTracer translates the parameters to the OpenTelemetry version
// and uses the OpenTelemetry tracer's Start() function to actually
// create a span. The OpenTelemetry Start() function takes the Go
// context as a parameter, so BridgeTracer at this point passes a
// temporary context to Start(). All the changes to the temporary
// context will be lost at the end of the StartSpan() function, so the
// OpenTelemetry tracer of choice should not do anything with the
// context. If the returned context is different, BridgeTracer will
// warn about it. The OpenTelemetry tracer of choice can learn about
// this situation by using the migration.SkipContextSetup()
// function. The tracer will receive an opportunity to set up the
// context at a later stage. Usually after StartSpan() is finished,
// users of the OpenTracing API are calling (either directly or
// through the opentracing.StartSpanFromContext() helper function) the
// opentracing.ContextWithSpan() function to insert the created
// OpenTracing span into the context. At that time, the OpenTelemetry
// tracer of choice has a chance of setting up the context through a
// hook invoked inside the opentracing.ContextWithSpan() function. For
// that to happen, the tracer should implement the
// migration.DeferredContextSetupTracerExtension interface. This so
// far explains the need for points 1. and 2.
//
// When the span is created with the OpenTelemetry API (with the
// Start() function) then migration.SkipContextSetup() will return
// false. This means that the tracer can do the usual setup of the
// context, but it also should set up the active OpenTracing span in
// the context. This is because OpenTracing API is not used at all in
// the creation of the span, but the OpenTracing API may be used
// during the time when the created OpenTelemetry span is current. For
// this case to work, we need to also set up active OpenTracing span
// in the context. This can be done with the ContextWithBridgeSpan()
// function. This means that the OpenTelemetry tracer of choice needs
// to have an access to the BridgeTracer instance. This should explain
// the need for points 3. and 4.
//
// Another difference related to the Go context handling is in logging
// - OpenTracing API does not take a context parameter in the
// LogFields() function, so when the call to the function gets
// translated to OpenTelemetry AddEvent() function, an empty context
// is passed.
package opentracing // import "go.opentelemetry.io/otel/bridge/opentracing"
