Skip to content

Commit a9518cd

Browse files
JaredTan95atoulme
andauthored
[connector/servicegraph] Change database_name_attribute to accept a list of values (#39133)
<!--Ex. Fixing a bug - Describe the bug and how this fixes the issue. Ex. Adding a feature - Explain what this achieves.--> #### Description Supporting a prioritized list of attribute names for database identification (e.g., db.name, db.system, db.system.name, database.name, sql.database) <!-- Issue number (e.g. #1234) or full URL to issue, if applicable. --> #### Link to tracking issue Fixes #37777 <!--Describe what testing was performed and which tests were added.--> #### Testing <!--Describe the documentation added.--> #### Documentation <!--Please delete paragraphs that you did not use before submitting.--> --------- Signed-off-by: Jared Tan <[email protected]> Co-authored-by: Antoine Toulme <[email protected]>
1 parent 16bb1d5 commit a9518cd

File tree

6 files changed

+104
-5
lines changed

6 files changed

+104
-5
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: enhancement
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
7+
component: servicegraphconnector
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Change database_name_attribute to accept a list of values.
11+
12+
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
13+
issues: [37777]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext:
19+
20+
# If your change doesn't affect end users or the exported elements of any package,
21+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
22+
# Optional: The change log or logs in which this entry should be included.
23+
# e.g. '[user]' or '[user, api]'
24+
# Include 'user' if the change is relevant to end users.
25+
# Include 'api' if there is a change to a library API.
26+
# Default: '[user]'
27+
change_logs: []

connector/servicegraphconnector/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,10 @@ The following settings can be optionally configured:
140140
- Default: `false`
141141
- `metrics_flush_interval`: the interval at which metrics are flushed to the exporter.
142142
- Default: `60s`
143-
- `database_name_attribute`: the attribute name used to identify the database name from span attributes.
143+
- `database_name_attribute`(DEPRECATED): the attribute name used to identify the database name from span attributes.
144144
- Default: `db.name`
145+
- `database_name_attributes`: the list of attribute names used to identify the database name from span attributes. The attributes are tried in order, selecting the first match.
146+
- Default: `[db.name]`
145147

146148
## Example configurations
147149

connector/servicegraphconnector/config.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,12 @@ type Config struct {
4949

5050
// DatabaseNameAttribute is the attribute name used to identify the database name from span attributes.
5151
// The default value is db.name.
52+
// Deprecated: [v0.124.0] Use database_name_attributes instead.
5253
DatabaseNameAttribute string `mapstructure:"database_name_attribute"`
54+
55+
// DatabaseNameAttributes is the attribute name list of attributes need to match used to identify the database name from span attributes, the higher the front, the higher the priority.
56+
// The default value is {"db.name"}.
57+
DatabaseNameAttributes []string `mapstructure:"database_name_attributes"`
5358
}
5459

5560
type StoreConfig struct {

connector/servicegraphconnector/connector.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ var (
4848
semconv.AttributePeerService, semconv.AttributeDBName, semconv.AttributeDBSystem,
4949
}
5050

51-
defaultDatabaseNameAttribute = semconv.AttributeDBName
51+
defaultDatabaseNameAttributes = []string{semconv.AttributeDBName}
5252

5353
defaultMetricsFlushInterval = 60 * time.Second // 1 DPM
5454
)
@@ -115,8 +115,10 @@ func newConnector(set component.TelemetrySettings, config component.Config, next
115115
pConfig.VirtualNodePeerAttributes = defaultPeerAttributes
116116
}
117117

118-
if pConfig.DatabaseNameAttribute == "" {
119-
pConfig.DatabaseNameAttribute = defaultDatabaseNameAttribute
118+
if pConfig.DatabaseNameAttribute != "" {
119+
pConfig.DatabaseNameAttributes = append(pConfig.DatabaseNameAttributes, pConfig.DatabaseNameAttribute)
120+
} else if len(pConfig.DatabaseNameAttributes) == 0 {
121+
pConfig.DatabaseNameAttributes = defaultDatabaseNameAttributes
120122
}
121123

122124
if pConfig.MetricsFlushInterval == nil {
@@ -273,7 +275,7 @@ func (p *serviceGraphConnector) aggregateMetrics(ctx context.Context, td ptrace.
273275

274276
// A database request will only have one span, we don't wait for the server
275277
// span but just copy details from the client span
276-
if dbName, ok := pdatautil.GetAttributeValue(p.config.DatabaseNameAttribute, rAttributes, span.Attributes()); ok {
278+
if dbName, ok := getFirstMatchingValue(p.config.DatabaseNameAttributes, rAttributes, span.Attributes()); ok {
277279
e.ConnectionType = store.Database
278280
e.ServerService = dbName
279281
e.ServerLatencySec = spanDuration(span)

connector/servicegraphconnector/util.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,14 @@ import (
1313
func findServiceName(attributes pcommon.Map) (string, bool) {
1414
return pdatautil.GetAttributeValue(semconv.AttributeServiceName, attributes)
1515
}
16+
17+
func getFirstMatchingValue(keys []string, attributes ...pcommon.Map) (string, bool) {
18+
for _, key := range keys {
19+
for _, attr := range attributes {
20+
if v, ok := pdatautil.GetAttributeValue(key, attr); ok {
21+
return v, true
22+
}
23+
}
24+
}
25+
return "", false
26+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright The OpenTelemetry Authors
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package servicegraphconnector
5+
6+
import (
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
"go.opentelemetry.io/collector/pdata/pcommon"
11+
)
12+
13+
func TestGetFirstMatchingValue(t *testing.T) {
14+
attr1 := pcommon.NewMap()
15+
attr1.PutStr("key1", "value1")
16+
attr1.PutStr("key2", "value2")
17+
attrs := []pcommon.Map{attr1}
18+
19+
tests := []struct {
20+
name string
21+
keys []string
22+
want string
23+
wantFound bool
24+
}{
25+
{
26+
name: "Found in first attribute",
27+
keys: []string{"key1"},
28+
want: "value1",
29+
wantFound: true,
30+
},
31+
{
32+
name: "Found in second attribute",
33+
keys: []string{"key2"},
34+
want: "value2",
35+
wantFound: true,
36+
},
37+
{
38+
name: "Not found",
39+
keys: []string{"key3"},
40+
want: "",
41+
wantFound: false,
42+
},
43+
}
44+
45+
for _, tt := range tests {
46+
t.Run(tt.name, func(t *testing.T) {
47+
got, gotFound := getFirstMatchingValue(tt.keys, attrs...)
48+
assert.Equal(t, tt.want, got)
49+
assert.Equal(t, tt.wantFound, gotFound)
50+
})
51+
}
52+
}

0 commit comments

Comments
 (0)