forked from kevadesu/forgejo
Open telemetry integration (#3972)
This PR adds opentelemetry and chi wrapper to have basic instrumentation <!--start release-notes-assistant--> ## Draft release notes <!--URL:https://codeberg.org/forgejo/forgejo--> - Features - [PR](https://codeberg.org/forgejo/forgejo/pulls/3972): <!--number 3972 --><!--line 0 --><!--description YWRkIHN1cHBvcnQgZm9yIGJhc2ljIHJlcXVlc3QgdHJhY2luZyB3aXRoIG9wZW50ZWxlbWV0cnk=-->add support for basic request tracing with opentelemetry<!--description--> <!--end release-notes-assistant--> Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3972 Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org> Co-authored-by: TheFox0x7 <thefox0x7@gmail.com> Co-committed-by: TheFox0x7 <thefox0x7@gmail.com>
This commit is contained in:
parent
7c74def6ff
commit
c738542201
19 changed files with 1281 additions and 10 deletions
90
modules/opentelemetry/resource.go
Normal file
90
modules/opentelemetry/resource.go
Normal file
|
@ -0,0 +1,90 @@
|
|||
// Copyright 2024 TheFox0x7. All rights reserved.
|
||||
// SPDX-License-Identifier: EUPL-1.2
|
||||
|
||||
package opentelemetry
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.25.0"
|
||||
)
|
||||
|
||||
const (
|
||||
decoderTelemetrySdk = "sdk"
|
||||
decoderProcess = "process"
|
||||
decoderOS = "os"
|
||||
decoderHost = "host"
|
||||
)
|
||||
|
||||
func newResource(ctx context.Context) (*resource.Resource, error) {
|
||||
opts := []resource.Option{
|
||||
resource.WithAttributes(parseSettingAttributes(setting.OpenTelemetry.ResourceAttributes)...),
|
||||
}
|
||||
opts = append(opts, parseDecoderOpts()...)
|
||||
opts = append(opts, resource.WithAttributes(
|
||||
semconv.ServiceName(setting.OpenTelemetry.ServiceName),
|
||||
semconv.ServiceVersion(setting.ForgejoVersion),
|
||||
))
|
||||
return resource.New(ctx, opts...)
|
||||
}
|
||||
|
||||
func parseDecoderOpts() []resource.Option {
|
||||
var opts []resource.Option
|
||||
for _, v := range strings.Split(setting.OpenTelemetry.ResourceDetectors, ",") {
|
||||
switch v {
|
||||
case decoderTelemetrySdk:
|
||||
opts = append(opts, resource.WithTelemetrySDK())
|
||||
case decoderProcess:
|
||||
opts = append(opts, resource.WithProcess())
|
||||
case decoderOS:
|
||||
opts = append(opts, resource.WithOS())
|
||||
case decoderHost:
|
||||
opts = append(opts, resource.WithHost())
|
||||
case "": // Don't warn on empty string
|
||||
default:
|
||||
log.Warn("Ignoring unknown resource decoder option: %s", v)
|
||||
}
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
func parseSettingAttributes(s string) []attribute.KeyValue {
|
||||
var attrs []attribute.KeyValue
|
||||
rawAttrs := strings.TrimSpace(s)
|
||||
|
||||
if rawAttrs == "" {
|
||||
return attrs
|
||||
}
|
||||
|
||||
pairs := strings.Split(rawAttrs, ",")
|
||||
|
||||
var invalid []string
|
||||
for _, p := range pairs {
|
||||
k, v, found := strings.Cut(p, "=")
|
||||
if !found {
|
||||
invalid = append(invalid, p)
|
||||
continue
|
||||
}
|
||||
key := strings.TrimSpace(k)
|
||||
val, err := url.PathUnescape(strings.TrimSpace(v))
|
||||
if err != nil {
|
||||
// Retain original value if decoding fails, otherwise it will be
|
||||
// an empty string.
|
||||
val = v
|
||||
log.Warn("Otel resource attribute decoding error, retaining unescaped value. key=%s, val=%s", key, val)
|
||||
}
|
||||
attrs = append(attrs, attribute.String(key, val))
|
||||
}
|
||||
if len(invalid) > 0 {
|
||||
log.Warn("Partial resource, missing values: %v", invalid)
|
||||
}
|
||||
|
||||
return attrs
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue