tstor/src/telemetry/setup.go

204 lines
5.3 KiB
Go
Raw Normal View History

2024-03-19 21:30:37 +00:00
package telemetry
import (
"context"
2024-04-06 13:50:43 +00:00
"fmt"
2024-03-19 21:30:37 +00:00
"log/slog"
"os"
2024-04-06 13:50:43 +00:00
"runtime"
2024-03-19 21:30:37 +00:00
"git.kmsign.ru/royalcat/tstor/pkg/rlog"
"github.com/agoda-com/opentelemetry-go/otelslog"
"github.com/agoda-com/opentelemetry-logs-go/exporters/otlp/otlplogs"
2024-06-02 21:20:43 +00:00
"github.com/agoda-com/opentelemetry-logs-go/exporters/otlp/otlplogs/otlplogshttp"
2024-03-19 21:30:37 +00:00
logsdk "github.com/agoda-com/opentelemetry-logs-go/sdk/logs"
2024-04-06 13:50:43 +00:00
otelpyroscope "github.com/grafana/otel-profiling-go"
"github.com/grafana/pyroscope-go"
2024-03-19 21:30:37 +00:00
"go.opentelemetry.io/otel"
2024-06-02 21:20:43 +00:00
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp"
2024-03-19 21:30:37 +00:00
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
"go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/resource"
"go.opentelemetry.io/otel/sdk/trace"
2024-06-02 21:20:43 +00:00
semconv "go.opentelemetry.io/otel/semconv/v1.25.0"
2024-03-19 21:30:37 +00:00
)
type Client struct {
2024-04-17 08:36:14 +00:00
log *rlog.Logger
2024-03-19 21:30:37 +00:00
tracerProvider *trace.TracerProvider
metricProvider *metric.MeterProvider
loggerProvider *logsdk.LoggerProvider
}
func (client *Client) Shutdown(ctx context.Context) {
if client.metricProvider == nil {
err := client.metricProvider.Shutdown(ctx)
if err != nil {
2024-04-17 08:36:14 +00:00
client.log.Error(ctx, "error shutting down metric provider", rlog.Error(err))
2024-03-19 21:30:37 +00:00
}
}
if client.tracerProvider == nil {
err := client.tracerProvider.Shutdown(ctx)
if err != nil {
2024-04-17 08:36:14 +00:00
client.log.Error(ctx, "error shutting down tracer provider", rlog.Error(err))
2024-03-19 21:30:37 +00:00
}
}
if client.loggerProvider == nil {
err := client.loggerProvider.Shutdown(ctx)
if err != nil {
2024-04-17 08:36:14 +00:00
client.log.Error(ctx, "error shutting down logger provider", rlog.Error(err))
2024-03-19 21:30:37 +00:00
}
}
}
const appName = "tstor"
func Setup(ctx context.Context, endpoint string) (*Client, error) {
client := &Client{
2024-05-13 16:56:20 +00:00
log: rlog.Component("telemetry"),
2024-03-19 21:30:37 +00:00
}
otel.SetErrorHandler(otel.ErrorHandlerFunc(func(cause error) {
2024-05-13 16:56:20 +00:00
client.log.Error(context.Background(), "otel error", rlog.Error(cause))
2024-03-19 21:30:37 +00:00
}))
hostName, _ := os.Hostname()
r, err := resource.Merge(
resource.Default(),
resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceName(appName),
semconv.HostName(hostName),
),
)
if err != nil {
return nil, err
}
2024-06-02 21:20:43 +00:00
meticExporter, err := otlpmetrichttp.New(ctx,
otlpmetrichttp.WithEndpoint(endpoint),
otlpmetrichttp.WithRetry(otlpmetrichttp.RetryConfig{
2024-04-17 08:36:14 +00:00
Enabled: false,
}),
)
2024-03-19 21:30:37 +00:00
if err != nil {
return nil, err
}
2024-04-17 08:36:14 +00:00
2024-03-19 21:30:37 +00:00
client.metricProvider = metric.NewMeterProvider(
2024-04-17 08:36:14 +00:00
metric.WithReader(metric.NewPeriodicReader(meticExporter)),
2024-03-19 21:30:37 +00:00
metric.WithResource(r),
)
otel.SetMeterProvider(client.metricProvider)
2024-05-13 16:56:20 +00:00
var meter = otel.Meter("git.kmsign.ru/royalcat/tstor/pkg/telemetry")
counter, err := meter.Int64Counter("up")
if err != nil {
return nil, err
}
counter.Add(ctx, 1)
client.log.Info(ctx, "metrics provider initialized")
2024-03-19 21:30:37 +00:00
traceExporter, err := otlptracehttp.New(ctx,
otlptracehttp.WithEndpoint(endpoint),
otlptracehttp.WithRetry(otlptracehttp.RetryConfig{
Enabled: false,
}),
)
if err != nil {
return nil, err
}
client.tracerProvider = trace.NewTracerProvider(
trace.WithBatcher(traceExporter),
trace.WithResource(r),
)
2024-04-06 13:50:43 +00:00
otel.SetTracerProvider(otelpyroscope.NewTracerProvider(client.tracerProvider))
2024-05-13 16:56:20 +00:00
client.log.Info(ctx, "tracing provider initialized")
2024-03-19 21:30:37 +00:00
logExporter, err := otlplogs.NewExporter(ctx,
otlplogs.WithClient(
2024-06-02 21:20:43 +00:00
otlplogshttp.NewClient(
otlplogshttp.WithEndpoint(endpoint),
2024-05-13 16:56:20 +00:00
),
2024-03-19 21:30:37 +00:00
),
)
if err != nil {
return nil, err
}
client.loggerProvider = logsdk.NewLoggerProvider(
logsdk.WithBatcher(logExporter),
logsdk.WithResource(r),
)
rlog.AddHandler(otelslog.NewOtelHandler(client.loggerProvider,
&otelslog.HandlerOptions{
Level: slog.LevelDebug,
}),
)
2024-05-13 16:56:20 +00:00
client.log.Info(ctx, "logger provider initialized")
// recreate telemetry logger
client.log = rlog.Component("telemetry")
2024-03-19 21:30:37 +00:00
2024-06-14 22:14:44 +00:00
runtime.SetMutexProfileFraction(5)
runtime.SetBlockProfileRate(5)
_, err = pyroscope.Start(pyroscope.Config{
ApplicationName: appName,
// replace this with the address of pyroscope server
ServerAddress: "https://pyroscope.kmsign.ru",
// you can disable logging by setting this to nil
Logger: &pyroscopeLogger{
log: client.log.WithComponent("pyroscope"),
},
ProfileTypes: []pyroscope.ProfileType{
// these profile types are enabled by default:
pyroscope.ProfileCPU,
pyroscope.ProfileAllocObjects,
pyroscope.ProfileAllocSpace,
pyroscope.ProfileInuseObjects,
pyroscope.ProfileInuseSpace,
// these profile types are optional:
// pyroscope.ProfileGoroutines,
// pyroscope.ProfileMutexCount,
// pyroscope.ProfileMutexDuration,
// pyroscope.ProfileBlockCount,
// pyroscope.ProfileBlockDuration,
},
})
if err != nil {
return client, nil
}
2024-04-06 13:50:43 +00:00
2024-03-19 21:30:37 +00:00
return client, nil
}
2024-04-06 13:50:43 +00:00
type pyroscopeLogger struct {
2024-04-17 08:36:14 +00:00
log *rlog.Logger
2024-04-06 13:50:43 +00:00
}
var _ pyroscope.Logger = (*pyroscopeLogger)(nil)
// Debugf implements pyroscope.Logger.
func (p *pyroscopeLogger) Debugf(msg string, args ...any) {
2024-04-17 08:36:14 +00:00
ctx := context.Background()
p.log.Debug(ctx, fmt.Sprintf(msg, args...))
2024-04-06 13:50:43 +00:00
}
// Errorf implements pyroscope.Logger.
func (p *pyroscopeLogger) Errorf(msg string, args ...any) {
2024-04-17 08:36:14 +00:00
ctx := context.Background()
p.log.Error(ctx, fmt.Sprintf(msg, args...))
2024-04-06 13:50:43 +00:00
}
// Infof implements pyroscope.Logger.
func (p *pyroscopeLogger) Infof(msg string, args ...any) {
2024-04-17 08:36:14 +00:00
ctx := context.Background()
p.log.Info(ctx, fmt.Sprintf(msg, args...))
}
func functionName() string {
var pcs [1]uintptr
runtime.Callers(1, pcs[:])
return runtime.FuncForPC(pcs[0]).Name()
2024-04-06 13:50:43 +00:00
}