From fb6dbef30a5669830ae336012a80294bde8a06ee Mon Sep 17 00:00:00 2001 From: Mario Macias Date: Sat, 23 Nov 2024 09:25:34 +0100 Subject: [PATCH] Rename svc.ID to svc.Attrs (#1393) --- pkg/export/alloy/traces.go | 4 +- pkg/export/alloy/traces_test.go | 12 +-- pkg/export/debug/debug.go | 12 +-- pkg/export/debug/debug_test.go | 2 +- pkg/export/otel/common.go | 8 +- pkg/export/otel/common_test.go | 2 +- pkg/export/otel/expirer_test.go | 28 +++--- pkg/export/otel/metrics.go | 16 ++-- pkg/export/otel/metrics_proc_test.go | 8 +- pkg/export/otel/metrics_test.go | 32 +++---- pkg/export/otel/traces.go | 8 +- pkg/export/otel/traces_test.go | 68 +++++++------- pkg/export/prom/prom.go | 30 +++---- pkg/export/prom/prom_proc_test.go | 10 +-- pkg/export/prom/prom_test.go | 30 +++---- pkg/internal/discover/attacher.go | 14 +-- pkg/internal/discover/typer.go | 2 +- pkg/internal/ebpf/common/httpfltr_test.go | 12 +-- pkg/internal/ebpf/common/pids.go | 32 +++---- pkg/internal/ebpf/common/pids_test.go | 30 +++---- pkg/internal/ebpf/common/ringbuf_test.go | 22 ++--- .../ebpf/common/tcp_detect_transform_test.go | 2 +- .../ebpf/generictracer/generictracer.go | 2 +- .../generictracer/generictracer_notlinux.go | 2 +- pkg/internal/ebpf/gotracer/gotracer.go | 2 +- pkg/internal/ebpf/httptracer/httptracer.go | 2 +- .../ebpf/httptracer/httptracer_notlinux.go | 2 +- pkg/internal/ebpf/tctracer/tctracer.go | 2 +- .../ebpf/tctracer/tctracer_notlinux.go | 2 +- pkg/internal/ebpf/tracer.go | 6 +- pkg/internal/exec/file.go | 4 +- pkg/internal/infraolly/process/collect.go | 8 +- pkg/internal/infraolly/process/harvest.go | 2 +- .../infraolly/process/harvest_test.go | 10 +-- pkg/internal/infraolly/process/status.go | 4 +- pkg/internal/kube/store_test.go | 90 +++++++++++++++++++ pkg/internal/pipe/instrumenter_test.go | 8 +- pkg/internal/request/metric_attributes.go | 4 +- pkg/internal/request/span.go | 4 +- pkg/internal/request/span_getters.go | 24 ++--- pkg/internal/request/span_test.go | 36 ++++---- pkg/internal/svc/svc.go | 27 +++--- pkg/internal/svc/svc_test.go | 4 +- pkg/internal/traces/read_decorator.go | 4 +- pkg/internal/traces/read_decorator_test.go | 4 +- pkg/transform/k8s.go | 20 ++--- pkg/transform/k8s_test.go | 62 ++++++------- pkg/transform/name_resolver.go | 18 ++-- pkg/transform/name_resolver_test.go | 26 +++--- 49 files changed, 426 insertions(+), 337 deletions(-) diff --git a/pkg/export/alloy/traces.go b/pkg/export/alloy/traces.go index 55ff700d0..17553ab1e 100644 --- a/pkg/export/alloy/traces.go +++ b/pkg/export/alloy/traces.go @@ -31,7 +31,7 @@ type tracesReceiver struct { } func (tr *tracesReceiver) spanDiscarded(span *request.Span) bool { - return span.IgnoreTraces() || span.ServiceID.ExportsOTelTraces() + return span.IgnoreTraces() || span.Service.ExportsOTelTraces() } func (tr *tracesReceiver) provideLoop() (pipe.FinalFunc[[]request.Span], error) { @@ -51,7 +51,7 @@ func (tr *tracesReceiver) provideLoop() (pipe.FinalFunc[[]request.Span], error) if tr.spanDiscarded(span) { continue } - envResourceAttrs := otel.ResourceAttrsFromEnv(&span.ServiceID) + envResourceAttrs := otel.ResourceAttrsFromEnv(&span.Service) for _, tc := range tr.cfg.Traces { traces := otel.GenerateTraces(span, tr.hostID, traceAttrs, envResourceAttrs) diff --git a/pkg/export/alloy/traces_test.go b/pkg/export/alloy/traces_test.go index 35bec48b7..21cefbdd1 100644 --- a/pkg/export/alloy/traces_test.go +++ b/pkg/export/alloy/traces_test.go @@ -16,12 +16,12 @@ import ( ) func TestTracesSkipsInstrumented(t *testing.T) { - svcNoExport := svc.ID{} + svcNoExport := svc.Attrs{} - svcNoExportTraces := svc.ID{} + svcNoExportTraces := svc.Attrs{} svcNoExportTraces.SetExportsOTelMetrics() - svcExportTraces := svc.ID{} + svcExportTraces := svc.Attrs{} svcExportTraces.SetExportsOTelTraces() tests := []struct { @@ -31,17 +31,17 @@ func TestTracesSkipsInstrumented(t *testing.T) { }{ { name: "Foo span is not filtered", - spans: []request.Span{{ServiceID: svcNoExport, Type: request.EventTypeHTTPClient, Method: "GET", Route: "/foo", RequestStart: 100, End: 200}}, + spans: []request.Span{{Service: svcNoExport, Type: request.EventTypeHTTPClient, Method: "GET", Route: "/foo", RequestStart: 100, End: 200}}, filtered: false, }, { name: "/v1/metrics span is not filtered", - spans: []request.Span{{ServiceID: svcNoExportTraces, Type: request.EventTypeHTTPClient, Method: "GET", Route: "/v1/metrics", RequestStart: 100, End: 200}}, + spans: []request.Span{{Service: svcNoExportTraces, Type: request.EventTypeHTTPClient, Method: "GET", Route: "/v1/metrics", RequestStart: 100, End: 200}}, filtered: false, }, { name: "/v1/traces span is filtered", - spans: []request.Span{{ServiceID: svcExportTraces, Type: request.EventTypeHTTPClient, Method: "GET", Route: "/v1/traces", RequestStart: 100, End: 200}}, + spans: []request.Span{{Service: svcExportTraces, Type: request.EventTypeHTTPClient, Method: "GET", Route: "/v1/traces", RequestStart: 100, End: 200}}, filtered: true, }, } diff --git a/pkg/export/debug/debug.go b/pkg/export/debug/debug.go index 608fd5516..25ff711c8 100644 --- a/pkg/export/debug/debug.go +++ b/pkg/export/debug/debug.go @@ -83,8 +83,8 @@ func textPrinter(input <-chan []request.Span) { hn := "" if spans[i].IsClientSpan() { - if spans[i].ServiceID.UID.Namespace != "" { - pn = "." + spans[i].ServiceID.UID.Namespace + if spans[i].Service.UID.Namespace != "" { + pn = "." + spans[i].Service.UID.Namespace } if spans[i].OtherNamespace != "" { hn = "." + spans[i].OtherNamespace @@ -93,8 +93,8 @@ func textPrinter(input <-chan []request.Span) { if spans[i].OtherNamespace != "" { pn = "." + spans[i].OtherNamespace } - if spans[i].ServiceID.UID.Namespace != "" { - hn = "." + spans[i].ServiceID.UID.Namespace + if spans[i].Service.UID.Namespace != "" { + hn = "." + spans[i].Service.UID.Namespace } } @@ -111,8 +111,8 @@ func textPrinter(input <-chan []request.Span) { spans[i].Host+" as "+request.SpanHost(&spans[i])+hn, spans[i].HostPort, spans[i].ContentLength, - &spans[i].ServiceID, - spans[i].ServiceID.SDKLanguage.String(), + &spans[i].Service, + spans[i].Service.SDKLanguage.String(), traceparent(&spans[i]), ) } diff --git a/pkg/export/debug/debug_test.go b/pkg/export/debug/debug_test.go index eab27807e..2f06a62f9 100644 --- a/pkg/export/debug/debug_test.go +++ b/pkg/export/debug/debug_test.go @@ -40,7 +40,7 @@ func TestTracePrinterValidEnabled(t *testing.T) { func traceFuncHelper(t *testing.T, tracePrinter TracePrinter) string { fakeSpan := request.Span{ - ServiceID: svc.ID{UID: svc.UID{Name: "bar", Namespace: "foo"}, SDKLanguage: svc.InstrumentableGolang}, + Service: svc.Attrs{UID: svc.UID{Name: "bar", Namespace: "foo"}, SDKLanguage: svc.InstrumentableGolang}, Type: request.EventTypeHTTP, Method: "method", Path: "path", diff --git a/pkg/export/otel/common.go b/pkg/export/otel/common.go index fae9d6d06..833d824e8 100644 --- a/pkg/export/otel/common.go +++ b/pkg/export/otel/common.go @@ -60,13 +60,13 @@ var DefaultBuckets = Buckets{ RequestSizeHistogram: []float64{0, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192}, } -func getAppResourceAttrs(hostID string, service *svc.ID) []attribute.KeyValue { +func getAppResourceAttrs(hostID string, service *svc.Attrs) []attribute.KeyValue { return append(getResourceAttrs(hostID, service), semconv.ServiceInstanceID(service.UID.Instance), ) } -func getResourceAttrs(hostID string, service *svc.ID) []attribute.KeyValue { +func getResourceAttrs(hostID string, service *svc.Attrs) []attribute.KeyValue { attrs := []attribute.KeyValue{ semconv.ServiceName(service.UID.Name), // SpanMetrics requires an extra attribute besides service name @@ -352,7 +352,7 @@ func headersFromEnv(varName string) map[string]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(svc *svc.ID, varName string, handler attributes.VarHandler) { +func parseOTELEnvVar(svc *svc.Attrs, varName string, handler attributes.VarHandler) { var envVar string ok := false @@ -371,7 +371,7 @@ func parseOTELEnvVar(svc *svc.ID, varName string, handler attributes.VarHandler) attributes.ParseOTELResourceVariable(envVar, handler) } -func ResourceAttrsFromEnv(svc *svc.ID) []attribute.KeyValue { +func ResourceAttrsFromEnv(svc *svc.Attrs) []attribute.KeyValue { var otelResourceAttrs []attribute.KeyValue apply := func(k string, v string) { otelResourceAttrs = append(otelResourceAttrs, attribute.String(k, v)) diff --git a/pkg/export/otel/common_test.go b/pkg/export/otel/common_test.go index 1a32caacf..a4d40e592 100644 --- a/pkg/export/otel/common_test.go +++ b/pkg/export/otel/common_test.go @@ -168,7 +168,7 @@ func TestParseOTELEnvVarPerService(t *testing.T) { actual[k] = v } - parseOTELEnvVar(&svc.ID{EnvVars: map[string]string{dummyVar: tc.envVar}}, dummyVar, apply) + parseOTELEnvVar(&svc.Attrs{EnvVars: map[string]string{dummyVar: tc.envVar}}, dummyVar, apply) assert.True(t, reflect.DeepEqual(actual, tc.expected)) }) diff --git a/pkg/export/otel/expirer_test.go b/pkg/export/otel/expirer_test.go index 2def7d7d4..ff0e5589a 100644 --- a/pkg/export/otel/expirer_test.go +++ b/pkg/export/otel/expirer_test.go @@ -126,8 +126,8 @@ func TestNetMetricsExpiration(t *testing.T) { } // the expiration logic is held at two levels: -// (1) by group of attributes within the same service ID, -// (2) by metric set of a given service ID +// (1) by group of attributes within the same service Attrs, +// (2) by metric set of a given service Attrs // this test verifies case 1 func TestAppMetricsExpiration_ByMetricAttrs(t *testing.T) { defer restoreEnvAfterExecution()() @@ -165,8 +165,8 @@ func TestAppMetricsExpiration_ByMetricAttrs(t *testing.T) { // WHEN it receives metrics metrics <- []request.Span{ - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Path: "/foo", RequestStart: 100, End: 200}, - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Path: "/bar", RequestStart: 150, End: 175}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Path: "/foo", RequestStart: 100, End: 200}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Path: "/bar", RequestStart: 150, End: 175}, } // THEN the metrics are exported @@ -189,7 +189,7 @@ func TestAppMetricsExpiration_ByMetricAttrs(t *testing.T) { // AND WHEN it keeps receiving a subset of the initial metrics during the TTL now.Advance(2 * time.Minute) metrics <- []request.Span{ - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Path: "/foo", RequestStart: 250, End: 280}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Path: "/foo", RequestStart: 250, End: 280}, } // THEN THE metrics that have been received during the TTL period are still visible @@ -203,7 +203,7 @@ func TestAppMetricsExpiration_ByMetricAttrs(t *testing.T) { now.Advance(2 * time.Minute) metrics <- []request.Span{ - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Path: "/foo", RequestStart: 300, End: 310}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Path: "/foo", RequestStart: 300, End: 310}, } // makes sure that the records channel is emptied and any remaining @@ -231,7 +231,7 @@ func TestAppMetricsExpiration_ByMetricAttrs(t *testing.T) { // AND WHEN the metrics labels that disappeared are received again now.Advance(2 * time.Minute) metrics <- []request.Span{ - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Path: "/bar", RequestStart: 450, End: 520}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Path: "/bar", RequestStart: 450, End: 520}, } // THEN they are reported again, starting from zero in the case of counters @@ -245,8 +245,8 @@ func TestAppMetricsExpiration_ByMetricAttrs(t *testing.T) { } // the expiration logic is held at two levels: -// (1) by group of attributes within the same service ID, -// (2) by metric set of a given service ID +// (1) by group of attributes within the same service Attrs, +// (2) by metric set of a given service Attrs // this test verifies case 2 func TestAppMetricsExpiration_BySvcID(t *testing.T) { defer restoreEnvAfterExecution()() @@ -284,8 +284,8 @@ func TestAppMetricsExpiration_BySvcID(t *testing.T) { // WHEN it receives metrics metrics <- []request.Span{ - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Path: "/foo", RequestStart: 100, End: 200}, - {ServiceID: svc.ID{UID: svc.UID{Instance: "bar"}}, Type: request.EventTypeHTTP, Path: "/bar", RequestStart: 150, End: 175}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Path: "/foo", RequestStart: 100, End: 200}, + {Service: svc.Attrs{UID: svc.UID{Instance: "bar"}}, Type: request.EventTypeHTTP, Path: "/bar", RequestStart: 150, End: 175}, } // THEN the metrics are exported @@ -308,7 +308,7 @@ func TestAppMetricsExpiration_BySvcID(t *testing.T) { // AND WHEN it keeps receiving a subset of the initial metrics during the TTL now.Advance(2 * time.Minute) metrics <- []request.Span{ - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Path: "/foo", RequestStart: 250, End: 280}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Path: "/foo", RequestStart: 250, End: 280}, } // THEN THE metrics that have been received during the TTL period are still visible @@ -322,7 +322,7 @@ func TestAppMetricsExpiration_BySvcID(t *testing.T) { now.Advance(2 * time.Minute) metrics <- []request.Span{ - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Path: "/foo", RequestStart: 300, End: 310}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Path: "/foo", RequestStart: 300, End: 310}, } // BUT not the metrics that haven't been received during that time. @@ -351,7 +351,7 @@ func TestAppMetricsExpiration_BySvcID(t *testing.T) { // AND WHEN the metrics labels that disappeared are received again now.Advance(2 * time.Minute) metrics <- []request.Span{ - {ServiceID: svc.ID{UID: svc.UID{Instance: "bar"}}, Type: request.EventTypeHTTP, Path: "/bar", RequestStart: 450, End: 520}, + {Service: svc.Attrs{UID: svc.UID{Instance: "bar"}}, Type: request.EventTypeHTTP, Path: "/bar", RequestStart: 450, End: 520}, } // THEN they are reported again, starting from zero in the case of counters diff --git a/pkg/export/otel/metrics.go b/pkg/export/otel/metrics.go index 0f0ced9d6..8edafb392 100644 --- a/pkg/export/otel/metrics.go +++ b/pkg/export/otel/metrics.go @@ -171,7 +171,7 @@ type MetricsReporter struct { hostID string attributes *attributes.AttrSelector exporter metric.Exporter - reporters ReporterPool[*svc.ID, *Metrics] + reporters ReporterPool[*svc.Attrs, *Metrics] is instrumentations.InstrumentationSelection // user-selected fields for each of the reported metrics @@ -190,7 +190,7 @@ type MetricsReporter struct { // There is a Metrics instance for each service/process instrumented by Beyla. type Metrics struct { ctx context.Context - service *svc.ID + service *svc.Attrs provider *metric.MeterProvider // IMPORTANT! Don't forget to clean each Expirer in cleanupAllMetricsInstances method @@ -286,7 +286,7 @@ func newMetricsReporter( request.SpanOTELGetters, mr.attributes.For(attributes.MessagingProcessDuration)) } - mr.reporters = NewReporterPool[*svc.ID, *Metrics](cfg.ReportersCacheLen, cfg.TTL, timeNow, + mr.reporters = NewReporterPool[*svc.Attrs, *Metrics](cfg.ReportersCacheLen, cfg.TTL, timeNow, func(id svc.UID, v *expirable[*Metrics]) { if mr.cfg.SpanMetricsEnabled() { attrOpt := instrument.WithAttributeSet(mr.metricResourceAttributes(v.value.service)) @@ -542,7 +542,7 @@ func (mr *MetricsReporter) setupGraphMeters(m *Metrics, meter instrument.Meter) return nil } -func (mr *MetricsReporter) newMetricSet(service *svc.ID) (*Metrics, error) { +func (mr *MetricsReporter) newMetricSet(service *svc.Attrs) (*Metrics, error) { mlog := mlog().With("service", service) mlog.Debug("creating new Metrics reporter") resourceAttributes := append(getAppResourceAttrs(mr.hostID, service), ResourceAttrsFromEnv(service)...) @@ -707,7 +707,7 @@ func otelHistogramConfig(metricName string, buckets []float64, useExponentialHis } -func (mr *MetricsReporter) metricResourceAttributes(service *svc.ID) attribute.Set { +func (mr *MetricsReporter) metricResourceAttributes(service *svc.Attrs) attribute.Set { attrs := []attribute.KeyValue{ request.ServiceMetric(service.UID.Name), semconv.ServiceInstanceID(service.UID.Instance), @@ -759,7 +759,7 @@ func (mr *MetricsReporter) serviceGraphAttributes() []attributes.Field[*request. } func otelSpanAccepted(span *request.Span, mr *MetricsReporter) bool { - return mr.cfg.OTelMetricsEnabled() && !span.ServiceID.ExportsOTelMetrics() + return mr.cfg.OTelMetricsEnabled() && !span.Service.ExportsOTelMetrics() } // nolint:cyclop @@ -855,10 +855,10 @@ func (mr *MetricsReporter) reportMetrics(input <-chan []request.Span) { if s.IgnoreMetrics() { continue } - reporter, err := mr.reporters.For(&s.ServiceID) + reporter, err := mr.reporters.For(&s.Service) if err != nil { mlog().Error("unexpected error creating OTEL resource. Ignoring metric", - "error", err, "service", s.ServiceID) + "error", err, "service", s.Service) continue } reporter.record(s, mr) diff --git a/pkg/export/otel/metrics_proc_test.go b/pkg/export/otel/metrics_proc_test.go index fef835f88..e90368743 100644 --- a/pkg/export/otel/metrics_proc_test.go +++ b/pkg/export/otel/metrics_proc_test.go @@ -55,13 +55,13 @@ func TestProcMetrics_Aggregated(t *testing.T) { // WHEN it receives process metrics metrics <- []*process.Status{ - {ID: process.ID{Command: "foo", Service: &svc.ID{}, UID: svc.UID{Instance: "foo"}}, + {ID: process.ID{Command: "foo", Service: &svc.Attrs{}, UID: svc.UID{Instance: "foo"}}, CPUUtilisationWait: 3, CPUUtilisationSystem: 2, CPUUtilisationUser: 1, CPUTimeUserDelta: 30, CPUTimeWaitDelta: 20, CPUTimeSystemDelta: 10, IOReadBytesDelta: 123, IOWriteBytesDelta: 456, NetRcvBytesDelta: 11, NetTxBytesDelta: 22, }, - {ID: process.ID{Command: "bar", Service: &svc.ID{}, UID: svc.UID{Instance: "bar"}}, + {ID: process.ID{Command: "bar", Service: &svc.Attrs{}, UID: svc.UID{Instance: "bar"}}, CPUUtilisationWait: 31, CPUUtilisationSystem: 21, CPUUtilisationUser: 11, CPUTimeUserDelta: 301, CPUTimeWaitDelta: 201, CPUTimeSystemDelta: 101, IOReadBytesDelta: 321, IOWriteBytesDelta: 654, @@ -129,7 +129,7 @@ func TestProcMetrics_Aggregated(t *testing.T) { // AND WHEN new metrics are received metrics <- []*process.Status{ - {ID: process.ID{Command: "foo", Service: &svc.ID{}, UID: svc.UID{Instance: "foo"}}, + {ID: process.ID{Command: "foo", Service: &svc.Attrs{}, UID: svc.UID{Instance: "foo"}}, CPUUtilisationWait: 4, CPUUtilisationSystem: 1, CPUUtilisationUser: 2, CPUTimeUserDelta: 3, CPUTimeWaitDelta: 2, CPUTimeSystemDelta: 1, IOReadBytesDelta: 1, IOWriteBytesDelta: 2, @@ -220,7 +220,7 @@ func TestProcMetrics_Disaggregated(t *testing.T) { // WHEN it receives process metrics metrics <- []*process.Status{ - {ID: process.ID{Command: "foo", Service: &svc.ID{}, UID: svc.UID{Instance: "foo"}}, + {ID: process.ID{Command: "foo", Service: &svc.Attrs{}, UID: svc.UID{Instance: "foo"}}, CPUUtilisationWait: 3, CPUUtilisationSystem: 2, CPUUtilisationUser: 1, CPUTimeUserDelta: 30, CPUTimeWaitDelta: 20, CPUTimeSystemDelta: 10, IOReadBytesDelta: 123, IOWriteBytesDelta: 456, diff --git a/pkg/export/otel/metrics_test.go b/pkg/export/otel/metrics_test.go index 34e9a9f76..c23e16eb6 100644 --- a/pkg/export/otel/metrics_test.go +++ b/pkg/export/otel/metrics_test.go @@ -492,15 +492,15 @@ func TestAppMetrics_ByInstrumentation(t *testing.T) { */ // WHEN it receives metrics metrics <- []request.Span{ - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Path: "/foo", RequestStart: 100, End: 200}, - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTPClient, Path: "/bar", RequestStart: 150, End: 175}, - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeGRPC, Path: "/foo", RequestStart: 100, End: 200}, - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeGRPCClient, Path: "/bar", RequestStart: 150, End: 175}, - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeSQLClient, Path: "SELECT", RequestStart: 150, End: 175}, - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeRedisClient, Method: "SET", RequestStart: 150, End: 175}, - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeRedisServer, Method: "GET", RequestStart: 150, End: 175}, - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeKafkaClient, Method: "publish", RequestStart: 150, End: 175}, - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeKafkaServer, Method: "process", RequestStart: 150, End: 175}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Path: "/foo", RequestStart: 100, End: 200}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTPClient, Path: "/bar", RequestStart: 150, End: 175}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeGRPC, Path: "/foo", RequestStart: 100, End: 200}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeGRPCClient, Path: "/bar", RequestStart: 150, End: 175}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeSQLClient, Path: "SELECT", RequestStart: 150, End: 175}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeRedisClient, Method: "SET", RequestStart: 150, End: 175}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeRedisServer, Method: "GET", RequestStart: 150, End: 175}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeKafkaClient, Method: "publish", RequestStart: 150, End: 175}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeKafkaServer, Method: "process", RequestStart: 150, End: 175}, } // Read the exported metrics, add +extraColl for HTTP size metrics @@ -545,7 +545,7 @@ func TestAppMetrics_ResourceAttributes(t *testing.T) { go otelExporter(metrics) metrics <- []request.Span{ - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Path: "/foo", RequestStart: 100, End: 200}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Path: "/foo", RequestStart: 100, End: 200}, } res := readNChan(t, otlp.Records(), 1, timeout) @@ -579,12 +579,12 @@ func TestSpanMetricsDiscarded(t *testing.T) { cfg: &mc, } - svcNoExport := svc.ID{} + svcNoExport := svc.Attrs{} - svcExportMetrics := svc.ID{} + svcExportMetrics := svc.Attrs{} svcExportMetrics.SetExportsOTelMetrics() - svcExportTraces := svc.ID{} + svcExportTraces := svc.Attrs{} svcExportTraces.SetExportsOTelTraces() tests := []struct { @@ -594,17 +594,17 @@ func TestSpanMetricsDiscarded(t *testing.T) { }{ { name: "Foo span is not filtered", - span: request.Span{ServiceID: svcNoExport, Type: request.EventTypeHTTPClient, Method: "GET", Route: "/foo", RequestStart: 100, End: 200}, + span: request.Span{Service: svcNoExport, Type: request.EventTypeHTTPClient, Method: "GET", Route: "/foo", RequestStart: 100, End: 200}, discarded: false, }, { name: "/v1/metrics span is filtered", - span: request.Span{ServiceID: svcExportMetrics, Type: request.EventTypeHTTPClient, Method: "GET", Route: "/v1/metrics", RequestStart: 100, End: 200}, + span: request.Span{Service: svcExportMetrics, Type: request.EventTypeHTTPClient, Method: "GET", Route: "/v1/metrics", RequestStart: 100, End: 200}, discarded: true, }, { name: "/v1/traces span is not filtered", - span: request.Span{ServiceID: svcExportTraces, Type: request.EventTypeHTTPClient, Method: "GET", Route: "/v1/traces", RequestStart: 100, End: 200}, + span: request.Span{Service: svcExportTraces, Type: request.EventTypeHTTPClient, Method: "GET", Route: "/v1/traces", RequestStart: 100, End: 200}, discarded: false, }, } diff --git a/pkg/export/otel/traces.go b/pkg/export/otel/traces.go index 95cde49ed..9caed4af6 100644 --- a/pkg/export/otel/traces.go +++ b/pkg/export/otel/traces.go @@ -170,7 +170,7 @@ func GetUserSelectedAttributes(attrs attributes.Selection) (map[attr.Name]struct } func (tr *tracesOTELReceiver) spanDiscarded(span *request.Span) bool { - return span.IgnoreTraces() || span.ServiceID.ExportsOTelTraces() || !tr.acceptSpan(span) + return span.IgnoreTraces() || span.Service.ExportsOTelTraces() || !tr.acceptSpan(span) } func (tr *tracesOTELReceiver) processSpans(exp exporter.Traces, spans []request.Span, traceAttrs map[attr.Name]struct{}, sampler trace.Sampler) { @@ -197,7 +197,7 @@ func (tr *tracesOTELReceiver) processSpans(exp exporter.Traces, spans []request. continue } - envResourceAttrs := ResourceAttrsFromEnv(&span.ServiceID) + envResourceAttrs := ResourceAttrsFromEnv(&span.Service) traces := GenerateTracesWithAttributes(span, tr.ctxInfo.HostID, finalAttrs, envResourceAttrs) err := exp.ConsumeTraces(tr.ctx, traces) if err != nil { @@ -409,7 +409,7 @@ func getRetrySettings(cfg TracesConfig) configretry.BackOffConfig { return backOffCfg } -func traceAppResourceAttrs(hostID string, service *svc.ID) []attribute.KeyValue { +func traceAppResourceAttrs(hostID string, service *svc.Attrs) []attribute.KeyValue { // TODO: remove? if service.UID == emptyUID { return getAppResourceAttrs(hostID, service) @@ -432,7 +432,7 @@ func GenerateTracesWithAttributes(span *request.Span, hostID string, attrs []att traces := ptrace.NewTraces() rs := traces.ResourceSpans().AppendEmpty() ss := rs.ScopeSpans().AppendEmpty() - resourceAttrs := traceAppResourceAttrs(hostID, &span.ServiceID) + resourceAttrs := traceAppResourceAttrs(hostID, &span.Service) resourceAttrs = append(resourceAttrs, envResourceAttrs...) resourceAttrsMap := attrsToMap(resourceAttrs) resourceAttrsMap.PutStr(string(semconv.OTelLibraryNameKey), reporterName) diff --git a/pkg/export/otel/traces_test.go b/pkg/export/otel/traces_test.go index 4bc863e0f..295b9afa1 100644 --- a/pkg/export/otel/traces_test.go +++ b/pkg/export/otel/traces_test.go @@ -594,7 +594,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(&span.ServiceID)) + traces := GenerateTraces(&span, "host-id", map[attr.Name]struct{}{}, ResourceAttrsFromEnv(&span.Service)) assert.Equal(t, 1, traces.ResourceSpans().Len()) rs := traces.ResourceSpans().At(0) @@ -615,7 +615,7 @@ func TestTraceSampling(t *testing.T) { Method: "GET", Route: "/test" + strconv.Itoa(i), Status: 200, - ServiceID: svc.ID{}, + Service: svc.Attrs{}, TraceID: randomTraceID(), } spans = append(spans, span) @@ -841,13 +841,13 @@ func TestTracesInstrumentations(t *testing.T) { } spans := []request.Span{ - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Method: "GET", Route: "/foo", RequestStart: 100, End: 200}, - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTPClient, Method: "PUT", Route: "/bar", RequestStart: 150, End: 175}, - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeGRPC, Path: "/grpcFoo", RequestStart: 100, End: 200}, - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeGRPCClient, Path: "/grpcGoo", RequestStart: 150, End: 175}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Method: "GET", Route: "/foo", RequestStart: 100, End: 200}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTPClient, Method: "PUT", Route: "/bar", RequestStart: 150, End: 175}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeGRPC, Path: "/grpcFoo", RequestStart: 100, End: 200}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeGRPCClient, Path: "/grpcGoo", RequestStart: 150, End: 175}, makeSQLRequestSpan("SELECT password FROM credentials WHERE username=\"bill\""), - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeRedisClient, Method: "SET", Path: "redis_db", RequestStart: 150, End: 175}, - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeRedisServer, Method: "GET", Path: "redis_db", RequestStart: 150, End: 175}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeRedisClient, Method: "SET", Path: "redis_db", RequestStart: 150, End: 175}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeRedisServer, Method: "GET", Path: "redis_db", RequestStart: 150, End: 175}, {Type: request.EventTypeKafkaClient, Method: "process", Path: "important-topic", Statement: "test"}, {Type: request.EventTypeKafkaServer, Method: "publish", Path: "important-topic", Statement: "test"}, } @@ -977,16 +977,16 @@ func TestTracesAttrReuse(t *testing.T) { }{ { name: "Reuses the trace attributes, with svc.Instance defined", - span: request.Span{ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Method: "GET", Route: "/foo", RequestStart: 100, End: 200}, + span: request.Span{Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Method: "GET", Route: "/foo", RequestStart: 100, End: 200}, same: true, }, { name: "No Instance, no caching of trace attributes", - span: request.Span{ServiceID: svc.ID{}, Type: request.EventTypeHTTP, Method: "GET", Route: "/foo", RequestStart: 100, End: 200}, + span: request.Span{Service: svc.Attrs{}, Type: request.EventTypeHTTP, Method: "GET", Route: "/foo", RequestStart: 100, End: 200}, same: false, }, { - name: "No ServiceID, no caching of trace attributes", + name: "No Service, no caching of trace attributes", span: request.Span{Type: request.EventTypeHTTP, Method: "GET", Route: "/foo", RequestStart: 100, End: 200}, same: false, }, @@ -994,20 +994,20 @@ func TestTracesAttrReuse(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - attr1 := traceAppResourceAttrs("123", &tt.span.ServiceID) - attr2 := traceAppResourceAttrs("123", &tt.span.ServiceID) + attr1 := traceAppResourceAttrs("123", &tt.span.Service) + attr2 := traceAppResourceAttrs("123", &tt.span.Service) assert.Equal(t, tt.same, &attr1[0] == &attr2[0], tt.name) }) } } func TestTracesSkipsInstrumented(t *testing.T) { - svcNoExport := svc.ID{} + svcNoExport := svc.Attrs{} - svcNoExportTraces := svc.ID{} + svcNoExportTraces := svc.Attrs{} svcNoExportTraces.SetExportsOTelMetrics() - svcExportTraces := svc.ID{} + svcExportTraces := svc.Attrs{} svcExportTraces.SetExportsOTelTraces() tests := []struct { @@ -1017,17 +1017,17 @@ func TestTracesSkipsInstrumented(t *testing.T) { }{ { name: "Foo span is not filtered", - spans: []request.Span{{ServiceID: svcNoExport, Type: request.EventTypeHTTPClient, Method: "GET", Route: "/foo", RequestStart: 100, End: 200}}, + spans: []request.Span{{Service: svcNoExport, Type: request.EventTypeHTTPClient, Method: "GET", Route: "/foo", RequestStart: 100, End: 200}}, filtered: false, }, { name: "/v1/metrics span is not filtered", - spans: []request.Span{{ServiceID: svcNoExportTraces, Type: request.EventTypeHTTPClient, Method: "GET", Route: "/v1/metrics", RequestStart: 100, End: 200}}, + spans: []request.Span{{Service: svcNoExportTraces, Type: request.EventTypeHTTPClient, Method: "GET", Route: "/v1/metrics", RequestStart: 100, End: 200}}, filtered: false, }, { name: "/v1/traces span is filtered", - spans: []request.Span{{ServiceID: svcExportTraces, Type: request.EventTypeHTTPClient, Method: "GET", Route: "/v1/traces", RequestStart: 100, End: 200}}, + spans: []request.Span{{Service: svcExportTraces, Type: request.EventTypeHTTPClient, Method: "GET", Route: "/v1/traces", RequestStart: 100, End: 200}}, filtered: true, }, } @@ -1210,91 +1210,91 @@ func TestHostPeerAttributes(t *testing.T) { }{ { name: "Same namespaces HTTP", - span: request.Span{Type: request.EventTypeHTTP, PeerName: "client", HostName: "server", OtherNamespace: "same", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: request.Span{Type: request.EventTypeHTTP, PeerName: "client", HostName: "server", OtherNamespace: "same", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "client", server: "server", }, { name: "Client in different namespace", - span: request.Span{Type: request.EventTypeHTTP, PeerName: "client", HostName: "server", OtherNamespace: "far", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: request.Span{Type: request.EventTypeHTTP, PeerName: "client", HostName: "server", OtherNamespace: "far", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "client.far", server: "server", }, { name: "Same namespaces for HTTP client", - span: request.Span{Type: request.EventTypeHTTPClient, PeerName: "client", HostName: "server", OtherNamespace: "same", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: request.Span{Type: request.EventTypeHTTPClient, PeerName: "client", HostName: "server", OtherNamespace: "same", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "client", server: "server", }, { name: "Server in different namespace ", - span: request.Span{Type: request.EventTypeHTTPClient, PeerName: "client", HostName: "server", OtherNamespace: "far", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: request.Span{Type: request.EventTypeHTTPClient, PeerName: "client", HostName: "server", OtherNamespace: "far", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "client", server: "server.far", }, { name: "Same namespaces GRPC", - span: request.Span{Type: request.EventTypeGRPC, PeerName: "client", HostName: "server", OtherNamespace: "same", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: request.Span{Type: request.EventTypeGRPC, PeerName: "client", HostName: "server", OtherNamespace: "same", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "client", server: "server", }, { name: "Client in different namespace GRPC", - span: request.Span{Type: request.EventTypeGRPC, PeerName: "client", HostName: "server", OtherNamespace: "far", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: request.Span{Type: request.EventTypeGRPC, PeerName: "client", HostName: "server", OtherNamespace: "far", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "client.far", server: "server", }, { name: "Same namespaces for GRPC client", - span: request.Span{Type: request.EventTypeGRPCClient, PeerName: "client", HostName: "server", OtherNamespace: "same", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: request.Span{Type: request.EventTypeGRPCClient, PeerName: "client", HostName: "server", OtherNamespace: "same", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "client", server: "server", }, { name: "Server in different namespace GRPC", - span: request.Span{Type: request.EventTypeGRPCClient, PeerName: "client", HostName: "server", OtherNamespace: "far", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: request.Span{Type: request.EventTypeGRPCClient, PeerName: "client", HostName: "server", OtherNamespace: "far", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "client", server: "server.far", }, { name: "Same namespaces for SQL client", - span: request.Span{Type: request.EventTypeSQLClient, PeerName: "client", HostName: "server", OtherNamespace: "same", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: request.Span{Type: request.EventTypeSQLClient, PeerName: "client", HostName: "server", OtherNamespace: "same", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "", server: "server", }, { name: "Server in different namespace SQL", - span: request.Span{Type: request.EventTypeSQLClient, PeerName: "client", HostName: "server", OtherNamespace: "far", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: request.Span{Type: request.EventTypeSQLClient, PeerName: "client", HostName: "server", OtherNamespace: "far", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "", server: "server.far", }, { name: "Same namespaces for Redis client", - span: request.Span{Type: request.EventTypeRedisClient, PeerName: "client", HostName: "server", OtherNamespace: "same", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: request.Span{Type: request.EventTypeRedisClient, PeerName: "client", HostName: "server", OtherNamespace: "same", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "", server: "server", }, { name: "Server in different namespace Redis", - span: request.Span{Type: request.EventTypeRedisClient, PeerName: "client", HostName: "server", OtherNamespace: "far", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: request.Span{Type: request.EventTypeRedisClient, PeerName: "client", HostName: "server", OtherNamespace: "far", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "", server: "server.far", }, { name: "Client in different namespace Redis", - span: request.Span{Type: request.EventTypeRedisServer, PeerName: "client", HostName: "server", OtherNamespace: "far", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: request.Span{Type: request.EventTypeRedisServer, PeerName: "client", HostName: "server", OtherNamespace: "far", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "", server: "server", }, { name: "Server in different namespace Kafka", - span: request.Span{Type: request.EventTypeKafkaClient, PeerName: "client", HostName: "server", OtherNamespace: "far", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: request.Span{Type: request.EventTypeKafkaClient, PeerName: "client", HostName: "server", OtherNamespace: "far", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "", server: "server.far", }, { name: "Client in different namespace Kafka", - span: request.Span{Type: request.EventTypeKafkaServer, PeerName: "client", HostName: "server", OtherNamespace: "far", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: request.Span{Type: request.EventTypeKafkaServer, PeerName: "client", HostName: "server", OtherNamespace: "far", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "", server: "server", }, diff --git a/pkg/export/prom/prom.go b/pkg/export/prom/prom.go index 61da41300..f623f97a3 100644 --- a/pkg/export/prom/prom.go +++ b/pkg/export/prom/prom.go @@ -196,7 +196,7 @@ type metricsReporter struct { kubeEnabled bool hostID string - serviceCache *expirable.LRU[svc.UID, svc.ID] + serviceCache *expirable.LRU[svc.UID, svc.Attrs] } func PrometheusEndpoint( @@ -467,7 +467,7 @@ func newReporter( } if cfg.SpanMetricsEnabled() { - mr.serviceCache = expirable.NewLRU(cfg.SpanMetricsServiceCacheSize, func(_ svc.UID, v svc.ID) { + mr.serviceCache = expirable.NewLRU(cfg.SpanMetricsServiceCacheSize, func(_ svc.UID, v svc.Attrs) { lv := mr.labelValuesTargetInfo(v) mr.tracesTargetInfo.WithLabelValues(lv...).metric.Sub(1) }, cfg.TTL) @@ -578,7 +578,7 @@ func (r *metricsReporter) collectMetrics(input <-chan []request.Span) { } func (r *metricsReporter) otelSpanObserved(span *request.Span) bool { - return r.cfg.OTelMetricsEnabled() && !span.ServiceID.ExportsOTelMetrics() + return r.cfg.OTelMetricsEnabled() && !span.Service.ExportsOTelMetrics() } // nolint:cyclop @@ -587,10 +587,10 @@ func (r *metricsReporter) observe(span *request.Span) { return } t := span.Timings() - r.beylaInfo.WithLabelValues(span.ServiceID.SDKLanguage.String()).metric.Set(1.0) + r.beylaInfo.WithLabelValues(span.Service.SDKLanguage.String()).metric.Set(1.0) duration := t.End.Sub(t.RequestStart).Seconds() - targetInfoLabelValues := r.labelValuesTargetInfo(span.ServiceID) + targetInfoLabelValues := r.labelValuesTargetInfo(span.Service) r.targetInfo.WithLabelValues(targetInfoLabelValues...).metric.Set(1) if r.otelSpanObserved(span) { @@ -653,9 +653,9 @@ func (r *metricsReporter) observe(span *request.Span) { r.spanMetricsCallsTotal.WithLabelValues(lv...).metric.Add(1) r.spanMetricsSizeTotal.WithLabelValues(lv...).metric.Add(float64(span.RequestLength())) - _, ok := r.serviceCache.Get(span.ServiceID.UID) + _, ok := r.serviceCache.Get(span.Service.UID) if !ok { - r.serviceCache.Add(span.ServiceID.UID, span.ServiceID) + r.serviceCache.Add(span.Service.UID, span.Service) r.tracesTargetInfo.WithLabelValues(targetInfoLabelValues...).metric.Add(1) } } @@ -682,7 +682,7 @@ func appendK8sLabelNames(names []string) []string { return names } -func appendK8sLabelValuesService(values []string, service svc.ID) []string { +func appendK8sLabelValuesService(values []string, service svc.Attrs) []string { // must follow the order in appendK8sLabelNames values = append(values, service.Metadata[(attr.K8sNamespaceName)], @@ -705,13 +705,13 @@ func labelNamesSpans() []string { func (r *metricsReporter) labelValuesSpans(span *request.Span) []string { return []string{ - span.ServiceID.UID.Name, - span.ServiceID.UID.Namespace, + span.Service.UID.Name, + span.Service.UID.Namespace, span.TraceName(), strconv.Itoa(int(request.SpanStatusCode(span))), span.ServiceGraphKind(), - string(span.ServiceID.UID.Instance), // app instance ID - span.ServiceID.Job(), + span.Service.UID.Instance, // app instance ID + span.Service.Job(), "beyla", } } @@ -726,7 +726,7 @@ func labelNamesTargetInfo(kubeEnabled bool) []string { return names } -func (r *metricsReporter) labelValuesTargetInfo(service svc.ID) []string { +func (r *metricsReporter) labelValuesTargetInfo(service svc.Attrs) []string { values := []string{ r.hostID, service.HostName, @@ -754,7 +754,7 @@ func (r *metricsReporter) labelValuesServiceGraph(span *request.Span) []string { if span.IsClientSpan() { return []string{ request.SpanPeer(span), - span.ServiceID.UID.Namespace, + span.Service.UID.Namespace, request.SpanHost(span), span.OtherNamespace, "beyla", @@ -764,7 +764,7 @@ func (r *metricsReporter) labelValuesServiceGraph(span *request.Span) []string { request.SpanPeer(span), span.OtherNamespace, request.SpanHost(span), - span.ServiceID.UID.Namespace, + span.Service.UID.Namespace, "beyla", } } diff --git a/pkg/export/prom/prom_proc_test.go b/pkg/export/prom/prom_proc_test.go index 8350a6f73..a2612728e 100644 --- a/pkg/export/prom/prom_proc_test.go +++ b/pkg/export/prom/prom_proc_test.go @@ -54,13 +54,13 @@ func TestProcPrometheusEndpoint_AggregatedMetrics(t *testing.T) { // WHEN it receives process metrics metrics <- []*process.Status{ - {ID: process.ID{Service: &svc.ID{}, Command: "foo"}, + {ID: process.ID{Service: &svc.Attrs{}, Command: "foo"}, CPUUtilisationWait: 3, CPUUtilisationSystem: 2, CPUUtilisationUser: 1, CPUTimeUserDelta: 30, CPUTimeWaitDelta: 20, CPUTimeSystemDelta: 10, IOReadBytesDelta: 123, IOWriteBytesDelta: 456, NetRcvBytesDelta: 12, NetTxBytesDelta: 34, }, - {ID: process.ID{Service: &svc.ID{}, Command: "bar"}, + {ID: process.ID{Service: &svc.Attrs{}, Command: "bar"}, CPUUtilisationWait: 31, CPUUtilisationSystem: 21, CPUUtilisationUser: 11, CPUTimeUserDelta: 301, CPUTimeWaitDelta: 201, CPUTimeSystemDelta: 101, IOReadBytesDelta: 321, IOWriteBytesDelta: 654, @@ -83,7 +83,7 @@ func TestProcPrometheusEndpoint_AggregatedMetrics(t *testing.T) { // AND WHEN new metrics are received metrics <- []*process.Status{ - {ID: process.ID{Service: &svc.ID{}, Command: "foo"}, + {ID: process.ID{Service: &svc.Attrs{}, Command: "foo"}, CPUUtilisationWait: 4, CPUUtilisationSystem: 1, CPUUtilisationUser: 2, CPUTimeUserDelta: 3, CPUTimeWaitDelta: 2, CPUTimeSystemDelta: 1, IOReadBytesDelta: 31, IOWriteBytesDelta: 10, @@ -141,7 +141,7 @@ func TestProcPrometheusEndpoint_DisaggregatedMetrics(t *testing.T) { // WHEN it receives process metrics metrics <- []*process.Status{ - {ID: process.ID{Service: &svc.ID{}, Command: "foo"}, + {ID: process.ID{Service: &svc.Attrs{}, Command: "foo"}, CPUUtilisationWait: 3, CPUUtilisationSystem: 2, CPUUtilisationUser: 1, CPUTimeUserDelta: 30, CPUTimeWaitDelta: 20, CPUTimeSystemDelta: 10, IOReadBytesDelta: 123, IOWriteBytesDelta: 456, @@ -166,7 +166,7 @@ func TestProcPrometheusEndpoint_DisaggregatedMetrics(t *testing.T) { // AND WHEN new metrics are received metrics <- []*process.Status{ - {ID: process.ID{Service: &svc.ID{}, Command: "foo"}, + {ID: process.ID{Service: &svc.Attrs{}, Command: "foo"}, CPUUtilisationWait: 4, CPUUtilisationSystem: 1, CPUUtilisationUser: 2, CPUTimeUserDelta: 3, CPUTimeWaitDelta: 2, CPUTimeSystemDelta: 1, IOReadBytesDelta: 3, IOWriteBytesDelta: 2, diff --git a/pkg/export/prom/prom_test.go b/pkg/export/prom/prom_test.go index 2816cf569..ca8302446 100644 --- a/pkg/export/prom/prom_test.go +++ b/pkg/export/prom/prom_test.go @@ -274,15 +274,15 @@ func TestAppMetrics_ByInstrumentation(t *testing.T) { go exporter(metrics) metrics <- []request.Span{ - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Path: "/foo", RequestStart: 100, End: 200}, - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTPClient, Path: "/bar", RequestStart: 150, End: 175}, - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeGRPC, Path: "/foo", RequestStart: 100, End: 200}, - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeGRPCClient, Path: "/bar", RequestStart: 150, End: 175}, - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeSQLClient, Path: "SELECT", RequestStart: 150, End: 175}, - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeRedisClient, Method: "SET", RequestStart: 150, End: 175}, - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeRedisServer, Method: "GET", RequestStart: 150, End: 175}, - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeKafkaClient, Method: "publish", RequestStart: 150, End: 175}, - {ServiceID: svc.ID{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeKafkaServer, Method: "process", RequestStart: 150, End: 175}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTP, Path: "/foo", RequestStart: 100, End: 200}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeHTTPClient, Path: "/bar", RequestStart: 150, End: 175}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeGRPC, Path: "/foo", RequestStart: 100, End: 200}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeGRPCClient, Path: "/bar", RequestStart: 150, End: 175}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeSQLClient, Path: "SELECT", RequestStart: 150, End: 175}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeRedisClient, Method: "SET", RequestStart: 150, End: 175}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeRedisServer, Method: "GET", RequestStart: 150, End: 175}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeKafkaClient, Method: "publish", RequestStart: 150, End: 175}, + {Service: svc.Attrs{UID: svc.UID{Instance: "foo"}}, Type: request.EventTypeKafkaServer, Method: "process", RequestStart: 150, End: 175}, } var exported string @@ -308,12 +308,12 @@ func TestSpanMetricsDiscarded(t *testing.T) { cfg: &mc, } - svcNoExport := svc.ID{} + svcNoExport := svc.Attrs{} - svcExportMetrics := svc.ID{} + svcExportMetrics := svc.Attrs{} svcExportMetrics.SetExportsOTelMetrics() - svcExportTraces := svc.ID{} + svcExportTraces := svc.Attrs{} svcExportTraces.SetExportsOTelTraces() tests := []struct { @@ -323,17 +323,17 @@ func TestSpanMetricsDiscarded(t *testing.T) { }{ { name: "Foo span is not filtered", - span: request.Span{ServiceID: svcNoExport, Type: request.EventTypeHTTPClient, Method: "GET", Route: "/foo", RequestStart: 100, End: 200}, + span: request.Span{Service: svcNoExport, Type: request.EventTypeHTTPClient, Method: "GET", Route: "/foo", RequestStart: 100, End: 200}, discarded: false, }, { name: "/v1/metrics span is filtered", - span: request.Span{ServiceID: svcExportMetrics, Type: request.EventTypeHTTPClient, Method: "GET", Route: "/v1/metrics", RequestStart: 100, End: 200}, + span: request.Span{Service: svcExportMetrics, Type: request.EventTypeHTTPClient, Method: "GET", Route: "/v1/metrics", RequestStart: 100, End: 200}, discarded: true, }, { name: "/v1/traces span is not filtered", - span: request.Span{ServiceID: svcExportTraces, Type: request.EventTypeHTTPClient, Method: "GET", Route: "/v1/traces", RequestStart: 100, End: 200}, + span: request.Span{Service: svcExportTraces, Type: request.EventTypeHTTPClient, Method: "GET", Route: "/v1/traces", RequestStart: 100, End: 200}, discarded: false, }, } diff --git a/pkg/internal/discover/attacher.go b/pkg/internal/discover/attacher.go index 589a65860..23fc892fd 100644 --- a/pkg/internal/discover/attacher.go +++ b/pkg/internal/discover/attacher.go @@ -292,20 +292,20 @@ func (ta *TraceAttacher) monitorPIDs(tracer *ebpf.ProcessTracer, ie *ebpf.Instru if ta.SpanSignalsShortcut != nil { spans := make([]request.Span, 0, len(ie.ChildPids)+1) // the forwarded signal must include - // - ServiceID, which includes several metadata about the process + // - Service, which includes several metadata about the process // - PID namespace, to allow further kubernetes decoration spans = append(spans, request.Span{ - Type: request.EventTypeProcessAlive, - ServiceID: ie.FileInfo.Service, - Pid: request.PidInfo{Namespace: ie.FileInfo.Ns}, + Type: request.EventTypeProcessAlive, + Service: ie.FileInfo.Service, + Pid: request.PidInfo{Namespace: ie.FileInfo.Ns}, }) for _, pid := range ie.ChildPids { service := ie.FileInfo.Service service.ProcPID = int32(pid) spans = append(spans, request.Span{ - Type: request.EventTypeProcessAlive, - ServiceID: service, - Pid: request.PidInfo{Namespace: ie.FileInfo.Ns}, + Type: request.EventTypeProcessAlive, + Service: service, + Pid: request.PidInfo{Namespace: ie.FileInfo.Ns}, }) } ta.SpanSignalsShortcut <- spans diff --git a/pkg/internal/discover/typer.go b/pkg/internal/discover/typer.go index 898a698fc..f6f79e8a1 100644 --- a/pkg/internal/discover/typer.go +++ b/pkg/internal/discover/typer.go @@ -70,7 +70,7 @@ func (t *typer) FilterClassify(evs []Event[ProcessMatch]) []Event[ebpf.Instrumen ev := &evs[i] switch evs[i].Type { case EventCreated: - svcID := svc.ID{ + svcID := svc.Attrs{ UID: svc.UID{ Name: ev.Obj.Criteria.Name, Namespace: ev.Obj.Criteria.Namespace, diff --git a/pkg/internal/ebpf/common/httpfltr_test.go b/pkg/internal/ebpf/common/httpfltr_test.go index 17215af3b..2ca4443a7 100644 --- a/pkg/internal/ebpf/common/httpfltr_test.go +++ b/pkg/internal/ebpf/common/httpfltr_test.go @@ -87,7 +87,7 @@ func TestCstr(t *testing.T) { } func TestToRequestTrace(t *testing.T) { - fltr := TestPidsFilter{services: map[uint32]svc.ID{}} + fltr := TestPidsFilter{services: map[uint32]svc.Attrs{}} var record BPFHTTPInfo record.Type = 1 @@ -117,13 +117,13 @@ func TestToRequestTrace(t *testing.T) { Start: 123456, End: 789012, HostPort: 1, - ServiceID: svc.ID{}, + Service: svc.Attrs{}, } assert.Equal(t, expected, result) } func TestToRequestTraceNoConnection(t *testing.T) { - fltr := TestPidsFilter{services: map[uint32]svc.ID{}} + fltr := TestPidsFilter{services: map[uint32]svc.Attrs{}} var record BPFHTTPInfo record.Type = 1 @@ -153,13 +153,13 @@ func TestToRequestTraceNoConnection(t *testing.T) { End: 789012, Status: 200, HostPort: 7033, - ServiceID: svc.ID{}, + Service: svc.Attrs{}, } assert.Equal(t, expected, result) } func TestToRequestTrace_BadHost(t *testing.T) { - fltr := TestPidsFilter{services: map[uint32]svc.ID{}} + fltr := TestPidsFilter{services: map[uint32]svc.Attrs{}} var record BPFHTTPInfo record.Type = 1 @@ -190,7 +190,7 @@ func TestToRequestTrace_BadHost(t *testing.T) { Start: 123456, End: 789012, HostPort: 0, - ServiceID: svc.ID{}, + Service: svc.Attrs{}, } assert.Equal(t, expected, result) diff --git a/pkg/internal/ebpf/common/pids.go b/pkg/internal/ebpf/common/pids.go index a69a46098..04e0b81d4 100644 --- a/pkg/internal/ebpf/common/pids.go +++ b/pkg/internal/ebpf/common/pids.go @@ -19,7 +19,7 @@ const ( PIDTypeGo ) -var activePids, _ = lru.New[uint32, *svc.ID](1024) +var activePids, _ = lru.New[uint32, *svc.Attrs](1024) // injectable functions (can be replaced in tests). It reads the // current process namespace from the /proc filesystem. It is required to @@ -27,16 +27,16 @@ var activePids, _ = lru.New[uint32, *svc.ID](1024) var readNamespacePIDs = exec.FindNamespacedPids type PIDInfo struct { - service *svc.ID + service *svc.Attrs pidType PIDType } type ServiceFilter interface { - AllowPID(uint32, uint32, *svc.ID, PIDType) + AllowPID(uint32, uint32, *svc.Attrs, PIDType) BlockPID(uint32, uint32) ValidPID(uint32, uint32, PIDType) bool Filter(inputSpans []request.Span) []request.Span - CurrentPIDs(PIDType) map[uint32]map[uint32]svc.ID + CurrentPIDs(PIDType) map[uint32]map[uint32]svc.Attrs } // PIDsFilter keeps a thread-safe copy of the PIDs whose traces are allowed to @@ -78,7 +78,7 @@ func CommonPIDsFilter(c *services.DiscoveryConfig) ServiceFilter { return commonPIDsFilter } -func (pf *PIDsFilter) AllowPID(pid, ns uint32, svc *svc.ID, pidType PIDType) { +func (pf *PIDsFilter) AllowPID(pid, ns uint32, svc *svc.Attrs, pidType PIDType) { pf.mux.Lock() defer pf.mux.Unlock() pf.addPID(pid, ns, svc, pidType) @@ -103,13 +103,13 @@ func (pf *PIDsFilter) ValidPID(userPID, ns uint32, pidType PIDType) bool { return false } -func (pf *PIDsFilter) CurrentPIDs(t PIDType) map[uint32]map[uint32]svc.ID { +func (pf *PIDsFilter) CurrentPIDs(t PIDType) map[uint32]map[uint32]svc.Attrs { pf.mux.RLock() defer pf.mux.RUnlock() - cp := map[uint32]map[uint32]svc.ID{} + cp := map[uint32]map[uint32]svc.Attrs{} for k, v := range pf.current { - cVal := map[uint32]svc.ID{} + cVal := map[uint32]svc.Attrs{} for kv, vv := range v { if vv.pidType == t { cVal[kv] = *vv.service @@ -144,7 +144,7 @@ func (pf *PIDsFilter) Filter(inputSpans []request.Span) []request.Span { if pf.detectOtel { checkIfExportsOTel(info.service, span) } - inputSpans[i].ServiceID = *info.service + inputSpans[i].Service = *info.service outputSpans = append(outputSpans, inputSpans[i]) } } @@ -158,7 +158,7 @@ func (pf *PIDsFilter) Filter(inputSpans []request.Span) []request.Span { return outputSpans } -func (pf *PIDsFilter) addPID(pid, nsid uint32, s *svc.ID, t PIDType) { +func (pf *PIDsFilter) addPID(pid, nsid uint32, s *svc.Attrs, t PIDType) { ns, nsExists := pf.current[nsid] if !nsExists { ns = make(map[uint32]PIDInfo) @@ -195,7 +195,7 @@ type IdentityPidsFilter struct { detectOTel bool } -func (pf *IdentityPidsFilter) AllowPID(_ uint32, _ uint32, _ *svc.ID, _ PIDType) {} +func (pf *IdentityPidsFilter) AllowPID(_ uint32, _ uint32, _ *svc.Attrs, _ PIDType) {} func (pf *IdentityPidsFilter) BlockPID(_ uint32, _ uint32) {} @@ -203,7 +203,7 @@ func (pf *IdentityPidsFilter) ValidPID(_ uint32, _ uint32, _ PIDType) bool { return true } -func (pf *IdentityPidsFilter) CurrentPIDs(_ PIDType) map[uint32]map[uint32]svc.ID { +func (pf *IdentityPidsFilter) CurrentPIDs(_ PIDType) map[uint32]map[uint32]svc.Attrs { return nil } @@ -214,12 +214,12 @@ func (pf *IdentityPidsFilter) Filter(inputSpans []request.Span) []request.Span { if pf.detectOTel { checkIfExportsOTel(svc, s) } - s.ServiceID = *svc + s.Service = *svc } return inputSpans } -func serviceInfo(pid uint32) *svc.ID { +func serviceInfo(pid uint32) *svc.Attrs { cached, ok := activePids.Get(pid) if ok { return cached @@ -227,14 +227,14 @@ func serviceInfo(pid uint32) *svc.ID { name := commName(pid) lang := exec.FindProcLanguage(int32(pid), nil, name) - result := svc.ID{UID: svc.UID{Name: name}, SDKLanguage: lang, ProcPID: int32(pid)} + result := svc.Attrs{UID: svc.UID{Name: name}, SDKLanguage: lang, ProcPID: int32(pid)} activePids.Add(pid, &result) return &result } -func checkIfExportsOTel(svc *svc.ID, span *request.Span) { +func checkIfExportsOTel(svc *svc.Attrs, span *request.Span) { if span.IsExportMetricsSpan() { svc.SetExportsOTelMetrics() } else if span.IsExportTracesSpan() { diff --git a/pkg/internal/ebpf/common/pids_test.go b/pkg/internal/ebpf/common/pids_test.go index 0cddc5779..cca698ad8 100644 --- a/pkg/internal/ebpf/common/pids_test.go +++ b/pkg/internal/ebpf/common/pids_test.go @@ -26,9 +26,9 @@ func TestFilter_SameNS(t *testing.T) { return []uint32{uint32(pid)}, nil } pf := newPIDsFilter(&services.DiscoveryConfig{}, slog.With("env", "testing")) - pf.AllowPID(123, 33, &svc.ID{}, PIDTypeGo) - pf.AllowPID(456, 33, &svc.ID{}, PIDTypeGo) - pf.AllowPID(789, 33, &svc.ID{}, PIDTypeGo) + pf.AllowPID(123, 33, &svc.Attrs{}, PIDTypeGo) + pf.AllowPID(456, 33, &svc.Attrs{}, PIDTypeGo) + pf.AllowPID(789, 33, &svc.Attrs{}, PIDTypeGo) // with the same namespace, it filters by user PID, as it is the PID // that is seen by Beyla's process discovery @@ -44,9 +44,9 @@ func TestFilter_DifferentNS(t *testing.T) { return []uint32{uint32(pid)}, nil } pf := newPIDsFilter(&services.DiscoveryConfig{}, slog.With("env", "testing")) - pf.AllowPID(123, 22, &svc.ID{}, PIDTypeGo) - pf.AllowPID(456, 22, &svc.ID{}, PIDTypeGo) - pf.AllowPID(666, 22, &svc.ID{}, PIDTypeGo) + pf.AllowPID(123, 22, &svc.Attrs{}, PIDTypeGo) + pf.AllowPID(456, 22, &svc.Attrs{}, PIDTypeGo) + pf.AllowPID(666, 22, &svc.Attrs{}, PIDTypeGo) // with the same namespace, it filters by user PID, as it is the PID // that is seen by Beyla's process discovery @@ -58,8 +58,8 @@ func TestFilter_Block(t *testing.T) { return []uint32{uint32(pid)}, nil } pf := newPIDsFilter(&services.DiscoveryConfig{}, slog.With("env", "testing")) - pf.AllowPID(123, 33, &svc.ID{}, PIDTypeGo) - pf.AllowPID(456, 33, &svc.ID{}, PIDTypeGo) + pf.AllowPID(123, 33, &svc.Attrs{}, PIDTypeGo) + pf.AllowPID(456, 33, &svc.Attrs{}, PIDTypeGo) pf.BlockPID(123, 33) // with the same namespace, it filters by user PID, as it is the PID @@ -76,9 +76,9 @@ func TestFilter_NewNSLater(t *testing.T) { return []uint32{uint32(pid)}, nil } pf := newPIDsFilter(&services.DiscoveryConfig{}, slog.With("env", "testing")) - pf.AllowPID(123, 33, &svc.ID{}, PIDTypeGo) - pf.AllowPID(456, 33, &svc.ID{}, PIDTypeGo) - pf.AllowPID(789, 33, &svc.ID{}, PIDTypeGo) + pf.AllowPID(123, 33, &svc.Attrs{}, PIDTypeGo) + pf.AllowPID(456, 33, &svc.Attrs{}, PIDTypeGo) + pf.AllowPID(789, 33, &svc.Attrs{}, PIDTypeGo) // with the same namespace, it filters by user PID, as it is the PID // that is seen by Beyla's process discovery @@ -88,7 +88,7 @@ func TestFilter_NewNSLater(t *testing.T) { {Pid: request.PidInfo{UserPID: 789, HostPID: 234, Namespace: 33}}, }, pf.Filter(spanSet)) - pf.AllowPID(1000, 44, &svc.ID{}, PIDTypeGo) + pf.AllowPID(1000, 44, &svc.Attrs{}, PIDTypeGo) assert.Equal(t, []request.Span{ {Pid: request.PidInfo{UserPID: 123, HostPID: 333, Namespace: 33}}, @@ -114,21 +114,21 @@ func TestFilter_NewNSLater(t *testing.T) { } func TestFilter_ExportsOTelDetection(t *testing.T) { - s := svc.ID{} + s := svc.Attrs{} span := request.Span{Type: request.EventTypeHTTP, Method: "GET", Path: "/random/server/span", RequestStart: 100, End: 200, Status: 200} checkIfExportsOTel(&s, &span) assert.False(t, s.ExportsOTelMetrics()) assert.False(t, s.ExportsOTelTraces()) - s = svc.ID{} + s = svc.Attrs{} span = request.Span{Type: request.EventTypeHTTPClient, Method: "GET", Path: "/v1/metrics", RequestStart: 100, End: 200, Status: 200} checkIfExportsOTel(&s, &span) assert.True(t, s.ExportsOTelMetrics()) assert.False(t, s.ExportsOTelTraces()) - s = svc.ID{} + s = svc.Attrs{} span = request.Span{Type: request.EventTypeHTTPClient, Method: "GET", Path: "/v1/traces", RequestStart: 100, End: 200, Status: 200} checkIfExportsOTel(&s, &span) diff --git a/pkg/internal/ebpf/common/ringbuf_test.go b/pkg/internal/ebpf/common/ringbuf_test.go index 01d6ccfb7..31b193466 100644 --- a/pkg/internal/ebpf/common/ringbuf_test.go +++ b/pkg/internal/ebpf/common/ringbuf_test.go @@ -31,8 +31,8 @@ func TestForwardRingbuf_CapacityFull(t *testing.T) { defer restore() metrics := &metricsReporter{} forwardedMessages := make(chan []request.Span, 100) - fltr := TestPidsFilter{services: map[uint32]svc.ID{}} - fltr.AllowPID(1, 1, &svc.ID{UID: svc.UID{Name: "myService"}}, PIDTypeGo) + fltr := TestPidsFilter{services: map[uint32]svc.Attrs{}} + fltr.AllowPID(1, 1, &svc.Attrs{UID: svc.UID{Name: "myService"}}, PIDTypeGo) go ForwardRingbuf( &config.EPPFTracer{BatchLength: 10}, nil, // the source ring buffer can be null @@ -55,13 +55,13 @@ func TestForwardRingbuf_CapacityFull(t *testing.T) { batch := testutil.ReadChannel(t, forwardedMessages, testTimeout) require.Len(t, batch, 10) for i := range batch { - assert.Equal(t, request.Span{Type: 1, Method: "GET", ContentLength: int64(i), ServiceID: svc.ID{UID: svc.UID{Name: "myService"}}, Pid: request.PidInfo{HostPID: 1}}, batch[i]) + assert.Equal(t, request.Span{Type: 1, Method: "GET", ContentLength: int64(i), Service: svc.Attrs{UID: svc.UID{Name: "myService"}}, Pid: request.PidInfo{HostPID: 1}}, batch[i]) } batch = testutil.ReadChannel(t, forwardedMessages, testTimeout) require.Len(t, batch, 10) for i := range batch { - assert.Equal(t, request.Span{Type: 1, Method: "GET", ContentLength: int64(10 + i), ServiceID: svc.ID{UID: svc.UID{Name: "myService"}}, Pid: request.PidInfo{HostPID: 1}}, batch[i]) + assert.Equal(t, request.Span{Type: 1, Method: "GET", ContentLength: int64(10 + i), Service: svc.Attrs{UID: svc.UID{Name: "myService"}}, Pid: request.PidInfo{HostPID: 1}}, batch[i]) } // AND metrics are properly updated assert.Equal(t, 2, metrics.flushes) @@ -83,8 +83,8 @@ func TestForwardRingbuf_Deadline(t *testing.T) { metrics := &metricsReporter{} forwardedMessages := make(chan []request.Span, 100) - fltr := TestPidsFilter{services: map[uint32]svc.ID{}} - fltr.AllowPID(1, 1, &svc.ID{UID: svc.UID{Name: "myService"}}, PIDTypeGo) + fltr := TestPidsFilter{services: map[uint32]svc.Attrs{}} + fltr.AllowPID(1, 1, &svc.Attrs{UID: svc.UID{Name: "myService"}}, PIDTypeGo) go ForwardRingbuf( &config.EPPFTracer{BatchLength: 10, BatchTimeout: 20 * time.Millisecond}, nil, // the source ring buffer can be null @@ -110,7 +110,7 @@ func TestForwardRingbuf_Deadline(t *testing.T) { } require.Len(t, batch, 7) for i := range batch { - assert.Equal(t, request.Span{Type: 1, Method: "GET", ContentLength: int64(i), ServiceID: svc.ID{UID: svc.UID{Name: "myService"}}, Pid: request.PidInfo{HostPID: 1}}, batch[i]) + assert.Equal(t, request.Span{Type: 1, Method: "GET", ContentLength: int64(i), Service: svc.Attrs{UID: svc.UID{Name: "myService"}}, Pid: request.PidInfo{HostPID: 1}}, batch[i]) } // AND metrics are properly updated @@ -217,10 +217,10 @@ func (m *metricsReporter) TracerFlush(len int) { } type TestPidsFilter struct { - services map[uint32]svc.ID + services map[uint32]svc.Attrs } -func (pf *TestPidsFilter) AllowPID(p uint32, _ uint32, s *svc.ID, _ PIDType) { +func (pf *TestPidsFilter) AllowPID(p uint32, _ uint32, s *svc.Attrs, _ PIDType) { pf.services[p] = *s } @@ -232,14 +232,14 @@ func (pf *TestPidsFilter) ValidPID(_ uint32, _ uint32, _ PIDType) bool { return true } -func (pf *TestPidsFilter) CurrentPIDs(_ PIDType) map[uint32]map[uint32]svc.ID { +func (pf *TestPidsFilter) CurrentPIDs(_ PIDType) map[uint32]map[uint32]svc.Attrs { return nil } func (pf *TestPidsFilter) Filter(inputSpans []request.Span) []request.Span { for i := range inputSpans { s := &inputSpans[i] - s.ServiceID = pf.services[s.Pid.HostPID] + s.Service = pf.services[s.Pid.HostPID] } return inputSpans } diff --git a/pkg/internal/ebpf/common/tcp_detect_transform_test.go b/pkg/internal/ebpf/common/tcp_detect_transform_test.go index 230931257..3179e7bc2 100644 --- a/pkg/internal/ebpf/common/tcp_detect_transform_test.go +++ b/pkg/internal/ebpf/common/tcp_detect_transform_test.go @@ -72,7 +72,7 @@ func TestSQLDetectionFails(t *testing.T) { // Test making sure that issue https://github.com/grafana/beyla/issues/854 is fixed func TestReadTCPRequestIntoSpan_Overflow(t *testing.T) { - fltr := TestPidsFilter{services: map[uint32]svc.ID{}} + fltr := TestPidsFilter{services: map[uint32]svc.Attrs{}} tri := TCPRequestInfo{ Len: 340, diff --git a/pkg/internal/ebpf/generictracer/generictracer.go b/pkg/internal/ebpf/generictracer/generictracer.go index 0ae42a0aa..2e2568cfe 100644 --- a/pkg/internal/ebpf/generictracer/generictracer.go +++ b/pkg/internal/ebpf/generictracer/generictracer.go @@ -114,7 +114,7 @@ func (p *Tracer) rebuildValidPids() { } } -func (p *Tracer) AllowPID(pid, ns uint32, svc *svc.ID) { +func (p *Tracer) AllowPID(pid, ns uint32, svc *svc.Attrs) { p.pidsFilter.AllowPID(pid, ns, svc, ebpfcommon.PIDTypeKProbes) p.rebuildValidPids() } diff --git a/pkg/internal/ebpf/generictracer/generictracer_notlinux.go b/pkg/internal/ebpf/generictracer/generictracer_notlinux.go index 27eef4019..6c15bf27d 100644 --- a/pkg/internal/ebpf/generictracer/generictracer_notlinux.go +++ b/pkg/internal/ebpf/generictracer/generictracer_notlinux.go @@ -22,7 +22,7 @@ import ( type Tracer struct{} func New(_ *beyla.Config, _ imetrics.Reporter) *Tracer { return nil } -func (p *Tracer) AllowPID(_, _ uint32, _ *svc.ID) {} +func (p *Tracer) AllowPID(_, _ uint32, _ *svc.Attrs) {} func (p *Tracer) BlockPID(_, _ uint32) {} func (p *Tracer) Load() (*ebpf.CollectionSpec, error) { return nil, nil } func (p *Tracer) BpfObjects() any { return nil } diff --git a/pkg/internal/ebpf/gotracer/gotracer.go b/pkg/internal/ebpf/gotracer/gotracer.go index 9385cea4d..1b8426c4c 100644 --- a/pkg/internal/ebpf/gotracer/gotracer.go +++ b/pkg/internal/ebpf/gotracer/gotracer.go @@ -56,7 +56,7 @@ func New(cfg *beyla.Config, metrics imetrics.Reporter) *Tracer { } } -func (p *Tracer) AllowPID(pid, ns uint32, svc *svc.ID) { +func (p *Tracer) AllowPID(pid, ns uint32, svc *svc.Attrs) { p.pidsFilter.AllowPID(pid, ns, svc, ebpfcommon.PIDTypeGo) } diff --git a/pkg/internal/ebpf/httptracer/httptracer.go b/pkg/internal/ebpf/httptracer/httptracer.go index d8c9e76bc..961772862 100644 --- a/pkg/internal/ebpf/httptracer/httptracer.go +++ b/pkg/internal/ebpf/httptracer/httptracer.go @@ -43,7 +43,7 @@ func New(cfg *beyla.Config) *Tracer { } } -func (p *Tracer) AllowPID(uint32, uint32, *svc.ID) {} +func (p *Tracer) AllowPID(uint32, uint32, *svc.Attrs) {} func (p *Tracer) BlockPID(uint32, uint32) {} diff --git a/pkg/internal/ebpf/httptracer/httptracer_notlinux.go b/pkg/internal/ebpf/httptracer/httptracer_notlinux.go index 3787a06f9..ddc46a26f 100644 --- a/pkg/internal/ebpf/httptracer/httptracer_notlinux.go +++ b/pkg/internal/ebpf/httptracer/httptracer_notlinux.go @@ -21,7 +21,7 @@ import ( type Tracer struct{} func New(_ *beyla.Config) *Tracer { return nil } -func (p *Tracer) AllowPID(_, _ uint32, _ *svc.ID) {} +func (p *Tracer) AllowPID(_, _ uint32, _ *svc.Attrs) {} func (p *Tracer) BlockPID(_, _ uint32) {} func (p *Tracer) Load() (*ebpf.CollectionSpec, error) { return nil, nil } func (p *Tracer) BpfObjects() any { return nil } diff --git a/pkg/internal/ebpf/tctracer/tctracer.go b/pkg/internal/ebpf/tctracer/tctracer.go index f199a760a..9bc552857 100644 --- a/pkg/internal/ebpf/tctracer/tctracer.go +++ b/pkg/internal/ebpf/tctracer/tctracer.go @@ -43,7 +43,7 @@ func New(cfg *beyla.Config) *Tracer { } } -func (p *Tracer) AllowPID(uint32, uint32, *svc.ID) {} +func (p *Tracer) AllowPID(uint32, uint32, *svc.Attrs) {} func (p *Tracer) BlockPID(uint32, uint32) {} diff --git a/pkg/internal/ebpf/tctracer/tctracer_notlinux.go b/pkg/internal/ebpf/tctracer/tctracer_notlinux.go index b2534a366..f08f27e3e 100644 --- a/pkg/internal/ebpf/tctracer/tctracer_notlinux.go +++ b/pkg/internal/ebpf/tctracer/tctracer_notlinux.go @@ -21,7 +21,7 @@ import ( type Tracer struct{} func New(_ *beyla.Config) *Tracer { return nil } -func (p *Tracer) AllowPID(_, _ uint32, _ *svc.ID) {} +func (p *Tracer) AllowPID(_, _ uint32, _ *svc.Attrs) {} func (p *Tracer) BlockPID(_, _ uint32) {} func (p *Tracer) Load() (*ebpf.CollectionSpec, error) { return nil, nil } func (p *Tracer) BpfObjects() any { return nil } diff --git a/pkg/internal/ebpf/tracer.go b/pkg/internal/ebpf/tracer.go index e35c2df1b..4d3495f3a 100644 --- a/pkg/internal/ebpf/tracer.go +++ b/pkg/internal/ebpf/tracer.go @@ -31,9 +31,9 @@ type PIDsAccounter interface { // AllowPID notifies the tracer to accept traces from the process with the // provided PID. Unless system-wide instrumentation, the Tracer should discard // traces from processes whose PID has not been allowed before - // We must use a pointer for svc.ID so that all child processes share the same + // We must use a pointer for svc.Attrs so that all child processes share the same // object. This is important when we tag a service as exporting traces or metrics. - AllowPID(uint32, uint32, *svc.ID) + AllowPID(uint32, uint32, *svc.Attrs) // BlockPID notifies the tracer to stop accepting traces from the process // with the provided PID. After receiving them via ringbuffer, it should // discard them. @@ -117,7 +117,7 @@ type ProcessTracer struct { Instrumentables map[uint64]*instrumenter } -func (pt *ProcessTracer) AllowPID(pid, ns uint32, svc *svc.ID) { +func (pt *ProcessTracer) AllowPID(pid, ns uint32, svc *svc.Attrs) { for i := range pt.Programs { pt.Programs[i].AllowPID(pid, ns, svc) } diff --git a/pkg/internal/exec/file.go b/pkg/internal/exec/file.go index fe4f0b17c..1ded02b79 100644 --- a/pkg/internal/exec/file.go +++ b/pkg/internal/exec/file.go @@ -14,7 +14,7 @@ import ( ) type FileInfo struct { - Service svc.ID + Service svc.Attrs CmdExePath string ProExeLinkPath string @@ -36,7 +36,7 @@ func (fi *FileInfo) ExecutableName() string { return parts[len(parts)-1] } -func FindExecELF(p *services.ProcessInfo, svcID svc.ID, k8sEnabled bool) (*FileInfo, error) { +func FindExecELF(p *services.ProcessInfo, svcID svc.Attrs, k8sEnabled bool) (*FileInfo, error) { // In container environments or K8s, we can't just open the executable exe path, because it might // be in the volume of another pod/container. We need to access it through the /proc//exe symbolic link ns, err := FindNamespace(p.Pid) diff --git a/pkg/internal/infraolly/process/collect.go b/pkg/internal/infraolly/process/collect.go index a48081803..c79868b97 100644 --- a/pkg/internal/infraolly/process/collect.go +++ b/pkg/internal/infraolly/process/collect.go @@ -70,8 +70,8 @@ func NewCollectorProvider(ctx context.Context, input *<-chan []request.Span, cfg } func (ps *Collector) Run(out chan<- []*Status) { - // TODO: set app metadata as key for later decoration? (e.g. K8s metadata, svc.ID) - pids := map[int32]*svc.ID{} + // TODO: set app metadata as key for later decoration? (e.g. K8s metadata, svc.Attrs) + pids := map[int32]*svc.Attrs{} collectTicker := time.NewTicker(ps.cfg.Interval) defer collectTicker.Stop() newPids := *ps.newPids @@ -82,7 +82,7 @@ func (ps *Collector) Run(out chan<- []*Status) { case spans := <-newPids: // updating PIDs map with spans information for i := range spans { - pids[spans[i].ServiceID.ProcPID] = &spans[i].ServiceID + pids[spans[i].Service.ProcPID] = &spans[i].Service } case <-collectTicker.C: procs, removed := ps.Collect(pids) @@ -96,7 +96,7 @@ func (ps *Collector) Run(out chan<- []*Status) { // Collect returns the status for all the running processes, decorated with Docker runtime information, if applies. // It also returns the PIDs that have to be removed from the map, as they do not exist anymore -func (ps *Collector) Collect(pids map[int32]*svc.ID) ([]*Status, []int32) { +func (ps *Collector) Collect(pids map[int32]*svc.Attrs) ([]*Status, []int32) { results := make([]*Status, 0, len(pids)) var removed []int32 diff --git a/pkg/internal/infraolly/process/harvest.go b/pkg/internal/infraolly/process/harvest.go index dccb7eed1..17db873a8 100644 --- a/pkg/internal/infraolly/process/harvest.go +++ b/pkg/internal/infraolly/process/harvest.go @@ -75,7 +75,7 @@ func newHarvester(cfg *CollectConfig, cache *simplelru.LRU[int32, *linuxProcess] // Harvest returns a status of a process whose PID is passed as argument. The 'elapsedSeconds' argument represents the // time since this process was statusd for the last time. If the process has been statusd for the first time, this value // will be ignored -func (ps *Harvester) Harvest(svcID *svc.ID) (*Status, error) { +func (ps *Harvester) Harvest(svcID *svc.Attrs) (*Status, error) { pid := svcID.ProcPID // Reuses process information that does not vary cached, hasCachedEntry := ps.cache.Get(pid) diff --git a/pkg/internal/infraolly/process/harvest_test.go b/pkg/internal/infraolly/process/harvest_test.go index 3de7972b7..7c361abc5 100644 --- a/pkg/internal/infraolly/process/harvest_test.go +++ b/pkg/internal/infraolly/process/harvest_test.go @@ -49,7 +49,7 @@ func TestLinuxHarvester_IsPrivileged(t *testing.T) { h := newHarvester(&CollectConfig{RunMode: c.mode}, cache) // If not privileged, it is expected to not report neither FDs nor IO counters - status, err := h.Harvest(&svc.ID{ProcPID: int32(os.Getpid())}) + status, err := h.Harvest(&svc.Attrs{ProcPID: int32(os.Getpid())}) require.NoError(t, err) if c.privileged { assert.NotZero(t, status.FdCount) @@ -68,7 +68,7 @@ func TestLinuxHarvester_Harvest(t *testing.T) { h := newHarvester(&CollectConfig{}, cache) // When retrieving for a given process status (e.g. the current testing executable) - status, err := h.Harvest(&svc.ID{ProcPID: int32(os.Getpid())}) + status, err := h.Harvest(&svc.Attrs{ProcPID: int32(os.Getpid())}) // It returns the corresponding process status with valid data require.NoError(t, err) @@ -99,7 +99,7 @@ func TestLinuxHarvester_Harvest_FullCommandLine(t *testing.T) { h := newHarvester(&CollectConfig{}, cache) // When retrieving for a given process status (e.g. the current testing executable) - status, err := h.Harvest(&svc.ID{ProcPID: int32(cmd.Process.Pid)}) + status, err := h.Harvest(&svc.Attrs{ProcPID: int32(cmd.Process.Pid)}) // It returns the corresponding Command line without stripping arguments require.NoError(t, err) @@ -123,7 +123,7 @@ func TestLinuxHarvester_Do_InvalidateCache_DifferentCmd(t *testing.T) { h := newHarvester(&CollectConfig{}, cache) // When the process is harvested - status, err := h.Harvest(&svc.ID{ProcPID: currentPid}) + status, err := h.Harvest(&svc.Attrs{ProcPID: currentPid}) require.NoError(t, err) // The status is updated @@ -141,7 +141,7 @@ func TestLinuxHarvester_Do_InvalidateCache_DifferentPid(t *testing.T) { h := newHarvester(&CollectConfig{}, cache) // When the process is harvested - status, err := h.Harvest(&svc.ID{ProcPID: currentPid}) + status, err := h.Harvest(&svc.Attrs{ProcPID: currentPid}) require.NoError(t, err) // The status is updated diff --git a/pkg/internal/infraolly/process/status.go b/pkg/internal/infraolly/process/status.go index e92f8ef31..f70f33fef 100644 --- a/pkg/internal/infraolly/process/status.go +++ b/pkg/internal/infraolly/process/status.go @@ -17,7 +17,7 @@ func pslog() *slog.Logger { } type ID struct { - Service *svc.ID + Service *svc.Attrs // UID for a process. Even if the Service field has its own UID, // a service might have multiple processes, so Application and Process @@ -73,7 +73,7 @@ type Status struct { NetRcvBytesDelta int64 } -func NewStatus(pid int32, svcID *svc.ID) *Status { +func NewStatus(pid int32, svcID *svc.Attrs) *Status { return &Status{ID: ID{ ProcessID: pid, Service: svcID, diff --git a/pkg/internal/kube/store_test.go b/pkg/internal/kube/store_test.go index 4bf30b05b..4f72b7de3 100644 --- a/pkg/internal/kube/store_test.go +++ b/pkg/internal/kube/store_test.go @@ -325,6 +325,96 @@ func TestMetaByIPEntryRemovedIfIPGroupChanges(t *testing.T) { assert.Equal(t, []string{"3.2.2.2", "3.3.3.3"}, om.Ips) } +func TestNoLeakOnUpdateOrDeletion(t *testing.T) { + store := NewStore(&fakeInformer{}, MetaSourceLabels{}) + topOwner := &informer.Owner{Name: "foo", Kind: "Deployment"} + require.NoError(t, store.On(&informer.Event{ + Type: informer.EventType_CREATED, + Resource: &informer.ObjectMeta{ + Name: "pod-foo-1", + Namespace: "namespaceA", + Ips: []string{"1.1.1.1", "2.2.2.2"}, + Kind: "Pod", + Pod: &informer.PodInfo{ + Owners: []*informer.Owner{topOwner}, + Containers: []*informer.ContainerInfo{ + {Id: "container1-1"}, + {Id: "container1-2"}, + }, + }, + }})) + require.NoError(t, store.On(&informer.Event{ + Type: informer.EventType_CREATED, + Resource: &informer.ObjectMeta{ + Name: "pod-foo-2", + Namespace: "namespaceA", + Ips: []string{"4.4.4.4", "5.5.5.5"}, + Kind: "Pod", + Pod: &informer.PodInfo{ + Owners: []*informer.Owner{topOwner}, + Containers: []*informer.ContainerInfo{ + {Id: "container2-1"}, + {Id: "container2-2"}, + }, + }, + }})) + require.NoError(t, store.On(&informer.Event{ + Type: informer.EventType_UPDATED, + Resource: &informer.ObjectMeta{ + Name: "pod-foo-1", + Namespace: "namespaceA", + Ips: []string{"1.1.1.1", "3.3.3.3"}, + Kind: "Pod", + Pod: &informer.PodInfo{ + Owners: []*informer.Owner{topOwner}, + Containers: []*informer.ContainerInfo{ + {Id: "container1-1"}, + {Id: "container1-3"}, + }, + }}})) + require.NoError(t, store.On(&informer.Event{ + Type: informer.EventType_DELETED, + Resource: &informer.ObjectMeta{ + Name: "pod-foo-1", + Namespace: "namespaceA", + Ips: []string{"1.1.1.1", "3.3.3.3"}, + Kind: "Pod", + Pod: &informer.PodInfo{ + Owners: []*informer.Owner{topOwner}, + Containers: []*informer.ContainerInfo{ + {Id: "container1"}, + {Id: "container3"}, + }, + }}})) + require.NoError(t, store.On(&informer.Event{ + Type: informer.EventType_DELETED, + Resource: &informer.ObjectMeta{ + Name: "foo", + Namespace: "namespaceA", + }})) + require.NoError(t, store.On(&informer.Event{ + Type: informer.EventType_DELETED, + Resource: &informer.ObjectMeta{ + Name: "pod-foo-2", + Namespace: "namespaceA", + Ips: []string{"4.4.4.4", "5.5.5.5"}, + Kind: "Pod", + Pod: &informer.PodInfo{ + Containers: []*informer.ContainerInfo{ + {Id: "container2-1"}, + {Id: "container2-3"}, + }, + }}})) + + assert.Empty(t, store.objectMetaByQName) + assert.Empty(t, store.objectMetaByIP) + assert.Empty(t, store.containerIDs) + assert.Empty(t, store.namespaces) + assert.Empty(t, store.namespaces) + assert.Empty(t, store.podsByContainer) + assert.Empty(t, store.containersByOwner) +} + type fakeInformer struct { mt sync.Mutex observers map[string]meta.Observer diff --git a/pkg/internal/pipe/instrumenter_test.go b/pkg/internal/pipe/instrumenter_test.go index 3f139f745..c9a5e6c8d 100644 --- a/pkg/internal/pipe/instrumenter_test.go +++ b/pkg/internal/pipe/instrumenter_test.go @@ -647,7 +647,7 @@ func newRequest(serviceName string, method, path, peer string, status int) []req Start: 2, RequestStart: 1, End: 3, - ServiceID: svc.ID{HostName: "the-host", UID: svc.UID{Namespace: "ns", Name: serviceName}, SDKLanguage: svc.InstrumentableGolang}, + Service: svc.Attrs{HostName: "the-host", UID: svc.UID{Namespace: "ns", Name: serviceName}, SDKLanguage: svc.InstrumentableGolang}, }} } @@ -663,7 +663,7 @@ func newRequestWithTiming(svcName string, kind request.EventType, method, path, RequestStart: int64(goStart), Start: int64(start), End: int64(end), - ServiceID: svc.ID{HostName: "the-host", UID: svc.UID{Name: svcName}, SDKLanguage: svc.InstrumentableGolang}, + Service: svc.Attrs{HostName: "the-host", UID: svc.UID{Name: svcName}, SDKLanguage: svc.InstrumentableGolang}, }} } @@ -678,7 +678,7 @@ func newGRPCRequest(svcName string, path string, status int) []request.Span { Start: 2, RequestStart: 1, End: 3, - ServiceID: svc.ID{HostName: "the-host", UID: svc.UID{Name: svcName}, SDKLanguage: svc.InstrumentableGolang}, + Service: svc.Attrs{HostName: "the-host", UID: svc.UID{Name: svcName}, SDKLanguage: svc.InstrumentableGolang}, }} } @@ -807,7 +807,7 @@ func newHTTPInfo(method, path, peer string, status int) []request.Span { Start: 2, RequestStart: 2, End: 3, - ServiceID: svc.ID{HostName: "the-host", UID: svc.UID{Name: "comm"}, SDKLanguage: svc.InstrumentableGolang}, + Service: svc.Attrs{HostName: "the-host", UID: svc.UID{Name: "comm"}, SDKLanguage: svc.InstrumentableGolang}, }} } diff --git a/pkg/internal/request/metric_attributes.go b/pkg/internal/request/metric_attributes.go index d8f582c33..e3d5f8665 100644 --- a/pkg/internal/request/metric_attributes.go +++ b/pkg/internal/request/metric_attributes.go @@ -120,7 +120,7 @@ func SpanPeer(span *Span) string { } func HostAsServer(span *Span) string { - if span.OtherNamespace != "" && span.OtherNamespace != span.ServiceID.UID.Namespace && span.HostName != "" { + if span.OtherNamespace != "" && span.OtherNamespace != span.Service.UID.Namespace && span.HostName != "" { if span.IsClientSpan() { return SpanHost(span) + "." + span.OtherNamespace } @@ -130,7 +130,7 @@ func HostAsServer(span *Span) string { } func PeerAsClient(span *Span) string { - if span.OtherNamespace != "" && span.OtherNamespace != span.ServiceID.UID.Namespace && span.PeerName != "" { + if span.OtherNamespace != "" && span.OtherNamespace != span.Service.UID.Namespace && span.PeerName != "" { if !span.IsClientSpan() { return SpanPeer(span) + "." + span.OtherNamespace } diff --git a/pkg/internal/request/span.go b/pkg/internal/request/span.go index 3010a44a8..e5c92eef1 100644 --- a/pkg/internal/request/span.go +++ b/pkg/internal/request/span.go @@ -138,7 +138,7 @@ type Span struct { RequestStart int64 `json:"-"` Start int64 `json:"-"` End int64 `json:"-"` - ServiceID svc.ID `json:"-"` // TODO: rename to Service or ResourceAttrs + Service svc.Attrs `json:"-"` TraceID trace2.TraceID `json:"traceID"` SpanID trace2.SpanID `json:"spanID"` ParentSpanID trace2.SpanID `json:"parentSpanID"` @@ -495,5 +495,5 @@ func (s *Span) IsExportTracesSpan() bool { } func (s *Span) IsSelfReferenceSpan() bool { - return s.Peer == s.Host && (s.ServiceID.UID.Namespace == s.OtherNamespace || s.OtherNamespace == "") + return s.Peer == s.Host && (s.Service.UID.Namespace == s.OtherNamespace || s.OtherNamespace == "") } diff --git a/pkg/internal/request/span_getters.go b/pkg/internal/request/span_getters.go index 2a15d2052..d5d4e59dc 100644 --- a/pkg/internal/request/span_getters.go +++ b/pkg/internal/request/span_getters.go @@ -22,7 +22,7 @@ func SpanOTELGetters(name attr.Name) (attributes.Getter[*Span, attribute.KeyValu case attr.ClientNamespace: getter = func(s *Span) attribute.KeyValue { if s.IsClientSpan() { - return ClientNamespaceMetric(s.ServiceID.UID.Namespace) + return ClientNamespaceMetric(s.Service.UID.Namespace) } return ClientNamespaceMetric(s.OtherNamespace) } @@ -53,16 +53,16 @@ func SpanOTELGetters(name attr.Name) (attributes.Getter[*Span, attribute.KeyValu if s.IsClientSpan() { return ServerNamespaceMetric(s.OtherNamespace) } - return ServerNamespaceMetric(s.ServiceID.UID.Namespace) + return ServerNamespaceMetric(s.Service.UID.Namespace) } case attr.Service: - getter = func(s *Span) attribute.KeyValue { return ServiceMetric(s.ServiceID.UID.Name) } + getter = func(s *Span) attribute.KeyValue { return ServiceMetric(s.Service.UID.Name) } case attr.ServiceInstanceID: - getter = func(s *Span) attribute.KeyValue { return semconv.ServiceInstanceID(string(s.ServiceID.UID.Instance)) } + getter = func(s *Span) attribute.KeyValue { return semconv.ServiceInstanceID(string(s.Service.UID.Instance)) } case attr.ServiceName: - getter = func(s *Span) attribute.KeyValue { return semconv.ServiceName(s.ServiceID.UID.Name) } + getter = func(s *Span) attribute.KeyValue { return semconv.ServiceName(s.Service.UID.Name) } case attr.ServiceNamespace: - getter = func(s *Span) attribute.KeyValue { return semconv.ServiceNamespace(s.ServiceID.UID.Namespace) } + getter = func(s *Span) attribute.KeyValue { return semconv.ServiceNamespace(s.Service.UID.Namespace) } case attr.SpanKind: getter = func(s *Span) attribute.KeyValue { return SpanKindMetric(s.ServiceGraphKind()) } case attr.SpanName: @@ -177,19 +177,19 @@ func SpanPromGetters(attrName attr.Name) (attributes.Getter[*Span, string], bool return "" } case attr.ServiceInstanceID: - getter = func(s *Span) string { return string(s.ServiceID.UID.Instance) } + getter = func(s *Span) string { return s.Service.UID.Instance } // resource metadata values below. Unlike OTEL, they are included here because they // belong to the metric, instead of the Resource case attr.Instance: - getter = func(s *Span) string { return string(s.ServiceID.UID.Instance) } + getter = func(s *Span) string { return s.Service.UID.Instance } case attr.Job: - getter = func(s *Span) string { return s.ServiceID.Job() } + getter = func(s *Span) string { return s.Service.Job() } case attr.ServiceName: - getter = func(s *Span) string { return s.ServiceID.UID.Name } + getter = func(s *Span) string { return s.Service.UID.Name } case attr.ServiceNamespace: - getter = func(s *Span) string { return s.ServiceID.UID.Namespace } + getter = func(s *Span) string { return s.Service.UID.Namespace } default: - getter = func(s *Span) string { return s.ServiceID.Metadata[attrName] } + getter = func(s *Span) string { return s.Service.Metadata[attrName] } } return getter, getter != nil } diff --git a/pkg/internal/request/span_test.go b/pkg/internal/request/span_test.go index 4340f0c3c..5ae24f71c 100644 --- a/pkg/internal/request/span_test.go +++ b/pkg/internal/request/span_test.go @@ -361,17 +361,17 @@ func TestSelfReferencingSpan(t *testing.T) { }{ { name: "Not a self-reference", - span: Span{Type: EventTypeHTTP, Method: "GET", Path: "/v1/metrics", RequestStart: 100, End: 200, Status: 200, Host: "10.10.10.10", Peer: "10.11.10.11", OtherNamespace: "", ServiceID: svc.ID{UID: svc.UID{Namespace: ""}}}, + span: Span{Type: EventTypeHTTP, Method: "GET", Path: "/v1/metrics", RequestStart: 100, End: 200, Status: 200, Host: "10.10.10.10", Peer: "10.11.10.11", OtherNamespace: "", Service: svc.Attrs{UID: svc.UID{Namespace: ""}}}, selfref: false, }, { name: "Not a self-reference, same IP, different namespace", - span: Span{Type: EventTypeHTTP, Method: "GET", Path: "/v1/metrics", RequestStart: 100, End: 200, Status: 200, Host: "10.10.10.10", Peer: "10.10.10.10", OtherNamespace: "B", ServiceID: svc.ID{UID: svc.UID{Namespace: "A"}}}, + span: Span{Type: EventTypeHTTP, Method: "GET", Path: "/v1/metrics", RequestStart: 100, End: 200, Status: 200, Host: "10.10.10.10", Peer: "10.10.10.10", OtherNamespace: "B", Service: svc.Attrs{UID: svc.UID{Namespace: "A"}}}, selfref: false, }, { name: "Same IP different namespace, but the other namespace is empty", - span: Span{Type: EventTypeHTTP, Method: "GET", Path: "/v1/metrics", RequestStart: 100, End: 200, Status: 200, Host: "10.10.10.10", Peer: "10.10.10.10", OtherNamespace: "", ServiceID: svc.ID{UID: svc.UID{Namespace: "A"}}}, + span: Span{Type: EventTypeHTTP, Method: "GET", Path: "/v1/metrics", RequestStart: 100, End: 200, Status: 200, Host: "10.10.10.10", Peer: "10.10.10.10", OtherNamespace: "", Service: svc.Attrs{UID: svc.UID{Namespace: "A"}}}, selfref: true, }, } @@ -393,91 +393,91 @@ func TestHostPeerClientServer(t *testing.T) { }{ { name: "Same namespaces HTTP", - span: Span{Type: EventTypeHTTP, PeerName: "client", HostName: "server", OtherNamespace: "same", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: Span{Type: EventTypeHTTP, PeerName: "client", HostName: "server", OtherNamespace: "same", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "client", server: "server", }, { name: "Client in different namespace", - span: Span{Type: EventTypeHTTP, PeerName: "client", HostName: "server", OtherNamespace: "far", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: Span{Type: EventTypeHTTP, PeerName: "client", HostName: "server", OtherNamespace: "far", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "client.far", server: "server", }, { name: "Client in different namespace", - span: Span{Type: EventTypeHTTP, Peer: "1.1.1.1", HostName: "server", OtherNamespace: "far", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: Span{Type: EventTypeHTTP, Peer: "1.1.1.1", HostName: "server", OtherNamespace: "far", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "1.1.1.1", server: "server", }, { name: "Same namespaces for HTTP client", - span: Span{Type: EventTypeHTTPClient, PeerName: "client", HostName: "server", OtherNamespace: "same", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: Span{Type: EventTypeHTTPClient, PeerName: "client", HostName: "server", OtherNamespace: "same", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "client", server: "server", }, { name: "Server in different namespace ", - span: Span{Type: EventTypeHTTPClient, PeerName: "client", HostName: "server", OtherNamespace: "far", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: Span{Type: EventTypeHTTPClient, PeerName: "client", HostName: "server", OtherNamespace: "far", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "client", server: "server.far", }, { name: "Server in different namespace ", - span: Span{Type: EventTypeHTTPClient, PeerName: "client", Host: "2.2.2.2", OtherNamespace: "far", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: Span{Type: EventTypeHTTPClient, PeerName: "client", Host: "2.2.2.2", OtherNamespace: "far", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "client", server: "2.2.2.2", }, { name: "Same namespaces GRPC", - span: Span{Type: EventTypeGRPC, PeerName: "client", HostName: "server", OtherNamespace: "same", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: Span{Type: EventTypeGRPC, PeerName: "client", HostName: "server", OtherNamespace: "same", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "client", server: "server", }, { name: "Client in different namespace GRPC", - span: Span{Type: EventTypeGRPC, PeerName: "client", HostName: "server", OtherNamespace: "far", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: Span{Type: EventTypeGRPC, PeerName: "client", HostName: "server", OtherNamespace: "far", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "client.far", server: "server", }, { name: "Same namespaces for GRPC client", - span: Span{Type: EventTypeGRPCClient, PeerName: "client", HostName: "server", OtherNamespace: "same", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: Span{Type: EventTypeGRPCClient, PeerName: "client", HostName: "server", OtherNamespace: "same", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "client", server: "server", }, { name: "Server in different namespace GRPC", - span: Span{Type: EventTypeGRPCClient, PeerName: "client", HostName: "server", OtherNamespace: "far", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: Span{Type: EventTypeGRPCClient, PeerName: "client", HostName: "server", OtherNamespace: "far", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "client", server: "server.far", }, { name: "Same namespaces for SQL client", - span: Span{Type: EventTypeSQLClient, PeerName: "client", HostName: "server", OtherNamespace: "same", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: Span{Type: EventTypeSQLClient, PeerName: "client", HostName: "server", OtherNamespace: "same", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "client", server: "server", }, { name: "Server in different namespace SQL", - span: Span{Type: EventTypeSQLClient, PeerName: "client", HostName: "server", OtherNamespace: "far", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: Span{Type: EventTypeSQLClient, PeerName: "client", HostName: "server", OtherNamespace: "far", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "client", server: "server.far", }, { name: "Same namespaces for Redis client", - span: Span{Type: EventTypeRedisClient, PeerName: "client", HostName: "server", OtherNamespace: "same", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: Span{Type: EventTypeRedisClient, PeerName: "client", HostName: "server", OtherNamespace: "same", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "client", server: "server", }, { name: "Server in different namespace Redis", - span: Span{Type: EventTypeRedisClient, PeerName: "client", HostName: "server", OtherNamespace: "far", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: Span{Type: EventTypeRedisClient, PeerName: "client", HostName: "server", OtherNamespace: "far", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "client", server: "server.far", }, { name: "Client in different namespace Redis", - span: Span{Type: EventTypeRedisServer, PeerName: "client", HostName: "server", OtherNamespace: "far", ServiceID: svc.ID{UID: svc.UID{Namespace: "same"}}}, + span: Span{Type: EventTypeRedisServer, PeerName: "client", HostName: "server", OtherNamespace: "far", Service: svc.Attrs{UID: svc.UID{Namespace: "same"}}}, client: "client.far", server: "server", }, diff --git a/pkg/internal/svc/svc.go b/pkg/internal/svc/svc.go index 6350258b2..24f8196d7 100644 --- a/pkg/internal/svc/svc.go +++ b/pkg/internal/svc/svc.go @@ -62,9 +62,8 @@ type UID struct { Instance string } -// ID stores the metadata attributes of a service/resource -// TODO: rename to svc.Attributes -type ID struct { +// Attrs stores the metadata attributes of a service/resource +type Attrs struct { // Instance uniquely identifies a service instance. It is not exported // in the metrics or traces, but it is used to compose the Instance UID UID @@ -87,49 +86,49 @@ type ID struct { flags idFlags } -func (i *ID) GetUID() UID { +func (i *Attrs) GetUID() UID { return i.UID } -func (i *ID) String() string { +func (i *Attrs) String() string { return i.Job() } -func (i *ID) Job() string { +func (i *Attrs) Job() string { if i.UID.Namespace != "" { return i.UID.Namespace + "/" + i.UID.Name } return i.UID.Name } -func (i *ID) setFlag(flag idFlags) { +func (i *Attrs) setFlag(flag idFlags) { i.flags |= flag } -func (i *ID) getFlag(flag idFlags) bool { +func (i *Attrs) getFlag(flag idFlags) bool { return (i.flags & flag) == flag } -func (i *ID) SetAutoName() { +func (i *Attrs) SetAutoName() { i.setFlag(autoName) } -func (i *ID) AutoName() bool { +func (i *Attrs) AutoName() bool { return i.getFlag(autoName) } -func (i *ID) SetExportsOTelMetrics() { +func (i *Attrs) SetExportsOTelMetrics() { i.setFlag(exportsOTelMetrics) } -func (i *ID) ExportsOTelMetrics() bool { +func (i *Attrs) ExportsOTelMetrics() bool { return i.getFlag(exportsOTelMetrics) } -func (i *ID) SetExportsOTelTraces() { +func (i *Attrs) SetExportsOTelTraces() { i.setFlag(exportsOTelTraces) } -func (i *ID) ExportsOTelTraces() bool { +func (i *Attrs) ExportsOTelTraces() bool { return i.getFlag(exportsOTelTraces) } diff --git a/pkg/internal/svc/svc_test.go b/pkg/internal/svc/svc_test.go index 16da4a6a1..78735207f 100644 --- a/pkg/internal/svc/svc_test.go +++ b/pkg/internal/svc/svc_test.go @@ -7,6 +7,6 @@ import ( ) func TestToString(t *testing.T) { - assert.Equal(t, "thens/thename", (&ID{UID: UID{Namespace: "thens", Name: "thename"}}).String()) - assert.Equal(t, "thename", (&ID{UID: UID{Name: "thename"}}).String()) + assert.Equal(t, "thens/thename", (&Attrs{UID: UID{Namespace: "thens", Name: "thename"}}).String()) + assert.Equal(t, "thename", (&Attrs{UID: UID{Name: "thename"}}).String()) } diff --git a/pkg/internal/traces/read_decorator.go b/pkg/internal/traces/read_decorator.go index 3d60e4ad7..ef91b60c0 100644 --- a/pkg/internal/traces/read_decorator.go +++ b/pkg/internal/traces/read_decorator.go @@ -77,8 +77,8 @@ func hostNamePIDDecorator(cfg *InstanceIDConfig) decorator { // caching instance ID composition for speed and saving memory generation return func(spans []request.Span) { for i := range spans { - spans[i].ServiceID.UID.Instance = fullHostName + ":" + strconv.Itoa(int(spans[i].Pid.HostPID)) - spans[i].ServiceID.HostName = fullHostName + spans[i].Service.UID.Instance = fullHostName + ":" + strconv.Itoa(int(spans[i].Pid.HostPID)) + spans[i].Service.HostName = fullHostName } } } diff --git a/pkg/internal/traces/read_decorator_test.go b/pkg/internal/traces/read_decorator_test.go index 9bfaf6ce7..144802fd4 100644 --- a/pkg/internal/traces/read_decorator_test.go +++ b/pkg/internal/traces/read_decorator_test.go @@ -60,9 +60,9 @@ func TestReadDecorator(t *testing.T) { } outSpans := testutil.ReadChannel(t, decoratedOutput, testTimeout) assert.Equal(t, []request.Span{ - {ServiceID: svc.ID{UID: svc.UID{Instance: tc.expectedInstance}, HostName: tc.expectedHN}, + {Service: svc.Attrs{UID: svc.UID{Instance: tc.expectedInstance}, HostName: tc.expectedHN}, Path: "/foo", Pid: request.PidInfo{HostPID: 1234}}, - {ServiceID: svc.ID{UID: svc.UID{Instance: tc.expectedInstance}, HostName: tc.expectedHN}, + {Service: svc.Attrs{UID: svc.UID{Instance: tc.expectedInstance}, HostName: tc.expectedHN}, Path: "/bar", Pid: request.PidInfo{HostPID: 1234}}, }, outSpans) }) diff --git a/pkg/transform/k8s.go b/pkg/transform/k8s.go index 24c91a979..6ba52b39c 100644 --- a/pkg/transform/k8s.go +++ b/pkg/transform/k8s.go @@ -103,7 +103,7 @@ func (md *metadataDecorator) do(span *request.Span) { md.appendMetadata(span, podMeta, containerName) } else { // do not leave the service attributes map as nil - span.ServiceID.Metadata = map[attr.Name]string{} + span.Service.Metadata = map[attr.Name]string{} } // override the peer and host names from Kubernetes metadata, if found if name, _ := md.db.ServiceNameNamespaceForIP(span.Host); name != "" { @@ -125,21 +125,21 @@ func (md *metadataDecorator) appendMetadata(span *request.Span, meta *informer.O // If the user has not defined criteria values for the reported // service name and namespace, we will automatically set it from // the kubernetes metadata - if span.ServiceID.AutoName() { - span.ServiceID.UID.Name = name + if span.Service.AutoName() { + span.Service.UID.Name = name } - if span.ServiceID.UID.Namespace == "" { - span.ServiceID.UID.Namespace = namespace + if span.Service.UID.Namespace == "" { + span.Service.UID.Namespace = namespace } // overriding the Instance here will avoid reusing the OTEL resource reporter // if the application/process was discovered and reported information // before the kubernetes metadata was available // (related issue: https://github.com/grafana/beyla/issues/1124) - span.ServiceID.UID.Instance = meta.Name + ":" + containerName + span.Service.UID.Instance = meta.Name + ":" + containerName // if, in the future, other pipeline steps modify the service metadata, we should // replace the map literal by individual entry insertions - span.ServiceID.Metadata = map[attr.Name]string{ + span.Service.Metadata = map[attr.Name]string{ attr.K8sNamespaceName: meta.Namespace, attr.K8sPodName: meta.Name, attr.K8sNodeName: meta.Pod.NodeName, @@ -151,17 +151,17 @@ func (md *metadataDecorator) appendMetadata(span *request.Span, meta *informer.O // ownerKind could be also "Pod", but we won't insert it as "owner" label to avoid // growing cardinality if topOwner != nil { - span.ServiceID.Metadata[attr.K8sOwnerName] = topOwner.Name + span.Service.Metadata[attr.K8sOwnerName] = topOwner.Name } for _, owner := range meta.Pod.Owners { if kindLabel := OwnerLabelName(owner.Kind); kindLabel != "" { - span.ServiceID.Metadata[kindLabel] = owner.Name + span.Service.Metadata[kindLabel] = owner.Name } } // override hostname by the Pod name - span.ServiceID.HostName = meta.Name + span.Service.HostName = meta.Name } func OwnerLabelName(kind string) attr.Name { diff --git a/pkg/transform/k8s_test.go b/pkg/transform/k8s_test.go index f20e008e2..73556c3b4 100644 --- a/pkg/transform/k8s_test.go +++ b/pkg/transform/k8s_test.go @@ -85,18 +85,18 @@ func TestDecoration(t *testing.T) { defer close(inputCh) go dec.nodeLoop(inputCh, outputhCh) - autoNameSvc := svc.ID{} + autoNameSvc := svc.Attrs{} autoNameSvc.SetAutoName() t.Run("complete pod info should set deployment as name", func(t *testing.T) { inputCh <- []request.Span{{ - Pid: request.PidInfo{Namespace: 1012}, ServiceID: autoNameSvc, + Pid: request.PidInfo{Namespace: 1012}, Service: autoNameSvc, }} deco := testutil.ReadChannel(t, outputhCh, timeout) require.Len(t, deco, 1) - assert.Equal(t, "the-ns", deco[0].ServiceID.UID.Namespace) - assert.Equal(t, "deployment-12", deco[0].ServiceID.UID.Name) - assert.EqualValues(t, "pod-12:a-container", deco[0].ServiceID.UID.Instance) + assert.Equal(t, "the-ns", deco[0].Service.UID.Namespace) + assert.Equal(t, "deployment-12", deco[0].Service.UID.Name) + assert.EqualValues(t, "pod-12:a-container", deco[0].Service.UID.Instance) assert.Equal(t, map[attr.Name]string{ "k8s.node.name": "the-node", "k8s.namespace.name": "the-ns", @@ -106,17 +106,17 @@ func TestDecoration(t *testing.T) { "k8s.owner.name": "deployment-12", "k8s.pod.start_time": "2020-01-02 12:12:56", "k8s.cluster.name": "the-cluster", - }, deco[0].ServiceID.Metadata) + }, deco[0].Service.Metadata) }) t.Run("pod info whose replicaset did not have an Owner should set the replicaSet name", func(t *testing.T) { inputCh <- []request.Span{{ - Pid: request.PidInfo{Namespace: 1034}, ServiceID: autoNameSvc, + Pid: request.PidInfo{Namespace: 1034}, Service: autoNameSvc, }} deco := testutil.ReadChannel(t, outputhCh, timeout) require.Len(t, deco, 1) - assert.Equal(t, "the-ns", deco[0].ServiceID.UID.Namespace) - assert.Equal(t, "rs", deco[0].ServiceID.UID.Name) - assert.EqualValues(t, "pod-34:a-container", deco[0].ServiceID.UID.Instance) + assert.Equal(t, "the-ns", deco[0].Service.UID.Namespace) + assert.Equal(t, "rs", deco[0].Service.UID.Name) + assert.EqualValues(t, "pod-34:a-container", deco[0].Service.UID.Instance) assert.Equal(t, map[attr.Name]string{ "k8s.node.name": "the-node", "k8s.namespace.name": "the-ns", @@ -126,17 +126,17 @@ func TestDecoration(t *testing.T) { "k8s.pod.uid": "uid-34", "k8s.pod.start_time": "2020-01-02 12:34:56", "k8s.cluster.name": "the-cluster", - }, deco[0].ServiceID.Metadata) + }, deco[0].Service.Metadata) }) t.Run("pod info with only pod name should set pod name as name", func(t *testing.T) { inputCh <- []request.Span{{ - Pid: request.PidInfo{Namespace: 1056}, ServiceID: autoNameSvc, + Pid: request.PidInfo{Namespace: 1056}, Service: autoNameSvc, }} deco := testutil.ReadChannel(t, outputhCh, timeout) require.Len(t, deco, 1) - assert.Equal(t, "the-ns", deco[0].ServiceID.UID.Namespace) - assert.Equal(t, "the-pod", deco[0].ServiceID.UID.Name) - assert.EqualValues(t, "the-pod:a-container", deco[0].ServiceID.UID.Instance) + assert.Equal(t, "the-ns", deco[0].Service.UID.Namespace) + assert.Equal(t, "the-pod", deco[0].Service.UID.Name) + assert.EqualValues(t, "the-pod:a-container", deco[0].Service.UID.Instance) assert.Equal(t, map[attr.Name]string{ "k8s.node.name": "the-node", "k8s.namespace.name": "the-ns", @@ -144,17 +144,17 @@ func TestDecoration(t *testing.T) { "k8s.pod.uid": "uid-56", "k8s.pod.start_time": "2020-01-02 12:56:56", "k8s.cluster.name": "the-cluster", - }, deco[0].ServiceID.Metadata) + }, deco[0].Service.Metadata) }) t.Run("user can override service name and annotations via labels", func(t *testing.T) { inputCh <- []request.Span{{ - Pid: request.PidInfo{Namespace: 1078}, ServiceID: autoNameSvc, + Pid: request.PidInfo{Namespace: 1078}, Service: autoNameSvc, }} deco := testutil.ReadChannel(t, outputhCh, timeout) require.Len(t, deco, 1) - assert.Equal(t, "a-cool-namespace", deco[0].ServiceID.UID.Namespace) - assert.Equal(t, "a-cool-name", deco[0].ServiceID.UID.Name) - assert.EqualValues(t, "overridden-meta:a-container", deco[0].ServiceID.UID.Instance) + assert.Equal(t, "a-cool-namespace", deco[0].Service.UID.Namespace) + assert.Equal(t, "a-cool-name", deco[0].Service.UID.Name) + assert.EqualValues(t, "overridden-meta:a-container", deco[0].Service.UID.Instance) assert.Equal(t, map[attr.Name]string{ "k8s.node.name": "the-node", "k8s.namespace.name": "the-ns", @@ -162,29 +162,29 @@ func TestDecoration(t *testing.T) { "k8s.pod.uid": "uid-78", "k8s.pod.start_time": "2020-01-02 12:56:56", "k8s.cluster.name": "the-cluster", - }, deco[0].ServiceID.Metadata) + }, deco[0].Service.Metadata) }) t.Run("process without pod Info won't be decorated", func(t *testing.T) { - svc := svc.ID{UID: svc.UID{Name: "exec"}} + svc := svc.Attrs{UID: svc.UID{Name: "exec"}} svc.SetAutoName() inputCh <- []request.Span{{ - Pid: request.PidInfo{Namespace: 1099}, ServiceID: svc, + Pid: request.PidInfo{Namespace: 1099}, Service: svc, }} deco := testutil.ReadChannel(t, outputhCh, timeout) require.Len(t, deco, 1) - assert.Empty(t, deco[0].ServiceID.UID.Namespace) - assert.Equal(t, "exec", deco[0].ServiceID.UID.Name) - assert.Empty(t, deco[0].ServiceID.Metadata) + assert.Empty(t, deco[0].Service.UID.Namespace) + assert.Equal(t, "exec", deco[0].Service.UID.Name) + assert.Empty(t, deco[0].Service.Metadata) }) t.Run("if service name or namespace are manually specified, don't override them", func(t *testing.T) { inputCh <- []request.Span{{ - Pid: request.PidInfo{Namespace: 1012}, ServiceID: svc.ID{UID: svc.UID{Name: "tralari", Namespace: "tralara"}}, + Pid: request.PidInfo{Namespace: 1012}, Service: svc.Attrs{UID: svc.UID{Name: "tralari", Namespace: "tralara"}}, }} deco := testutil.ReadChannel(t, outputhCh, timeout) require.Len(t, deco, 1) - assert.Equal(t, "tralara", deco[0].ServiceID.UID.Namespace) - assert.Equal(t, "tralari", deco[0].ServiceID.UID.Name) - assert.EqualValues(t, "pod-12:a-container", deco[0].ServiceID.UID.Instance) + assert.Equal(t, "tralara", deco[0].Service.UID.Namespace) + assert.Equal(t, "tralari", deco[0].Service.UID.Name) + assert.EqualValues(t, "pod-12:a-container", deco[0].Service.UID.Instance) assert.Equal(t, map[attr.Name]string{ "k8s.node.name": "the-node", "k8s.namespace.name": "the-ns", @@ -194,7 +194,7 @@ func TestDecoration(t *testing.T) { "k8s.owner.name": "deployment-12", "k8s.pod.start_time": "2020-01-02 12:12:56", "k8s.cluster.name": "the-cluster", - }, deco[0].ServiceID.Metadata) + }, deco[0].Service.Metadata) }) } diff --git a/pkg/transform/name_resolver.go b/pkg/transform/name_resolver.go index 922966241..bea3ae520 100644 --- a/pkg/transform/name_resolver.go +++ b/pkg/transform/name_resolver.go @@ -115,14 +115,14 @@ func trimPrefixIgnoreCase(s, prefix string) string { func (nr *NameResolver) resolveNames(span *request.Span) { var hn, pn, ns string if span.IsClientSpan() { - hn, span.OtherNamespace = nr.resolve(&span.ServiceID, span.Host) - pn, ns = nr.resolve(&span.ServiceID, span.Peer) + hn, span.OtherNamespace = nr.resolve(&span.Service, span.Host) + pn, ns = nr.resolve(&span.Service, span.Peer) } else { - pn, span.OtherNamespace = nr.resolve(&span.ServiceID, span.Peer) - hn, ns = nr.resolve(&span.ServiceID, span.Host) + pn, span.OtherNamespace = nr.resolve(&span.Service, span.Peer) + hn, ns = nr.resolve(&span.Service, span.Host) } - if span.ServiceID.UID.Namespace == "" && ns != "" { - span.ServiceID.UID.Namespace = ns + if span.Service.UID.Namespace == "" && ns != "" { + span.Service.UID.Namespace = ns } // don't set names if the peer and host names have been already decorated // in a previous stage (e.g. Kubernetes decorator) @@ -134,7 +134,7 @@ func (nr *NameResolver) resolveNames(span *request.Span) { } } -func (nr *NameResolver) resolve(svc *svc.ID, ip string) (string, string) { +func (nr *NameResolver) resolve(svc *svc.Attrs, ip string) (string, string) { var name, ns string if len(ip) > 0 { @@ -150,7 +150,7 @@ func (nr *NameResolver) resolve(svc *svc.ID, ip string) (string, string) { return name, ns } -func (nr *NameResolver) cleanName(svc *svc.ID, ip, n string) string { +func (nr *NameResolver) cleanName(svc *svc.Attrs, ip, n string) string { n = strings.TrimSuffix(n, ".") n = trimSuffixIgnoreCase(n, ".svc.cluster.local") n = trimSuffixIgnoreCase(n, "."+svc.UID.Namespace) @@ -166,7 +166,7 @@ func (nr *NameResolver) cleanName(svc *svc.ID, ip, n string) string { return n } -func (nr *NameResolver) dnsResolve(svc *svc.ID, ip string) (string, string) { +func (nr *NameResolver) dnsResolve(svc *svc.Attrs, ip string) (string, string) { if ip == "" { return "", "" } diff --git a/pkg/transform/name_resolver_test.go b/pkg/transform/name_resolver_test.go index 89eafc82d..43b650844 100644 --- a/pkg/transform/name_resolver_test.go +++ b/pkg/transform/name_resolver_test.go @@ -71,7 +71,7 @@ func TestResolvePodsFromK8s(t *testing.T) { Type: request.EventTypeHTTPClient, Peer: "10.0.0.1", Host: "10.0.0.2", - ServiceID: svc.ID{UID: svc.UID{ + Service: svc.Attrs{UID: svc.UID{ Name: "pod1", Namespace: "", }}, @@ -81,7 +81,7 @@ func TestResolvePodsFromK8s(t *testing.T) { Type: request.EventTypeHTTP, Peer: "10.0.0.1", Host: "10.0.0.2", - ServiceID: svc.ID{UID: svc.UID{ + Service: svc.Attrs{UID: svc.UID{ Name: "pod2", Namespace: "something", }}, @@ -90,7 +90,7 @@ func TestResolvePodsFromK8s(t *testing.T) { nr.resolveNames(&clientSpan) assert.Equal(t, "pod1", clientSpan.PeerName) - assert.Equal(t, "", clientSpan.ServiceID.UID.Namespace) + assert.Equal(t, "", clientSpan.Service.UID.Namespace) assert.Equal(t, "pod2", clientSpan.HostName) assert.Equal(t, "something", clientSpan.OtherNamespace) @@ -99,7 +99,7 @@ func TestResolvePodsFromK8s(t *testing.T) { assert.Equal(t, "pod1", serverSpan.PeerName) assert.Equal(t, "", serverSpan.OtherNamespace) assert.Equal(t, "pod2", serverSpan.HostName) - assert.Equal(t, "something", serverSpan.ServiceID.UID.Namespace) + assert.Equal(t, "something", serverSpan.Service.UID.Namespace) } func TestResolveServiceFromK8s(t *testing.T) { @@ -142,7 +142,7 @@ func TestResolveServiceFromK8s(t *testing.T) { Type: request.EventTypeHTTPClient, Peer: "10.0.0.1", Host: "10.0.0.2", - ServiceID: svc.ID{UID: svc.UID{ + Service: svc.Attrs{UID: svc.UID{ Name: "pod1", Namespace: "", }}, @@ -152,7 +152,7 @@ func TestResolveServiceFromK8s(t *testing.T) { Type: request.EventTypeHTTP, Peer: "10.0.0.1", Host: "10.0.0.2", - ServiceID: svc.ID{UID: svc.UID{ + Service: svc.Attrs{UID: svc.UID{ Name: "pod2", Namespace: "something", }}, @@ -161,7 +161,7 @@ func TestResolveServiceFromK8s(t *testing.T) { nr.resolveNames(&clientSpan) assert.Equal(t, "pod1", clientSpan.PeerName) - assert.Equal(t, "", clientSpan.ServiceID.UID.Namespace) + assert.Equal(t, "", clientSpan.Service.UID.Namespace) assert.Equal(t, "pod2", clientSpan.HostName) assert.Equal(t, "something", clientSpan.OtherNamespace) @@ -170,11 +170,11 @@ func TestResolveServiceFromK8s(t *testing.T) { assert.Equal(t, "pod1", serverSpan.PeerName) assert.Equal(t, "", serverSpan.OtherNamespace) assert.Equal(t, "pod2", serverSpan.HostName) - assert.Equal(t, "something", serverSpan.ServiceID.UID.Namespace) + assert.Equal(t, "something", serverSpan.Service.UID.Namespace) } func TestCleanName(t *testing.T) { - s := svc.ID{ + s := svc.Attrs{ UID: svc.UID{ Name: "service", Namespace: "special.namespace", @@ -234,7 +234,7 @@ func TestResolveNodesFromK8s(t *testing.T) { Type: request.EventTypeHTTPClient, Peer: "10.0.0.1", Host: "10.0.0.2", - ServiceID: svc.ID{UID: svc.UID{ + Service: svc.Attrs{UID: svc.UID{ Name: "node1", Namespace: "", }}, @@ -244,7 +244,7 @@ func TestResolveNodesFromK8s(t *testing.T) { Type: request.EventTypeHTTP, Peer: "10.0.0.1", Host: "10.0.0.2", - ServiceID: svc.ID{UID: svc.UID{ + Service: svc.Attrs{UID: svc.UID{ Name: "node2", Namespace: "something", }}, @@ -253,7 +253,7 @@ func TestResolveNodesFromK8s(t *testing.T) { nr.resolveNames(&clientSpan) assert.Equal(t, "node1", clientSpan.PeerName) - assert.Equal(t, "", clientSpan.ServiceID.UID.Namespace) + assert.Equal(t, "", clientSpan.Service.UID.Namespace) assert.Equal(t, "node2", clientSpan.HostName) assert.Equal(t, "something", clientSpan.OtherNamespace) @@ -262,5 +262,5 @@ func TestResolveNodesFromK8s(t *testing.T) { assert.Equal(t, "node1", serverSpan.PeerName) assert.Equal(t, "", serverSpan.OtherNamespace) assert.Equal(t, "node2", serverSpan.HostName) - assert.Equal(t, "something", serverSpan.ServiceID.UID.Namespace) + assert.Equal(t, "something", serverSpan.Service.UID.Namespace) }