feat: add otel attrs

This commit is contained in:
Kevin Franklin Kim 2025-10-06 10:37:43 +02:00
parent dac0212e09
commit d709caae3d
No known key found for this signature in database
3 changed files with 81 additions and 37 deletions

View File

@ -10,6 +10,7 @@ import (
otelpyroscope "github.com/grafana/otel-profiling-go"
"github.com/grafana/pyroscope-go"
"go.opentelemetry.io/otel"
semconv "go.opentelemetry.io/otel/semconv/v1.37.0"
)
func NewProfiler(ctx context.Context) (*pyroscope.Profiler, error) {
@ -18,14 +19,6 @@ func NewProfiler(ctx context.Context) (*pyroscope.Profiler, error) {
tags["pod"] = v
}
if v := os.Getenv("OTEL_SERVICE_GIT_REF"); v != "" {
tags["service_git_ref"] = v
}
if v := os.Getenv("OTEL_SERVICE_REPOSITORY"); v != "" {
tags["service_repository"] = v
}
if v := os.Getenv("OTEL_SERVICE_ROOT_PATH"); v != "" {
tags["service_root_path"] = v
}
@ -68,12 +61,21 @@ func NewProfiler(ctx context.Context) (*pyroscope.Profiler, error) {
return nil, err
}
for _, value := range resource.Attributes() {
if value.Key == "service.name" {
for _, attr := range resource.Attributes() {
var (
key string
)
switch attr.Key {
case "service.name":
continue
case semconv.VCSRefHeadRevisionKey:
key = "service_git_ref"
case semconv.VCSRepositoryURLFullKey:
key = "service_repository"
default:
key = strings.ReplaceAll(string(attr.Key), ".", "_")
}
tags[strings.ReplaceAll(string(value.Key), ".", "_")] = value.Value.Emit()
tags[key] = attr.Value.Emit()
}
p, err := pyroscope.Start(pyroscope.Config{

View File

@ -2,15 +2,39 @@ package telemetry
import (
"context"
"os"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/sdk/resource"
semconv "go.opentelemetry.io/otel/semconv/v1.37.0"
)
// NewResource creates and returns a default resource for telemetry data, using the provided context.
func NewResource(ctx context.Context) (*resource.Resource, error) {
var attrs []attribute.KeyValue
envs := map[attribute.Key][]string{
semconv.VCSRepositoryNameKey: {"REPO_NAME", "GIT_REPOSITORY_NAME", "GITHUB_REPOSITORY_NAME", "GIT_OTEL_VCS_REPOSITORY_NAME"},
semconv.VCSRepositoryURLFullKey: {"REPO_URL", "GIT_REPOSITORY_URL", "GITHUB_REPOSITORY", "OTEL_VCS_REPOSITORY_URL_FULL"},
semconv.VCSRefBaseNameKey: {"OTEL_VCS_BASE_NAME"},
semconv.VCSRefBaseRevisionKey: {"OTEL_VCS_BASE_REVSION"},
semconv.VCSRefBaseTypeKey: {"OTEL_VCS_BASE_TYPE"},
semconv.VCSRefHeadNameKey: {"GIT_BRANCH", "OTEL_VCS_HEAD_NAME"},
semconv.VCSRefHeadRevisionKey: {"GIT_COMMIT_HASH", "OTEL_VCS_HEAD_REVSION"},
semconv.VCSRefHeadTypeKey: {"OTEL_VCS_HEAD_TYPE"},
}
for k, keys := range envs {
for _, key := range keys {
if v := os.Getenv(key); v != "" {
attrs = append(attrs, k.String(v))
break
}
}
}
return resource.New(ctx,
resource.WithFromEnv(),
resource.WithSchemaURL(semconv.SchemaURL),
resource.WithAttributes(attrs...),
)
}

View File

@ -2,46 +2,53 @@ package telemetry
import (
"context"
"errors"
"net/http"
"runtime"
"strings"
"github.com/grafana/pyroscope-go"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
semconv "go.opentelemetry.io/otel/semconv/v1.37.0"
"go.opentelemetry.io/otel/trace"
)
// Deprecated: use StartFunc instead.
func Start(ctx context.Context, spanName string, opts ...trace.SpanStartOption) (context.Context, trace.Span) {
return Tracer().Start(ctx, spanName, opts...) //nolint:spancheck
}
func Span(ctx context.Context, handler func(ctx context.Context, span trace.Span) error) (err error) { //nolint:nonamedreturns
name := "unknown"
pc, _, _, ok := runtime.Caller(1)
if ok {
details := runtime.FuncForPC(pc)
if details != nil {
name = details.Name()
func StartFunc(ctx context.Context) (context.Context, func(errs ...error)) {
name := "FUNC"
var attrs []attribute.KeyValue
if pc, file, line, ok := runtime.Caller(1); ok {
attrs = append(attrs,
semconv.CodeLineNumber(line),
semconv.CodeFilePath(file),
)
if details := runtime.FuncForPC(pc); details != nil {
funcName := details.Name()
attrs = append(attrs, semconv.CodeFunctionName(funcName))
lastSlash := strings.LastIndexByte(funcName, '/')
if lastSlash < 0 {
lastSlash = 0
}
lastDot := strings.LastIndexByte(funcName[lastSlash:], '.') + lastSlash
name += " " + funcName[lastDot+1:]
}
}
pyroscope.TagWrapper(ctx, pyroscope.Labels("span_name", name), func(c context.Context) {
ctx, span := Tracer().Start(ctx, name)
defer func() {
if err != nil {
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
}
span.End()
}()
err = handler(ctx, span)
})
return
ctx, span := Tracer().Start(ctx, name, trace.WithAttributes(attrs...))
span.SetStatus(codes.Ok, "")
return ctx, end(span)
}
func StartFuncRequest(r *http.Request) (*http.Request, func(errs ...error)) {
ctx, end := StartFunc(r.Context())
return r.WithContext(ctx), end
}
// Deprecated: use StartFunc instead.
func End(sp trace.Span, err error) {
sp.SetStatus(codes.Ok, "")
@ -52,3 +59,14 @@ func End(sp trace.Span, err error) {
sp.End()
}
func end(span trace.Span) func(errs ...error) {
return func(errs ...error) {
if len(errs) > 0 {
err := errors.Join(errs...)
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
}
span.End()
}
}