Skip to content

Commit

Permalink
[extension/observers] Set image and tag fields for container observers (
Browse files Browse the repository at this point in the history
#7279)

**Description:**
Conform to the
(specification)[https://github.com/open-telemetry/opentelemetry-specification/blob/main/semantic_conventions/resource/container.yaml]
for container resources. Adds the `Tag` field to container endpoints and
correctly sets the `Image` field.
  • Loading branch information
Mark Stumpf authored Jan 20, 2022
1 parent 29b515d commit b37ee4c
Show file tree
Hide file tree
Showing 11 changed files with 51 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
- `prometheusreceiver`: Use the OTLP data conversion path by default. (#TBD)
- Use `--feature-gates=-receiver.prometheus.OTLPDirect` to re-enable the
OpenCensus conversion path.
- `extension/observers`: Correctly set image and tag on container endpoints (#7279)

## 🛑 Breaking changes 🛑

Expand Down
9 changes: 8 additions & 1 deletion extension/observer/dockerobserver/extension.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"go.uber.org/zap"

"github.com/open-telemetry/opentelemetry-collector-contrib/extension/observer"
dcommon "github.com/open-telemetry/opentelemetry-collector-contrib/internal/common/docker"
docker "github.com/open-telemetry/opentelemetry-collector-contrib/internal/docker"
)

Expand Down Expand Up @@ -308,9 +309,15 @@ func (d *dockerObserver) endpointForPort(portObj nat.Port, c *dtypes.ContainerJS
id = observer.EndpointID(fmt.Sprintf("%s:%d", c.ID, port))
}

imageRef, err := dcommon.ParseImageName(c.Config.Image)
if err != nil {
d.logger.Error("could not parse container image name", zap.Error(err))
}

details := &observer.Container{
Name: strings.TrimPrefix(c.Name, "/"),
Image: c.Config.Image,
Image: imageRef.Repository,
Tag: imageRef.Tag,
Command: strings.Join(c.Config.Cmd, " "),
ContainerID: c.ID,
Transport: portProtoToTransport(proto),
Expand Down
5 changes: 5 additions & 0 deletions extension/observer/dockerobserver/extension_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ func TestCollectEndpointsDefaultConfig(t *testing.T) {
Details: &observer.Container{
Name: "agitated_wu",
Image: "nginx",
Tag: "1.17",
Command: "nginx -g daemon off;",
ContainerID: "babc5a6d7af2a48e7f52e1da26047024dcf98b737e754c9c3459bb84d1e4f80c",
Transport: observer.ProtocolTCP,
Expand Down Expand Up @@ -134,6 +135,7 @@ func TestCollectEndpointsAllConfigSettings(t *testing.T) {
Details: &observer.Container{
Name: "agitated_wu",
Image: "nginx",
Tag: "1.17",
Command: "nginx -g daemon off;",
ContainerID: "babc5a6d7af2a48e7f52e1da26047024dcf98b737e754c9c3459bb84d1e4f80c",
Transport: observer.ProtocolTCP,
Expand Down Expand Up @@ -181,6 +183,7 @@ func TestCollectEndpointsUseHostnameIfPresent(t *testing.T) {
Details: &observer.Container{
Name: "agitated_wu",
Image: "nginx",
Tag: "1.17",
Command: "nginx -g daemon off;",
ContainerID: "babc5a6d7af2a48e7f52e1da26047024dcf98b737e754c9c3459bb84d1e4f80c",
Transport: observer.ProtocolTCP,
Expand Down Expand Up @@ -228,6 +231,7 @@ func TestCollectEndpointsUseHostBindings(t *testing.T) {
Details: &observer.Container{
Name: "agitated_wu",
Image: "nginx",
Tag: "1.17",
Command: "nginx -g daemon off;",
ContainerID: "babc5a6d7af2a48e7f52e1da26047024dcf98b737e754c9c3459bb84d1e4f80c",
Transport: observer.ProtocolTCP,
Expand Down Expand Up @@ -275,6 +279,7 @@ func TestCollectEndpointsIgnoreNonHostBindings(t *testing.T) {
Details: &observer.Container{
Name: "agitated_wu",
Image: "nginx",
Tag: "1.17",
Command: "nginx -g daemon off;",
ContainerID: "babc5a6d7af2a48e7f52e1da26047024dcf98b737e754c9c3459bb84d1e4f80c",
Transport: observer.ProtocolTCP,
Expand Down
24 changes: 16 additions & 8 deletions extension/observer/dockerobserver/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package dockerobserver

import (
"context"
"fmt"
"sync"
"testing"
"time"
Expand Down Expand Up @@ -56,8 +57,9 @@ func paramsAndContext(t *testing.T) (component.ExtensionCreateSettings, context.

func TestObserverEmitsEndpointsIntegration(t *testing.T) {
c := container.New(t)
image := "docker.io/library/nginx:1.17"
cntr := c.StartImage(image, container.WithPortReady(80))
image := "docker.io/library/nginx"
tag := "1.17"
cntr := c.StartImage(fmt.Sprintf("%s:%s", image, tag), container.WithPortReady(80))
config := NewFactory().CreateDefaultConfig().(*Config)
config.CacheSyncInterval = 1 * time.Second
config.UseHostBindings = true
Expand All @@ -72,13 +74,15 @@ func TestObserverEmitsEndpointsIntegration(t *testing.T) {
require.Equal(t, uint16(80), e.Details.Env()["alternate_port"])
require.Equal(t, string(cntr.ID), e.Details.Env()["container_id"])
require.Equal(t, image, e.Details.Env()["image"])
require.Equal(t, tag, e.Details.Env()["tag"])
}
}

func TestObserverUpdatesEndpointsIntegration(t *testing.T) {
c := container.New(t)
image := "docker.io/library/nginx:1.17"
cntr := c.StartImage(image, container.WithPortReady(80))
image := "docker.io/library/nginx"
tag := "1.17"
cntr := c.StartImage(fmt.Sprintf("%s:%s", image, tag), container.WithPortReady(80))
mn := &mockNotifier{endpointsMap: map[observer.EndpointID]observer.Endpoint{}}
obvs := startObserver(t, mn)
defer stopObserver(t, obvs)
Expand All @@ -89,6 +93,7 @@ func TestObserverUpdatesEndpointsIntegration(t *testing.T) {
require.Equal(t, uint16(80), e.Details.Env()["port"])
require.Equal(t, string(cntr.ID), e.Details.Env()["container_id"])
require.Equal(t, image, e.Details.Env()["image"])
require.Equal(t, tag, e.Details.Env()["tag"])
}

c.RenameContainer(cntr, "nginx-updated")
Expand All @@ -101,13 +106,15 @@ func TestObserverUpdatesEndpointsIntegration(t *testing.T) {
require.Equal(t, uint16(80), e.Details.Env()["port"])
require.Equal(t, string(cntr.ID), e.Details.Env()["container_id"])
require.Equal(t, image, e.Details.Env()["image"])
require.Equal(t, tag, e.Details.Env()["tag"])
}
}

func TestObserverRemovesEndpointsIntegration(t *testing.T) {
d := container.New(t)
image := "docker.io/library/nginx:1.17"
tmpCntr := d.StartImage(image, container.WithPortReady(80))
c := container.New(t)
image := "docker.io/library/nginx"
tag := "1.17"
tmpCntr := c.StartImage(fmt.Sprintf("%s:%s", image, tag), container.WithPortReady(80))
mn := &mockNotifier{endpointsMap: map[observer.EndpointID]observer.Endpoint{}}
obvs := startObserver(t, mn)
defer stopObserver(t, obvs)
Expand All @@ -118,8 +125,9 @@ func TestObserverRemovesEndpointsIntegration(t *testing.T) {
require.Equal(t, uint16(80), e.Details.Env()["port"])
require.Equal(t, string(tmpCntr.ID), e.Details.Env()["container_id"])
require.Equal(t, image, e.Details.Env()["image"])
require.Equal(t, tag, e.Details.Env()["tag"])
}
d.RemoveContainer(tmpCntr)
c.RemoveContainer(tmpCntr)
require.Eventually(t, func() bool { return mn.RemoveCount() == 1 }, 3*time.Second, 10*time.Millisecond)
require.Empty(t, mn.EndpointsMap())
}
Expand Down
2 changes: 1 addition & 1 deletion extension/observer/dockerobserver/testdata/container.json
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@
"-g",
"daemon off;"
],
"Image": "nginx",
"Image": "nginx:1.17",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": [
Expand Down
9 changes: 8 additions & 1 deletion extension/observer/ecstaskobserver/extension.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (

"github.com/open-telemetry/opentelemetry-collector-contrib/extension/observer"
"github.com/open-telemetry/opentelemetry-collector-contrib/internal/aws/ecsutil"
dcommon "github.com/open-telemetry/opentelemetry-collector-contrib/internal/common/docker"
)

const runningStatus = "RUNNING"
Expand Down Expand Up @@ -75,13 +76,19 @@ func (e *ecsTaskObserver) endpointsFromTaskMetadata(taskMetadata *ecsutil.TaskMe
target = fmt.Sprintf("%s:%d", target, port)
}

imageRef, err := dcommon.ParseImageName(container.Image)
if err != nil {
e.telemetry.Logger.Error("could not parse container image name", zap.Error(err))
}

endpoint := observer.Endpoint{
ID: observer.EndpointID(fmt.Sprintf("%s-%s", container.ContainerName, container.DockerID)),
Target: target,
Details: &observer.Container{
ContainerID: container.DockerID,
Host: host,
Image: container.Image,
Image: imageRef.Repository,
Tag: imageRef.Tag,
Labels: container.Labels,
Name: container.ContainerName,
Port: port,
Expand Down
6 changes: 4 additions & 2 deletions extension/observer/ecstaskobserver/extension_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ func TestEndpointsFromTaskMetadata(t *testing.T) {
Details: &observer.Container{
ContainerID: "5302b3fac16c62951717f444030cb1b8f233f40c03fe5507fc127ca1a70597da",
Host: "172.17.0.3",
Image: "nginx:latest",
Image: "nginx",
Tag: "latest",
Labels: map[string]string{
"com.amazonaws.ecs.cluster": "test200",
"com.amazonaws.ecs.container-name": "nginx100",
Expand All @@ -59,7 +60,8 @@ func TestEndpointsFromTaskMetadata(t *testing.T) {
Details: &observer.Container{
ContainerID: "4a984770705c4f4f95e1267af3623ab0923c602b7cd4ed7d77b7f8356537337f",
Host: "172.17.0.4",
Image: "nginx:latest",
Image: "nginx",
Tag: "latest",
Labels: map[string]string{
"com.amazonaws.ecs.cluster": "test200",
"com.amazonaws.ecs.container-name": "nginx300",
Expand Down
1 change: 1 addition & 0 deletions extension/observer/ecstaskobserver/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ require (
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/mapstructure v1.4.3 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/open-telemetry/opentelemetry-collector-contrib/internal/common v0.42.0 // indirect
github.com/open-telemetry/opentelemetry-collector-contrib/internal/coreinternal v0.42.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rs/cors v1.8.2 // indirect
Expand Down
2 changes: 2 additions & 0 deletions extension/observer/ecstaskobserver/go.sum

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions extension/observer/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ type Container struct {
Name string
// Image is the name of the container image
Image string
// Tag is the container image tag, e.g. '0.1'
Tag string
// Port is the exposed port of container
Port uint16
// AlternatePort is the exposed port accessed through some kind of redirection,
Expand All @@ -192,6 +194,7 @@ func (c *Container) Env() EndpointEnv {
return map[string]interface{}{
"name": c.Name,
"image": c.Image,
"tag": c.Tag,
"port": c.Port,
"alternate_port": c.AlternatePort,
"command": c.Command,
Expand Down
2 changes: 2 additions & 0 deletions extension/observer/endpoints_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ func TestEndpointEnv(t *testing.T) {
Details: &Container{
Name: "otel-collector",
Image: "otel-collector-image",
Tag: "1.0.0",
Port: 2379,
AlternatePort: 2380,
Command: "./cmd --config config.yaml",
Expand All @@ -147,6 +148,7 @@ func TestEndpointEnv(t *testing.T) {
"type": "container",
"name": "otel-collector",
"image": "otel-collector-image",
"tag": "1.0.0",
"port": uint16(2379),
"alternate_port": uint16(2380),
"command": "./cmd --config config.yaml",
Expand Down

0 comments on commit b37ee4c

Please sign in to comment.