mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Adds support for logs (specify level), metrics (enable metrics and Prometheus /metrics endpoint and traces (jaeger or otlp) for standalone API server. This will allow any grafana core service part of standalone apiserver to use logging, metrics and traces as normal.
145 lines
3.8 KiB
Go
145 lines
3.8 KiB
Go
package tracing
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/grafana/grafana/pkg/setting"
|
|
"go.opentelemetry.io/otel/attribute"
|
|
)
|
|
|
|
type TracingConfig struct {
|
|
enabled string
|
|
Address string
|
|
Propagation string
|
|
CustomAttribs []attribute.KeyValue
|
|
|
|
Sampler string
|
|
SamplerParam float64
|
|
SamplerRemoteURL string
|
|
|
|
ServiceName string
|
|
ServiceVersion string
|
|
}
|
|
|
|
func ProvideTracingConfig(cfg *setting.Cfg) (*TracingConfig, error) {
|
|
return ParseTracingConfig(cfg)
|
|
}
|
|
|
|
func NewEmptyTracingConfig() *TracingConfig {
|
|
return &TracingConfig{
|
|
CustomAttribs: []attribute.KeyValue{},
|
|
}
|
|
}
|
|
|
|
func NewJaegerTracingConfig(address string, propagation string) (*TracingConfig, error) {
|
|
if address == "" {
|
|
return nil, fmt.Errorf("address cannot be empty")
|
|
}
|
|
|
|
cfg := NewEmptyTracingConfig()
|
|
cfg.enabled = jaegerExporter
|
|
cfg.Address = address
|
|
cfg.Propagation = propagation
|
|
return cfg, nil
|
|
}
|
|
|
|
func NewOTLPTracingConfig(address string, propagation string) (*TracingConfig, error) {
|
|
if address == "" {
|
|
return nil, fmt.Errorf("address cannot be empty")
|
|
}
|
|
|
|
cfg := NewEmptyTracingConfig()
|
|
cfg.enabled = otlpExporter
|
|
cfg.Address = address
|
|
cfg.Propagation = propagation
|
|
return cfg, nil
|
|
}
|
|
|
|
func ParseTracingConfig(cfg *setting.Cfg) (*TracingConfig, error) {
|
|
if cfg == nil {
|
|
return nil, fmt.Errorf("cfg cannot be nil")
|
|
}
|
|
tc := NewEmptyTracingConfig()
|
|
tc.ServiceName = "grafana"
|
|
tc.ServiceVersion = cfg.BuildVersion
|
|
|
|
legacyAddress, legacyTags := "", ""
|
|
if section, err := cfg.Raw.GetSection("tracing.jaeger"); err == nil {
|
|
legacyAddress = section.Key("address").MustString("")
|
|
if legacyAddress == "" {
|
|
host, port := os.Getenv(envJaegerAgentHost), os.Getenv(envJaegerAgentPort)
|
|
if host != "" || port != "" {
|
|
legacyAddress = fmt.Sprintf("%s:%s", host, port)
|
|
}
|
|
}
|
|
legacyTags = section.Key("always_included_tag").MustString("")
|
|
tc.Sampler = section.Key("sampler_type").MustString("")
|
|
tc.SamplerParam = section.Key("sampler_param").MustFloat64(1)
|
|
tc.SamplerRemoteURL = section.Key("sampling_server_url").MustString("")
|
|
}
|
|
section := cfg.Raw.Section("tracing.opentelemetry")
|
|
var err error
|
|
// we default to legacy tag set (attributes) if the new config format is absent
|
|
tc.CustomAttribs, err = splitCustomAttribs(section.Key("custom_attributes").MustString(legacyTags))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// if sampler_type is set in tracing.opentelemetry, we ignore the config in tracing.jaeger
|
|
sampler := section.Key("sampler_type").MustString("")
|
|
if sampler != "" {
|
|
tc.Sampler = sampler
|
|
}
|
|
|
|
samplerParam := section.Key("sampler_param").MustFloat64(0)
|
|
if samplerParam != 0 {
|
|
tc.SamplerParam = samplerParam
|
|
}
|
|
|
|
samplerRemoteURL := section.Key("sampling_server_url").MustString("")
|
|
if samplerRemoteURL != "" {
|
|
tc.SamplerRemoteURL = samplerRemoteURL
|
|
}
|
|
|
|
section = cfg.Raw.Section("tracing.opentelemetry.jaeger")
|
|
tc.enabled = noopExporter
|
|
|
|
// we default to legacy Jaeger agent address if the new config value is empty
|
|
tc.Address = section.Key("address").MustString(legacyAddress)
|
|
tc.Propagation = section.Key("propagation").MustString("")
|
|
if tc.Address != "" {
|
|
tc.enabled = jaegerExporter
|
|
return tc, nil
|
|
}
|
|
|
|
section = cfg.Raw.Section("tracing.opentelemetry.otlp")
|
|
tc.Address = section.Key("address").MustString("")
|
|
if tc.Address != "" {
|
|
tc.enabled = otlpExporter
|
|
}
|
|
tc.Propagation = section.Key("propagation").MustString("")
|
|
return tc, nil
|
|
}
|
|
|
|
func (tc TracingConfig) OTelExporterEnabled() bool {
|
|
return tc.enabled == otlpExporter
|
|
}
|
|
|
|
func splitCustomAttribs(s string) ([]attribute.KeyValue, error) {
|
|
res := []attribute.KeyValue{}
|
|
|
|
attribs := strings.Split(s, ",")
|
|
for _, v := range attribs {
|
|
parts := strings.SplitN(v, ":", 2)
|
|
if len(parts) > 1 {
|
|
res = append(res, attribute.String(parts[0], parts[1]))
|
|
} else if v != "" {
|
|
return nil, fmt.Errorf("custom attribute malformed - must be in 'key:value' form: %q", v)
|
|
}
|
|
}
|
|
|
|
return res, nil
|
|
}
|