tencent cloud

Tencent Cloud Observability Platform

Release Notes and Announcements
Release Notes
Product Introduction
Overview
Strengths
Basic Features
Basic Concepts
Use Cases
Use Limits
Purchase Guide
Tencent Cloud Product Monitoring
Application Performance Management
Mobile App Performance Monitoring
Real User Monitoring
Cloud Automated Testing
Prometheus Monitoring
Grafana
EventBridge
PTS
Quick Start
Monitoring Overview
Instance Group
Tencent Cloud Product Monitoring
Application Performance Management
Real User Monitoring
Cloud Automated Testing
Performance Testing Service
Prometheus Getting Started
Grafana
Dashboard Creation
EventBridge
Alarm Service
Cloud Product Monitoring
Tencent Cloud Service Metrics
Operation Guide
CVM Agents
Cloud Product Monitoring Integration with Grafana
Troubleshooting
Practical Tutorial
Application Performance Management
Product Introduction
Access Guide
Operation Guide
Practical Tutorial
Parameter Information
FAQs
Mobile App Performance Monitoring
Overview
Operation Guide
Access Guide
Practical Tutorial
Tencent Cloud Real User Monitoring
Product Introduction
Operation Guide
Connection Guide
FAQs
Cloud Automated Testing
Product Introduction
Operation Guide
FAQs
Performance Testing Service
Overview
Operation Guide
Practice Tutorial
JavaScript API List
FAQs
Prometheus Monitoring
Product Introduction
Access Guide
Operation Guide
Practical Tutorial
Terraform
FAQs
Grafana
Product Introduction
Operation Guide
Guide on Grafana Common Features
FAQs
Dashboard
Overview
Operation Guide
Alarm Management
Console Operation Guide
Troubleshooting
FAQs
EventBridge
Product Introduction
Operation Guide
Practical Tutorial
FAQs
Report Management
FAQs
General
Alarm Service
Concepts
Monitoring Charts
CVM Agents
Dynamic Alarm Threshold
CM Connection to Grafana
Documentation Guide
Related Agreements
Application Performance Management Service Level Agreement
APM Privacy Policy
APM Data Processing And Security Agreement
RUM Service Level Agreement
Mobile Performance Monitoring Service Level Agreement
Cloud Automated Testing Service Level Agreement
Prometheus Service Level Agreement
TCMG Service Level Agreements
PTS Service Level Agreement
PTS Use Limits
Cloud Monitor Service Level Agreement
API Documentation
History
Introduction
API Category
Making API Requests
Monitoring Data Query APIs
Alarm APIs
Legacy Alert APIs
Notification Template APIs
TMP APIs
Grafana Service APIs
Event Center APIs
TencentCloud Managed Service for Prometheus APIs
Monitoring APIs
Data Types
Error Codes
Glossary

Connecting Go Applications Using OpenTelemetry-Go (Recommended)

PDF
포커스 모드
폰트 크기
마지막 업데이트 시간: 2025-10-13 19:10:48
Note:
OpenTelemetry is a collection of tools, APIs, and SDKs for monitoring, generating, collecting, and exporting telemetry data (metrics, logs, and traces) to help users analyze the performance and behaviors of the software. For more information about OpenTelemetry, see the OpenTelemetry Official Website.
The OpenTelemetry community is active, with rapid technological changes, and widely compatible with mainstream programming languages, components, and frameworks, making its link-tracing capability highly popular for cloud-native microservices and container architectures.
This document will introduce how to connect Go applications with the community's OpenTelemetry-Go scheme. OpenTelemetry-Go provides a series of APIs so that users can send performance data to the observability platform's server. This document introduces how to connect Tencent Cloud APM based on OpenTelemetry Go through the most common application behaviors, such as HTTP services and database access. For more uses of OpenTelemetry-Go, see the Project Homepage.

Prerequisites

This scheme supports the officially supported versions of Go, currently supports version 1.21 to 1.24. For lower versions, the connection is theoretically possible, but the community does not maintain full compatibility. For specific information, see the community's Compatibility Description.

Preliminary steps: Get the connect point and Token.

1. Log in to the TCOP console.
2. In the left menu column, select Application Performance Management > Application list, then click Access application.
3. In the Access application drawer that pops up on the right, click the Go language.
4. On the Access Go application page, select the Region and Business System you want to connect.
5. Select Access protocol type as OpenTelemetry.
6. Choose your desired Reporting method, and obtain your Access Point and Token.
Note:
Private network reporting: Using this reporting method, your service needs to run in the Tencent Cloud VPC. Through VPC connecting directly, you can avoid the security risks of public network communication and save on reporting traffic overhead.
Public network reporting: If your service is deployed locally or in non-Tencent Cloud VPC, you can report data in this method. However, it involves security risks in public network communication and incurs reporting traffic fees.

