Мониторинг Go приложений с помощью Proto Observability

Подключение трейсинга и сбора метрик для Go приложений.

На этой странице:

Введение

Общий процесс подключения Go приложения на мониторинг в Proto Observability Platform :

  1. Установка ProtoOBP Агента.
  2. Установка трейсера.
  3. Конфигурация трейсера (опционально).

После подключения будут доступны все возможности модуля Application Performance Monitoring Proto Observability Platform.

Установка Go трейсера

Существует два способа инструментации вашего Go приложения:

  1. Инструментация на этапе компиляции:

    • Обеспечивает максимальную полноту трассировки.
    • Не требует изменения исходного кода, что делает этот способ идеальным для интеграции на уровне CI/CD.
  2. Инструментация вручную:

    Используются модули трейсера в сочетании с пакетами интеграции для автоматической генерации спанов для выбранных вами библиотек. Этот вариант:

    • Дает вам полный контроль над тем, какие части вашего приложения будут отслеживаться.
    • Требует изменения исходного кода приложения.

Инструментация на этапе компиляции (рекомендуется)

Пакет Orchestrion автоматически добавляет инструментацию в приложения Go во время компиляции, устраняя необходимость в модификации кода. Пакет обеспечивает всестороннее покрытие трассировкой:

  • Инструментирует ваш код и все зависимости, включая стандартную библиотеку Go.
  • Инструментирует ваш код во время компиляции, предотвращая пробелы в покрытии трассировки из-за упущенной ручной инструментации.

Требования для инструментации на этапе компиляции:

Для добавления в Go приложение инструментации на этапе компиляции выполните:

  1. Установите пакет Orchestrion:

    go install github.com/DataDog/orchestrion@latest
    
  2. Выполните команду:

    orchestrion pin
    
  3. Добавьте префикс orchestrion к обычным командам go:

    orchestrion go build .
    orchestrion go run .
    orchestrion go test ./...
    

Пример Dockerfile:

FROM golang:1.24

WORKDIR /home/apm-tutorial-golang

COPY go.mod ./
COPY go.sum ./
RUN go mod download

#Copy notes application
COPY notes notes/
COPY cmd/notes cmd/notes/ 

# добавление инструментации
RUN go install github.com/DataDog/orchestrion@latest
RUN orchestrion pin
RUN orchestrion go build -o cmd/notes/notes ./cmd/notes

#Set sample rate
ENV DD_TRACE_SAMPLE_RATE 1

#Run application
ENTRYPOINT ["./cmd/notes/notes"]  

Инструментация вручную

Добавьте библиотеку трейсера в свое приложение Сначала импортируйте и запустите трейсер в своем коде, следуя инструкциям в документации по настройке библиотеки. Инструкции по настройке и подробную информацию об использовании API см. ниже.

Добавление модуля pobptrace:

go get -u git.proto.group/protoobp/pobp-trace-go/pobptrace

или добавьте в main.go файл:

import(
  "git.proto.group/protoobp/pobp-trace-go/pobptrace/tracer"
)

Добавление модуля ddtrace:

go get -u github.com/DataDog/dd-trace-go/v2

или добавьте в main.go файл:

import(
	"github.com/DataDog/dd-trace-go/v2/ddtrace/ext"
	"github.com/DataDog/dd-trace-go/v2/ddtrace/tracer"
)

Используйте документацию трейсера:

https://pkg.go.dev/github.com/DataDog/dd-trace-go/v2/ddtrace

Скоро

  1. Выполните шаги, указанные на странице подключения инструметации OpenTelemetry для Go:

    https://opentelemetry.io/docs/languages/go/

  2. Выполните шаги, указанные на странице настройки OpenTelemetry в Proto Observability Platform.

