gitlab.com/gitlab-org/labkit@v1.21.0/tracing/doc.go (about) 1 /* 2 Package tracing is the primary entrypoint into LabKit's distributed tracing functionality. 3 4 (This documentation assumes some minimal knowledge of Distributed Tracing, and uses 5 tracing terminology without providing definitions. Please review 6 https://opentracing.io/docs/overview/what-is-tracing/ for an broad overview of distributed 7 tracing if you are not familiar with the technology) 8 9 Internally the `tracing` package relies on Opentracing, but avoids leaking this abstraction. 10 In theory, LabKit could replace Opentracing with another distributed tracing interface, such 11 as Zipkin or OpenCensus, without needing to make changes to the application (other than updating 12 the LabKit dependency, of course). 13 14 This design decision is deliberate: the package should not leak the underlying tracing implementation. 15 16 The package provides three primary exports: 17 18 * `tracing.Initialize()` for initializing the global tracer using the `GITLAB_TRACING` environment variable. 19 * An HTTP Handler middleware, `tracing.Handler()`, for instrumenting incoming HTTP requests. 20 * An HTTP RoundTripper, `tracing.NewRoundTripper()` for instrumenting outbound HTTP requests to other services. 21 22 The provided example in `example_test.go` demonstrates usage of both the HTTP Middleware and the HTTP RoundTripper. 23 24 *Initializing the global tracer* 25 26 Opentracing makes use of a global tracer. Opentracing ships with a default NoOp tracer which does 27 nothing at all. This is always configured, meaning that, without initialization, Opentracing does nothing and 28 has a very low overhead. 29 30 LabKit's tracing is configured through an environment variable, `GITLAB_TRACING`. This environment variable contains 31 a "connection string"-like configuration, such as: 32 33 * `opentracing://jaeger?udp_endpoint=localhost:6831` 34 * `opentracing://datadog` 35 * `opentracing://lightstep` 36 * `opentracing://stackdriver?sampler_probability=0.001&project_id=gitlab-pre` 37 38 The parameters for these connection-strings are implementation specific. 39 40 This configuration is identical to the one used to configure GitLab's ruby tracing libraries in the `Gitlab::Tracing` 41 package. Having a consistent configuration makes it easy to configure multiple processes at the same time. For example, 42 in GitLab Development Kit, tracing can be configured with a single environment variable, `GITLAB_TRACING=... gdk run`, 43 since `GITLAB_TRACING` will configure Workhorse (written in Go), Gitaly (written in Go) and GitLab's rails components, 44 using the same configuration. 45 46 *Compiling applications with Tracing support* 47 48 Go's Opentracing interface does not allow tracing implementations to be loaded dynamically; implementations need to be 49 compiled into the application. With LabKit, this is done conditionally, using build tags. Two build tags need to be 50 specified: 51 52 * `tracer_static` - this compiles in the static plugin registry support 53 * `tracer_static_[DRIVER_NAME]` - this compile in support for the given driver. 54 55 For example, to compile support for Jaeger, compile your Go app with `tracer_static,tracer_static_jaeger` 56 57 Note that multiple (or all) drivers can be compiled in alongside one another: using the tags: 58 `tracer_static,tracer_static_jaeger,tracer_static_lightstep,tracer_static_datadog,tracer_static_stackdriver` 59 60 If the `GITLAB_TRACING` environment variable references an unknown or unregistered driver, it will log a message 61 and continue without tracing. This is a deliberate decision: the risk of bringing down a cluster during a rollout 62 with a misconfigured tracer configuration is greater than the risk of an operator loosing some time because 63 their application was not compiled with the correct tracers. 64 65 *Using the HTTP Handler middleware to instrument incoming HTTP requests* 66 67 When an incoming HTTP request arrives on the server, it may already include Distributed Tracing headers, 68 propagated from an upstream service. 69 70 The tracing middleware will attempt to extract the tracing information from the headers (the exact headers used are 71 tracing implementation specific), set up a span and pass the information through the request context. 72 73 It is up to the Opentracing implementation to decide whether the span will be sent to the tracing infrastructure. 74 This will be implementation-specific, but generally relies on server load, sampler configuration, whether an 75 error occurred, whether certain spans took an anomalous amount of time, etc. 76 77 *Using the HTTP RoundTripper to instrument outgoing HTTP requests* 78 79 The RoundTripper should be added to the HTTP client RoundTripper stack (see the example). When an outbound 80 HTTP request is sent from the HTTP client, the RoundTripper will determine whether there is an active span 81 and if so, will inject headers into the outgoing HTTP request identifying the span. The details of these 82 headers is implementation specific. 83 84 It is important to ensure that the context is passed into the outgoing request, using `req.WithContext(ctx)` 85 so that the correct span information can be injected into the request headers. 86 87 *Propagating tracing information to child processes* 88 89 Sometimes we want a trace to continue from a parent process to a spawned child process. For this, 90 the tracing package provides `tracing.NewEnvInjector()` and `tracing.ExtractFromEnv()`, for the 91 parent and child processes respectively. 92 93 NewEnvInjector() will configure a []string array of environment variables, ensuring they have the 94 correct tracing configuration and any trace and span identifiers. NewEnvInjector() should be called 95 in the child process and will extract the trace and span information from the environment. 96 97 Please review the examples in the godocs for details of how to implement both approaches. 98 */ 99 package tracing