Skip to content

Commit

Permalink
Discover service names from process env vars
Browse files Browse the repository at this point in the history
  • Loading branch information
grcevski committed Sep 23, 2024
1 parent c3901b2 commit 7e3b203
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 12 deletions.
2 changes: 1 addition & 1 deletion pkg/export/alloy/traces.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,14 @@ func (tr *tracesReceiver) provideLoop() (pipe.FinalFunc[[]request.Span], error)
if err != nil {
slog.Error("error fetching user defined attributes", "error", err)
}
envResourceAttrs := otel.ResourceAttrsFromEnv()

for spans := range in {
for i := range spans {
span := &spans[i]
if tr.spanDiscarded(span) {
continue
}
envResourceAttrs := otel.ResourceAttrsFromEnv(&span.ServiceID)

for _, tc := range tr.cfg.Traces {
traces := otel.GenerateTraces(span, tr.hostID, traceAttrs, envResourceAttrs)
Expand Down
19 changes: 14 additions & 5 deletions pkg/export/otel/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ func headersFromEnv(varName string) map[string]string {
headers[k] = v
}

parseOTELEnvVar(varName, addToMap)
parseOTELEnvVar(nil, varName, addToMap)

return headers
}
Expand All @@ -352,8 +352,17 @@ type varHandler func(k string, v string)
// OTEL_RESOURCE_ATTRIBUTES, i.e. a comma-separated list of
// key=values. For example: api-key=key,other-config-value=value
// The values are passed as parameters to the handler function
func parseOTELEnvVar(varName string, handler varHandler) {
envVar, ok := os.LookupEnv(varName)
func parseOTELEnvVar(svc *svc.ID, varName string, handler varHandler) {
var envVar string
ok := false

if svc.EnvVars != nil {
envVar, ok = svc.EnvVars[varName]
}

if !ok {
envVar, ok = os.LookupEnv(varName)
}

if !ok {
return
Expand All @@ -379,12 +388,12 @@ func parseOTELEnvVar(varName string, handler varHandler) {
}
}

func ResourceAttrsFromEnv() []attribute.KeyValue {
func ResourceAttrsFromEnv(svc *svc.ID) []attribute.KeyValue {
var otelResourceAttrs []attribute.KeyValue
apply := func(k string, v string) {
otelResourceAttrs = append(otelResourceAttrs, attribute.String(k, v))
}

parseOTELEnvVar(envResourceAttrs, apply)
parseOTELEnvVar(svc, envResourceAttrs, apply)
return otelResourceAttrs
}
4 changes: 2 additions & 2 deletions pkg/export/otel/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func TestParseOTELEnvVar(t *testing.T) {

assert.NoError(t, err)

parseOTELEnvVar(dummyVar, apply)
parseOTELEnvVar(nil, dummyVar, apply)

assert.True(t, reflect.DeepEqual(actual, tc.expected))

Expand All @@ -141,7 +141,7 @@ func TestParseOTELEnvVar_nil(t *testing.T) {
actual[k] = v
}

parseOTELEnvVar("NOT_SET_VAR", apply)
parseOTELEnvVar(nil, "NOT_SET_VAR", apply)

assert.True(t, reflect.DeepEqual(actual, map[string]string{}))
}
2 changes: 1 addition & 1 deletion pkg/export/otel/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ func (mr *MetricsReporter) setupGraphMeters(m *Metrics, meter instrument.Meter)
func (mr *MetricsReporter) newMetricSet(service *svc.ID) (*Metrics, error) {
mlog := mlog().With("service", service)
mlog.Debug("creating new Metrics reporter")
resourceAttributes := append(getAppResourceAttrs(mr.hostID, service), ResourceAttrsFromEnv()...)
resourceAttributes := append(getAppResourceAttrs(mr.hostID, service), ResourceAttrsFromEnv(service)...)
resources := resource.NewWithAttributes(semconv.SchemaURL, resourceAttributes...)

opts := []metric.Option{
Expand Down
3 changes: 1 addition & 2 deletions pkg/export/otel/traces.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,14 +198,13 @@ func (tr *tracesOTELReceiver) provideLoop() (pipe.FinalFunc[[]request.Span], err
return
}

envResourceAttrs := ResourceAttrsFromEnv()

for spans := range in {
for i := range spans {
span := &spans[i]
if tr.spanDiscarded(span) {
continue
}
envResourceAttrs := ResourceAttrsFromEnv(&span.ServiceID)
traces := GenerateTraces(span, tr.ctxInfo.HostID, traceAttrs, envResourceAttrs)
err := exp.ConsumeTraces(tr.ctx, traces)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion pkg/export/otel/traces_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,7 @@ func TestGenerateTracesAttributes(t *testing.T) {
defer restoreEnvAfterExecution()()
require.NoError(t, os.Setenv(envResourceAttrs, "deployment.environment=productions,source.upstream=beyla"))
span := request.Span{Type: request.EventTypeHTTP, Method: "GET", Route: "/test", Status: 200}
traces := GenerateTraces(&span, "host-id", map[attr.Name]struct{}{}, ResourceAttrsFromEnv())
traces := GenerateTraces(&span, "host-id", map[attr.Name]struct{}{}, ResourceAttrsFromEnv(&span.ServiceID))

assert.Equal(t, 1, traces.ResourceSpans().Len())
rs := traces.ResourceSpans().At(0)
Expand Down
16 changes: 16 additions & 0 deletions pkg/internal/exec/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ type FileInfo struct {
Ns uint32
}

const (
envServiceName = "OTEL_SERVICE_NAME"
)

func (fi *FileInfo) ExecutableName() string {
parts := strings.Split(fi.CmdExePath, "/")
return parts[len(parts)-1]
Expand Down Expand Up @@ -59,5 +63,17 @@ func FindExecELF(p *services.ProcessInfo, svcID svc.ID) (*FileInfo, error) {
} else {
return nil, err
}

envVars, err := EnvVars(p.Pid)

if err != nil {
return nil, err
}

file.Service.EnvVars = envVars
if svcName, ok := file.Service.EnvVars[envServiceName]; ok {
file.Service.Name = svcName
}

return &file, nil
}
35 changes: 35 additions & 0 deletions pkg/internal/exec/procenv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package exec

import (
"fmt"
"strings"

"github.com/prometheus/procfs"
)

func EnvVars(pid int32) (map[string]string, error) {
proc, err := procfs.NewProc(int(pid))

if err != nil {
return nil, err
}

varsStr, err := proc.Environ()

if err != nil {
return nil, err
}

vars := make(map[string]string, len(varsStr))

for _, s := range varsStr {
parts := strings.Split(s, "=")
if len(parts) == 2 {
vars[parts[0]] = parts[1]
}
}

fmt.Printf("%v\n", vars)

return vars, nil
}
2 changes: 2 additions & 0 deletions pkg/internal/svc/svc.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ type ID struct {
// by other metadata if available (e.g., Pod Name, Node Name, etc...)
HostName string

EnvVars map[string]string

flags idFlags
}

Expand Down

0 comments on commit 7e3b203

Please sign in to comment.