Активируйте интеграции Go для создания спанов Активируйте интеграции Go для генерации спанов. Предлагаются ряд подключаемых пакетов, которые обеспечивают готовую поддержку для инструментации ряда библиотек и фреймворков. Список этих пакетов можно найти на странице «Требования к совместимости». Импортируйте эти пакеты в свое приложение и следуйте инструкциям по настройке, указанным рядом с каждой интеграцией.

Дополнительные модули интеграции – пример добавления:

go get -u git.proto.group/protoobp/pobp-trace-go/contrib/net/http

Для автоматической инструментации вызововов поддерживаются следующие библиотеки и фреймворки (примеры доступны в документации по ссылкам):

Фреймворк Документация по интеграции
Gin https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/gin-gonic/gin
Gorilla Mux https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/gorilla/mux
gRPC https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/google.golang.org/grpc
gRPC v1.2 https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/google.golang.org/grpc.v12
chi https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/go-chi/chi
echo v4 https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/labstack/echo.v4
echo v3 https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go//contrib/labstack/echo
Fiber https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/gofiber/fiber.v2
Библиотека Документация по интеграции
AWS SDK https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/aws/aws-sdk-go/aws
Elasticsearch https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/olivere/elastic
Cassandra https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/gocql/gocql
GraphQL https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/graph-gophers/graphql-go
HTTP https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/net/http
HTTP router https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/julienschmidt/httprouter
Redis (go-redis) https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/go-redis/redis
Redis (go-redis-v8) https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/go-redis/redis.v8
Redis (redigo) https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/garyburd/redigo
Redis (new redigo) https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/gomodule/redigo
SQL https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/database/sql
SQLx https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/jmoiron/sqlx
MongoDB https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/go.mongodb.org/mongo-driver/mongo
MongoDB (mgo)73 https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/globalsign/mgo
BuntDB https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/tidwall/buntdb
LevelDB https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/syndtr/goleveldb/leveldb
miekg/dns https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/miekg/dns
Kafka (confluent) https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/confluentinc/confluent-kafka-go
Kafka (sarama) https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/Shopify/sarama
Google API https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/google.golang.org/api
go-restful https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/emicklei/go-restful
Twirp https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/twitchtv/twirp
Vault https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/hashicorp/vault
Consul https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/hashicorp/consul
Gorm https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/jinzhu/gorm
Gorm v2 https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/gorm.io/gorm.v1
Kubernetes https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/k8s.io/client-go/kubernetes
Memcache https://pkg.go.dev/git.proto.group/protoobp/pobp-trace-go/contrib/bradfitz/gomemcache/memcache

Пакеты для интеграции должны быть импортированы следующим образом:

import "git.proto.group/protoobp/pobp-trace-go/contrib/<PACKAGE_DIR>/<PACKAGE_NAME>"

Пример использования пакета для инструментации стандартных net/http:

package main

import (
	"fmt"
	"net/http"

	httptrace "git.proto.group/protoobp/pobp-trace-go/contrib/net/http" // дополнительный пакет
	"git.proto.group/protoobp/pobp-trace-go/pobptrace/tracer"
)

func hello(w http.ResponseWriter, req *http.Request) {

	w.Write([]byte("Hello My World!\n"))

}

func headers(w http.ResponseWriter, req *http.Request) {

	for name, headers := range req.Header {
		for _, h := range headers {
			fmt.Fprintf(w, "%v: %v\n", name, h)
		}
	}
}

func main() {

	tracer.Start(
		tracer.WithService("test-server"), 
		tracer.WithRuntimeMetrics(),       
		tracer.WithAgentAddr("protoobp-agent:8126"),
		tracer.WithDogstatsdAddress("protoobp-agent"),
	)
	mux := httptrace.NewServeMux()

	defer tracer.Stop()

	mux.HandleFunc("/hello", hello)
	mux.HandleFunc("/headers", headers)

	http.ListenAndServe(":8090", mux)
}

Пакеты интеграции импортируются следующим образом:

