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