Connecting Go Applications

Step 1: Introduce OpenTelemetry-related dependencies to implement the SDK initialization logic.

package main import ( "context" "errors" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/sdk/resource" "go.opentelemetry.io/otel/sdk/trace" sdktrace "go.opentelemetry.io/otel/sdk/trace" "log" )
func setupOTelSDK(ctx context.Context) (*trace.TracerProvider, error) { opts := []otlptracegrpc.Option{ otlptracegrpc.WithEndpoint("<endpoint>"), // Replace <endpoint> with the reporting address otlptracegrpc.WithInsecure(), } exporter, err := otlptracegrpc.New(ctx, opts...) if err != nil { log.Fatal(err) } r, err := resource.New(ctx, []resource.Option{ resource.WithAttributes( attribute.KeyValue{Key: "token", Value: "<token>"}, // Replace <token> with the business system Token attribute.KeyValue{Key: "service.name", Value: "<servceName>"}, // Replace <serviceName> with the application name attribute.KeyValue{Key: "host.name", Value: "<hostName>"}, // Replace <hostName> with the IP address ), }...) if err != nil { log.Fatal(err) } tp := sdktrace.NewTracerProvider( sdktrace.WithSampler(sdktrace.AlwaysSample()), sdktrace.WithBatcher(exporter), sdktrace.WithResource(r), ) otel.SetTracerProvider(tp) otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})) return tp, nil }
The corresponding field descriptions are as follows, replace them according to actual conditions.
<serviceName>: Application name. Multiple application processes connecting with the same serviceName are displayed as multiple instances under the same application in APM. The application name can be up to 63 characters and can only contain lowercase letters, digits, and the separator (-), and it must start with a lowercase letter and end with a digit or lowercase letter.
<token>: The business system Token obtained in the preliminary steps.
<hostName>: The hostname of this instance, which is the unique identifier of the application instance. It can usually be set to the IP address of the application instance.
<endpoint>: The connect point obtained in the preliminary steps.

Step 2: SDK initialization and start the HTTP service.

package main

import ( "context" "errors" "fmt" "log" "net" "net/http" "os" "os/signal" "time" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" )
func main() { if err := run(); err != nil { log.Fatalln(err) } } func run() (err error) { ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt) defer stop() // Initialize SDK otelShutdown, err := setupOTelSDK(ctx) if err != nil { return } // Graceful shutdown defer func() { err = errors.Join(err, otelShutdown(context.Background())) }() // Start HTTP service srv := &http.Server{ Addr: ":8080", BaseContext: func(_ net.Listener) context.Context { return ctx }, ReadTimeout: time.Second, WriteTimeout: 10 * time.Second, Handler: newHTTPHandler(), } srvErr := make(chan error, 1) go func() { srvErr <- srv.ListenAndServe() }()
select { case err = <-srvErr: return case <-ctx.Done(): stop() } err = srv.Shutdown(context.Background()) return }
If implementing an HTTP service through frameworks like Gin, the Event Tracking method will differ. See the community's Framework List for details on other frameworks' Event Tracking methods.

Step 3: Enhanced Event Tracking for HTTP APIs.

func newHTTPHandler() http.Handler { mux := http.NewServeMux() handleFunc := func(pattern string, handlerFunc func(http.ResponseWriter, *http.Request)) { // HTTP routes Event Tracking handler := otelhttp.WithRouteTag(pattern, http.HandlerFunc(handlerFunc)) mux.Handle(pattern, handler) } // Register APIs handleFunc("/simple", simpleIOHandler) // Enhanced Event Tracking for all APIs handler := otelhttp.NewHandler(mux, "/") return handler }

func simpleIOHandler(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "ok") }

Connection Verification

After you start the Go application, access the corresponding API through port 8080, for example, https://localhost:8080/simple, the application reports HTTP request-related link data to APM. In normal traffic cases, the connected application will be displayed in Application Performance Monitoring > Application list. Click Application name/ID to enter the application details page, then select Instance Analysis to view the connected application instance. Since there is a certain latency in the processing of observable data, if the application or instance does not appear in the console after connecting, wait for about 30 seconds.

More Event Tracking Sample

Accessing Redis

Initialization
import (
"github.com/redis/go-redis/v9"
"github.com/redis/go-redis/extra/redisotel/v9"
)

var rdb *redis.Client

// InitRedis initializing Redis client.
func InitRedis() *redis.Client {
rdb := redis.NewClient(&redis.Options{
Addr: "127.0.0.1:6379",
Password: "", // no password
})
if err := redisotel.InstrumentTracing(rdb); err != nil {
panic(err)
}
if err := redisotel.InstrumentMetrics(rdb); err != nil {
panic(err)
}
return rdb
}
Data Access
func redisRequest(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
rdb := InitRedis()
val, err := rdb.Get(ctx, "foo").Result()
if err != nil {
log.Printf("redis err......")
panic(err)
}
fmt.Println("redis res: ", val)
}

Accessing MySQL

Initialization
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/schema"
"gorm.io/plugin/opentelemetry/tracing"
)

var GormDB *gorm.DB

type TableDemo struct {
ID int gorm:"column:id"
Value string gorm:"column:value"
}

func InitGorm() {
var err error

dsn := "root:4T$er3deffYuD#9Q@tcp(127.0.0.1:3306)/db_demo?charset=utf8mb4&parseTime=True&loc=Local"
GormDB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
NamingStrategy: schema.NamingStrategy{
SingularTable: true, // Use singular table names.
},
})
if err != nil {
panic(err)
}
// Add tracing reporting logic.
//Fill in DBName based on actual conditions. In the APM topology diagram, identify the node using the DBName field. In this example, use mockdb-mysql.
if err = GormDB.Use(tracing.NewPlugin(tracing.WithoutMetrics(),tracing.WithDBName("mockdb-mysql"))); err != nil {
panic(err)
}
}
Data Access
func gormRequest(ctx context.Context) {
var val string
if err := gormclient.GormDB.WithContext(ctx).Model(&gormclient.TableDemo{}).Where("id = ?", 1).Pluck("value", &val).Error; err != nil {
panic(err)
}
fmt.Println("MySQL query result: ", val)
}

Custom Event Tracking

Users can append a custom Span in the current link context to enhance link data richness. When performing custom event tracking, set Span Kind via tracer.WithSpanKind(). Span Kind includes server, client, internal, consumer, and producer. Configure it according to specific business scenarios. This document provides sample code for internal method tracking and external resource access tracking.

Internal Method

Here demonstrates adding a internal kind Span inside a server Type Span.
func entryFunc(w http.ResponseWriter, r *http.Request) {
_, span := tracer.Start(r.Context(), "entryFunc", trace.WithSpanKind(trace.SpanKindServer)) // server span
defer span.End()
internalInvoke(r)
io.WriteString(w, "ok")
}

func internalInvoke(r *http.Request) {
create Internal Span
_, span := tracer.Start(r.Context(), "internalInvoke", trace.WithSpanKind(trace.SpanKindInternal)) // internal span
defer span.End()
// business logic omitted
}

Access External Resources

To access external resources, a Span of type client is usually required to be appended in the current link context.
func clientInvoke(ctx context.Context) {
_, span := tracer.Start(ctx, "child", trace.WithSpanKind(trace.SpanKindClient))
defer span.End()
_, err := http.Get("https://www.example.com")
if err != nil {
fmt.Println("err occurred when call extrnal api: ", err)
return
}
}

Retrieve Current Span Context

In code, you can obtain the current Span context information to add or modify span attributes, or output the obtained TraceID/SpanID in logs.

Retrieving TraceID/SpanID

func internalInvoke(ctx context.Context) {
spanCtx := trace.SpanContextFromContext(ctx) // Retrieve current span context
if spanCtx.HasTraceID() {
traceID := spanCtx.TraceID()
fmt.Println(traceID.String())
}
if spanCtx.HasSpanID() {
spanID := spanCtx.SpanID()
fmt.Println(spanID.String())
}
// business logic omitted
}

Setting Span Attribute

First get the Span object, then set attributes.
func gormRequest(ctx context.Context) {
span := trace.SpanFromContext(ctx) // Retrieve current span object
if span == nil {
fmt.Println("no active span detected")
return
}
span.SetAttributes(
attribute.String("key1", "value1"),
attribute.Int64("key2", 123),
)

var val string
if err := gormclient.GormDB.WithContext(ctx).Model(&gormclient.TableDemo{}).Where("id = ?", 1).Pluck("value", &val).Error; err != nil {
panic(err)
}
fmt.Println("MySQL query result: ", val)
}



도움말 및 지원

문제 해결에 도움이 되었나요?

피드백