import "github.com/DataDog/dd-trace-go/contrib/<PACKAGE_DIR>/<PACKAGE_NAME>/v2"
Фреймворк GoDoc Документация
Gin github.com/DataDog/dd-trace-go/contrib/gin-gonic/gin/v2
Gorilla Mux github.com/DataDog/dd-trace-go/contrib/gorilla/mux/v2
gRPC github.com/DataDog/dd-trace-go/contrib/google.golang.org/grpc/v2
chi github.com/DataDog/dd-trace-go/contrib/go-chi/chi/v2
echo v4 github.com/DataDog/dd-trace-go/contrib/labstack/echo.v4/v2
Fiber github.com/DataDog/dd-trace-go/contrib/gofiber/fiber.v2/v2

Трейсер поддерживает следующие библиотеки и хранилища данных:

Библиотека Примеры использования и документация
AWS SDK github.com/DataDog/dd-trace-go/contrib/aws/aws-sdk-go/aws/v2
AWS SDK v2 github.com/DataDog/dd-trace-go/contrib/aws/aws-sdk-go-v2/aws/v2
Elasticsearch github.com/DataDog/dd-trace-go/contrib/olivere/elastic.v5/v2
Cassandra github.com/DataDog/dd-trace-go/contrib/gocql/gocql/v2
GraphQL github.com/DataDog/dd-trace-go/contrib/graph-gophers/graphql-go/v2
HTTP github.com/DataDog/dd-trace-go/contrib/net/http/v2
HTTP router github.com/DataDog/dd-trace-go/contrib/julienschmidt/httprouter/v2
Redis (go-redis) github.com/DataDog/dd-trace-go/contrib/go-redis/redis/v2
Redis (go-redis-v8) github.com/DataDog/dd-trace-go/contrib/go-redis/redis.v8/v2
Redis (redigo) github.com/DataDog/dd-trace-go/contrib/garyburd/redigo/v2
Redis (new redigo) github.com/DataDog/dd-trace-go/contrib/gomodule/redigo/v2
SQL github.com/DataDog/dd-trace-go/contrib/database/sql/v2
SQLx github.com/DataDog/dd-trace-go/contrib/jmoiron/sqlx/v2
MongoDB github.com/DataDog/dd-trace-go/contrib/go.mongodb.org/mongo-driver/mongo/v2
MongoDB (mgo) github.com/DataDog/dd-trace-go/contrib/globalsign/mgo/v2
BuntDB github.com/DataDog/dd-trace-go/contrib/tidwall/buntdb/v2
LevelDB github.com/DataDog/dd-trace-go/contrib/syndtr/goleveldb/leveldb/v2
miekg/dns github.com/DataDog/dd-trace-go/contrib/miekg/dns/v2
Kafka (confluent) github.com/DataDog/dd-trace-go/contrib/confluentinc/confluent-kafka-go/v2
Kafka (sarama) github.com/DataDog/dd-trace-go/contrib/IBM/sarama/v2
Google API github.com/DataDog/dd-trace-go/contrib/google.golang.org/api/v2
go-restful github.com/DataDog/dd-trace-go/contrib/emicklei/go-restful.v3/v2
Twirp github.com/DataDog/dd-trace-go/contrib/twitchtv/twirp/v2
Vault github.com/DataDog/dd-trace-go/contrib/hashicorp/vault/v2
Consul github.com/DataDog/dd-trace-go/contrib/hashicorp/consul/v2
Gorm v2 github.com/DataDog/dd-trace-go/contrib/gorm.io/gorm.v1/v2
Kubernetes github.com/DataDog/dd-trace-go/contrib/k8s.io/client-go/kubernetes/v2
Memcache github.com/DataDog/dd-trace-go/contrib/bradfitz/gomemcache/memcache/v2

Скоро

  1. Выполните шаги, указанные на странице подключения инструметации OpenTelemetry для Go:

    https://opentelemetry.io/docs/languages/go/

  2. Выполните шаги, указанные на странице настройки OpenTelemetry в Proto Observability Platform.

