Skip to content

Commit 8890a1c

Browse files
committed
cli-plugins: remove docker.cli specific otel attributes after usage
Remove the `docker.cli` prefixed attributes from `OTEL_RESOURCE_ATTRIBUTES` after the telemetry provider has been created within a plugin. This prevents accidentally sending the attributes to something downstream for the user. This also fixes an issue with compose where the self-injected `OTEL_RESOURCE_ATTRIBUTES` would override an existing attribute in the environment file because the "user environment" overrode the environment file, but the "user environment" was created by the `docker` tool rather than by the user's environment. When `OTEL_RESOURCE_ATTRIBUTES` is empty after pruning, the environment variable is unset. Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
1 parent cfe0605 commit 8890a1c

File tree

3 files changed

+54
-15
lines changed

3 files changed

+54
-15
lines changed

‎cli-plugins/manager/cobra.go‎

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ func AddPluginCommandStubs(dockerCli command.Cli, rootCmd *cobra.Command) (err e
107107
}
108108

109109
const (
110-
dockerCliAttributePrefix = attribute.Key("docker.cli")
110+
dockerCliAttributePrefix = command.DockerCliAttributePrefix
111111

112112
cobraCommandPath = attribute.Key("cobra.command_path")
113113
)
@@ -126,7 +126,7 @@ func getPluginResourceAttributes(cmd *cobra.Command, plugin Plugin) attribute.Se
126126
for iter := attrSet.Iter(); iter.Next(); {
127127
attr := iter.Attribute()
128128
kvs = append(kvs, attribute.KeyValue{
129-
Key: dockerCliAttributePrefix + "." + attr.Key,
129+
Key: dockerCliAttributePrefix + attr.Key,
130130
Value: attr.Value,
131131
})
132132
}
@@ -135,26 +135,18 @@ func getPluginResourceAttributes(cmd *cobra.Command, plugin Plugin) attribute.Se
135135

136136
func appendPluginResourceAttributesEnvvar(env []string, cmd *cobra.Command, plugin Plugin) []string {
137137
if attrs := getPluginResourceAttributes(cmd, plugin); attrs.Len() > 0 {
138-
// values in environment variables need to be in baggage format
139-
// otel/baggage package can be used after update to v1.22, currently it encodes incorrectly
140138
// Construct baggage members for each of the attributes.
141139
// Ignore any failures as these aren't significant and
142140
// represent an internal issue.
143-
var b baggage.Baggage
141+
members := make([]baggage.Member, 0, attrs.Len())
144142
for iter := attrs.Iter(); iter.Next(); {
145143
attr := iter.Attribute()
146144
m, err := baggage.NewMemberRaw(string(attr.Key), attr.Value.AsString())
147145
if err != nil {
148146
otel.Handle(err)
149147
continue
150148
}
151-
152-
newB, err := b.SetMember(m)
153-
if err != nil {
154-
otel.Handle(err)
155-
continue
156-
}
157-
b = newB
149+
members = append(members, m)
158150
}
159151

160152
// Combine plugin added resource attributes with ones found in the environment
@@ -165,8 +157,10 @@ func appendPluginResourceAttributesEnvvar(env []string, cmd *cobra.Command, plug
165157
if v := strings.TrimSpace(os.Getenv(ResourceAttributesEnvvar)); v != "" {
166158
attrsSlice = append(attrsSlice, v)
167159
}
168-
if v := b.String(); v != "" {
169-
attrsSlice = append(attrsSlice, v)
160+
if b, err := baggage.New(members...); err != nil {
161+
otel.Handle(err)
162+
} else if b.Len() > 0 {
163+
attrsSlice = append(attrsSlice, b.String())
170164
}
171165

172166
if len(attrsSlice) > 0 {

‎cli-plugins/manager/manager.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ const (
2626

2727
// ResourceAttributesEnvvar is the name of the envvar that includes additional
2828
// resource attributes for OTEL.
29-
ResourceAttributesEnvvar = "OTEL_RESOURCE_ATTRIBUTES"
29+
ResourceAttributesEnvvar = command.ResourceAttributesEnvvar
3030
)
3131

3232
// errPluginNotFound is the error returned when a plugin could not be found.

‎cli/command/cli.go‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"path/filepath"
1212
"runtime"
1313
"strconv"
14+
"strings"
1415
"sync"
1516
"time"
1617

@@ -292,6 +293,7 @@ func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions, ops ...CLIOption)
292293
if cli.enableGlobalTracer {
293294
cli.createGlobalTracerProvider(cli.baseCtx)
294295
}
296+
filterResourceAttributesEnvvar()
295297

296298
return nil
297299
}
@@ -591,3 +593,46 @@ func DefaultContextStoreConfig() store.Config {
591593
defaultStoreEndpoints...,
592594
)
593595
}
596+
597+
const (
598+
// ResourceAttributesEnvvar is the name of the envvar that includes additional
599+
// resource attributes for OTEL.
600+
ResourceAttributesEnvvar = "OTEL_RESOURCE_ATTRIBUTES"
601+
602+
// DockerCliAttributePrefix is the prefix for any docker cli OTEL attributes.
603+
DockerCliAttributePrefix = "docker.cli."
604+
)
605+
606+
func filterResourceAttributesEnvvar() {
607+
if v := os.Getenv(ResourceAttributesEnvvar); v != "" {
608+
if filtered := filterResourceAttributes(v); filtered != "" {
609+
os.Setenv(ResourceAttributesEnvvar, filtered)
610+
} else {
611+
os.Unsetenv(ResourceAttributesEnvvar)
612+
}
613+
}
614+
}
615+
616+
func filterResourceAttributes(s string) string {
617+
if trimmed := strings.TrimSpace(s); trimmed == "" {
618+
return trimmed
619+
}
620+
621+
pairs := strings.Split(s, ",")
622+
elems := make([]string, 0, len(pairs))
623+
for _, p := range pairs {
624+
k, _, found := strings.Cut(p, "=")
625+
if !found {
626+
// Do not interact with invalid otel resources.
627+
elems = append(elems, p)
628+
continue
629+
}
630+
631+
// Skip attributes that have our docker.cli prefix.
632+
if strings.HasPrefix(k, DockerCliAttributePrefix) {
633+
continue
634+
}
635+
elems = append(elems, p)
636+
}
637+
return strings.Join(elems, ",")
638+
}

0 commit comments

Comments
 (0)