Skip to content

Commit d638a79

Browse files
committed
[exporter/awscloudwatchlogsexporter] resolve {PodName} placeholder via k8s.pod.name attribute
Motivation: Issue #46202 reports that the `{PodName}` placeholder in `log_group_name`/`log_stream_name` does not resolve for standard EKS pipelines. The root cause, identified in the issue thread, is that `patternKeyToAttributeMap` only mapped `PodName` to the legacy attribute name `pod`. The `k8sattributesprocessor` sets the semantic-convention attribute `k8s.pod.name` (confirmed in processor/k8sattributesprocessor/metadata.yaml, enabled by default), not `pod`, so `{PodName}` silently resolved to `undefined` for the common case of a k8sattributesprocessor + awscloudwatchlogsexporter pipeline, unless users added an extra processor to rename the attribute. Approach: Change `patternKeyToAttributeMap` from `map[string]string` to `map[string][]string` so each placeholder can list multiple candidate resource attribute names, checked in order. `PodName` now checks `pod` first (preserving existing behavior), then falls back to `k8s.pod.name`. All other placeholders keep their single existing attribute name, just wrapped in a one-element slice, so their behavior is unchanged. Validation: Ran `go test ./...` and `go vet ./...` in exporter/awscloudwatchlogsexporter — all tests pass, including the new TestReplacePatternValidPodNameFromK8sSemconv (verifies `{PodName}` resolves from `k8s.pod.name` alone) and TestReplacePatternPodNamePrefersLegacyPodAttribute (verifies `pod` still wins over `k8s.pod.name` when both are present, preserving backwards compatibility). Fixes #46202 Assisted-by: Claude Sonnet 5 Signed-off-by: Pujitha Paladugu <10557236+pujitha24@users.noreply.github.com>
1 parent 4c1583c commit d638a79

4 files changed

Lines changed: 82 additions & 14 deletions

File tree

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
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: bug_fix
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. receiver/filelog)
7+
component: exporter/awscloudwatchlogs
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Resolve the `{PodName}` placeholder in `log_group_name`/`log_stream_name` from the `k8s.pod.name` resource attribute as well as the legacy `pod` attribute.
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: [46202]
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+
The `k8sattributesprocessor` sets the semantic convention attribute
20+
`k8s.pod.name`, not the legacy `pod` attribute that `{PodName}` previously
21+
looked up. This left `{PodName}` resolving to `undefined` for standard EKS
22+
pipelines unless users added an extra processor to rename the attribute.
23+
24+
# If your change doesn't affect end users or the exported elements of any package,
25+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
26+
# Optional: The change log or logs in which this entry should be included.
27+
# e.g. '[user]' or '[user, api]'
28+
# Include 'user' if the change is relevant to end users.
29+
# Include 'api' if there is a change to a library API.
30+
# Default: '[user]'
31+
change_logs: [user]

exporter/awscloudwatchlogsexporter/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ The following settings are required:
2828
- `{ClusterName}`: `aws.ecs.cluster.name`
2929
- `{TaskId}`: `aws.ecs.task.id`
3030
- `{NodeName}`: `k8s.node.name`
31-
- `{PodName}`: `pod`
31+
- `{PodName}`: `pod` or `k8s.pod.name`
3232
- `{ServiceName}`: `service.name`
3333
- `{ContainerInstanceId}`: `aws.ecs.container.instance.id`
3434
- `{TaskDefinitionFamily}`: `aws.ecs.task.family`

exporter/awscloudwatchlogsexporter/util.go

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,19 @@ import (
1212
"go.uber.org/zap"
1313
)
1414

15-
var patternKeyToAttributeMap = map[string]string{
16-
"ClusterName": "aws.ecs.cluster.name",
17-
"TaskId": "aws.ecs.task.id",
18-
"NodeName": "k8s.node.name",
19-
"PodName": "pod",
20-
"ServiceName": "service.name",
21-
"ContainerInstanceId": "aws.ecs.container.instance.id",
22-
"TaskDefinitionFamily": "aws.ecs.task.family",
23-
"InstanceId": "service.instance.id",
24-
"FaasName": "faas.name",
25-
"FaasVersion": "faas.version",
15+
// patternKeyToAttributeMap maps each placeholder key to the resource attribute names
16+
// that are searched, in order, to resolve its value.
17+
var patternKeyToAttributeMap = map[string][]string{
18+
"ClusterName": {"aws.ecs.cluster.name"},
19+
"TaskId": {"aws.ecs.task.id"},
20+
"NodeName": {"k8s.node.name"},
21+
"PodName": {"pod", "k8s.pod.name"},
22+
"ServiceName": {"service.name"},
23+
"ContainerInstanceId": {"aws.ecs.container.instance.id"},
24+
"TaskDefinitionFamily": {"aws.ecs.task.family"},
25+
"InstanceId": {"service.instance.id"},
26+
"FaasName": {"faas.name"},
27+
"FaasVersion": {"faas.version"},
2628
}
2729

2830
func isPatternValid(s string) (bool, string) {
@@ -59,8 +61,11 @@ func replacePatternWithAttrValue(s, patternKey string, attrMap map[string]string
5961
if strings.Contains(s, pattern) {
6062
if value, ok := attrMap[patternKey]; ok {
6163
return replace(s, pattern, value, logger)
62-
} else if value, ok := attrMap[patternKeyToAttributeMap[patternKey]]; ok {
63-
return replace(s, pattern, value, logger)
64+
}
65+
for _, attrName := range patternKeyToAttributeMap[patternKey] {
66+
if value, ok := attrMap[attrName]; ok {
67+
return replace(s, pattern, value, logger)
68+
}
6469
}
6570
logger.Debug("No resource attribute found for pattern " + pattern)
6671
return strings.ReplaceAll(s, pattern, "undefined"), false

exporter/awscloudwatchlogsexporter/util_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,38 @@ func TestReplacePatternValidPod(t *testing.T) {
104104
assert.True(t, success)
105105
}
106106

107+
func TestReplacePatternValidPodNameFromK8sSemconv(t *testing.T) {
108+
logger := zap.NewNop()
109+
110+
input := "/aws/eks/containerinsights/{PodName}/performance"
111+
112+
attrMap := map[string]any{
113+
"aws.eks.cluster.name": "test-cluster-name",
114+
"k8s.pod.name": "test-pod-001",
115+
}
116+
117+
s, success := replacePatterns(input, anyMapToStringMap(attrMap), logger)
118+
119+
assert.Equal(t, "/aws/eks/containerinsights/test-pod-001/performance", s)
120+
assert.True(t, success)
121+
}
122+
123+
func TestReplacePatternPodNamePrefersLegacyPodAttribute(t *testing.T) {
124+
logger := zap.NewNop()
125+
126+
input := "/aws/eks/containerinsights/{PodName}/performance"
127+
128+
attrMap := map[string]any{
129+
"pod": "legacy-pod-name",
130+
"k8s.pod.name": "semconv-pod-name",
131+
}
132+
133+
s, success := replacePatterns(input, anyMapToStringMap(attrMap), logger)
134+
135+
assert.Equal(t, "/aws/eks/containerinsights/legacy-pod-name/performance", s)
136+
assert.True(t, success)
137+
}
138+
107139
func TestReplacePatternMissingPodName(t *testing.T) {
108140
logger := zap.NewNop()
109141

0 commit comments

Comments
 (0)