Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
* [FEATURE] New block encoding vParquet5-preview5 with virtual span row numbers. This is a preview, breaking changes are expected. [#5943](https://github.com/grafana/tempo/pull/5943) (@stoewer)
* [FEATURE] Add SSE-C encryption support to S3 backend [#5789](https://github.com/grafana/tempo/pull/5789) (@steffsas)
* [FEATURE] Add support for `Accept: application/vnd.grafana.llm` to Tempo endpoints. Currently supported directly by trace by id and tag values [#5961](https://github.com/grafana/tempo/pull/5961) (@joe-elliott)
* [FEATURE] add database_name_attributes config to service graph processor [#5398](https://github.com/grafana/tempo/pull/5398) (@KyriosGN0)
This response is subject to change and should not be relied on. It is intended for LLM consumption only. Even a fundamental change to its representation (yaml? markdown?) would not be considered breaking.
* [ENHANCEMENT] docs: Add explicit notes about authentication [#5735](https://github.com/grafana/tempo/pull/5735) (@electron0zero)
* [ENHANCEMENT] On startup, first record for live store to consume is not older than two complete block timeouts [#5693](https://github.com/grafana/tempo/pull/5693) (@ruslan-mikhailov)
Expand Down
3 changes: 3 additions & 0 deletions docs/sources/tempo/configuration/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,9 @@ metrics_generator:
# Enables additional labels for services and virtual nodes.
[enable_virtual_node_label: <bool> | default = false]

# List of attribute names used to identify the database name from span attributes. If it isn't set, the order is peer.service -> server.address -> network.peer.address -> db.name
[database_name_attributes: <list of string> | default = ["db.namespace","db.name","db.system"]]

span_metrics:

# Buckets for the latency histogram in seconds.
Expand Down
4 changes: 4 additions & 0 deletions docs/sources/tempo/configuration/manifest.md
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,10 @@ metrics_generator:
- db.system
span_multiplier_key: ""
enable_virtual_node_label: false
database_name_attributes:
- db.namespace
- db.name
- db.system
span_metrics:
histogram_buckets:
- 0.002
Expand Down
11 changes: 11 additions & 0 deletions modules/generator/processor/servicegraphs/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (

"github.com/grafana/tempo/modules/generator/registry"
"github.com/prometheus/client_golang/prometheus"
semconv "go.opentelemetry.io/otel/semconv/v1.25.0"
semconvnew "go.opentelemetry.io/otel/semconv/v1.34.0"
)

type Config struct {
Expand Down Expand Up @@ -45,6 +47,9 @@ type Config struct {

// EnableVirtualNodeLabel enables additional labels for uninstrumented services
EnableVirtualNodeLabel bool `yaml:"enable_virtual_node_label"`

// DatabaseNameAttributes the list of attribute names used to identify the database name from span attributes.
DatabaseNameAttributes []string `yaml:"database_name_attributes"`
}

func (cfg *Config) RegisterFlagsAndApplyDefaults(string, *flag.FlagSet) {
Expand All @@ -62,4 +67,10 @@ func (cfg *Config) RegisterFlagsAndApplyDefaults(string, *flag.FlagSet) {
cfg.PeerAttributes = peerAttr

cfg.EnableMessagingSystemLatencyHistogram = false

cfg.DatabaseNameAttributes = []string{
string(semconvnew.DBNamespaceKey),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i nearly commented that these are out of order with the previous checks, but these are in fact correct. the previous logic is just awfully convoluted. nice catch

string(semconv.DBNameKey),
string(semconv.DBSystemKey),
}
}
19 changes: 4 additions & 15 deletions modules/generator/processor/servicegraphs/servicegraphs.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"github.com/prometheus/client_golang/prometheus/promauto"
"go.opentelemetry.io/otel/attribute"
semconv "go.opentelemetry.io/otel/semconv/v1.25.0"
semconvnew "go.opentelemetry.io/otel/semconv/v1.34.0"

gen "github.com/grafana/tempo/modules/generator/processor"
"github.com/grafana/tempo/modules/generator/processor/servicegraphs/store"
Expand Down Expand Up @@ -276,19 +275,11 @@ func (p *Processor) upsertDatabaseRequest(e *store.Edge, resourceAttr []*v1_comm
)

// Check for db.name or db.namespace first. The dbName is set initially to maintain backwards compatbility.
if name, ok := processor_util.FindAttributeValue(string(semconv.DBNameKey), resourceAttr, span.Attributes); ok {
dbName = name
isDatabase = true
}
if name, ok := processor_util.FindAttributeValue(string(semconvnew.DBNamespaceKey), span.Attributes); ok {
dbName = name
isDatabase = true
}

// Check for db.system only if we don't have db.name above
if !isDatabase {
if _, ok := processor_util.FindAttributeValue(string(semconv.DBSystemKey), resourceAttr, span.Attributes); ok {
for _, attrName := range p.Cfg.DatabaseNameAttributes {
if name, ok := processor_util.FindAttributeValue(attrName, resourceAttr, span.Attributes); ok {
dbName = name
isDatabase = true
break
}
}

Expand All @@ -299,8 +290,6 @@ func (p *Processor) upsertDatabaseRequest(e *store.Edge, resourceAttr []*v1_comm
e.ConnectionType = store.Database
e.ServerLatencySec = spanDurationSec(span)

// Set the service name by order of precedence

// Check for peer.service
if name, ok := processor_util.FindAttributeValue(string(semconv.PeerServiceKey), resourceAttr, span.Attributes); ok {
e.ServerService = name
Expand Down
37 changes: 33 additions & 4 deletions modules/generator/processor/servicegraphs/servicegraphs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,15 @@ import (

"github.com/go-kit/log"
"github.com/gogo/protobuf/jsonpb"
"github.com/grafana/tempo/modules/generator/registry"
"github.com/grafana/tempo/pkg/tempopb"
"github.com/grafana/tempo/pkg/util/test"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/prometheus/model/labels"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
semconv "go.opentelemetry.io/otel/semconv/v1.25.0"
semconvnew "go.opentelemetry.io/otel/semconv/v1.34.0"

"github.com/grafana/tempo/modules/generator/registry"
"github.com/grafana/tempo/pkg/tempopb"
"github.com/grafana/tempo/pkg/util/test"
)

// NOTE: This is a way to know if the contents of the semconv package have changed.
Expand Down Expand Up @@ -543,6 +542,36 @@ func TestServiceGraphs_prefixDimensionsAndEnableExtraLabels(t *testing.T) {
assert.Equal(t, 0.0, testRegistry.Query(`traces_service_graph_request_failed_total`, dbSystemSystemLabels))
}

func TestServiceGraphs_DatabaseNameAttributes(t *testing.T) {
testRegistry := registry.NewTestRegistry()

cfg := Config{}
cfg.RegisterFlagsAndApplyDefaults("", nil)

cfg.HistogramBuckets = []float64{0.04}
cfg.Dimensions = []string{"beast", "god"}
cfg.DatabaseNameAttributes = []string{"db.system"}

p := New(cfg, "test", testRegistry, log.NewNopLogger(), prometheus.NewCounter(prometheus.CounterOpts{}))
defer p.Shutdown(context.Background())

request, err := loadTestData("testdata/trace-with-queue-database.json")
require.NoError(t, err)

p.PushSpans(context.Background(), request)

// The server label should be set to the value of db.system
labels := labels.FromMap(map[string]string{
"client": "mythical-server",
"server": "postgresql",
"connection_type": "database",
"beast": "",
"god": "",
})
print(testRegistry.Query(`traces_service_graph_request_total`, labels))
assert.Equal(t, 1.0, testRegistry.Query(`traces_service_graph_request_total`, labels))
}

func BenchmarkServiceGraphs(b *testing.B) {
testRegistry := registry.NewTestRegistry()

Expand Down
Loading