diff --git a/CHANGELOG.md b/CHANGELOG.md index 5760e39f19fc..934e39531f29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,8 @@ for specific instructions. - [FEATURE] Add `operator-detach` command to agentctl to allow zero-downtime upgrades when removing an Operator CRD. (@rfratto) +- [FEATURE] Service graphs processor (@mapno) + - [ENHANCEMENT] The Grafana Agent Operator will now default to deploying the matching release version of the Grafana Agent instead of v0.14.0. (@rfratto) diff --git a/docs/configuration/traces-config.md b/docs/configuration/traces-config.md index 010c5663b481..7bb1461a515a 100644 --- a/docs/configuration/traces-config.md +++ b/docs/configuration/traces-config.md @@ -195,7 +195,7 @@ spanmetrics: # a complete trace. This is achieved by waiting a given time for all the spans # before evaluating the trace. # -# Tail sampling also supports multiple agent deployments, allowing to group all +# Tail sampling also supports multi agent deployments, allowing to group all # spans of a trace in the same agent by load balancing the spans by trace ID # between the instances. # * To make use of this feature, check load_balancing below * @@ -255,6 +255,33 @@ load_balancing: [ username: ] [ password: ] [ password_file: ] + +# service_graphs configures processing of traces for building service graphs in +# the form of prometheus metrics. The generated metrics represent edges between +# nodes in the graph. Nodes are represented by `client` and `server` labels. +# +# e.g. tempo_service_graph_request_total{client="app", server="db"} 20 +# +# Service graphs works by inspecting spans and looking for the tag `span.kind`. +# If it finds the span kind to be client or server, it stores the request in a +# local in-memory store. +# +# That request waits until its corresponding client or server pair span is +# processed or until the maximum waiting time has passed. +# When either of those conditions is reached, the request is processed and +# removed from the local store. If the request is complete by that time, it'll +# be recorded as an edge in the graph. +# +# Service graphs supports multi agent deployments, allowing to group all spans +# of a trace in the same agent by load balancing the spans by trace ID between +# the instances. +# * To make use of this feature, check load_balancing above * +service_graphs: + [ enabled: | default = false ] + + [ wait: | default = "10s"] + + [ max_items: | default = 10_000 ] ``` > **Note:** More information on the following types can be found on the diff --git a/example/docker-compose/agent/config/agent.yaml b/example/docker-compose/agent/config/agent.yaml index 06ffd2ab992a..228a4f844312 100644 --- a/example/docker-compose/agent/config/agent.yaml +++ b/example/docker-compose/agent/config/agent.yaml @@ -23,7 +23,7 @@ metrics: - job_name: local_scrape static_configs: - - targets: ['127.0.0.1:12345'] + - targets: ['127.0.0.1:12345', '0.0.0.0:8889'] labels: cluster: 'docker_compose' container: 'agent' @@ -97,4 +97,6 @@ traces: processes: true roots: true spanmetrics: - metrics_instance: test + handler_endpoint: 0.0.0.0:8889 + service_graphs: + enabled: true diff --git a/go.mod b/go.mod index 4310499b0e3e..46149db40045 100644 --- a/go.mod +++ b/go.mod @@ -24,10 +24,11 @@ require ( github.com/google/go-jsonnet v0.17.0 github.com/gorilla/mux v1.8.0 github.com/grafana/loki v1.6.2-0.20210429132126-d88f3996eaa2 + github.com/grafana/tempo v1.0.1 github.com/hashicorp/consul/api v1.10.1 github.com/hashicorp/go-cleanhttp v0.5.2 github.com/hashicorp/go-getter v1.5.3 - github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/go-multierror v1.1.1 github.com/infinityworks/github-exporter v0.0.0-20201016091012-831b72461034 github.com/jsternberg/zap-logfmt v1.2.0 github.com/miekg/dns v1.1.42 @@ -40,6 +41,7 @@ require ( github.com/onsi/gomega v1.11.0 // indirect github.com/open-telemetry/opentelemetry-collector-contrib/exporter/loadbalancingexporter v0.36.0 github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusexporter v0.36.0 + github.com/open-telemetry/opentelemetry-collector-contrib/pkg/batchpersignal v0.36.0 github.com/open-telemetry/opentelemetry-collector-contrib/processor/attributesprocessor v0.36.0 github.com/open-telemetry/opentelemetry-collector-contrib/processor/spanmetricsprocessor v0.36.0 github.com/open-telemetry/opentelemetry-collector-contrib/processor/tailsamplingprocessor v0.36.0 @@ -50,6 +52,7 @@ require ( github.com/opentracing-contrib/go-grpc v0.0.0-20210225150812-73cb765af46e github.com/opentracing-contrib/go-stdlib v1.0.0 github.com/opentracing/opentracing-go v1.2.0 + github.com/patrickmn/go-cache v0.0.0-20180527043350-9f6ff22cfff8 github.com/percona/mongodb_exporter v0.0.0-00010101000000-000000000000 github.com/pkg/errors v0.9.1 github.com/prometheus-community/elasticsearch_exporter v1.2.1 diff --git a/go.sum b/go.sum index b498877712e8..7dfac51464c6 100644 --- a/go.sum +++ b/go.sum @@ -56,10 +56,12 @@ cloud.google.com/go/storage v1.3.0/go.mod h1:9IAwXhoyBJ7z9LcAwkj0/7NnPzYaPeZxxVp cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0 h1:STgFzyU5/8miMl0//zKh2aQeTyeaUH3WN9bSUiJ09bA= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.15.0 h1:Ljj+ZXVEhCr/1+4ZhvtteN1ND7UUsNTlduGclLh8GO0= +cloud.google.com/go/storage v1.15.0/go.mod h1:mjjQMoxxyGH7Jr8K5qrx6N2O0AHsczI61sMNn03GIZI= code.cloudfoundry.org/clock v1.0.0/go.mod h1:QD9Lzhd/ux6eNQVUDVRJX/RKTigpewimNYBi7ivZKY8= collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= +contrib.go.opencensus.io/exporter/prometheus v0.2.0/go.mod h1:TYmVAyE8Tn1lyPcltF5IYYfWp2KHu7lQGIZnj8iZMys= contrib.go.opencensus.io/exporter/prometheus v0.4.0 h1:0QfIkj9z/iVZgK31D9H9ohjjIDApI2GOPScCKwxedbs= contrib.go.opencensus.io/exporter/prometheus v0.4.0/go.mod h1:o7cosnyfuPVK0tB8q0QmaQNhGnptITnPQB+z1+qeFB0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -202,6 +204,7 @@ github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE= +github.com/alecthomas/kong v0.2.11/go.mod h1:kQOmtJgV+Lb4aj+I2LEn40cbtawdWJ9Y8QLq+lElKxE= github.com/alecthomas/kong v0.2.17/go.mod h1:ka3VZ8GZNPXv9Ov+j4YNLkI8mTuhXyr/0ktSlqIydQQ= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -966,6 +969,7 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go v2.0.2+incompatible h1:silFMLAnr330+NRuag/VjIGF7TLp/LBrV2CJKFLWEww= @@ -1032,6 +1036,8 @@ github.com/grafana/prometheus v1.8.2-0.20210608193638-7b78de4ccffc h1:brKRMe6V7k github.com/grafana/prometheus v1.8.2-0.20210608193638-7b78de4ccffc/go.mod h1:yUzDYX0hIYu5YVHmpj/JXLOclB6QcLNDgmagD3FUnSU= github.com/grafana/tail v0.0.0-20201004203643-7aa4e4a91f03 h1:fGgFrAraMB0BaPfYumu+iulfDXwHm+GFyHA4xEtBqI8= github.com/grafana/tail v0.0.0-20201004203643-7aa4e4a91f03/go.mod h1:GIMXMPB/lRAllP5rVDvcGif87ryO2hgD7tCtHMdHrho= +github.com/grafana/tempo v1.0.1 h1:8M4u1D/noVASoYmFlDNY9LNerMbVZ+8zPep7Qs0ldfA= +github.com/grafana/tempo v1.0.1/go.mod h1:hd+8igGfN6WE4uIuJxXuPeyZDslpy6Gt0LRAsUWPrKg= github.com/grafana/windows_exporter v0.15.1-0.20210325142439-9e8f66d53433 h1:3WaMH1VOp8T2gCwjM5iHtH2SW3BpN8pAmRhzy9TYVAA= github.com/grafana/windows_exporter v0.15.1-0.20210325142439-9e8f66d53433/go.mod h1:FZy59lGh3jUzgaaS6jYzzTfk1NTNrH5+UK3NCeQF4Ao= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= @@ -1092,6 +1098,7 @@ github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9 github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.12.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v0.14.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs= github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= @@ -1111,6 +1118,7 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-plugin v0.0.0-20180331002553-e8d22c780116/go.mod h1:JSqWYsict+jzcj0+xElxyrBQRPNoiWQuddnxArJ7XHQ= github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= +github.com/hashicorp/go-plugin v1.3.0/go.mod h1:F9eH4LrE/ZsRdbwhfjs9k9HoDUwAHnYtXdgmf1AVNs0= github.com/hashicorp/go-plugin v1.4.3/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ= github.com/hashicorp/go-retryablehttp v0.0.0-20180531211321-3b087ef2d313/go.mod h1:fXcdFsQoipQa7mwORhKad5jmDCeSy/RCGzWA08PO0lM= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= @@ -1297,6 +1305,7 @@ github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdY github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.12/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= @@ -1343,8 +1352,6 @@ github.com/leesper/go_rng v0.0.0-20190531154944-a612b043e353/go.mod h1:N0SVk0uhy github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= github.com/leodido/ragel-machinery v0.0.0-20181214104525-299bdde78165 h1:bCiVCRCs1Heq84lurVinUPy19keqGEe4jh5vtK37jcg= github.com/leodido/ragel-machinery v0.0.0-20181214104525-299bdde78165/go.mod h1:WZxr2/6a/Ar9bMDc2rN/LJrE/hF6bXE4LPyDSIxwAfg= -github.com/leoluk/perflib_exporter v0.1.0 h1:fXe/mDaf9jR+Zk8FjFlcCSksACuIj2VNN4GyKHmQqtA= -github.com/leoluk/perflib_exporter v0.1.0/go.mod h1:rpV0lYj7lemdTm31t7zpCqYqPnw7xs86f+BaaNBVYFM= github.com/lib/pq v0.0.0-20180523175426-90697d60dd84/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -1667,6 +1674,7 @@ github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIw github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/patrickmn/go-cache v0.0.0-20180527043350-9f6ff22cfff8 h1:BR6MM54q4W9pn0SySwg6yctZtBKlTdUq6a+b0kArBnE= github.com/patrickmn/go-cache v0.0.0-20180527043350-9f6ff22cfff8/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= github.com/pborman/getopt v0.0.0-20190409184431-ee0cd42419d3/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= @@ -1693,6 +1701,7 @@ github.com/pierrec/lz4 v2.6.0+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM= github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4/v4 v4.1.1/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pierrec/lz4/v4 v4.1.3/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -1786,6 +1795,7 @@ github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.6.1-0.20210313121648-b565fefb1664 h1:iPfnlmqQag8dZBuhfBlGOWunH3dg/LmHObW/aC283hA= github.com/prometheus/procfs v0.6.1-0.20210313121648-b565fefb1664/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/statsd_exporter v0.15.0/go.mod h1:Dv8HnkoLQkeEjkIE4/2ndAA7WL1zHKK7WMqFQqu72rw= github.com/prometheus/statsd_exporter v0.21.0/go.mod h1:rbT83sZq2V+p73lHhPZfMc3MLCHmSHelCh9hSGYNLTQ= github.com/prometheus/statsd_exporter v0.22.2 h1:mZkkLY25lWw4JmYsvO43MaKcTKshRE6UUC/nkdLgD9I= github.com/prometheus/statsd_exporter v0.22.2/go.mod h1:N4Z1+iSqc9rnxlT1N8Qn3l65Vzb5t4Uq0jpg8nxyhio= @@ -1930,6 +1940,7 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spf13/viper v1.9.0 h1:yR6EXjTp0y0cLN8OZg1CRZmOBdI88UcGkhgyJhu6nZk= github.com/spf13/viper v1.9.0/go.mod h1:+i6ajR7OX2XaiBkrcZJFK21htRk7eDeLg7+O6bhUPP4= @@ -2005,6 +2016,7 @@ github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 h1:nrZ3ySNYwJ github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80/go.mod h1:iFyPdL66DjUD96XmzVL3ZntbzcflLnznH0fr99w5VqE= github.com/tonistiigi/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:Q5IRRDY+cjIaiOjTAnXN5LKQV5MPqVx5ofQn85Jy5Yw= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/uber-go/atomic v1.4.0/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= github.com/uber/jaeger-client-go v2.20.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.22.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-client-go v2.24.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= @@ -2043,8 +2055,10 @@ github.com/wavefronthq/wavefront-sdk-go v0.9.2/go.mod h1:hQI6y8M9OtTCtc0xdwh+dCE github.com/weaveworks/promrus v1.2.0 h1:jOLf6pe6/vss4qGHjXmGz4oDJQA+AOCqEL3FvvZGz7M= github.com/weaveworks/promrus v1.2.0/go.mod h1:SaE82+OJ91yqjrE1rsvBWVzNZKcHYFtMUyS1+Ogs/KA= github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= +github.com/willf/bloom v2.0.3+incompatible/go.mod h1:MmAltL9pDMNTrvUkxdg0k0q5I0suxmuwp3KbyrZLOZ8= github.com/wvanbergen/kafka v0.0.0-20171203153745-e2edea948ddf/go.mod h1:nxx7XRXbR9ykhnC8lXqQyJS0rfvJGxKyKw/sT1YOttg= github.com/wvanbergen/kazoo-go v0.0.0-20180202103751-f72d8611297a/go.mod h1:vQQATAGxVK20DC1rRubTJbZDDhhpA4QfU02pMdPxGO4= github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs= @@ -2378,6 +2392,7 @@ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= @@ -2417,7 +2432,6 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2520,6 +2534,7 @@ golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210412220455-f1c623a9e750/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210503080704-8803ae5d1324/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2701,6 +2716,7 @@ google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBz google.golang.org/api v0.42.0/go.mod h1:+Oj4s6ch2SEGtPjGqfUfZonBH0GjQH89gTeKKAEGZKI= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= +google.golang.org/api v0.45.0/go.mod h1:ISLIJCedJolbZvDfAk+Ctuq5hf+aJ33WgtUsfyFoLXA= google.golang.org/api v0.46.0/go.mod h1:ceL4oozhkAiTID8XMmJBsIxID/9wMXJVVFXPg4ylg3I= google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= @@ -2782,6 +2798,8 @@ google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210312152112-fc591d9ea70f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210413151531-c14fb6ef47c3/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210420162539-3c870d7478d2/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210429181445-86c259c2b4ab/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= diff --git a/pkg/traces/config.go b/pkg/traces/config.go index 08daa7110806..3a1ab30d1958 100644 --- a/pkg/traces/config.go +++ b/pkg/traces/config.go @@ -15,6 +15,7 @@ import ( "github.com/grafana/agent/pkg/traces/noopreceiver" "github.com/grafana/agent/pkg/traces/promsdprocessor" "github.com/grafana/agent/pkg/traces/remotewriteexporter" + "github.com/grafana/agent/pkg/traces/servicegraphprocessor" "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/loadbalancingexporter" "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusexporter" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/attributesprocessor" @@ -122,10 +123,13 @@ type InstanceConfig struct { AutomaticLogging *automaticloggingprocessor.AutomaticLoggingConfig `yaml:"automatic_logging,omitempty"` // TailSampling defines a sampling strategy for the pipeline - TailSampling *tailSamplingConfig `yaml:"tail_sampling"` + TailSampling *tailSamplingConfig `yaml:"tail_sampling,omitempty"` // LoadBalancing is used to distribute spans of the same trace to the same agent instance LoadBalancing *loadBalancingConfig `yaml:"load_balancing"` + + // ServiceGraphs + ServiceGraphs *serviceGraphsConfig `yaml:"service_graphs,omitempty"` } const ( @@ -243,6 +247,12 @@ type exporterConfig struct { BasicAuth *prom_config.BasicAuth `yaml:"basic_auth,omitempty"` } +type serviceGraphsConfig struct { + Enabled bool `yaml:"enabled,omitempty"` + Wait time.Duration `yaml:"wait,omitempty"` + MaxItems int `yaml:"max_items,omitempty"` +} + // exporter builds an OTel exporter from RemoteWriteConfig func exporter(rwCfg RemoteWriteConfig) (map[string]interface{}, error) { if len(rwCfg.Endpoint) == 0 { @@ -564,6 +574,14 @@ func (c *InstanceConfig) otelConfig() (*config.Config, error) { } } + if c.ServiceGraphs != nil && c.ServiceGraphs.Enabled { + processors[servicegraphprocessor.TypeStr] = map[string]interface{}{ + "wait": c.ServiceGraphs.Wait, + "max_items": c.ServiceGraphs.MaxItems, + } + processorNames = append(processorNames, servicegraphprocessor.TypeStr) + } + // Build Pipelines splitPipeline := c.LoadBalancing != nil orderedSplitProcessors := orderProcessors(processorNames, splitPipeline) @@ -660,6 +678,7 @@ func tracingFactories() (component.Factories, error) { spanmetricsprocessor.NewFactory(), automaticloggingprocessor.NewFactory(), tailsamplingprocessor.NewFactory(), + servicegraphprocessor.NewFactory(), ) if err != nil { return component.Factories{}, err @@ -680,9 +699,10 @@ func orderProcessors(processors []string, splitPipelines bool) [][]string { order := map[string]int{ "attributes": 0, "spanmetrics": 1, - "tail_sampling": 2, - "automatic_logging": 3, - "batch": 4, + "service_graphs": 2, + "tail_sampling": 3, + "automatic_logging": 4, + "batch": 5, } sort.Slice(processors, func(i, j int) bool { diff --git a/pkg/traces/config_test.go b/pkg/traces/config_test.go index 5d51159acc95..4c8e33396c3b 100644 --- a/pkg/traces/config_test.go +++ b/pkg/traces/config_test.go @@ -869,6 +869,39 @@ service: exporters: ["otlphttp/0", "otlp/1"] processors: [] receivers: ["jaeger"] +`, + }, + { + name: "service graphs", + cfg: ` +receivers: + jaeger: + protocols: + grpc: +remote_write: + - endpoint: example.com:12345 +service_graphs: + enabled: true +`, + expectedConfig: ` +receivers: + jaeger: + protocols: + grpc: +exporters: + otlp/0: + endpoint: example.com:12345 + compression: gzip + retry_on_failure: + max_elapsed_time: 60s +processors: + service_graphs: +service: + pipelines: + traces: + exporters: ["otlp/0"] + processors: ["service_graphs"] + receivers: ["jaeger"] `, }, { @@ -1006,11 +1039,14 @@ tail_sampling: values: - value1 - value2 +service_graphs: + enabled: true `, expectedProcessors: map[string][]config.ComponentID{ "traces": { config.NewID("attributes"), config.NewID("spanmetrics"), + config.NewID("service_graphs"), config.NewID("tail_sampling"), config.NewID("automatic_logging"), config.NewID("batch"), @@ -1062,11 +1098,14 @@ load_balancing: dns: hostname: agent port: 4318 +service_graphs: + enabled: true `, expectedProcessors: map[string][]config.ComponentID{ "traces/0": { config.NewID("attributes"), config.NewID("spanmetrics"), + config.NewID("service_graphs"), }, "traces/1": { config.NewID("tail_sampling"), diff --git a/pkg/traces/contextkeys/keys.go b/pkg/traces/contextkeys/keys.go index a43342d09eb7..a6049731de8a 100644 --- a/pkg/traces/contextkeys/keys.go +++ b/pkg/traces/contextkeys/keys.go @@ -8,4 +8,7 @@ const ( // Metrics is used to pass instance.Manager through the context Metrics + + // PrometheusRegisterer is used to pass prometheus.Registerer through the context + PrometheusRegisterer ) diff --git a/pkg/traces/instance.go b/pkg/traces/instance.go index b3cc6321a195..dc3ec53901ea 100644 --- a/pkg/traces/instance.go +++ b/pkg/traces/instance.go @@ -9,6 +9,7 @@ import ( "github.com/grafana/agent/pkg/build" "github.com/grafana/agent/pkg/logs" "github.com/grafana/agent/pkg/metrics/instance" + "github.com/grafana/agent/pkg/traces/automaticloggingprocessor" "github.com/grafana/agent/pkg/traces/contextkeys" "github.com/grafana/agent/pkg/util" "github.com/prometheus/client_golang/prometheus" @@ -44,14 +45,14 @@ func NewInstance(logsSubsystem *logs.Logs, reg prometheus.Registerer, cfg Instan return nil, fmt.Errorf("failed to create metric views: %w", err) } - if err := instance.ApplyConfig(logsSubsystem, promInstanceManager, cfg); err != nil { + if err := instance.ApplyConfig(logsSubsystem, promInstanceManager, reg, cfg); err != nil { return nil, err } return instance, nil } // ApplyConfig updates the configuration of the Instance. -func (i *Instance) ApplyConfig(logsSubsystem *logs.Logs, promInstanceManager instance.Manager, cfg InstanceConfig) error { +func (i *Instance) ApplyConfig(logsSubsystem *logs.Logs, promInstanceManager instance.Manager, reg prometheus.Registerer, cfg InstanceConfig) error { i.mut.Lock() defer i.mut.Unlock() @@ -64,8 +65,7 @@ func (i *Instance) ApplyConfig(logsSubsystem *logs.Logs, promInstanceManager ins // Shut down any existing pipeline i.stop() - createCtx := context.WithValue(context.Background(), contextkeys.Logs, logsSubsystem) - err := i.buildAndStartPipeline(createCtx, cfg, promInstanceManager) + err := i.buildAndStartPipeline(context.Background(), cfg, logsSubsystem, promInstanceManager, reg) if err != nil { return fmt.Errorf("failed to create pipeline: %w", err) } @@ -131,7 +131,7 @@ func (i *Instance) stop() { i.exporter = nil } -func (i *Instance) buildAndStartPipeline(ctx context.Context, cfg InstanceConfig, promManager instance.Manager) error { +func (i *Instance) buildAndStartPipeline(ctx context.Context, cfg InstanceConfig, logs *logs.Logs, instManager instance.Manager, reg prometheus.Registerer) error { // create component factories otelConfig, err := cfg.otelConfig() if err != nil { @@ -150,12 +150,20 @@ func (i *Instance) buildAndStartPipeline(ctx context.Context, cfg InstanceConfig } if cfg.SpanMetrics != nil && len(cfg.SpanMetrics.MetricsInstance) != 0 { - ctx = context.WithValue(ctx, contextkeys.Metrics, promManager) + ctx = context.WithValue(ctx, contextkeys.Metrics, instManager) } - if cfg.TailSampling != nil && cfg.LoadBalancing == nil { - i.logger.Warn("Configuring tail_sampling without load_balance." + - "Load balancing is required for tail sampling to properly work in multi instance deployments") + if cfg.LoadBalancing == nil && (cfg.TailSampling != nil || cfg.ServiceGraphs != nil) { + i.logger.Warn("Configuring tail_sampling and/or service_graphs without load_balance." + + "Load balancing is required for those features to properly work in multi agent deployments") + } + + if cfg.AutomaticLogging != nil && cfg.AutomaticLogging.Backend != automaticloggingprocessor.BackendStdout { + ctx = context.WithValue(ctx, contextkeys.Logs, logs) + } + + if cfg.ServiceGraphs != nil { + ctx = context.WithValue(ctx, contextkeys.PrometheusRegisterer, reg) } factories, err := tracingFactories() diff --git a/pkg/traces/remotewriteexporter/exporter.go b/pkg/traces/remotewriteexporter/exporter.go index 17fe6fa0240f..2f7b4319d9e3 100644 --- a/pkg/traces/remotewriteexporter/exporter.go +++ b/pkg/traces/remotewriteexporter/exporter.go @@ -70,7 +70,7 @@ func newRemoteWriteExporter(cfg *Config) (component.MetricsExporter, error) { func (e *remoteWriteExporter) Start(ctx context.Context, _ component.Host) error { manager, ok := ctx.Value(contextkeys.Metrics).(instance.Manager) if !ok || manager == nil { - return fmt.Errorf("key does not contain a Prometheus instance") + return fmt.Errorf("key does not contain a InstanceManager instance") } e.manager = manager return nil diff --git a/pkg/traces/remotewriteexporter/factory.go b/pkg/traces/remotewriteexporter/factory.go index 7cbbca46193b..96a10d2ea8f5 100644 --- a/pkg/traces/remotewriteexporter/factory.go +++ b/pkg/traces/remotewriteexporter/factory.go @@ -20,7 +20,7 @@ type label struct { var _ config.Exporter = (*Config)(nil) -// Config holds the configuration for the Prometheus SD processor. +// Config holds the configuration for the Prometheus remote write processor. type Config struct { config.ExporterSettings `mapstructure:",squash"` @@ -29,7 +29,7 @@ type Config struct { PromInstance string `mapstructure:"metrics_instance"` } -// NewFactory returns a new factory for the Attributes processor. +// NewFactory returns a new factory for the Prometheus remote write processor. func NewFactory() component.ExporterFactory { return exporterhelper.NewFactory( TypeStr, diff --git a/pkg/traces/servicegraphprocessor/factory.go b/pkg/traces/servicegraphprocessor/factory.go new file mode 100644 index 000000000000..1c752cb47526 --- /dev/null +++ b/pkg/traces/servicegraphprocessor/factory.go @@ -0,0 +1,62 @@ +package servicegraphprocessor + +import ( + "context" + "time" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/config" + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/processor/processorhelper" +) + +const ( + // TypeStr is the unique identifier for the Prometheus service graph exporter. + TypeStr = "service_graphs" + + // DefaultWait is the default value to wait for an edgeRequest to be completed + DefaultWait = time.Second * 10 + // DefaultMaxItems is the default amount of edges that will be stored in the store + DefaultMaxItems = 10_000 +) + +// Config holds the configuration for the Prometheus service graph processor. +type Config struct { + config.ProcessorSettings `mapstructure:",squash"` + + Wait time.Duration `mapstructure:"wait"` + MaxItems int `mapstructure:"max_items"` + + SuccessCodes *successCodes `mapstructure:"success_codes"` +} + +type successCodes struct { + http []int64 `mapstructure:"http"` + grpc []int64 `mapstructure:"grpc"` +} + +// NewFactory returns a new factory for the Prometheus service graph processor. +func NewFactory() component.ProcessorFactory { + return processorhelper.NewFactory( + TypeStr, + createDefaultConfig, + processorhelper.WithTraces(createTracesProcessor), + ) +} + +func createDefaultConfig() config.Processor { + return &Config{ + ProcessorSettings: config.NewProcessorSettings(config.NewIDWithName(TypeStr, TypeStr)), + } +} + +func createTracesProcessor( + _ context.Context, + _ component.ProcessorCreateSettings, + cfg config.Processor, + nextConsumer consumer.Traces, +) (component.TracesProcessor, error) { + eCfg := cfg.(*Config) + + return newProcessor(nextConsumer, eCfg), nil +} diff --git a/pkg/traces/servicegraphprocessor/processor.go b/pkg/traces/servicegraphprocessor/processor.go new file mode 100644 index 000000000000..2bc728b6c472 --- /dev/null +++ b/pkg/traces/servicegraphprocessor/processor.go @@ -0,0 +1,313 @@ +package servicegraphprocessor + +import ( + "context" + "errors" + "fmt" + "time" + + util "github.com/cortexproject/cortex/pkg/util/log" + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/log/level" + "github.com/grafana/agent/pkg/traces/contextkeys" + "github.com/hashicorp/go-multierror" + "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/batchpersignal" + "github.com/patrickmn/go-cache" + "github.com/prometheus/client_golang/prometheus" + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/model/pdata" + semconv "go.opentelemetry.io/collector/model/semconv/v1.6.1" + "google.golang.org/grpc/codes" +) + +var ( + errTooManyItems = errors.New("too many items in store") +) + +// edgeRequest is a request between two nodes in the graph +type edgeRequest struct { + serverService, clientService string + serverLatency, clientLatency time.Duration + + // If either the client or the server spans have status code error, + // the request will be considered as failed. + failed bool +} + +// complete returns true if the corresponding client and server +// pair spans have been processed for the given request +func (e *edgeRequest) complete() bool { + return len(e.clientService) != 0 && len(e.serverService) != 0 +} + +var _ component.TracesProcessor = (*processor)(nil) + +type processor struct { + nextConsumer consumer.Traces + reg prometheus.Registerer + + // store is a local storage for request between graphs nodes + store *cache.Cache + maxItems int + + serviceGraphRequestTotal *prometheus.CounterVec + serviceGraphRequestFailedTotal *prometheus.CounterVec + serviceGraphRequestServerHistogram *prometheus.HistogramVec + serviceGraphRequestClientHistogram *prometheus.HistogramVec + serviceGraphUnpairedSpansTotal *prometheus.CounterVec + serviceGraphDroppedSpansTotal *prometheus.CounterVec + + httpSuccessCode map[int]struct{} + grpcSuccessCode map[int]struct{} + + logger log.Logger +} + +func newProcessor(nextConsumer consumer.Traces, cfg *Config) *processor { + logger := log.With(util.Logger, "component", "tempo service graphs") + + if cfg.Wait == 0 { + cfg.Wait = DefaultWait + } + if cfg.MaxItems == 0 { + cfg.MaxItems = DefaultMaxItems + } + + var ( + httpSuccessCode = make(map[int]struct{}) + grpcSuccessCode = make(map[int]struct{}) + ) + if cfg.SuccessCodes != nil { + for _, sc := range cfg.SuccessCodes.http { + httpSuccessCode[int(sc)] = struct{}{} + } + for _, sc := range cfg.SuccessCodes.grpc { + grpcSuccessCode[int(sc)] = struct{}{} + } + } + + // TODO(mapno): Add support for an external cache (e.g. memcached) + p := &processor{ + nextConsumer: nextConsumer, + // Cleanup period is hardcoded to twice the waiting time for simplicity + // Most likely not ideal in every scenario + store: cache.New(cfg.Wait, cfg.Wait*2), + maxItems: cfg.MaxItems, + logger: logger, + } + + return p +} + +func (p *processor) Start(ctx context.Context, _ component.Host) error { + reg, ok := ctx.Value(contextkeys.PrometheusRegisterer).(prometheus.Registerer) + if !ok || reg == nil { + return fmt.Errorf("key does not contain a prometheus registerer") + } + p.reg = reg + return p.registerMetrics() +} + +func (p *processor) registerMetrics() error { + p.serviceGraphRequestTotal = prometheus.NewCounterVec(prometheus.CounterOpts{ + Name: "tempo_service_graph_request_total", + Help: "Total count of requests between two nodes", + }, []string{"client", "server"}) + p.serviceGraphRequestFailedTotal = prometheus.NewCounterVec(prometheus.CounterOpts{ + Name: "tempo_service_graph_request_failed_total", + Help: "Total count of failed requests between two nodes", + }, []string{"client", "server"}) + p.serviceGraphRequestServerHistogram = prometheus.NewHistogramVec(prometheus.HistogramOpts{ + Name: "tempo_service_graph_request_server_seconds", + Help: "Time for a request between two nodes as seen from the server", + Buckets: prometheus.ExponentialBuckets(0.01, 2, 12), + }, []string{"client", "server"}) + p.serviceGraphRequestClientHistogram = prometheus.NewHistogramVec(prometheus.HistogramOpts{ + Name: "tempo_service_graph_request_client_seconds", + Help: "Time for a request between two nodes as seen from the client", + Buckets: prometheus.ExponentialBuckets(0.01, 2, 12), + }, []string{"client", "server"}) + p.serviceGraphUnpairedSpansTotal = prometheus.NewCounterVec(prometheus.CounterOpts{ + Name: "tempo_service_graph_unpaired_spans_total", + Help: "Total count of unpaired spans", + }, []string{"client", "server"}) + p.serviceGraphDroppedSpansTotal = prometheus.NewCounterVec(prometheus.CounterOpts{ + Name: "tempo_service_graph_dropped_spans_total", + Help: "Total count of dropped spans", + }, []string{"service"}) + + cs := []prometheus.Collector{ + p.serviceGraphRequestTotal, + p.serviceGraphRequestFailedTotal, + p.serviceGraphRequestServerHistogram, + p.serviceGraphRequestClientHistogram, + p.serviceGraphUnpairedSpansTotal, + p.serviceGraphDroppedSpansTotal, + } + + for _, c := range cs { + if err := p.reg.Register(c); err != nil { + return err + } + } + + // Collect unpaired spans when evicting items from the store during + // periodic cleanup + p.store.OnEvicted(func(s string, i interface{}) { + e := i.(edgeRequest) + if !e.complete() { + p.serviceGraphUnpairedSpansTotal.WithLabelValues(e.clientService, e.serverService).Inc() + } + }) + + return nil +} + +func (p *processor) Shutdown(context.Context) error { + p.unregisterMetrics() + p.store.Flush() + return nil +} + +func (p *processor) unregisterMetrics() { + cs := []prometheus.Collector{ + p.serviceGraphRequestTotal, + p.serviceGraphRequestFailedTotal, + p.serviceGraphRequestServerHistogram, + p.serviceGraphRequestClientHistogram, + p.serviceGraphUnpairedSpansTotal, + } + + for _, c := range cs { + p.reg.Unregister(c) + } +} + +func (p *processor) Capabilities() consumer.Capabilities { + return consumer.Capabilities{} +} + +func (p *processor) ConsumeTraces(ctx context.Context, td pdata.Traces) error { + level.Debug(p.logger).Log("msg", "consuming traces") + + var errs error + for _, trace := range batchpersignal.SplitTraces(td) { + if err := p.consume(trace); err != nil { + if errors.Is(err, errTooManyItems) { + level.Info(p.logger).Log("msg", "skipped processing of spans", "maxItems", p.maxItems, "err", errTooManyItems) + break + } + errs = multierror.Append(errs, err) + } + } + if errs != nil { + level.Error(p.logger).Log("msg", "failed consuming traces", "err", errs) + } + + p.collectMetrics() + + return p.nextConsumer.ConsumeTraces(ctx, td) +} + +func (p *processor) collectMetrics() { + for k, v := range p.store.Items() { + e := v.Object.(edgeRequest) + if e.complete() { + p.serviceGraphRequestTotal.WithLabelValues(e.clientService, e.serverService).Inc() + if e.failed { + p.serviceGraphRequestFailedTotal.WithLabelValues(e.clientService, e.serverService).Inc() + } + p.serviceGraphRequestServerHistogram.WithLabelValues(e.clientService, e.serverService).Observe(e.serverLatency.Seconds()) + p.serviceGraphRequestClientHistogram.WithLabelValues(e.clientService, e.serverService).Observe(e.clientLatency.Seconds()) + p.store.Delete(k) + } + } +} + +func (p *processor) consume(trace pdata.Traces) error { + rSpansSlice := trace.ResourceSpans() + for i := 0; i < rSpansSlice.Len(); i++ { + rSpan := rSpansSlice.At(i) + + svc, ok := rSpan.Resource().Attributes().Get(semconv.AttributeServiceName) + if !ok { + continue + } + + ilsSlice := rSpan.InstrumentationLibrarySpans() + for j := 0; j < ilsSlice.Len(); j++ { + ils := ilsSlice.At(j) + + for k := 0; k < ils.Spans().Len(); k++ { + + if p.store.ItemCount() >= p.maxItems { + remainingSpans := float64(ils.Spans().Len() - k) + p.serviceGraphDroppedSpansTotal.WithLabelValues(svc.StringVal()).Add(remainingSpans) + + return errTooManyItems + } + + span := ils.Spans().At(k) + + switch span.Kind() { + case pdata.SpanKindClient: + k := key(span.TraceID().HexString(), span.SpanID().HexString()) + + var r edgeRequest + if v, ok := p.store.Get(k); ok { + r = v.(edgeRequest) + } + r.clientService = svc.StringVal() + r.clientLatency = spanDuration(span) + r.failed = p.spanFailed(span) + p.store.SetDefault(k, r) + + case pdata.SpanKindServer: + k := key(span.TraceID().HexString(), span.ParentSpanID().HexString()) + + var r edgeRequest + if v, ok := p.store.Get(k); ok { + r = v.(edgeRequest) + } + + r.serverService = svc.StringVal() + r.serverLatency = spanDuration(span) + r.failed = p.spanFailed(span) + p.store.SetDefault(k, r) + + default: + } + } + } + } + return nil +} + +func (p *processor) spanFailed(span pdata.Span) bool { + // Request considered failed if status is not 2XX or added as a successful status code + if statusCode, ok := span.Attributes().Get("http.status_code"); ok { + sc := int(statusCode.IntVal()) + if _, ok := p.httpSuccessCode[sc]; !ok || sc/100 != 2 { + return true + } + } + + // Request considered failed if status is not OK or added as a successful status code + if statusCode, ok := span.Attributes().Get("grpc.status_code"); ok { + sc := int(statusCode.IntVal()) + if _, ok := p.grpcSuccessCode[sc]; !ok || sc != int(codes.OK) { + return true + } + } + + return span.Status().Code() == pdata.StatusCodeError +} + +func spanDuration(span pdata.Span) time.Duration { + return span.EndTimestamp().AsTime().Sub(span.StartTimestamp().AsTime()) +} + +func key(k1, k2 string) string { + return fmt.Sprintf("%s-%s", k1, k2) +} diff --git a/pkg/traces/servicegraphprocessor/processor_test.go b/pkg/traces/servicegraphprocessor/processor_test.go new file mode 100644 index 000000000000..a32e9c8d4e50 --- /dev/null +++ b/pkg/traces/servicegraphprocessor/processor_test.go @@ -0,0 +1,192 @@ +package servicegraphprocessor + +import ( + "bytes" + "context" + "os" + "testing" + "time" + + "github.com/gogo/protobuf/jsonpb" + "github.com/grafana/agent/pkg/traces/contextkeys" + "github.com/grafana/tempo/pkg/tempopb" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/testutil" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/model/otlp" + "go.opentelemetry.io/collector/model/pdata" +) + +const ( + traceSamplePath = "testdata/trace-sample.json" + unpairedTraceSamplePath = "testdata/unpaired-trace-sample.json" +) + +func TestConsumeMetrics(t *testing.T) { + for _, tc := range []struct { + name string + sampleDataPath string + cfg *Config + expectedMetrics string + }{ + { + name: "happy case", + sampleDataPath: traceSamplePath, + cfg: &Config{}, + expectedMetrics: happyCaseExpectedMetrics, + }, + { + name: "unpaired spans", + sampleDataPath: unpairedTraceSamplePath, + cfg: &Config{ + Wait: time.Millisecond, + }, + expectedMetrics: ` + # HELP tempo_service_graph_unpaired_spans_total Total count of unpaired spans + # TYPE tempo_service_graph_unpaired_spans_total counter + tempo_service_graph_unpaired_spans_total{client="",server="db"} 2 + tempo_service_graph_unpaired_spans_total{client="app",server=""} 3 + tempo_service_graph_unpaired_spans_total{client="lb",server=""} 3 +`, + }, + { + name: "max items in store is reached", + sampleDataPath: traceSamplePath, + cfg: &Config{ + Wait: time.Millisecond, + MaxItems: 1, // Configure max number of items in store to 1. Only one edgeRequest will be processed. + }, + expectedMetrics: ` + # HELP tempo_service_graph_dropped_spans_total Total count of dropped spans + # TYPE tempo_service_graph_dropped_spans_total counter + tempo_service_graph_dropped_spans_total{service="lb"} 1 + # HELP tempo_service_graph_unpaired_spans_total Total count of unpaired spans + # TYPE tempo_service_graph_unpaired_spans_total counter + tempo_service_graph_unpaired_spans_total{client="lb",server=""} 1 +`, + }, + } { + t.Run(tc.name, func(t *testing.T) { + p := newProcessor(&mockConsumer{}, tc.cfg) + + reg := prometheus.NewRegistry() + ctx := context.WithValue(context.Background(), contextkeys.PrometheusRegisterer, reg) + + err := p.Start(ctx, nil) + require.NoError(t, err) + + traces := traceSamples(t, tc.sampleDataPath) + err = p.ConsumeTraces(context.Background(), traces) + require.NoError(t, err) + + assert.Eventually(t, func() bool { + return testutil.GatherAndCompare(reg, bytes.NewBufferString(tc.expectedMetrics)) == nil + }, time.Second, time.Millisecond*100) + err = testutil.GatherAndCompare(reg, bytes.NewBufferString(tc.expectedMetrics)) + require.NoError(t, err) + }) + } + +} + +func traceSamples(t *testing.T, path string) pdata.Traces { + f, err := os.Open(path) + require.NoError(t, err) + + r := &tempopb.Trace{} + err = jsonpb.Unmarshal(f, r) + require.NoError(t, err) + + b, err := r.Marshal() + require.NoError(t, err) + + traces, err := otlp.NewProtobufTracesUnmarshaler().UnmarshalTraces(b) + require.NoError(t, err) + + return traces +} + +type mockConsumer struct{} + +func (m *mockConsumer) Capabilities() consumer.Capabilities { return consumer.Capabilities{} } + +func (m *mockConsumer) ConsumeTraces(context.Context, pdata.Traces) error { return nil } + +const ( + happyCaseExpectedMetrics = ` + # HELP tempo_service_graph_request_client_seconds Time for a request between two nodes as seen from the client + # TYPE tempo_service_graph_request_client_seconds histogram + tempo_service_graph_request_client_seconds_bucket{client="app",server="db",le="0.01"} 0 + tempo_service_graph_request_client_seconds_bucket{client="app",server="db",le="0.02"} 0 + tempo_service_graph_request_client_seconds_bucket{client="app",server="db",le="0.04"} 0 + tempo_service_graph_request_client_seconds_bucket{client="app",server="db",le="0.08"} 0 + tempo_service_graph_request_client_seconds_bucket{client="app",server="db",le="0.16"} 0 + tempo_service_graph_request_client_seconds_bucket{client="app",server="db",le="0.32"} 0 + tempo_service_graph_request_client_seconds_bucket{client="app",server="db",le="0.64"} 0 + tempo_service_graph_request_client_seconds_bucket{client="app",server="db",le="1.28"} 2 + tempo_service_graph_request_client_seconds_bucket{client="app",server="db",le="2.56"} 3 + tempo_service_graph_request_client_seconds_bucket{client="app",server="db",le="5.12"} 3 + tempo_service_graph_request_client_seconds_bucket{client="app",server="db",le="10.24"} 3 + tempo_service_graph_request_client_seconds_bucket{client="app",server="db",le="20.48"} 3 + tempo_service_graph_request_client_seconds_bucket{client="app",server="db",le="+Inf"} 3 + tempo_service_graph_request_client_seconds_sum{client="app",server="db"} 4.4 + tempo_service_graph_request_client_seconds_count{client="app",server="db"} 3 + tempo_service_graph_request_client_seconds_bucket{client="lb",server="app",le="0.01"} 0 + tempo_service_graph_request_client_seconds_bucket{client="lb",server="app",le="0.02"} 0 + tempo_service_graph_request_client_seconds_bucket{client="lb",server="app",le="0.04"} 0 + tempo_service_graph_request_client_seconds_bucket{client="lb",server="app",le="0.08"} 0 + tempo_service_graph_request_client_seconds_bucket{client="lb",server="app",le="0.16"} 0 + tempo_service_graph_request_client_seconds_bucket{client="lb",server="app",le="0.32"} 0 + tempo_service_graph_request_client_seconds_bucket{client="lb",server="app",le="0.64"} 0 + tempo_service_graph_request_client_seconds_bucket{client="lb",server="app",le="1.28"} 0 + tempo_service_graph_request_client_seconds_bucket{client="lb",server="app",le="2.56"} 2 + tempo_service_graph_request_client_seconds_bucket{client="lb",server="app",le="5.12"} 3 + tempo_service_graph_request_client_seconds_bucket{client="lb",server="app",le="10.24"} 3 + tempo_service_graph_request_client_seconds_bucket{client="lb",server="app",le="20.48"} 3 + tempo_service_graph_request_client_seconds_bucket{client="lb",server="app",le="+Inf"} 3 + tempo_service_graph_request_client_seconds_sum{client="lb",server="app"} 7.8 + tempo_service_graph_request_client_seconds_count{client="lb",server="app"} 3 + # HELP tempo_service_graph_request_failed_total Total count of failed requests between two nodes + # TYPE tempo_service_graph_request_failed_total counter + tempo_service_graph_request_failed_total{client="app",server="db"} 3 + tempo_service_graph_request_failed_total{client="lb",server="app"} 3 + # HELP tempo_service_graph_request_server_seconds Time for a request between two nodes as seen from the server + # TYPE tempo_service_graph_request_server_seconds histogram + tempo_service_graph_request_server_seconds_bucket{client="app",server="db",le="0.01"} 0 + tempo_service_graph_request_server_seconds_bucket{client="app",server="db",le="0.02"} 0 + tempo_service_graph_request_server_seconds_bucket{client="app",server="db",le="0.04"} 0 + tempo_service_graph_request_server_seconds_bucket{client="app",server="db",le="0.08"} 0 + tempo_service_graph_request_server_seconds_bucket{client="app",server="db",le="0.16"} 0 + tempo_service_graph_request_server_seconds_bucket{client="app",server="db",le="0.32"} 0 + tempo_service_graph_request_server_seconds_bucket{client="app",server="db",le="0.64"} 0 + tempo_service_graph_request_server_seconds_bucket{client="app",server="db",le="1.28"} 1 + tempo_service_graph_request_server_seconds_bucket{client="app",server="db",le="2.56"} 3 + tempo_service_graph_request_server_seconds_bucket{client="app",server="db",le="5.12"} 3 + tempo_service_graph_request_server_seconds_bucket{client="app",server="db",le="10.24"} 3 + tempo_service_graph_request_server_seconds_bucket{client="app",server="db",le="20.48"} 3 + tempo_service_graph_request_server_seconds_bucket{client="app",server="db",le="+Inf"} 3 + tempo_service_graph_request_server_seconds_sum{client="app",server="db"} 5 + tempo_service_graph_request_server_seconds_count{client="app",server="db"} 3 + tempo_service_graph_request_server_seconds_bucket{client="lb",server="app",le="0.01"} 0 + tempo_service_graph_request_server_seconds_bucket{client="lb",server="app",le="0.02"} 0 + tempo_service_graph_request_server_seconds_bucket{client="lb",server="app",le="0.04"} 0 + tempo_service_graph_request_server_seconds_bucket{client="lb",server="app",le="0.08"} 0 + tempo_service_graph_request_server_seconds_bucket{client="lb",server="app",le="0.16"} 0 + tempo_service_graph_request_server_seconds_bucket{client="lb",server="app",le="0.32"} 0 + tempo_service_graph_request_server_seconds_bucket{client="lb",server="app",le="0.64"} 0 + tempo_service_graph_request_server_seconds_bucket{client="lb",server="app",le="1.28"} 1 + tempo_service_graph_request_server_seconds_bucket{client="lb",server="app",le="2.56"} 2 + tempo_service_graph_request_server_seconds_bucket{client="lb",server="app",le="5.12"} 3 + tempo_service_graph_request_server_seconds_bucket{client="lb",server="app",le="10.24"} 3 + tempo_service_graph_request_server_seconds_bucket{client="lb",server="app",le="20.48"} 3 + tempo_service_graph_request_server_seconds_bucket{client="lb",server="app",le="+Inf"} 3 + tempo_service_graph_request_server_seconds_sum{client="lb",server="app"} 6.2 + tempo_service_graph_request_server_seconds_count{client="lb",server="app"} 3 + # HELP tempo_service_graph_request_total Total count of requests between two nodes + # TYPE tempo_service_graph_request_total counter + tempo_service_graph_request_total{client="app",server="db"} 3 + tempo_service_graph_request_total{client="lb",server="app"} 3 +` +) diff --git a/pkg/traces/servicegraphprocessor/testdata/trace-sample.json b/pkg/traces/servicegraphprocessor/testdata/trace-sample.json new file mode 100644 index 000000000000..763a70658fc1 --- /dev/null +++ b/pkg/traces/servicegraphprocessor/testdata/trace-sample.json @@ -0,0 +1,1916 @@ +{ + "batches":[ + { + "resource":{ + "attributes":[ + { + "key":"service.name", + "value":{ + "stringValue":"lb" + } + }, + { + "key":"cluster", + "value":{ + "stringValue":"tns-demo" + } + }, + { + "key":"namespace", + "value":{ + "stringValue":"tns-demo" + } + }, + { + "key":"opencensus.exporterversion", + "value":{ + "stringValue":"Jaeger-Go-2.22.1" + } + }, + { + "key":"host.name", + "value":{ + "stringValue":"loadgen-6b59dff4c-jdkdk" + } + }, + { + "key":"ip", + "value":{ + "stringValue":"10.136.11.153" + } + }, + { + "key":"client-uuid", + "value":{ + "stringValue":"653fad9a76c115ac" + } + }, + { + "key":"container", + "value":{ + "stringValue":"loadgen" + } + }, + { + "key":"pod", + "value":{ + "stringValue":"loadgen-6b59dff4c-jdkdk" + } + } + ] + }, + "instrumentationLibrarySpans":[ + { + "instrumentationLibrary":{ + + }, + "spans":[ + { + "traceId":"AAAAAAAAAABbdZuWJO/uiw==", + "spanId":"W3WbliTv7os=", + "name":"HTTP Client", + "startTimeUnixNano":"1626717505784699000", + "endTimeUnixNano":"1626717505833874000", + "attributes":[ + { + "key":"sampler.type", + "value":{ + "stringValue":"const" + } + }, + { + "key":"sampler.param", + "value":{ + "boolValue":true + } + } + ], + "status":{ + + } + }, + { + "traceId":"AAAAAAAAAABbdZuWJO/uiw==", + "spanId":"d5ZXpoG4mUc=", + "parentSpanId":"W3WbliTv7os=", + "name":"HTTP POST", + "kind":"SPAN_KIND_CLIENT", + "startTimeUnixNano":"1626717503329568000", + "endTimeUnixNano":"1626717505829568000", + "attributes":[ + { + "key":"http.status_code", + "value":{ + "intValue":"302" + } + }, + { + "key":"component", + "value":{ + "stringValue":"net/http" + } + }, + { + "key":"http.method", + "value":{ + "stringValue":"POST" + } + }, + { + "key":"http.url", + "value":{ + "stringValue":"app:80" + } + }, + { + "key":"net/http.reused", + "value":{ + "boolValue":false + } + }, + { + "key":"net/http.was_idle", + "value":{ + "boolValue":false + } + } + ], + "events":[ + { + "timeUnixNano":"1626717505784725000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GetConn" + } + } + ] + }, + { + "timeUnixNano":"1626717505784771000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"DNSStart" + } + }, + { + "key":"host", + "value":{ + "stringValue":"app" + } + } + ] + }, + { + "timeUnixNano":"1626717505822812000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"DNSDone" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.116.196" + } + } + ] + }, + { + "timeUnixNano":"1626717505822821000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ConnectStart" + } + }, + { + "key":"network", + "value":{ + "stringValue":"tcp" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.116.196:80" + } + } + ] + }, + { + "timeUnixNano":"1626717505822983000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ConnectDone" + } + }, + { + "key":"network", + "value":{ + "stringValue":"tcp" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.116.196:80" + } + } + ] + }, + { + "timeUnixNano":"1626717505823035000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GotConn" + } + } + ] + }, + { + "timeUnixNano":"1626717505823116000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"WroteHeaders" + } + } + ] + }, + { + "timeUnixNano":"1626717505823121000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"WroteRequest" + } + } + ] + }, + { + "timeUnixNano":"1626717505829460000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GotFirstResponseByte" + } + } + ] + }, + { + "timeUnixNano":"1626717505829568000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ClosedBody" + } + } + ] + } + ], + "status":{ + "deprecatedCode":"DEPRECATED_STATUS_CODE_UNKNOWN_ERROR", + "code":"STATUS_CODE_ERROR" + } + }, + { + "traceId":"AAAAAAAAAABbdZuWJO/uiw==", + "spanId":"T3b9lSy4e6o=", + "parentSpanId":"W3WbliTv7os=", + "name":"HTTP GET", + "kind":"SPAN_KIND_CLIENT", + "startTimeUnixNano":"1626717504533933000", + "endTimeUnixNano":"1626717505833933000", + "attributes":[ + { + "key":"http.status_code", + "value":{ + "intValue":"200" + } + }, + { + "key":"component", + "value":{ + "stringValue":"net/http" + } + }, + { + "key":"http.method", + "value":{ + "stringValue":"GET" + } + }, + { + "key":"http.url", + "value":{ + "stringValue":"app:80" + } + }, + { + "key":"net/http.reused", + "value":{ + "boolValue":false + } + }, + { + "key":"net/http.was_idle", + "value":{ + "boolValue":false + } + } + ], + "events":[ + { + "timeUnixNano":"1626717505829603000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GetConn" + } + } + ] + }, + { + "timeUnixNano":"1626717505829642000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"DNSStart" + } + }, + { + "key":"host", + "value":{ + "stringValue":"app" + } + } + ] + }, + { + "timeUnixNano":"1626717505830180000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"DNSDone" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.116.196" + } + } + ] + }, + { + "timeUnixNano":"1626717505830186000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ConnectStart" + } + }, + { + "key":"network", + "value":{ + "stringValue":"tcp" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.116.196:80" + } + } + ] + }, + { + "timeUnixNano":"1626717505830301000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ConnectDone" + } + }, + { + "key":"network", + "value":{ + "stringValue":"tcp" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.116.196:80" + } + } + ] + }, + { + "timeUnixNano":"1626717505830332000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GotConn" + } + } + ] + }, + { + "timeUnixNano":"1626717505830372000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"WroteHeaders" + } + } + ] + }, + { + "timeUnixNano":"1626717505830373000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"WroteRequest" + } + } + ] + }, + { + "timeUnixNano":"1626717505833806000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GotFirstResponseByte" + } + } + ] + }, + { + "timeUnixNano":"1626717505833933000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ClosedBody" + } + } + ] + } + ], + "status":{ + + } + } + ] + } + ] + }, + { + "resource":{ + "attributes":[ + { + "key":"service.name", + "value":{ + "stringValue":"app" + } + }, + { + "key":"cluster", + "value":{ + "stringValue":"tns-demo" + } + }, + { + "key":"namespace", + "value":{ + "stringValue":"tns-demo" + } + }, + { + "key":"opencensus.exporterversion", + "value":{ + "stringValue":"Jaeger-Go-2.22.1" + } + }, + { + "key":"host.name", + "value":{ + "stringValue":"app-7c474df6bc-xpm6j" + } + }, + { + "key":"ip", + "value":{ + "stringValue":"10.136.11.151" + } + }, + { + "key":"client-uuid", + "value":{ + "stringValue":"264ce1d77c354156" + } + }, + { + "key":"container", + "value":{ + "stringValue":"app" + } + }, + { + "key":"pod", + "value":{ + "stringValue":"app-7c474df6bc-xpm6j" + } + } + ] + }, + "instrumentationLibrarySpans":[ + { + "instrumentationLibrary":{ + + }, + "spans":[ + { + "traceId":"AAAAAAAAAABbdZuWJO/uiw==", + "spanId":"CyLVKnG8lfk=", + "parentSpanId":"d5ZXpoG4mUc=", + "name":"HTTP POST - post", + "kind":"SPAN_KIND_SERVER", + "startTimeUnixNano":"1626717504829303000", + "endTimeUnixNano":"1626717505829303000", + "attributes":[ + { + "key":"http.status_code", + "value":{ + "intValue":"302" + } + }, + { + "key":"http.method", + "value":{ + "stringValue":"POST" + } + }, + { + "key":"http.url", + "value":{ + "stringValue":"/post" + } + }, + { + "key":"component", + "value":{ + "stringValue":"net/http" + } + } + ], + "status":{ + + } + }, + { + "traceId":"AAAAAAAAAABbdZuWJO/uiw==", + "spanId":"bzp4d/duh20=", + "parentSpanId":"CyLVKnG8lfk=", + "name":"HTTP Client", + "startTimeUnixNano":"1626717505823375000", + "endTimeUnixNano":"1626717505829164000", + "status":{ + + } + }, + { + "traceId":"AAAAAAAAAABbdZuWJO/uiw==", + "spanId":"T/rh1/wSL9g=", + "parentSpanId":"bzp4d/duh20=", + "name":"HTTP POST", + "kind":"SPAN_KIND_CLIENT", + "startTimeUnixNano":"1626717504929264000", + "endTimeUnixNano":"1626717505829264000", + "attributes":[ + { + "key":"http.status_code", + "value":{ + "intValue":"208" + } + }, + { + "key":"component", + "value":{ + "stringValue":"net/http" + } + }, + { + "key":"http.method", + "value":{ + "stringValue":"POST" + } + }, + { + "key":"http.url", + "value":{ + "stringValue":"db:80" + } + }, + { + "key":"net/http.reused", + "value":{ + "boolValue":false + } + }, + { + "key":"net/http.was_idle", + "value":{ + "boolValue":false + } + } + ], + "events":[ + { + "timeUnixNano":"1626717505823393000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GetConn" + } + } + ] + }, + { + "timeUnixNano":"1626717505823439000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"DNSStart" + } + }, + { + "key":"host", + "value":{ + "stringValue":"db" + } + } + ] + }, + { + "timeUnixNano":"1626717505827663000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"DNSDone" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.106.8" + } + } + ] + }, + { + "timeUnixNano":"1626717505827673000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ConnectStart" + } + }, + { + "key":"network", + "value":{ + "stringValue":"tcp" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.106.8:80" + } + } + ] + }, + { + "timeUnixNano":"1626717505827797000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ConnectDone" + } + }, + { + "key":"network", + "value":{ + "stringValue":"tcp" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.106.8:80" + } + } + ] + }, + { + "timeUnixNano":"1626717505827824000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GotConn" + } + } + ] + }, + { + "timeUnixNano":"1626717505827896000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"WroteHeaders" + } + } + ] + }, + { + "timeUnixNano":"1626717505827901000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"WroteRequest" + } + } + ] + }, + { + "timeUnixNano":"1626717505829057000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GotFirstResponseByte" + } + } + ] + }, + { + "timeUnixNano":"1626717505829264000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ClosedBody" + } + } + ] + } + ], + "status":{ + + } + }, + { + "traceId":"AAAAAAAAAABbdZuWJO/uiw==", + "spanId":"NvbVfAxyM10=", + "parentSpanId":"T3b9lSy4e6o=", + "name":"HTTP GET - root", + "kind":"SPAN_KIND_SERVER", + "startTimeUnixNano":"1626717503833939000", + "endTimeUnixNano":"1626717505833939000", + "attributes":[ + { + "key":"http.status_code", + "value":{ + "intValue":"200" + } + }, + { + "key":"http.method", + "value":{ + "stringValue":"GET" + } + }, + { + "key":"http.url", + "value":{ + "stringValue":"/" + } + }, + { + "key":"component", + "value":{ + "stringValue":"net/http" + } + } + ], + "status":{ + + } + }, + { + "traceId":"AAAAAAAAAABbdZuWJO/uiw==", + "spanId":"M464LUSGHVU=", + "parentSpanId":"NvbVfAxyM10=", + "name":"HTTP Client", + "startTimeUnixNano":"1626717505830578000", + "endTimeUnixNano":"1626717505833516000", + "status":{ + + } + }, + { + "traceId":"AAAAAAAAAABbdZuWJO/uiw==", + "spanId":"FcfJmhEwNxM=", + "parentSpanId":"M464LUSGHVU=", + "name":"HTTP GET", + "kind":"SPAN_KIND_CLIENT", + "startTimeUnixNano":"1626717504833879000", + "endTimeUnixNano":"1626717505833879000", + "attributes":[ + { + "key":"http.status_code", + "value":{ + "intValue":"200" + } + }, + { + "key":"component", + "value":{ + "stringValue":"net/http" + } + }, + { + "key":"http.method", + "value":{ + "stringValue":"GET" + } + }, + { + "key":"http.url", + "value":{ + "stringValue":"db:80" + } + }, + { + "key":"net/http.reused", + "value":{ + "boolValue":false + } + }, + { + "key":"net/http.was_idle", + "value":{ + "boolValue":false + } + } + ], + "events":[ + { + "timeUnixNano":"1626717505830596000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GetConn" + } + } + ] + }, + { + "timeUnixNano":"1626717505830647000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"DNSStart" + } + }, + { + "key":"host", + "value":{ + "stringValue":"db" + } + } + ] + }, + { + "timeUnixNano":"1626717505832975000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"DNSDone" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.106.8" + } + } + ] + }, + { + "timeUnixNano":"1626717505832983000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ConnectStart" + } + }, + { + "key":"network", + "value":{ + "stringValue":"tcp" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.106.8:80" + } + } + ] + }, + { + "timeUnixNano":"1626717505833096000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ConnectDone" + } + }, + { + "key":"network", + "value":{ + "stringValue":"tcp" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.106.8:80" + } + } + ] + }, + { + "timeUnixNano":"1626717505833116000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GotConn" + } + } + ] + }, + { + "timeUnixNano":"1626717505833153000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"WroteHeaders" + } + } + ] + }, + { + "timeUnixNano":"1626717505833154000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"WroteRequest" + } + } + ] + }, + { + "timeUnixNano":"1626717505833460000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GotFirstResponseByte" + } + } + ] + }, + { + "timeUnixNano":"1626717505833880000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ClosedBody" + } + } + ] + } + ], + "status":{ + + } + } + ] + } + ] + }, + { + "resource":{ + "attributes":[ + { + "key":"service.name", + "value":{ + "stringValue":"db" + } + }, + { + "key":"cluster", + "value":{ + "stringValue":"tns-demo" + } + }, + { + "key":"namespace", + "value":{ + "stringValue":"tns-demo" + } + }, + { + "key":"opencensus.exporterversion", + "value":{ + "stringValue":"Jaeger-Go-2.22.1" + } + }, + { + "key":"host.name", + "value":{ + "stringValue":"db-7488656cb4-m8ljw" + } + }, + { + "key":"ip", + "value":{ + "stringValue":"10.136.11.152" + } + }, + { + "key":"client-uuid", + "value":{ + "stringValue":"392a5faabe967ba3" + } + }, + { + "key":"container", + "value":{ + "stringValue":"db" + } + }, + { + "key":"pod", + "value":{ + "stringValue":"db-7488656cb4-m8ljw" + } + } + ] + }, + "instrumentationLibrarySpans":[ + { + "instrumentationLibrary":{ + + }, + "spans":[ + { + "traceId":"AAAAAAAAAABbdZuWJO/uiw==", + "spanId":"IElW8xeWvqs=", + "parentSpanId":"T/rh1/wSL9g=", + "name":"HTTP POST - post", + "kind":"SPAN_KIND_SERVER", + "startTimeUnixNano":"1626717504328961000", + "endTimeUnixNano":"1626717505828961000", + "attributes":[ + { + "key":"http.status_code", + "value":{ + "intValue":"208" + } + }, + { + "key":"http.method", + "value":{ + "stringValue":"POST" + } + }, + { + "key":"http.url", + "value":{ + "stringValue":"/post" + } + }, + { + "key":"component", + "value":{ + "stringValue":"net/http" + } + } + ], + "status":{ + + } + }, + { + "traceId":"AAAAAAAAAABbdZuWJO/uiw==", + "spanId":"frLAE97IEMg=", + "parentSpanId":"FcfJmhEwNxM=", + "name":"HTTP GET - root", + "kind":"SPAN_KIND_SERVER", + "startTimeUnixNano":"1626717504833394000", + "endTimeUnixNano":"1626717505833394000", + "attributes":[ + { + "key":"http.status_code", + "value":{ + "intValue":"200" + } + }, + { + "key":"http.method", + "value":{ + "stringValue":"GET" + } + }, + { + "key":"http.url", + "value":{ + "stringValue":"/" + } + }, + { + "key":"component", + "value":{ + "stringValue":"net/http" + } + } + ], + "status":{ + + } + } + ] + } + ] + }, + { + "resource":{ + "attributes":[ + { + "key":"service.name", + "value":{ + "stringValue":"lb" + } + }, + { + "key":"cluster", + "value":{ + "stringValue":"tns-demo" + } + }, + { + "key":"namespace", + "value":{ + "stringValue":"tns-demo" + } + }, + { + "key":"opencensus.exporterversion", + "value":{ + "stringValue":"Jaeger-Go-2.22.1" + } + }, + { + "key":"host.name", + "value":{ + "stringValue":"loadgen-6b59dff4c-jdkdk" + } + }, + { + "key":"ip", + "value":{ + "stringValue":"10.136.11.153" + } + }, + { + "key":"client-uuid", + "value":{ + "stringValue":"653fad9a76c115ac" + } + }, + { + "key":"container", + "value":{ + "stringValue":"loadgen" + } + }, + { + "key":"pod", + "value":{ + "stringValue":"loadgen-6b59dff4c-jdkdk" + } + } + ] + }, + "instrumentationLibrarySpans":[ + { + "instrumentationLibrary":{ + + }, + "spans":[ + { + "traceId":"AAAAAAAAAABFFdxqWiBZ9g==", + "spanId":"RRXcalogWfY=", + "name":"HTTP Client", + "startTimeUnixNano":"1626717505125848000", + "endTimeUnixNano":"1626717505130325000", + "attributes":[ + { + "key":"sampler.type", + "value":{ + "stringValue":"const" + } + }, + { + "key":"sampler.param", + "value":{ + "boolValue":true + } + } + ], + "status":{ + + } + }, + { + "traceId":"AAAAAAAAAABFFdxqWiBZ9g==", + "spanId":"Uoyxh+9zsBo=", + "parentSpanId":"RRXcalogWfY=", + "name":"HTTP GET", + "kind":"SPAN_KIND_CLIENT", + "startTimeUnixNano":"1626717501130383000", + "endTimeUnixNano":"1626717505130383000", + "attributes":[ + { + "key":"http.status_code", + "value":{ + "intValue":"200" + } + }, + { + "key":"component", + "value":{ + "stringValue":"net/http" + } + }, + { + "key":"http.method", + "value":{ + "stringValue":"GET" + } + }, + { + "key":"http.url", + "value":{ + "stringValue":"app:80" + } + }, + { + "key":"net/http.reused", + "value":{ + "boolValue":false + } + }, + { + "key":"net/http.was_idle", + "value":{ + "boolValue":false + } + } + ], + "events":[ + { + "timeUnixNano":"1626717505125868000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GetConn" + } + } + ] + }, + { + "timeUnixNano":"1626717505125909000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"DNSStart" + } + }, + { + "key":"host", + "value":{ + "stringValue":"app" + } + } + ] + }, + { + "timeUnixNano":"1626717505126450000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"DNSDone" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.116.196" + } + } + ] + }, + { + "timeUnixNano":"1626717505126455000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ConnectStart" + } + }, + { + "key":"network", + "value":{ + "stringValue":"tcp" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.116.196:80" + } + } + ] + }, + { + "timeUnixNano":"1626717505126534000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ConnectDone" + } + }, + { + "key":"network", + "value":{ + "stringValue":"tcp" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.116.196:80" + } + } + ] + }, + { + "timeUnixNano":"1626717505126556000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GotConn" + } + } + ] + }, + { + "timeUnixNano":"1626717505126585000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"WroteHeaders" + } + } + ] + }, + { + "timeUnixNano":"1626717505126586000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"WroteRequest" + } + } + ] + }, + { + "timeUnixNano":"1626717505130263000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GotFirstResponseByte" + } + } + ] + }, + { + "timeUnixNano":"1626717505130383000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ClosedBody" + } + } + ] + } + ], + "status":{ + + } + } + ] + } + ] + }, + { + "resource":{ + "attributes":[ + { + "key":"service.name", + "value":{ + "stringValue":"app" + } + }, + { + "key":"cluster", + "value":{ + "stringValue":"tns-demo" + } + }, + { + "key":"namespace", + "value":{ + "stringValue":"tns-demo" + } + }, + { + "key":"opencensus.exporterversion", + "value":{ + "stringValue":"Jaeger-Go-2.22.1" + } + }, + { + "key":"host.name", + "value":{ + "stringValue":"app-7c474df6bc-xpm6j" + } + }, + { + "key":"ip", + "value":{ + "stringValue":"10.136.11.151" + } + }, + { + "key":"client-uuid", + "value":{ + "stringValue":"264ce1d77c354156" + } + }, + { + "key":"pod", + "value":{ + "stringValue":"app-7c474df6bc-xpm6j" + } + }, + { + "key":"container", + "value":{ + "stringValue":"app" + } + } + ] + }, + "instrumentationLibrarySpans":[ + { + "instrumentationLibrary":{ + + }, + "spans":[ + { + "traceId":"AAAAAAAAAABFFdxqWiBZ9g==", + "spanId":"UQZfs+d8Sdw=", + "parentSpanId":"Uoyxh+9zsBo=", + "name":"HTTP GET - root", + "kind":"SPAN_KIND_SERVER", + "startTimeUnixNano":"1626717501930340000", + "endTimeUnixNano":"1626717505130340000", + "attributes":[ + { + "key":"http.status_code", + "value":{ + "intValue":"200" + } + }, + { + "key":"http.method", + "value":{ + "stringValue":"GET" + } + }, + { + "key":"http.url", + "value":{ + "stringValue":"/" + } + }, + { + "key":"component", + "value":{ + "stringValue":"net/http" + } + } + ], + "status":{ + + } + }, + { + "traceId":"AAAAAAAAAABFFdxqWiBZ9g==", + "spanId":"H7/n/FTsqf0=", + "parentSpanId":"UQZfs+d8Sdw=", + "name":"HTTP Client", + "startTimeUnixNano":"1626717505126741000", + "endTimeUnixNano":"1626717505130038000", + "status":{ + + } + }, + { + "traceId":"AAAAAAAAAABFFdxqWiBZ9g==", + "spanId":"ERieXkZU3MU=", + "parentSpanId":"H7/n/FTsqf0=", + "name":"HTTP GET", + "kind":"SPAN_KIND_CLIENT", + "startTimeUnixNano":"1626717502630304000", + "endTimeUnixNano":"1626717505130304000", + "attributes":[ + { + "key":"http.status_code", + "value":{ + "intValue":"200" + } + }, + { + "key":"component", + "value":{ + "stringValue":"net/http" + } + }, + { + "key":"http.method", + "value":{ + "stringValue":"GET" + } + }, + { + "key":"http.url", + "value":{ + "stringValue":"db:80" + } + }, + { + "key":"net/http.reused", + "value":{ + "boolValue":false + } + }, + { + "key":"net/http.was_idle", + "value":{ + "boolValue":false + } + } + ], + "events":[ + { + "timeUnixNano":"1626717505126754000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GetConn" + } + } + ] + }, + { + "timeUnixNano":"1626717505126800000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"DNSStart" + } + }, + { + "key":"host", + "value":{ + "stringValue":"db" + } + } + ] + }, + { + "timeUnixNano":"1626717505129605000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"DNSDone" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.106.8" + } + } + ] + }, + { + "timeUnixNano":"1626717505129609000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ConnectStart" + } + }, + { + "key":"network", + "value":{ + "stringValue":"tcp" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.106.8:80" + } + } + ] + }, + { + "timeUnixNano":"1626717505129678000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ConnectDone" + } + }, + { + "key":"network", + "value":{ + "stringValue":"tcp" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.106.8:80" + } + } + ] + }, + { + "timeUnixNano":"1626717505129695000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GotConn" + } + } + ] + }, + { + "timeUnixNano":"1626717505129727000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"WroteHeaders" + } + } + ] + }, + { + "timeUnixNano":"1626717505129727000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"WroteRequest" + } + } + ] + }, + { + "timeUnixNano":"1626717505129965000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GotFirstResponseByte" + } + } + ] + }, + { + "timeUnixNano":"1626717505130303000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ClosedBody" + } + } + ] + } + ], + "status":{ + + } + } + ] + } + ] + }, + { + "resource":{ + "attributes":[ + { + "key":"service.name", + "value":{ + "stringValue":"db" + } + }, + { + "key":"cluster", + "value":{ + "stringValue":"tns-demo" + } + }, + { + "key":"namespace", + "value":{ + "stringValue":"tns-demo" + } + }, + { + "key":"opencensus.exporterversion", + "value":{ + "stringValue":"Jaeger-Go-2.22.1" + } + }, + { + "key":"host.name", + "value":{ + "stringValue":"db-7488656cb4-m8ljw" + } + }, + { + "key":"ip", + "value":{ + "stringValue":"10.136.11.152" + } + }, + { + "key":"client-uuid", + "value":{ + "stringValue":"392a5faabe967ba3" + } + }, + { + "key":"container", + "value":{ + "stringValue":"db" + } + }, + { + "key":"pod", + "value":{ + "stringValue":"db-7488656cb4-m8ljw" + } + } + ] + }, + "instrumentationLibrarySpans":[ + { + "instrumentationLibrary":{ + + }, + "spans":[ + { + "traceId":"AAAAAAAAAABFFdxqWiBZ9g==", + "spanId":"ZCqiD3w+XGc=", + "parentSpanId":"ERieXkZU3MU=", + "name":"HTTP GET - root", + "kind":"SPAN_KIND_SERVER", + "startTimeUnixNano":"1626717502629891000", + "endTimeUnixNano":"1626717505129891000", + "attributes":[ + { + "key":"http.status_code", + "value":{ + "intValue":"200" + } + }, + { + "key":"http.method", + "value":{ + "stringValue":"GET" + } + }, + { + "key":"http.url", + "value":{ + "stringValue":"/" + } + }, + { + "key":"component", + "value":{ + "stringValue":"net/http" + } + } + ], + "status":{ + + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/pkg/traces/servicegraphprocessor/testdata/unpaired-trace-sample.json b/pkg/traces/servicegraphprocessor/testdata/unpaired-trace-sample.json new file mode 100644 index 000000000000..ad3a0f6a2f69 --- /dev/null +++ b/pkg/traces/servicegraphprocessor/testdata/unpaired-trace-sample.json @@ -0,0 +1,1900 @@ +{ + "batches":[ + { + "resource":{ + "attributes":[ + { + "key":"service.name", + "value":{ + "stringValue":"lb" + } + }, + { + "key":"cluster", + "value":{ + "stringValue":"tns-demo" + } + }, + { + "key":"namespace", + "value":{ + "stringValue":"tns-demo" + } + }, + { + "key":"opencensus.exporterversion", + "value":{ + "stringValue":"Jaeger-Go-2.22.1" + } + }, + { + "key":"host.name", + "value":{ + "stringValue":"loadgen-6b59dff4c-jdkdk" + } + }, + { + "key":"ip", + "value":{ + "stringValue":"10.136.11.153" + } + }, + { + "key":"client-uuid", + "value":{ + "stringValue":"653fad9a76c115ac" + } + }, + { + "key":"container", + "value":{ + "stringValue":"loadgen" + } + }, + { + "key":"pod", + "value":{ + "stringValue":"loadgen-6b59dff4c-jdkdk" + } + } + ] + }, + "instrumentationLibrarySpans":[ + { + "instrumentationLibrary":{ + + }, + "spans":[ + { + "traceId":"AAAAAAAAAABbdZuWJO/uiw==", + "spanId":"W3WbliTv7os=", + "name":"HTTP Client", + "startTimeUnixNano":"1626717505784699000", + "endTimeUnixNano":"1626717505833874000", + "attributes":[ + { + "key":"sampler.type", + "value":{ + "stringValue":"const" + } + }, + { + "key":"sampler.param", + "value":{ + "boolValue":true + } + } + ], + "status":{ + + } + }, + { + "traceId":"AAAAAAAAAABbdZuWJO/uiw==", + "spanId":"d5ZXpoG4mUc=", + "name":"HTTP POST", + "kind":"SPAN_KIND_CLIENT", + "startTimeUnixNano":"1626717503329568000", + "endTimeUnixNano":"1626717505829568000", + "attributes":[ + { + "key":"http.status_code", + "value":{ + "intValue":"302" + } + }, + { + "key":"component", + "value":{ + "stringValue":"net/http" + } + }, + { + "key":"http.method", + "value":{ + "stringValue":"POST" + } + }, + { + "key":"http.url", + "value":{ + "stringValue":"app:80" + } + }, + { + "key":"net/http.reused", + "value":{ + "boolValue":false + } + }, + { + "key":"net/http.was_idle", + "value":{ + "boolValue":false + } + } + ], + "events":[ + { + "timeUnixNano":"1626717505784725000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GetConn" + } + } + ] + }, + { + "timeUnixNano":"1626717505784771000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"DNSStart" + } + }, + { + "key":"host", + "value":{ + "stringValue":"app" + } + } + ] + }, + { + "timeUnixNano":"1626717505822812000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"DNSDone" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.116.196" + } + } + ] + }, + { + "timeUnixNano":"1626717505822821000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ConnectStart" + } + }, + { + "key":"network", + "value":{ + "stringValue":"tcp" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.116.196:80" + } + } + ] + }, + { + "timeUnixNano":"1626717505822983000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ConnectDone" + } + }, + { + "key":"network", + "value":{ + "stringValue":"tcp" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.116.196:80" + } + } + ] + }, + { + "timeUnixNano":"1626717505823035000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GotConn" + } + } + ] + }, + { + "timeUnixNano":"1626717505823116000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"WroteHeaders" + } + } + ] + }, + { + "timeUnixNano":"1626717505823121000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"WroteRequest" + } + } + ] + }, + { + "timeUnixNano":"1626717505829460000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GotFirstResponseByte" + } + } + ] + }, + { + "timeUnixNano":"1626717505829568000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ClosedBody" + } + } + ] + } + ], + "status":{ + + } + }, + { + "traceId":"AAAAAAAAAABbdZuWJO/uiw==", + "spanId":"T3b9lSy4e6o=", + "name":"HTTP GET", + "kind":"SPAN_KIND_CLIENT", + "startTimeUnixNano":"1626717504533933000", + "endTimeUnixNano":"1626717505833933000", + "attributes":[ + { + "key":"http.status_code", + "value":{ + "intValue":"200" + } + }, + { + "key":"component", + "value":{ + "stringValue":"net/http" + } + }, + { + "key":"http.method", + "value":{ + "stringValue":"GET" + } + }, + { + "key":"http.url", + "value":{ + "stringValue":"app:80" + } + }, + { + "key":"net/http.reused", + "value":{ + "boolValue":false + } + }, + { + "key":"net/http.was_idle", + "value":{ + "boolValue":false + } + } + ], + "events":[ + { + "timeUnixNano":"1626717505829603000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GetConn" + } + } + ] + }, + { + "timeUnixNano":"1626717505829642000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"DNSStart" + } + }, + { + "key":"host", + "value":{ + "stringValue":"app" + } + } + ] + }, + { + "timeUnixNano":"1626717505830180000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"DNSDone" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.116.196" + } + } + ] + }, + { + "timeUnixNano":"1626717505830186000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ConnectStart" + } + }, + { + "key":"network", + "value":{ + "stringValue":"tcp" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.116.196:80" + } + } + ] + }, + { + "timeUnixNano":"1626717505830301000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ConnectDone" + } + }, + { + "key":"network", + "value":{ + "stringValue":"tcp" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.116.196:80" + } + } + ] + }, + { + "timeUnixNano":"1626717505830332000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GotConn" + } + } + ] + }, + { + "timeUnixNano":"1626717505830372000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"WroteHeaders" + } + } + ] + }, + { + "timeUnixNano":"1626717505830373000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"WroteRequest" + } + } + ] + }, + { + "timeUnixNano":"1626717505833806000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GotFirstResponseByte" + } + } + ] + }, + { + "timeUnixNano":"1626717505833933000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ClosedBody" + } + } + ] + } + ], + "status":{ + + } + } + ] + } + ] + }, + { + "resource":{ + "attributes":[ + { + "key":"service.name", + "value":{ + "stringValue":"app" + } + }, + { + "key":"cluster", + "value":{ + "stringValue":"tns-demo" + } + }, + { + "key":"namespace", + "value":{ + "stringValue":"tns-demo" + } + }, + { + "key":"opencensus.exporterversion", + "value":{ + "stringValue":"Jaeger-Go-2.22.1" + } + }, + { + "key":"host.name", + "value":{ + "stringValue":"app-7c474df6bc-xpm6j" + } + }, + { + "key":"ip", + "value":{ + "stringValue":"10.136.11.151" + } + }, + { + "key":"client-uuid", + "value":{ + "stringValue":"264ce1d77c354156" + } + }, + { + "key":"container", + "value":{ + "stringValue":"app" + } + }, + { + "key":"pod", + "value":{ + "stringValue":"app-7c474df6bc-xpm6j" + } + } + ] + }, + "instrumentationLibrarySpans":[ + { + "instrumentationLibrary":{ + + }, + "spans":[ + { + "traceId":"AAAAAAAAAABbdZuWJO/uiw==", + "spanId":"CyLVKnG8lfk=", + "name":"HTTP POST - post", + "kind":"SPAN_KIND_SERVER", + "startTimeUnixNano":"1626717504829303000", + "endTimeUnixNano":"1626717505829303000", + "attributes":[ + { + "key":"http.status_code", + "value":{ + "intValue":"302" + } + }, + { + "key":"http.method", + "value":{ + "stringValue":"POST" + } + }, + { + "key":"http.url", + "value":{ + "stringValue":"/post" + } + }, + { + "key":"component", + "value":{ + "stringValue":"net/http" + } + } + ], + "status":{ + + } + }, + { + "traceId":"AAAAAAAAAABbdZuWJO/uiw==", + "spanId":"bzp4d/duh20=", + "name":"HTTP Client", + "startTimeUnixNano":"1626717505823375000", + "endTimeUnixNano":"1626717505829164000", + "status":{ + + } + }, + { + "traceId":"AAAAAAAAAABbdZuWJO/uiw==", + "spanId":"T/rh1/wSL9g=", + "name":"HTTP POST", + "kind":"SPAN_KIND_CLIENT", + "startTimeUnixNano":"1626717504929264000", + "endTimeUnixNano":"1626717505829264000", + "attributes":[ + { + "key":"http.status_code", + "value":{ + "intValue":"208" + } + }, + { + "key":"component", + "value":{ + "stringValue":"net/http" + } + }, + { + "key":"http.method", + "value":{ + "stringValue":"POST" + } + }, + { + "key":"http.url", + "value":{ + "stringValue":"db:80" + } + }, + { + "key":"net/http.reused", + "value":{ + "boolValue":false + } + }, + { + "key":"net/http.was_idle", + "value":{ + "boolValue":false + } + } + ], + "events":[ + { + "timeUnixNano":"1626717505823393000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GetConn" + } + } + ] + }, + { + "timeUnixNano":"1626717505823439000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"DNSStart" + } + }, + { + "key":"host", + "value":{ + "stringValue":"db" + } + } + ] + }, + { + "timeUnixNano":"1626717505827663000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"DNSDone" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.106.8" + } + } + ] + }, + { + "timeUnixNano":"1626717505827673000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ConnectStart" + } + }, + { + "key":"network", + "value":{ + "stringValue":"tcp" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.106.8:80" + } + } + ] + }, + { + "timeUnixNano":"1626717505827797000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ConnectDone" + } + }, + { + "key":"network", + "value":{ + "stringValue":"tcp" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.106.8:80" + } + } + ] + }, + { + "timeUnixNano":"1626717505827824000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GotConn" + } + } + ] + }, + { + "timeUnixNano":"1626717505827896000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"WroteHeaders" + } + } + ] + }, + { + "timeUnixNano":"1626717505827901000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"WroteRequest" + } + } + ] + }, + { + "timeUnixNano":"1626717505829057000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GotFirstResponseByte" + } + } + ] + }, + { + "timeUnixNano":"1626717505829264000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ClosedBody" + } + } + ] + } + ], + "status":{ + + } + }, + { + "traceId":"AAAAAAAAAABbdZuWJO/uiw==", + "spanId":"NvbVfAxyM10=", + "name":"HTTP GET - root", + "kind":"SPAN_KIND_SERVER", + "startTimeUnixNano":"1626717503833939000", + "endTimeUnixNano":"1626717505833939000", + "attributes":[ + { + "key":"http.status_code", + "value":{ + "intValue":"200" + } + }, + { + "key":"http.method", + "value":{ + "stringValue":"GET" + } + }, + { + "key":"http.url", + "value":{ + "stringValue":"/" + } + }, + { + "key":"component", + "value":{ + "stringValue":"net/http" + } + } + ], + "status":{ + + } + }, + { + "traceId":"AAAAAAAAAABbdZuWJO/uiw==", + "spanId":"M464LUSGHVU=", + "name":"HTTP Client", + "startTimeUnixNano":"1626717505830578000", + "endTimeUnixNano":"1626717505833516000", + "status":{ + + } + }, + { + "traceId":"AAAAAAAAAABbdZuWJO/uiw==", + "spanId":"FcfJmhEwNxM=", + "name":"HTTP GET", + "kind":"SPAN_KIND_CLIENT", + "startTimeUnixNano":"1626717504833879000", + "endTimeUnixNano":"1626717505833879000", + "attributes":[ + { + "key":"http.status_code", + "value":{ + "intValue":"200" + } + }, + { + "key":"component", + "value":{ + "stringValue":"net/http" + } + }, + { + "key":"http.method", + "value":{ + "stringValue":"GET" + } + }, + { + "key":"http.url", + "value":{ + "stringValue":"db:80" + } + }, + { + "key":"net/http.reused", + "value":{ + "boolValue":false + } + }, + { + "key":"net/http.was_idle", + "value":{ + "boolValue":false + } + } + ], + "events":[ + { + "timeUnixNano":"1626717505830596000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GetConn" + } + } + ] + }, + { + "timeUnixNano":"1626717505830647000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"DNSStart" + } + }, + { + "key":"host", + "value":{ + "stringValue":"db" + } + } + ] + }, + { + "timeUnixNano":"1626717505832975000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"DNSDone" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.106.8" + } + } + ] + }, + { + "timeUnixNano":"1626717505832983000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ConnectStart" + } + }, + { + "key":"network", + "value":{ + "stringValue":"tcp" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.106.8:80" + } + } + ] + }, + { + "timeUnixNano":"1626717505833096000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ConnectDone" + } + }, + { + "key":"network", + "value":{ + "stringValue":"tcp" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.106.8:80" + } + } + ] + }, + { + "timeUnixNano":"1626717505833116000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GotConn" + } + } + ] + }, + { + "timeUnixNano":"1626717505833153000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"WroteHeaders" + } + } + ] + }, + { + "timeUnixNano":"1626717505833154000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"WroteRequest" + } + } + ] + }, + { + "timeUnixNano":"1626717505833460000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GotFirstResponseByte" + } + } + ] + }, + { + "timeUnixNano":"1626717505833880000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ClosedBody" + } + } + ] + } + ], + "status":{ + + } + } + ] + } + ] + }, + { + "resource":{ + "attributes":[ + { + "key":"service.name", + "value":{ + "stringValue":"db" + } + }, + { + "key":"cluster", + "value":{ + "stringValue":"tns-demo" + } + }, + { + "key":"namespace", + "value":{ + "stringValue":"tns-demo" + } + }, + { + "key":"opencensus.exporterversion", + "value":{ + "stringValue":"Jaeger-Go-2.22.1" + } + }, + { + "key":"host.name", + "value":{ + "stringValue":"db-7488656cb4-m8ljw" + } + }, + { + "key":"ip", + "value":{ + "stringValue":"10.136.11.152" + } + }, + { + "key":"client-uuid", + "value":{ + "stringValue":"392a5faabe967ba3" + } + }, + { + "key":"container", + "value":{ + "stringValue":"db" + } + }, + { + "key":"pod", + "value":{ + "stringValue":"db-7488656cb4-m8ljw" + } + } + ] + }, + "instrumentationLibrarySpans":[ + { + "instrumentationLibrary":{ + + }, + "spans":[ + { + "traceId":"AAAAAAAAAABbdZuWJO/uiw==", + "spanId":"IElW8xeWvqs=", + "name":"HTTP POST - post", + "kind":"SPAN_KIND_SERVER", + "startTimeUnixNano":"1626717504328961000", + "endTimeUnixNano":"1626717505828961000", + "attributes":[ + { + "key":"http.status_code", + "value":{ + "intValue":"208" + } + }, + { + "key":"http.method", + "value":{ + "stringValue":"POST" + } + }, + { + "key":"http.url", + "value":{ + "stringValue":"/post" + } + }, + { + "key":"component", + "value":{ + "stringValue":"net/http" + } + } + ], + "status":{ + + } + }, + { + "traceId":"AAAAAAAAAABbdZuWJO/uiw==", + "spanId":"frLAE97IEMg=", + "name":"HTTP GET - root", + "kind":"SPAN_KIND_SERVER", + "startTimeUnixNano":"1626717504833394000", + "endTimeUnixNano":"1626717505833394000", + "attributes":[ + { + "key":"http.status_code", + "value":{ + "intValue":"200" + } + }, + { + "key":"http.method", + "value":{ + "stringValue":"GET" + } + }, + { + "key":"http.url", + "value":{ + "stringValue":"/" + } + }, + { + "key":"component", + "value":{ + "stringValue":"net/http" + } + } + ], + "status":{ + + } + } + ] + } + ] + }, + { + "resource":{ + "attributes":[ + { + "key":"service.name", + "value":{ + "stringValue":"lb" + } + }, + { + "key":"cluster", + "value":{ + "stringValue":"tns-demo" + } + }, + { + "key":"namespace", + "value":{ + "stringValue":"tns-demo" + } + }, + { + "key":"opencensus.exporterversion", + "value":{ + "stringValue":"Jaeger-Go-2.22.1" + } + }, + { + "key":"host.name", + "value":{ + "stringValue":"loadgen-6b59dff4c-jdkdk" + } + }, + { + "key":"ip", + "value":{ + "stringValue":"10.136.11.153" + } + }, + { + "key":"client-uuid", + "value":{ + "stringValue":"653fad9a76c115ac" + } + }, + { + "key":"container", + "value":{ + "stringValue":"loadgen" + } + }, + { + "key":"pod", + "value":{ + "stringValue":"loadgen-6b59dff4c-jdkdk" + } + } + ] + }, + "instrumentationLibrarySpans":[ + { + "instrumentationLibrary":{ + + }, + "spans":[ + { + "traceId":"AAAAAAAAAABFFdxqWiBZ9g==", + "spanId":"RRXcalogWfY=", + "name":"HTTP Client", + "startTimeUnixNano":"1626717505125848000", + "endTimeUnixNano":"1626717505130325000", + "attributes":[ + { + "key":"sampler.type", + "value":{ + "stringValue":"const" + } + }, + { + "key":"sampler.param", + "value":{ + "boolValue":true + } + } + ], + "status":{ + + } + }, + { + "traceId":"AAAAAAAAAABFFdxqWiBZ9g==", + "spanId":"Uoyxh+9zsBo=", + "name":"HTTP GET", + "kind":"SPAN_KIND_CLIENT", + "startTimeUnixNano":"1626717501130383000", + "endTimeUnixNano":"1626717505130383000", + "attributes":[ + { + "key":"http.status_code", + "value":{ + "intValue":"200" + } + }, + { + "key":"component", + "value":{ + "stringValue":"net/http" + } + }, + { + "key":"http.method", + "value":{ + "stringValue":"GET" + } + }, + { + "key":"http.url", + "value":{ + "stringValue":"app:80" + } + }, + { + "key":"net/http.reused", + "value":{ + "boolValue":false + } + }, + { + "key":"net/http.was_idle", + "value":{ + "boolValue":false + } + } + ], + "events":[ + { + "timeUnixNano":"1626717505125868000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GetConn" + } + } + ] + }, + { + "timeUnixNano":"1626717505125909000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"DNSStart" + } + }, + { + "key":"host", + "value":{ + "stringValue":"app" + } + } + ] + }, + { + "timeUnixNano":"1626717505126450000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"DNSDone" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.116.196" + } + } + ] + }, + { + "timeUnixNano":"1626717505126455000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ConnectStart" + } + }, + { + "key":"network", + "value":{ + "stringValue":"tcp" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.116.196:80" + } + } + ] + }, + { + "timeUnixNano":"1626717505126534000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ConnectDone" + } + }, + { + "key":"network", + "value":{ + "stringValue":"tcp" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.116.196:80" + } + } + ] + }, + { + "timeUnixNano":"1626717505126556000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GotConn" + } + } + ] + }, + { + "timeUnixNano":"1626717505126585000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"WroteHeaders" + } + } + ] + }, + { + "timeUnixNano":"1626717505126586000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"WroteRequest" + } + } + ] + }, + { + "timeUnixNano":"1626717505130263000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GotFirstResponseByte" + } + } + ] + }, + { + "timeUnixNano":"1626717505130383000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ClosedBody" + } + } + ] + } + ], + "status":{ + + } + } + ] + } + ] + }, + { + "resource":{ + "attributes":[ + { + "key":"service.name", + "value":{ + "stringValue":"app" + } + }, + { + "key":"cluster", + "value":{ + "stringValue":"tns-demo" + } + }, + { + "key":"namespace", + "value":{ + "stringValue":"tns-demo" + } + }, + { + "key":"opencensus.exporterversion", + "value":{ + "stringValue":"Jaeger-Go-2.22.1" + } + }, + { + "key":"host.name", + "value":{ + "stringValue":"app-7c474df6bc-xpm6j" + } + }, + { + "key":"ip", + "value":{ + "stringValue":"10.136.11.151" + } + }, + { + "key":"client-uuid", + "value":{ + "stringValue":"264ce1d77c354156" + } + }, + { + "key":"pod", + "value":{ + "stringValue":"app-7c474df6bc-xpm6j" + } + }, + { + "key":"container", + "value":{ + "stringValue":"app" + } + } + ] + }, + "instrumentationLibrarySpans":[ + { + "instrumentationLibrary":{ + + }, + "spans":[ + { + "traceId":"AAAAAAAAAABFFdxqWiBZ9g==", + "spanId":"UQZfs+d8Sdw=", + "name":"HTTP GET - root", + "kind":"SPAN_KIND_SERVER", + "startTimeUnixNano":"1626717501930340000", + "endTimeUnixNano":"1626717505130340000", + "attributes":[ + { + "key":"http.status_code", + "value":{ + "intValue":"200" + } + }, + { + "key":"http.method", + "value":{ + "stringValue":"GET" + } + }, + { + "key":"http.url", + "value":{ + "stringValue":"/" + } + }, + { + "key":"component", + "value":{ + "stringValue":"net/http" + } + } + ], + "status":{ + + } + }, + { + "traceId":"AAAAAAAAAABFFdxqWiBZ9g==", + "spanId":"H7/n/FTsqf0=", + "name":"HTTP Client", + "startTimeUnixNano":"1626717505126741000", + "endTimeUnixNano":"1626717505130038000", + "status":{ + + } + }, + { + "traceId":"AAAAAAAAAABFFdxqWiBZ9g==", + "spanId":"ERieXkZU3MU=", + "name":"HTTP GET", + "kind":"SPAN_KIND_CLIENT", + "startTimeUnixNano":"1626717502630304000", + "endTimeUnixNano":"1626717505130304000", + "attributes":[ + { + "key":"http.status_code", + "value":{ + "intValue":"200" + } + }, + { + "key":"component", + "value":{ + "stringValue":"net/http" + } + }, + { + "key":"http.method", + "value":{ + "stringValue":"GET" + } + }, + { + "key":"http.url", + "value":{ + "stringValue":"db:80" + } + }, + { + "key":"net/http.reused", + "value":{ + "boolValue":false + } + }, + { + "key":"net/http.was_idle", + "value":{ + "boolValue":false + } + } + ], + "events":[ + { + "timeUnixNano":"1626717505126754000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GetConn" + } + } + ] + }, + { + "timeUnixNano":"1626717505126800000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"DNSStart" + } + }, + { + "key":"host", + "value":{ + "stringValue":"db" + } + } + ] + }, + { + "timeUnixNano":"1626717505129605000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"DNSDone" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.106.8" + } + } + ] + }, + { + "timeUnixNano":"1626717505129609000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ConnectStart" + } + }, + { + "key":"network", + "value":{ + "stringValue":"tcp" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.106.8:80" + } + } + ] + }, + { + "timeUnixNano":"1626717505129678000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ConnectDone" + } + }, + { + "key":"network", + "value":{ + "stringValue":"tcp" + } + }, + { + "key":"addr", + "value":{ + "stringValue":"10.188.106.8:80" + } + } + ] + }, + { + "timeUnixNano":"1626717505129695000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GotConn" + } + } + ] + }, + { + "timeUnixNano":"1626717505129727000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"WroteHeaders" + } + } + ] + }, + { + "timeUnixNano":"1626717505129727000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"WroteRequest" + } + } + ] + }, + { + "timeUnixNano":"1626717505129965000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"GotFirstResponseByte" + } + } + ] + }, + { + "timeUnixNano":"1626717505130303000", + "attributes":[ + { + "key":"event", + "value":{ + "stringValue":"ClosedBody" + } + } + ] + } + ], + "status":{ + + } + } + ] + } + ] + }, + { + "resource":{ + "attributes":[ + { + "key":"service.name", + "value":{ + "stringValue":"db" + } + }, + { + "key":"cluster", + "value":{ + "stringValue":"tns-demo" + } + }, + { + "key":"namespace", + "value":{ + "stringValue":"tns-demo" + } + }, + { + "key":"opencensus.exporterversion", + "value":{ + "stringValue":"Jaeger-Go-2.22.1" + } + }, + { + "key":"host.name", + "value":{ + "stringValue":"db-7488656cb4-m8ljw" + } + }, + { + "key":"ip", + "value":{ + "stringValue":"10.136.11.152" + } + }, + { + "key":"client-uuid", + "value":{ + "stringValue":"392a5faabe967ba3" + } + }, + { + "key":"container", + "value":{ + "stringValue":"db" + } + }, + { + "key":"pod", + "value":{ + "stringValue":"db-7488656cb4-m8ljw" + } + } + ] + }, + "instrumentationLibrarySpans":[ + { + "instrumentationLibrary":{ + + }, + "spans":[ + { + "traceId":"AAAAAAAAAABFFdxqWiBZ9g==", + "spanId":"ZCqiD3w+XGc=", + "name":"HTTP GET - root", + "kind":"SPAN_KIND_SERVER", + "startTimeUnixNano":"1626717502629891000", + "endTimeUnixNano":"1626717505129891000", + "attributes":[ + { + "key":"http.status_code", + "value":{ + "intValue":"200" + } + }, + { + "key":"http.method", + "value":{ + "stringValue":"GET" + } + }, + { + "key":"http.url", + "value":{ + "stringValue":"/" + } + }, + { + "key":"component", + "value":{ + "stringValue":"net/http" + } + } + ], + "status":{ + + } + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/pkg/traces/traces.go b/pkg/traces/traces.go index ba5d765432ce..9a9c001b866b 100644 --- a/pkg/traces/traces.go +++ b/pkg/traces/traces.go @@ -60,9 +60,14 @@ func (t *Traces) ApplyConfig(logsSubsystem *logs.Logs, promInstanceManager insta newInstances := make(map[string]*Instance, len(cfg.Configs)) for _, c := range cfg.Configs { + var ( + instLogger = t.logger.With(zap.String("traces_config", c.Name)) + instReg = prom_client.WrapRegistererWith(prom_client.Labels{"traces_config": c.Name}, t.reg) + ) + // If an old instance exists, update it and move it to the new map. if old, ok := t.instances[c.Name]; ok { - err := old.ApplyConfig(logsSubsystem, promInstanceManager, c) + err := old.ApplyConfig(logsSubsystem, promInstanceManager, instReg, c) if err != nil { return err } @@ -71,11 +76,6 @@ func (t *Traces) ApplyConfig(logsSubsystem *logs.Logs, promInstanceManager insta continue } - var ( - instLogger = t.logger.With(zap.String("traces_config", c.Name)) - instReg = prom_client.WrapRegistererWith(prom_client.Labels{"traces_config": c.Name}, t.reg) - ) - inst, err := NewInstance(logsSubsystem, instReg, c, instLogger, t.promInstanceManager) if err != nil { return fmt.Errorf("failed to create tracing instance %s: %w", c.Name, err) diff --git a/pkg/traces/traces_test.go b/pkg/traces/traces_test.go index 96831df2d448..d289cc7be909 100644 --- a/pkg/traces/traces_test.go +++ b/pkg/traces/traces_test.go @@ -28,15 +28,15 @@ func TestTraces(t *testing.T) { configs: - name: default receivers: - jaeger: - protocols: - thrift_compact: - push_config: - endpoint: %s - insecure: true - batch: - timeout: 100ms - send_batch_size: 1 + jaeger: + protocols: + thrift_compact: + remote_write: + - endpoint: %s + insecure: true + batch: + timeout: 100ms + send_batch_size: 1 `, tracesAddr)) var cfg Config @@ -75,16 +75,18 @@ func TestTrace_ApplyConfig(t *testing.T) { configs: - name: default receivers: - jaeger: - protocols: - thrift_compact: - push_config: - endpoint: 127.0.0.1:80 # deliberately the wrong endpoint - insecure: true - batch: - timeout: 100ms - send_batch_size: 1 - `) + jaeger: + protocols: + thrift_compact: + remote_write: + - endpoint: 127.0.0.1:80 # deliberately the wrong endpoint + insecure: true + batch: + timeout: 100ms + send_batch_size: 1 + service_graphs: + enabled: true +`) var cfg Config dec := yaml.NewDecoder(strings.NewReader(tracesCfgText)) @@ -101,15 +103,15 @@ configs: configs: - name: default receivers: - jaeger: - protocols: - thrift_compact: - push_config: - endpoint: %s - insecure: true - batch: - timeout: 100ms - send_batch_size: 1 + jaeger: + protocols: + thrift_compact: + remote_write: + - endpoint: %s + insecure: true + batch: + timeout: 100ms + send_batch_size: 1 `, tracesAddr)) var fixedConfig Config