Конфигурация трейсера

Трейсер поддерживает конфигурацию через переменные окружения или через параметры инициализации в коде вашего приложения.

Конфигурация трейсера через переменные окружения (рекомендуется)

POBP_AGENT_HOST – адрес Агента, на который будет отсылать данные трейсер:

  • если Агент запущен в Docker контейнере, укажите имя Docker контейнера Агента:
    ENV POBP_AGENT_HOST="protoobp-agent"
    
    Убедитесь, что контейнер Агента и контейнер приложения находятся в одной Docker сети. Адрес агента должен быть доступен из Docker контейнера приложения.
  • если Агент запущен на хосте как сервис (не в контейнере):
    ENV POBP_AGENT_HOST="host.docker.internal"
    
    Убедитесь что в конфигурации Агента разрешен прием APM данных от контейнеров:
    apm_config:
      apm_non_local_traffic: true
    

POBP_SERVICE – имя сервиса, которое будет отображаться в интерфейсе Proto OBP:

ENV POBP_SERVICE="my_service_name"

POBP_ENV – окружение сервиса, которое будет отображаться в интерфейсе Proto OBP:

ENV POBP_ENV="prod" # prod/test/stage/dev и тд

POBP_RUNTIME_METRICS_ENABLED – обязательно установите в true для получения runtime метрик

ENV POBP_RUNTIME_METRICS_ENABLED="true"

POBP_TRACE_TELEMETRY_ENABLED – установите в false

ENV POBP_TRACE_TELEMETRY_ENABLED="false"

DD_AGENT_HOST – адрес Агента, на который будет отсылать данные трейсер:

  • если Агент запущен в Docker контейнере, укажите имя Docker контейнера Агента:
    ENV DD_AGENT_HOST="protoobp-agent"
    
    Убедитесь, что контейнер Агента и контейнер приложения находятся в одной Docker сети. Адрес агента должен быть доступен из Docker контейнера приложения.
  • если Агент запущен на хосте как сервис (не в контейнере):
    ENV DD_AGENT_HOST="host.docker.internal"
    
    Убедитесь что в конфигурации Агента разрешен прием APM данных от контейнеров:
    apm_config:
      apm_non_local_traffic: true
    

DD_SERVICE – имя сервиса, которое будет отображаться в интерфейсе Proto OBP:

ENV DD_SERVICE="my_service_name"

DD_ENV – окружение сервиса, которое будет отображаться в интерфейсе Proto OBP:

ENV DD_ENV="prod" # prod/test/stage/dev и тд

DD_RUNTIME_METRICS_ENABLED – обязательно установите в true для получения runtime метрик

ENV DD_RUNTIME_METRICS_ENABLED="true"

DD_TRACE_TELEMETRY_ENABLED – установите в false

ENV DD_TRACE_TELEMETRY_ENABLED="false"

Скоро

Если приложение запускается в Docker контейнере

Пример готового Dockerfile:

ENV POBP_SERVICE=dispatch
ENV POBP_DOGSTATSD_NON_LOCAL_TRAFFIC=true
# следующие переменные лучше задавать в среде выполнения, а не в Dockerfile 
ENV POBP_ENV=prod                             
ENV POBP_AGENT_HOST=protoobp-agent
ENV DD_SERVICE=dispatch
ENV DD_DOGSTATSD_NON_LOCAL_TRAFFIC=true
# следующие переменные лучше задавать в среде выполнения, а не в Dockerfile 
ENV DD_ENV=prod                             
ENV DD_AGENT_HOST=protoobp-agent

Скоро

  1. Выполните шаги, указанные на странице подключения инструметации OpenTelemetry для Go:

    https://opentelemetry.io/docs/languages/go/

  2. Выполните шаги, указанные на странице настройки OpenTelemetry в Proto Observability Platform.

Если приложение работает в Kubernetes

Убедитесь, что у вас успешно установлен и настроен ProtoOBP Агент для Kubernetes.

