opentracing-go
OpenTracing API for Go. 🛑 This library is DEPRECATED! https://github.com/opentracing/specification/issues/163
Top Related Projects
🛑 This library is DEPRECATED!
Quick Overview
OpenTracing-Go is the Go implementation of the OpenTracing API, which provides a vendor-neutral framework for distributed tracing. It allows developers to instrument their applications for tracing without tying them to any specific tracing system, enabling easier integration and switching between different tracing backends.
Pros
- Vendor-neutral: Works with various tracing systems like Jaeger, Zipkin, and others
- Easy to integrate: Provides a simple API for instrumenting Go applications
- Flexible: Supports both manual and automatic instrumentation
- Lightweight: Minimal overhead when added to applications
Cons
- Learning curve: Requires understanding of distributed tracing concepts
- Limited features: Some advanced tracing features may not be available in all backends
- Maintenance concerns: The project has been in maintenance mode since the introduction of OpenTelemetry
Code Examples
- Creating a simple span:
span := opentracing.StartSpan("operation_name")
defer span.Finish()
- Creating a child span:
parentSpan := opentracing.StartSpan("parent_operation")
childSpan := opentracing.StartSpan(
"child_operation",
opentracing.ChildOf(parentSpan.Context()),
)
defer childSpan.Finish()
defer parentSpan.Finish()
- Adding tags to a span:
span := opentracing.StartSpan("operation_name")
span.SetTag("key", "value")
span.SetTag("error", true)
defer span.Finish()
Getting Started
- Install the package:
go get github.com/opentracing/opentracing-go
- Import the package in your Go code:
import "github.com/opentracing/opentracing-go"
- Initialize a tracer (example using Jaeger):
import (
"github.com/opentracing/opentracing-go"
"github.com/uber/jaeger-client-go"
"github.com/uber/jaeger-client-go/config"
)
func initJaeger(service string) (opentracing.Tracer, io.Closer) {
cfg := &config.Configuration{
ServiceName: service,
Sampler: &config.SamplerConfig{
Type: "const",
Param: 1,
},
Reporter: &config.ReporterConfig{
LogSpans: true,
},
}
tracer, closer, err := cfg.NewTracer(config.Logger(jaeger.StdLogger))
if err != nil {
panic(fmt.Sprintf("ERROR: cannot init Jaeger: %v\n", err))
}
return tracer, closer
}
func main() {
tracer, closer := initJaeger("your-service-name")
defer closer.Close()
opentracing.SetGlobalTracer(tracer)
// Your application code here
}
Competitor Comparisons
🛑 This library is DEPRECATED!
Pros of jaeger-client-go
- Provides a complete implementation of the Jaeger tracing system
- Offers advanced features like adaptive sampling and context propagation
- Includes built-in support for various Jaeger-specific configurations
Cons of jaeger-client-go
- More complex and heavyweight compared to the generic OpenTracing interface
- Tightly coupled with Jaeger, limiting flexibility for switching tracing backends
- May require more configuration and setup for basic use cases
Code Comparison
opentracing-go:
span := opentracing.StartSpan("operation_name")
defer span.Finish()
span.SetTag("key", "value")
jaeger-client-go:
tracer, closer := jaeger.NewTracer("service_name", jaeger.NewConstSampler(true), jaeger.NewNullReporter())
defer closer.Close()
span := tracer.StartSpan("operation_name")
defer span.Finish()
span.SetTag("key", "value")
The jaeger-client-go example requires explicit tracer initialization and configuration, while opentracing-go provides a more straightforward interface for basic tracing operations. However, jaeger-client-go offers more control and Jaeger-specific features at the cost of increased complexity.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
OpenTracing API for Go
This package is a Go platform API for OpenTracing.
Required Reading
In order to understand the Go platform API, one must first be familiar with the OpenTracing project and terminology more specifically.
API overview for those adding instrumentation
Everyday consumers of this opentracing
package really only need to worry
about a couple of key abstractions: the StartSpan
function, the Span
interface, and binding a Tracer
at main()
-time. Here are code snippets
demonstrating some important use cases.
Singleton initialization
The simplest starting point is ./default_tracer.go
. As early as possible, call
import "github.com/opentracing/opentracing-go"
import ".../some_tracing_impl"
func main() {
opentracing.SetGlobalTracer(
// tracing impl specific:
some_tracing_impl.New(...),
)
...
}
Non-Singleton initialization
If you prefer direct control to singletons, manage ownership of the
opentracing.Tracer
implementation explicitly.
Creating a Span given an existing Go context.Context
If you use context.Context
in your application, OpenTracing's Go library will
happily rely on it for Span
propagation. To start a new (blocking child)
Span
, you can use StartSpanFromContext
.
func xyz(ctx context.Context, ...) {
...
span, ctx := opentracing.StartSpanFromContext(ctx, "operation_name")
defer span.Finish()
span.LogFields(
log.String("event", "soft error"),
log.String("type", "cache timeout"),
log.Int("waited.millis", 1500))
...
}
Starting an empty trace by creating a "root span"
It's always possible to create a "root" Span
with no parent or other causal
reference.
func xyz() {
...
sp := opentracing.StartSpan("operation_name")
defer sp.Finish()
...
}
Creating a (child) Span given an existing (parent) Span
func xyz(parentSpan opentracing.Span, ...) {
...
sp := opentracing.StartSpan(
"operation_name",
opentracing.ChildOf(parentSpan.Context()))
defer sp.Finish()
...
}
Serializing to the wire
func makeSomeRequest(ctx context.Context) ... {
if span := opentracing.SpanFromContext(ctx); span != nil {
httpClient := &http.Client{}
httpReq, _ := http.NewRequest("GET", "http://myservice/", nil)
// Transmit the span's TraceContext as HTTP headers on our
// outbound request.
opentracing.GlobalTracer().Inject(
span.Context(),
opentracing.HTTPHeaders,
opentracing.HTTPHeadersCarrier(httpReq.Header))
resp, err := httpClient.Do(httpReq)
...
}
...
}
Deserializing from the wire
http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
var serverSpan opentracing.Span
appSpecificOperationName := ...
wireContext, err := opentracing.GlobalTracer().Extract(
opentracing.HTTPHeaders,
opentracing.HTTPHeadersCarrier(req.Header))
if err != nil {
// Optionally record something about err here
}
// Create the span referring to the RPC client if available.
// If wireContext == nil, a root span will be created.
serverSpan = opentracing.StartSpan(
appSpecificOperationName,
ext.RPCServerOption(wireContext))
defer serverSpan.Finish()
ctx := opentracing.ContextWithSpan(context.Background(), serverSpan)
...
}
Conditionally capture a field using log.Noop
In some situations, you may want to dynamically decide whether or not to log a field. For example, you may want to capture additional data, such as a customer ID, in non-production environments:
func Customer(order *Order) log.Field {
if os.Getenv("ENVIRONMENT") == "dev" {
return log.String("customer", order.Customer.ID)
}
return log.Noop()
}
Goroutine-safety
The entire public API is goroutine-safe and does not require external synchronization.
API pointers for those implementing a tracing system
Tracing system implementors may be able to reuse or copy-paste-modify the basictracer
package, found here. In particular, see basictracer.New(...)
.
API compatibility
For the time being, "mild" backwards-incompatible changes may be made without changing the major version number. As OpenTracing and opentracing-go
mature, backwards compatibility will become more of a priority.
Tracer test suite
A test suite is available in the harness package that can assist Tracer implementors to assert that their Tracer is working correctly.
Licensing
Top Related Projects
🛑 This library is DEPRECATED!
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot