Skip to content
Draft
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
27 changes: 27 additions & 0 deletions .chloggen/MigrateNET-45297.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Use this changelog template to create an entry for release notes.

# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: enhancement

# The name of the component, or a single word describing the area of concern, (e.g. receiver/filelog)
component: pkg/coreinternal

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Migrates semantic conventions from v1.25.0 to v1.40.0

# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
issues: [45297]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:

# If your change doesn't affect end users or the exported elements of any package,
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
# Optional: The change log or logs in which this entry should be included.
# e.g. '[user]' or '[user, api]'
# Include 'user' if the change is relevant to end users.
# Include 'api' if there is a change to a library API.
# Default: '[user]'
change_logs: []
2 changes: 2 additions & 0 deletions internal/coreinternal/documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ This component has the following feature gates:
| `internal.coreinternal.goldendataset.DontEmitV0HTTPConventions` | alpha | When enabled, goldendataset no longer generates spans with deprecated semconv HTTP attributes http.user_agent, http.flavor (semconv v1.19.0), and http.client_ip. | v0.154.0 | N/A | [Link](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/45293) |
| `internal.coreinternal.goldendataset.DontEmitV0MessagingConventions` | alpha | When enabled, goldendataset no longer generates spans with deprecated semconv attributes messaging.destination (semconv v1.16.0) and messaging.destination.kind (semconv v1.19.0). | v0.155.0 | N/A | [Link](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/45077) |
| `internal.coreinternal.goldendataset.DontEmitV0NetworkConventions` | beta | When enabled, goldendataset no longer generates spans with deprecated semconv v1.12.0 attributes (net.host.ip, net.peer.ip, http.host, http.server_name). | v0.147.0 | N/A | [Link](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/45076) |
| `internal.coreinternal.goldendataset.DontEmitV0NetworkV125Conventions` | alpha | When enabled, goldendataset no longer generates spans with deprecated semconv v1.25.0 attributes (net.host.port, net.peer.name, net.peer.port, net.transport). | v0.158.0 | N/A | [Link](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/45297) |
| `internal.coreinternal.goldendataset.DontEmitV0RPCConventions` | beta | When enabled, goldendataset no longer generates spans with deprecated semconv RPC attributes rpc.service and peer.service. | v0.148.0 | N/A | [Link](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/47548) |
| `internal.coreinternal.goldendataset.EmitV1DatabaseConventions` | alpha | When enabled, goldendataset generates spans with db.system.name (semconv v1.40.0) instead of the deprecated db.system (semconv v1.28.0). | v0.154.0 | N/A | [Link](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/45299) |
| `internal.coreinternal.goldendataset.EmitV1FaaSConventions` | alpha | When enabled, goldendataset generates spans with faas.invocation_id (semconv v1.40.0) alongside legacy faas.execution to support migration. | v0.155.0 | N/A | [Link](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/45293) |
| `internal.coreinternal.goldendataset.EmitV1HTTPConventions` | alpha | When enabled, goldendataset generates spans with user_agent.original, network.protocol.name, network.protocol.version, and client.address (semconv v1.40.0) alongside legacy http.user_agent, http.flavor, and http.client_ip to support migration. | v0.154.0 | N/A | [Link](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/45293) |
| `internal.coreinternal.goldendataset.EmitV1MessagingConventions` | alpha | When enabled, goldendataset generates spans with messaging.destination.name (semconv v1.40.0) alongside legacy messaging.destination to support migration. | v0.155.0 | N/A | [Link](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/45077) |
| `internal.coreinternal.goldendataset.EmitV1NetworkConventions` | beta | When enabled, goldendataset generates spans with network.local.address, network.peer.address, and server.address (semconv v1.38.0) instead of the deprecated net.host.ip, net.peer.ip, http.host, http.server_name (semconv v1.12.0). Enable together with pkg.translator.zipkin.EmitV1NetworkConventions for consistent round-trip translation in tests. | v0.147.0 | N/A | [Link](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/45076) |
| `internal.coreinternal.goldendataset.EmitV1NetworkV125Conventions` | alpha | When enabled, goldendataset generates spans with network.transport, server.address, server.port, and client.port instead of the deprecated net.transport, net.peer.name, net.host.port, and net.peer.port (semconv v1.25.0). | v0.158.0 | N/A | [Link](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/45297) |
| `internal.coreinternal.goldendataset.EmitV1RPCConventions` | beta | When enabled, goldendataset generates spans with rpc.method and service.peer.name (semconv v1.40.0) alongside legacy rpc.service and peer.service to support migration. | v0.148.0 | N/A | [Link](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/47548) |

For more information about feature gates, see the [Feature Gates](https://github.com/open-telemetry/opentelemetry-collector/blob/main/featuregate/README.md) documentation.
73 changes: 51 additions & 22 deletions internal/coreinternal/goldendataset/span_generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,20 +207,26 @@ func appendDatabaseSQLAttributes(attrMap pcommon.Map) {
attrMap.PutStr(string(conventionsv125.DBUserKey), "billing_user")
if !metadata.InternalCoreinternalGoldendatasetDontEmitV0NetworkConventionsFeatureGate.IsEnabled() {
attrMap.PutStr("net.host.ip", "192.0.3.122")
}
if metadata.InternalCoreinternalGoldendatasetEmitV1NetworkConventionsFeatureGate.IsEnabled() {
attrMap.PutStr(string(conventions.NetworkLocalAddressKey), "192.0.3.122")
}
attrMap.PutInt(string(conventionsv125.NetHostPortKey), 51306)
attrMap.PutStr(string(conventionsv125.NetPeerNameKey), "shopdb.example.com")
if !metadata.InternalCoreinternalGoldendatasetDontEmitV0NetworkConventionsFeatureGate.IsEnabled() {
attrMap.PutStr("net.peer.ip", "192.0.2.12")
}
if !metadata.InternalCoreinternalGoldendatasetDontEmitV0NetworkV125ConventionsFeatureGate.IsEnabled() {
attrMap.PutInt(string(conventionsv125.NetHostPortKey), 51306)
attrMap.PutStr(string(conventionsv125.NetPeerNameKey), "shopdb.example.com")
attrMap.PutInt(string(conventionsv125.NetPeerPortKey), 3306)
attrMap.PutStr(string(conventionsv125.NetTransportKey), "IP.TCP")
}
if metadata.InternalCoreinternalGoldendatasetEmitV1NetworkConventionsFeatureGate.IsEnabled() {
attrMap.PutStr(string(conventions.NetworkLocalAddressKey), "192.0.3.122")
attrMap.PutStr(string(conventions.NetworkPeerAddressKey), "192.0.2.12")
}
attrMap.PutInt(string(conventionsv125.NetPeerPortKey), 3306)
attrMap.PutStr(string(conventionsv125.NetTransportKey), "IP.TCP")
if metadata.InternalCoreinternalGoldendatasetEmitV1NetworkV125ConventionsFeatureGate.IsEnabled() {
// This is a client span, so both net.peer.name and net.peer.port map to the
// server.* attributes. net.host.port (the local port) has no server.* role here
// and would collide with net.peer.port, so it is intentionally not migrated.
attrMap.PutStr(string(conventions.ServerAddressKey), "shopdb.example.com")
attrMap.PutInt(string(conventions.ServerPortKey), 3306)
attrMap.PutStr(string(conventions.NetworkTransportKey), "tcp")
}
attrMap.PutStr(string(conventionsv125.DBNameKey), "shopdb")
attrMap.PutStr(string(conventionsv125.DBStatementKey), "SELECT * FROM orders WHERE order_id = 'o4711'")
attrMap.PutStr(string(conventionsv126.EnduserIDKey), "unittest")
Expand All @@ -234,15 +240,22 @@ func appendDatabaseNoSQLAttributes(attrMap pcommon.Map) {
attrMap.PutStr(string(conventions.DBSystemNameKey), "mongodb")
}
attrMap.PutStr(string(conventionsv125.DBUserKey), "the_user")
attrMap.PutStr(string(conventionsv125.NetPeerNameKey), "mongodb0.example.com")
if !metadata.InternalCoreinternalGoldendatasetDontEmitV0NetworkConventionsFeatureGate.IsEnabled() {
attrMap.PutStr("net.peer.ip", "192.0.2.14")
}
if !metadata.InternalCoreinternalGoldendatasetDontEmitV0NetworkV125ConventionsFeatureGate.IsEnabled() {
attrMap.PutStr(string(conventionsv125.NetPeerNameKey), "mongodb0.example.com")
attrMap.PutInt(string(conventionsv125.NetPeerPortKey), 27017)
attrMap.PutStr(string(conventionsv125.NetTransportKey), "IP.TCP")
}
if metadata.InternalCoreinternalGoldendatasetEmitV1NetworkConventionsFeatureGate.IsEnabled() {
attrMap.PutStr(string(conventions.NetworkPeerAddressKey), "192.0.2.14")
}
attrMap.PutInt(string(conventionsv125.NetPeerPortKey), 27017)
attrMap.PutStr(string(conventionsv125.NetTransportKey), "IP.TCP")
if metadata.InternalCoreinternalGoldendatasetEmitV1NetworkV125ConventionsFeatureGate.IsEnabled() {
attrMap.PutStr(string(conventions.ServerAddressKey), "mongodb0.example.com")
attrMap.PutInt(string(conventions.ServerPortKey), 27017)
attrMap.PutStr(string(conventions.NetworkTransportKey), "tcp")
}
attrMap.PutStr(string(conventionsv125.DBNameKey), "shopDb")
attrMap.PutStr(string(conventionsv125.DBOperationKey), "findAndModify")
attrMap.PutStr(string(conventionsv125.DBMongoDBCollectionKey), "products")
Expand Down Expand Up @@ -346,10 +359,15 @@ func appendHTTPServerAttributes(includeStatus bool, attrMap pcommon.Map) {
if !metadata.InternalCoreinternalGoldendatasetDontEmitV0NetworkConventionsFeatureGate.IsEnabled() {
attrMap.PutStr("http.server_name", "api22.opentelemetry.io")
}
if !metadata.InternalCoreinternalGoldendatasetDontEmitV0NetworkV125ConventionsFeatureGate.IsEnabled() {
attrMap.PutInt(string(conventionsv125.NetHostPortKey), 443)
}
if metadata.InternalCoreinternalGoldendatasetEmitV1NetworkConventionsFeatureGate.IsEnabled() {
attrMap.PutStr(string(conventions.ServerAddressKey), "api22.opentelemetry.io")
}
attrMap.PutInt(string(conventionsv125.NetHostPortKey), 443)
if metadata.InternalCoreinternalGoldendatasetEmitV1NetworkV125ConventionsFeatureGate.IsEnabled() {
attrMap.PutInt(string(conventions.ServerPortKey), 443)
}
attrMap.PutStr(string(conventionsv125.HTTPTargetKey), "/blog/posts")
if !metadata.InternalCoreinternalGoldendatasetDontEmitV0HTTPConventionsFeatureGate.IsEnabled() {
attrMap.PutStr(string(conventionsv119.HTTPFlavorKey), "2")
Expand Down Expand Up @@ -427,10 +445,15 @@ func appendGRPCClientAttributes(attrMap pcommon.Map) {
if !metadata.InternalCoreinternalGoldendatasetDontEmitV0NetworkConventionsFeatureGate.IsEnabled() {
attrMap.PutStr("net.peer.ip", "2600:1700:1f00:11c0:4de0:c223:a800:4e87")
}
if !metadata.InternalCoreinternalGoldendatasetDontEmitV0NetworkV125ConventionsFeatureGate.IsEnabled() {
attrMap.PutInt(string(conventionsv125.NetHostPortKey), 8443)
}
if metadata.InternalCoreinternalGoldendatasetEmitV1NetworkConventionsFeatureGate.IsEnabled() {
attrMap.PutStr(string(conventions.NetworkPeerAddressKey), "2600:1700:1f00:11c0:4de0:c223:a800:4e87")
}
attrMap.PutInt(string(conventionsv125.NetHostPortKey), 8443)
if metadata.InternalCoreinternalGoldendatasetEmitV1NetworkV125ConventionsFeatureGate.IsEnabled() {
attrMap.PutInt(string(conventions.ServerPortKey), 8443)
}
attrMap.PutStr(string(conventionsv126.EnduserIDKey), "unittest")
}

Expand Down Expand Up @@ -460,18 +483,19 @@ func appendMaxCountAttributes(includeStatus bool, attrMap pcommon.Map) {
attrMap.PutStr(string(conventionsv125.HTTPSchemeKey), "https")
if !metadata.InternalCoreinternalGoldendatasetDontEmitV0NetworkConventionsFeatureGate.IsEnabled() {
attrMap.PutStr("http.host", "api.opentelemetry.io")
}
if metadata.InternalCoreinternalGoldendatasetEmitV1NetworkConventionsFeatureGate.IsEnabled() {
attrMap.PutStr(string(conventions.ServerAddressKey), "api.opentelemetry.io")
}
attrMap.PutStr(string(conventionsv125.NetHostNameKey), "api22.opentelemetry.io")
if !metadata.InternalCoreinternalGoldendatasetDontEmitV0NetworkConventionsFeatureGate.IsEnabled() {
attrMap.PutStr("net.host.ip", "2600:1700:1f00:11c0:1ced:afa5:fd88:9d48")
}
if !metadata.InternalCoreinternalGoldendatasetDontEmitV0NetworkV125ConventionsFeatureGate.IsEnabled() {
attrMap.PutInt(string(conventionsv125.NetHostPortKey), 443)
}
if metadata.InternalCoreinternalGoldendatasetEmitV1NetworkConventionsFeatureGate.IsEnabled() {
attrMap.PutStr(string(conventions.ServerAddressKey), "api.opentelemetry.io")
attrMap.PutStr(string(conventions.NetworkLocalAddressKey), "2600:1700:1f00:11c0:1ced:afa5:fd88:9d48")
}
attrMap.PutInt(string(conventionsv125.NetHostPortKey), 443)
if metadata.InternalCoreinternalGoldendatasetEmitV1NetworkV125ConventionsFeatureGate.IsEnabled() {
attrMap.PutInt(string(conventions.ServerPortKey), 443)
}
attrMap.PutStr(string(conventionsv125.NetHostNameKey), "api22.opentelemetry.io")
attrMap.PutStr(string(conventionsv125.HTTPTargetKey), "/blog/posts")
if !metadata.InternalCoreinternalGoldendatasetDontEmitV0HTTPConventionsFeatureGate.IsEnabled() {
attrMap.PutStr(string(conventionsv119.HTTPFlavorKey), "2")
Expand Down Expand Up @@ -508,10 +532,15 @@ func appendMaxCountAttributes(includeStatus bool, attrMap pcommon.Map) {
if !metadata.InternalCoreinternalGoldendatasetDontEmitV0NetworkConventionsFeatureGate.IsEnabled() {
attrMap.PutStr("net.peer.ip", "2600:1700:1f00:11c0:1ced:afa5:fd77:9ddc")
}
if !metadata.InternalCoreinternalGoldendatasetDontEmitV0NetworkV125ConventionsFeatureGate.IsEnabled() {
attrMap.PutInt(string(conventionsv125.NetPeerPortKey), 39111)
}
if metadata.InternalCoreinternalGoldendatasetEmitV1NetworkConventionsFeatureGate.IsEnabled() {
attrMap.PutStr(string(conventions.NetworkPeerAddressKey), "2600:1700:1f00:11c0:1ced:afa5:fd77:9ddc")
}
attrMap.PutInt(string(conventionsv125.NetPeerPortKey), 39111)
if metadata.InternalCoreinternalGoldendatasetEmitV1NetworkV125ConventionsFeatureGate.IsEnabled() {
attrMap.PutInt(string(conventions.ClientPortKey), 39111)
}
attrMap.PutDouble("ai-sampler.weight", 0.07)
attrMap.PutBool("ai-sampler.absolute", false)
attrMap.PutInt("ai-sampler.maxhops", 6)
Expand Down
106 changes: 106 additions & 0 deletions internal/coreinternal/goldendataset/span_generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,3 +193,109 @@ func TestGenerateMessagingProducerSpanFeatureGates(t *testing.T) {
})
}
}

func TestGenerateNetworkConventionsFeatureGates(t *testing.T) {
// This exercises a database SQL client span. On a client span both net.peer.name
// and net.peer.port map to server.*; net.host.port has no server.* role here, so
// server.port must carry the peer port (3306, the MySQL server port) rather than
// the local host port (51306).
testCases := []struct {
name string
dontEmitV0 bool
emitV1 bool
expectedKeys []string
absentKeys []string
expectedValues map[string]any
}{
{
name: "default_v0_only",
dontEmitV0: false,
emitV1: false,
expectedKeys: []string{"net.host.ip", "net.host.port", "net.peer.name", "net.peer.ip", "net.peer.port", "net.transport"},
absentKeys: []string{"network.local.address", "server.address", "network.peer.address", "server.port", "network.transport"},
expectedValues: map[string]any{
"net.host.port": int64(51306),
"net.peer.name": "shopdb.example.com",
"net.peer.port": int64(3306),
"net.transport": "IP.TCP",
},
},
{
name: "double_publish",
dontEmitV0: false,
emitV1: true,
expectedKeys: []string{"net.host.ip", "net.host.port", "net.peer.name", "net.peer.ip", "net.peer.port", "net.transport", "network.local.address", "server.address", "network.peer.address", "server.port", "network.transport"},
absentKeys: []string{},
expectedValues: map[string]any{
"net.host.port": int64(51306),
"net.peer.port": int64(3306),
"server.address": "shopdb.example.com",
"server.port": int64(3306),
"network.transport": "tcp",
},
},
{
name: "v1_only",
dontEmitV0: true,
emitV1: true,
expectedKeys: []string{"network.local.address", "server.address", "network.peer.address", "server.port", "network.transport"},
absentKeys: []string{"net.host.ip", "net.host.port", "net.peer.name", "net.peer.ip", "net.peer.port", "net.transport"},
expectedValues: map[string]any{
"server.address": "shopdb.example.com",
"server.port": int64(3306),
"network.transport": "tcp",
},
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
require.NoError(t, featuregate.GlobalRegistry().Set(metadata.InternalCoreinternalGoldendatasetDontEmitV0NetworkConventionsFeatureGate.ID(), tc.dontEmitV0))
require.NoError(t, featuregate.GlobalRegistry().Set(metadata.InternalCoreinternalGoldendatasetEmitV1NetworkConventionsFeatureGate.ID(), tc.emitV1))
require.NoError(t, featuregate.GlobalRegistry().Set(metadata.InternalCoreinternalGoldendatasetDontEmitV0NetworkV125ConventionsFeatureGate.ID(), tc.dontEmitV0))
require.NoError(t, featuregate.GlobalRegistry().Set(metadata.InternalCoreinternalGoldendatasetEmitV1NetworkV125ConventionsFeatureGate.ID(), tc.emitV1))

t.Cleanup(func() {
require.NoError(t, featuregate.GlobalRegistry().Set(metadata.InternalCoreinternalGoldendatasetDontEmitV0NetworkConventionsFeatureGate.ID(), false))
require.NoError(t, featuregate.GlobalRegistry().Set(metadata.InternalCoreinternalGoldendatasetEmitV1NetworkConventionsFeatureGate.ID(), false))
require.NoError(t, featuregate.GlobalRegistry().Set(metadata.InternalCoreinternalGoldendatasetDontEmitV0NetworkV125ConventionsFeatureGate.ID(), false))
require.NoError(t, featuregate.GlobalRegistry().Set(metadata.InternalCoreinternalGoldendatasetEmitV1NetworkV125ConventionsFeatureGate.ID(), false))
})

random := rand.Reader
traceID := generateTraceID(random)
spanInputs := &PICTSpanInputs{
Parent: SpanParentRoot,
Tracestate: TraceStateEmpty,
Kind: SpanKindClient,
Attributes: SpanAttrDatabaseSQL,
Events: SpanChildCountEmpty,
Links: SpanChildCountEmpty,
Status: SpanStatusOk,
}
span := ptrace.NewSpan()
fillSpan(traceID, pcommon.SpanID([8]byte{}), "/gotest-parent", spanInputs, random, span)

attrs := span.Attributes()
for _, k := range tc.expectedKeys {
_, ok := attrs.Get(k)
assert.True(t, ok, "Expected attribute %s to be present", k)
}
for _, k := range tc.absentKeys {
_, ok := attrs.Get(k)
assert.False(t, ok, "Expected attribute %s to be absent", k)
}
for k, want := range tc.expectedValues {
v, ok := attrs.Get(k)
if assert.True(t, ok, "Expected attribute %s to be present", k) {
switch expected := want.(type) {
case int64:
assert.Equal(t, expected, v.Int(), "Unexpected value for attribute %s", k)
case string:
assert.Equal(t, expected, v.Str(), "Unexpected value for attribute %s", k)
}
}
}
})
}
}
Loading
Loading