Дополнительно необходимо передать поду переменную окружения POBP_AGENT_HOST со значением IP адреса воркер-ноды, а также переменные окружения для связи трейсов с инфраструктурой (имя k8s кластера нужно задать вручную).

apiVersion: apps/v1
kind: Deployment
#(...)
    spec:
      containers:
      - name: "<CONTAINER_NAME>"
        image: "<CONTAINER_IMAGE>/<TAG>"
        env:
          - name: POBP_SERVICE
            value: dispatch			
          - name: POBP_AGENT_HOST
            valueFrom:
              fieldRef:
                fieldPath: status.hostIP
          - name: NODE_NAME
            valueFrom:
              fieldRef:
                fieldPath: spec.nodeName
          - name: POD_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: POBP_TAGS
            value: "pod_name:$(POD_NAME),node:$(NODE_NAME),kube_namespace:$(POD_NAMESPACE),kube_cluster_name:<my_cluster_name>"            
            

Дополнительно необходимо передать поду переменную окружения DD_AGENT_HOST со значением IP адреса воркер-ноды, а также переменные окружения для связи трейсов с инфраструктурой (имя k8s кластера нужно задать вручную).

apiVersion: apps/v1
kind: Deployment
#(...)
    spec:
      containers:
      - name: "<CONTAINER_NAME>"
        image: "<CONTAINER_IMAGE>/<TAG>"
        env:
          - name: DD_SERVICE
            value: dispatch			
          - name: DD_AGENT_HOST
            valueFrom:
              fieldRef:
                fieldPath: status.hostIP
          - name: NODE_NAME
            valueFrom:
              fieldRef:
                fieldPath: spec.nodeName
          - name: POD_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: DD_TAGS
            value: "pod_name:$(POD_NAME),node:$(NODE_NAME),kube_namespace:$(POD_NAMESPACE),kube_cluster_name:<my_cluster_name>"            
            

Скоро

  1. Выполните шаги, указанные на странице подключения инструметации OpenTelemetry для Go:

    https://opentelemetry.io/docs/languages/go/

  2. Выполните шаги, указанные на странице настройки OpenTelemetry в Proto Observability Platform.

Метрики Go runtime

Помимо трейсов, ошибок и метрик по трейсам, Proto OBP также собирает runtime метрики Go приложений. Runtime метрики отображаются на дашборде конкретного инстанса сервиса.

Включение метрик Go runtime

Убедитесь, что у Агента установлена переменная окружения:

POBP_DOGSTATSD_NON_LOCAL_TRAFFIC=true

Добавьте переменную окружения к приложению:

POBP_RUNTIME_METRICS_ENABLED=true  

Добавьте переменную окружения к приложению:

DD_RUNTIME_METRICS_ENABLED=true  

Список метрик Go runtime, собираемых Proto OBP

