mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 18:13:42 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			172 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			172 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
[](https://gitter.im/opentracing/public) [](https://travis-ci.org/opentracing/opentracing-go) [](http://godoc.org/github.com/opentracing/opentracing-go)
 | 
						|
[](https://sourcegraph.com/github.com/opentracing/opentracing-go?badge)
 | 
						|
 | 
						|
# 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](https://opentracing.io) and
 | 
						|
[terminology](https://opentracing.io/specification/) 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
 | 
						|
 | 
						|
```go
 | 
						|
    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`.
 | 
						|
 | 
						|
```go
 | 
						|
    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.
 | 
						|
 | 
						|
```go
 | 
						|
    func xyz() {
 | 
						|
        ...
 | 
						|
        sp := opentracing.StartSpan("operation_name")
 | 
						|
        defer sp.Finish()
 | 
						|
        ...
 | 
						|
    }
 | 
						|
```
 | 
						|
 | 
						|
#### Creating a (child) Span given an existing (parent) Span
 | 
						|
 | 
						|
```go
 | 
						|
    func xyz(parentSpan opentracing.Span, ...) {
 | 
						|
        ...
 | 
						|
        sp := opentracing.StartSpan(
 | 
						|
            "operation_name",
 | 
						|
            opentracing.ChildOf(parentSpan.Context()))
 | 
						|
        defer sp.Finish()
 | 
						|
        ...
 | 
						|
    }
 | 
						|
```
 | 
						|
 | 
						|
#### Serializing to the wire
 | 
						|
 | 
						|
```go
 | 
						|
    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
 | 
						|
 | 
						|
```go
 | 
						|
    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:
 | 
						|
 | 
						|
```go
 | 
						|
    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](https://github.com/opentracing/basictracer-go). 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](https://godoc.org/github.com/opentracing/opentracing-go/harness) package that can assist Tracer implementors to assert that their Tracer is working correctly.
 | 
						|
 | 
						|
## Licensing
 | 
						|
 | 
						|
[Apache 2.0 License](./LICENSE).
 |