All Products
Search
Document Center

Application Real-Time Monitoring Service:Use Zipkin to submit the trace data of a Go application

Last Updated:Jan 15, 2024

Zipkin is a distributed tracing system. It is an open source system that is developed by Twitter to trace real-time data. Zipkin gathers real-time monitoring data from various heterogeneous systems. You can use Zipkin to submit the trace data of a Go application to the Tracing Analysis console.

Prerequisites

To obtain an endpoint of Jaeger or Zipkin, perform the following steps:

  1. Log on to the Managed Service for OpenTelemetry console.

  2. In the left-side navigation pane, click Cluster Configurations. Then, click the Access point information tab.

  3. In the top navigation bar, select a region. In the Cluster Information section, turn on Show Token.

  4. In the Client section, click Jaeger or Zipkin.

    Obtain an endpoint of Jaeger or Zipkin in the Related Information column of the table in the lower part.

    Jaeger/Zipkin接入点信息

    Note

    If your application is deployed in an Alibaba Cloud production environment, use a VPC endpoint. Otherwise, use a public endpoint. Generally, use the endpoint of v2 for Zipkin. Use the endpoint of v1 only if you know Zipkin well.

Background information

The following figure shows how to report data by using Zipkin.

通过Zipkin上报数据

Instrument the application

Before you use Zipkin to submit the trace data of a Go application to the Tracing Analysis console, you must instrument the application.

  1. Add dependencies:

    [[constraint]]
      name = "github.com/openzipkin/zipkin-go"
      version = "0.1.1"
    
    [[constraint]]
      name = "github.com/gorilla/mux"
      version = "1.6.2"
  2. Create a tracer. You can use tracers to create spans that record the time of distributed operations. Tracers contain information such as the endpoint from which data is submitted, the IP address of the on-premises machine, and the sampling rate. You can adjust the sampling rate to reduce the cost of submitting data:

    func getTracer(serviceName string, ip string) *zipkin.Tracer {
      // Create a reporter to be used by the tracer.
      reporter := httpreporter.NewReporter("http://tracing-analysis-dc-hz.aliyuncs.com/adapt_aokcdqnxyz@123456ff_abcdef123@abcdef123/api/v2/spans")
      // Configure the local endpoint for the service.
      endpoint, _ := zipkin.NewEndpoint(serviceName, ip)
      // Configure the sampling strategy.
      sampler := zipkin.NewModuloSampler(1)
      // Initialize the tracer.
      tracer, _ := zipkin.NewTracer(
        reporter,
        zipkin.WithLocalEndpoint(endpoint),
        zipkin.WithSampler(sampler),
      )
      return tracer;
    }
  3. Record the request data:

    // The tracer can now be used to create spans.
    span := tracer.StartSpan("some_operation")
    // Enter the configurations based on your needs.
    span.Finish()
    // Output:
    Note

    You can run the preceding code to create a root span that records the root operation of a request. If you need to record the previous and next operations of a request, inject a context. Example:

    childSpan := tracer.StartSpan("some_operation2", zipkin.Parent(span.Context()))
    // Enter the configurations based on your needs.
    childSpan.Finish()
  4. Optional:You can add custom tags to a span to troubleshoot errors. For example, you can check whether an error occurs, record the return value of a request, or configure the error message.

    Add a custom tag:

    childSpan.Tag("http.status_code", statusCode)

    Create a custom error message:

    childSpan := tracer.StartSpan("some_operation2", zipkin.Parent(span.Context()))
    // Enter the configurations based on your needs.
    var events = make(map[string]string)
    events["event"] = "error"
    events["stack"] = "Runtime Exception: unable to find userid"
    jsonStr, err := json.Marshal(events)
    if err == nil {
       childSpan.Annotate(time.Now(), string(jsonStr))
    }
    childSpan.Finish()
  5. In a distributed system, remote procedure call (RPC) requests are sent together with the trace data. The trace data includes the values of the TraceId, ParentSpanId, SpanId, and Sampled parameters. You can call the Extract or Inject method to specify data in HTTP request headers. The following example shows how to call the Extract or Inject method to specify data in HTTP request headers:

       Client Span                                                Server Span
    ┌──────────────────┐                                       ┌──────────────────┐
    │                  │                                       │                  │
    │   TraceContext   │           HTTP Request Headers        │   TraceContext   │
    │ ┌──────────────┐ │          ┌───────────────────┐        │ ┌──────────────┐ │
    │ │ TraceId      │ │          │ X-B3-TraceId      │        │ │ TraceId      │ │
    │ │              │ │          │                   │        │ │              │ │
    │ │ ParentSpanId │ │ Inject   │ X-B3-ParentSpanId │Extract │ │ ParentSpanId │ │
    │ │              ├─┼─────────>│                   ├────────┼>│              │ │
    │ │ SpanId       │ │          │ X-B3-SpanId       │        │ │ SpanId       │ │
    │ │              │ │          │                   │        │ │              │ │
    │ │ Sampled      │ │          │ X-B3-Sampled      │        │ │ Sampled      │ │
    │ └──────────────┘ │          └───────────────────┘        │ └──────────────┘ │
    │                  │                                       │                  │
    └──────────────────┘                                       └──────────────────┘
    Note

    Zipkin allows you to pass context information by using the HTTP protocol or gRPC framework.

    1. Call the Inject method on the client to specify the context information:

      req, _ := http.NewRequest("GET", "/", nil)
      // Configure a function that injects a trace context into a request.
      injector := b3.InjectHTTP(req)
      injector(sp.Context())
    2. Call the Extract method on the server to extract the context information:

      req, _ := http.NewRequest("GET", "/", nil)
              b3.InjectHTTP(req)(sp.Context())
      
              b.ResetTimer()
              _ = b3.ExtractHTTP(copyRequest(req))

Getting started with Data Encryption Service

The following example shows how to use Zipkin to submit the trace data of a Go application.

  1. Download the Demo file.

  2. Change the endpoint from which data is submitted in the utils.go file.

    Important

    Replace <endpoint> with the endpoint of the region where the client resides. You can obtain the endpoint on the Overview page in the Managed Service for OpenTelemetry console. For more information, see the Prerequisites topic.

  3. Install the following dependency:

    dep ensure
  4. Run the test program:

    go run main.go

    Log on to the ARMS console. In the left-side navigation pane, choose Application Monitoring > Applications. On the Applications page, click the name of the application. On the page that appears, view the trace data.

    Note

    If the Java图标 icon is displayed in the Language column, the application is connected to Application Monitoring. If a hyphen (-) is displayed, the application is connected to Managed Service for OpenTelemetry.

FAQ

Why is no data submitted?

You can check the error message that is returned when the program is running and check whether the endpoint_url parameter is valid. For example, if the failed the request with status code 403 message is returned, the username or password is invalid.