runtime_go_num_cpu
(gauge)
Процессоры, обнаруженные средой выполнения.
runtime_go_num_goroutine
(gauge)
Созданные goroutines.
runtime_go_num_cgo_call
(gauge)
Выполненные вызовы CGO.
runtime_go_mem_stats_alloc
(gauge)
Alloc — это байты выделенных объектов кучи.
runtime_go_mem_stats_total_alloc
(gauge)
TotalAlloc — это совокупный объем выделенной памяти для объектов кучи.
runtime_go_mem_stats_sys
(gauge)
Sys — это общий объем памяти, полученной от ОС. Отображается в байтах
runtime_go_mem_stats_lookups
(gauge)
Lookups — количество поисков указателей, выполненных.
runtime_go_mem_stats_mallocs
(gauge)
Mallocs — совокупное количество выделенных объектов кучи.
runtime_go_mem_stats_frees
(gauge)
Frees — это совокупное количество освобожденных объектов кучи.
runtime_go_mem_stats_heap_alloc
(gauge)
HeapAlloc — это байты выделенных объектов кучи.
runtime_go_mem_stats_heap_sys
(gauge)
HeapSys — это количество байтов кучи памяти, полученных от ОС.
runtime_go_mem_stats_heap_idle
(gauge)
HeapIdle — это количество байтов в неиспользуемых (незанятых) интервалах.
runtime_go_mem_stats_heap_inuse
(gauge)
HeapInuse — это байты в используемых диапазонах.
runtime_go_mem_stats_heap_released
(gauge)
HeapReleased — это количество байтов физической памяти, возвращенных ОС.
runtime_go_mem_stats_heap_objects
(gauge)
HeapObjects — это количество выделенных объектов кучи.
runtime_go_mem_stats_stack_inuse
(gauge)
StackInuse — это количество байтов в стеке.
runtime_go_mem_stats_stack_sys
(gauge)
StackSys — это количество байтов памяти стека, полученных от ОС.
runtime_go_mem_stats_m_span_inuse
(gauge)
MSpanInuse — это количество байтов выделенных структур mspan.
runtime_go_mem_stats_m_span_sys
(gauge)
MSpanSys — это количество байтов памяти, полученных от ОС для структур mspan.
runtime_go_mem_stats_m_cache_inuse
(gauge)
MCacheInuse — это количество байтов выделенных структур mcache.
runtime_go_mem_stats_m_cache_sys
(gauge)
MCacheSys — это количество байтов памяти, полученных от ОС
runtime_go_mem_stats_buck_hash_sys
(gauge)
BuckHashSys — это байты памяти в хэш-таблицах профилирования.
runtime_go_mem_stats_gc_sys
(gauge)
GCSys — это байты памяти в метаданных сборки мусора.
runtime_go_mem_stats_other_sys
(gauge)
OtherSys — это байты памяти в различных внекупочных областях.
runtime_go_mem_stats_next_gc
(gauge)
NextGC — это целевой размер кучи для следующего цикла GC.
runtime_go_mem_stats_last_gc
(gauge)
LastGC — время завершения последней сборки мусора в наносекундах с 1970 года (эпоха UNIX).
runtime_go_mem_stats_pause_total_ns
(gauge)
PauseTotalNs — это совокупное количество наносекунд в GC.
runtime_go_mem_stats_num_gc
(gauge)
NumGC — количество завершенных циклов GC.
runtime_go_mem_stats_num_forced_gc
(gauge)
NumForcedGC — количество циклов GC, которые были принудительно запущены приложением, вызвавшим функцию GC.
runtime_go_mem_stats_gc_cpu_fraction
(gauge)
GCCPUFraction — доля доступного времени ЦП данной программы, использованного GC с момента запуска программы.
runtime_go_gc_stats_pause_quantiles_min
(gauge)
Распределение времени пауз GC: минимальные значения. Отображается в наносекундах
runtime_go_gc_stats_pause_quantiles_25p
(gauge)
Распределение времени пауз GC: 25-й процентиль. Отображается в наносекундах
runtime_go_gc_stats_pause_quantiles_75p
(gauge)
Распределение времени пауз GC: 50-й процентиль. Отображается в наносекундах
runtime_go_gc_stats_pause_quantiles_95p
(gauge)
Распределение времени паузы GC: 75-й процентиль. Отображается в наносекундах
runtime_go_gc_stats_pause_quantiles_max
(gauge)
Распределение времени паузы GC: максимальные значения. Отображается в наносекундах

Отображение метрик Go runtime

Для отображения метрик Go runtime выберите сервис, перейдите на вкладки Инстансы и откройте дашборд интересующего инстанса:

Трейсер ProtoOBP – дополнительная документация

Конфигурация трейсера при инициализации в коде

Параметры можно задать явным образом при инициализаци трейсера. В случае добавления ранее переменных окружения, достаточно указать только tracer.WithRuntimeMetrics() для отдачи метрик.


package main

import (
    "git.proto.group/protoobp/pobp-trace-go/pobptrace/tracer"
)

func main() {
	tracer.Start(
		tracer.WithService("test-server"), 				// имя сервиса 
		tracer.WithRuntimeMetrics(),       				// включение передачи Go метрик
		tracer.WithAgentAddr("protoobp-agent"),	        // адрес по которому доступен ProtoOBP агент
		tracer.WithDogstatsdAddress("protoobp-agent"),	// адрес по которому доступен ProtoOBP агент
	)

    defer tracer.Stop()
}

Использование трейсера

Создание трейсера


package main

import (
    "git.proto.group/protoobp/pobp-trace-go/pobptrace/tracer"
)

func main() {
	tracer.Start(
		tracer.WithService("test-server"), 				// имя сервиса 
		tracer.WithRuntimeMetrics(),       				// включение передачи Go метрик
	)

    defer tracer.Stop()
}

Ручное добавление спанов

Если автоматической инструментации библиотек и фреймворков недостаточно, вы можете вручную добавить спаны. Для добавления спанов доступно две функции - StartSpan и StartSpanFromContext

//Создание спана с эндпонитом /user, который дочерный к родительскому спану.
span := tracer.StartSpan("mainOp", tracer.ResourceName("/user"), tracer.ChildOf(parentSpan))

// Создание спана, который будет дочерним к спану в контексте ctx, если в контексте есть спан.
// Возвращает новый спан, и новый контекст, содержащий спан.
span, ctx := tracer.StartSpanFromContext(ctx, "mainOp", tracer.ResourceName("/user"))
Пример ручного создания спанов
package main

import (
	"io/ioutil"
	"log"

	"git.proto.group/protoobp/pobp-trace-go/pobptrace/ext"
	"git.proto.group/protoobp/pobp-trace-go/pobptrace/tracer"
)

func main() {
	// Запускаем трейсер и не забывает про Stop.
	tracer.Start(tracer.WithAgentAddr("host:port"))
	defer tracer.Stop()

	// Начинаем корневой спан.
	span := tracer.StartSpan("get.data")
	defer span.Finish()

	// Создаем дочерный спан, вычисляем время, необходимое для открытия файла.
	child := tracer.StartSpan("read.file", tracer.ChildOf(span.Context()))
	child.SetTag(ext.ResourceName, "test.json")

	// Выполняем операцию.
	_, err := ioutil.ReadFile("~/test.json")

	// Мы можем завершить дочерный спан используя возвращаемую ошибку. Если это 
	// nil, будет отброшено.
	child.Finish(tracer.WithError(err))
	if err != nil {
		log.Fatal(err)
	}
}

Добавление тегов к спану

package main

import (
    "log"
    "net/http"

    "git.proto.group/protoobp/pobp-trace-go/pobptrace/tracer"
)

func handler(w http.ResponseWriter, r *http.Request) {
    // Создание спана для web request для запросов к /posts.
	// ResourceName - имя эндпоинта в Proto OBP
    span := tracer.StartSpan("web.request", tracer.ResourceName("/posts"))
    defer span.Finish()

    // Добавляем тег
    span.SetTag("http.url", r.URL.Path)
    span.SetTag("<TAG_KEY>", "<TAG_VALUE>")
}

func main() {
    tracer.Start(tracer.WithService("<SERVICE_NAME>"))
    defer tracer.Stop()
    http.HandleFunc("/posts", handler)
    log.Fatal(http.ListenAndServe(":8080", nil))
}
Пример добавления тэга к спану со значением кастомного HTTP заголовка

Используйте функцию span.SetTag("<KEY>", "<VALUE>") для добавления HTTP заголовка в тэг трейса, где:

KEY - должен начинаться с http.request.headers.<ИМЯ_HTTP_ЗАГОЛОВКА>

VALUE - значение заголовка

Пример:

package main

import (
    "log"
    "net/http"

    "git.proto.group/protoobp/pobp-trace-go/pobptrace/tracer"
)

func handler(w http.ResponseWriter, r *http.Request) {
    // Создание спана для web request для запросов к /posts.
	// ResourceName - имя эндпоинта в Proto OBP
    span := tracer.StartSpan("web.request", tracer.ResourceName("/posts"))
    defer span.Finish()

    // Добавляем тег
    span.SetTag("http.url", r.URL.Path)
	//Добавляем HTTP заголовк в тэг трейса
    span.SetTag("http.request.headers.x-request-id", "<VALUE>")
}

func main() {
    tracer.Start(tracer.WithService("<SERVICE_NAME>"))
    defer tracer.Stop()
    http.HandleFunc("/posts", handler)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

Распределенный трейсинг и обработка контекста

Мы используем тип Context для связи спанов. Если нужно добавить теги связанные с Context, вызывайте SpanFromContext:


package main

import (
    "net/http"

    "git.proto.group/protoobp/pobp-trace-go/pobptrace/tracer"
)

func handler(w http.ResponseWriter, r *http.Request) {
    // Спан для веб запроса связанный с Go Context.
    if span, ok := tracer.SpanFromContext(r.Context()); ok {
        // добавляем тег.
        span.SetTag("http.url", r.URL.Path)
    }
}

Создание распределенного трейса путем ручного внедрения контекста:

package main

import (
    "net/http"

    "git.proto.group/protoobp/pobp-trace-go/pobptrace/tracer"
)

func handler(w http.ResponseWriter, r *http.Request) {
    span, ctx := tracer.StartSpanFromContext(r.Context(), "post.process")
    defer span.Finish()

    req, err := http.NewRequest("GET", "http://example.com", nil)
    req = req.WithContext(ctx)
    // Внедрение Context хедеры Request
    err = tracer.Inject(span.Context(), tracer.HTTPHeadersCarrier(req.Header))
    if err != nil {
        // Обработка или логгирование ошибки внедрения контекста
    }
    http.DefaultClient.Do(req)
}

Далее на серверной стороне для продолжения трейса создайте новый спан из извлеченного контекста:


package main

import (
    "net/http"

    "git.proto.group/protoobp/pobp-trace-go/pobptrace/tracer"
)

func handler(w http.ResponseWriter, r *http.Request) {
    // Извлекаем контекст спана и продолжаем трейс в этом сервисе
    sctx, err := tracer.Extract(tracer.HTTPHeadersCarrier(r.Header))
    if err != nil {
        // Обработка или логгирование ошибки извлечения контекста
    }

    span := tracer.StartSpan("post.filter", tracer.ChildOf(sctx))
    defer span.Finish()
}

Ошибочный спан

Для добавления признака ошибки, используйте tracer.WithError:

err := someOperation()
span.Finish(tracer.WithError(err))

Трейсинг асинхронных запросов

func main() {
	span, ctx := tracer.StartSpanFromContext(context.Background(), "mainOp")
	defer span.Finish()

	go func() {
		asyncSpan := tracer.StartSpanFromContext(ctx, "asyncOp")
		defer asyncSpan.Finish()
		performOp()
	}()
}

Использование трейсера вместе с OpenTracing

package main

import (
	opentracing "github.com/opentracing/opentracing-go"

	"git.proto.group/protoobp/pobp-trace-go/pobptrace/opentracer"
	"git.proto.group/protoobp/pobp-trace-go/pobptrace/tracer"
)

func main() {
	//Запускаем POBP tracer, опционально передаем опции (лучше все определить через переменные окружения),
	// возвращем opentracing.Tracer который оборачивает его.
	t := opentracer.New(tracer.WithAgentAddr("host:port"))
	defer tracer.Stop() // не забываем останавливать, иначе трейсы не придут

	// Используем с Opentracing API. Уже запущенный POBP tracer
	// может быть использован параллельно с Opentracing API если нужно.
	opentracing.SetGlobalTracer(t)
}