From ec1a30fab8e1ae38bdaa86570133e488e4a6f2d9 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 22 Apr 2024 15:22:51 +0200 Subject: [PATCH 01/26] Add Azure resource detectory --- detectors/azure/vm/go.mod | 20 +++++ detectors/azure/vm/go.sum | 24 ++++++ detectors/azure/vm/vm.go | 142 ++++++++++++++++++++++++++++++++++ detectors/azure/vm/vm_test.go | 103 ++++++++++++++++++++++++ 4 files changed, 289 insertions(+) create mode 100644 detectors/azure/vm/go.mod create mode 100644 detectors/azure/vm/go.sum create mode 100644 detectors/azure/vm/vm.go create mode 100644 detectors/azure/vm/vm_test.go diff --git a/detectors/azure/vm/go.mod b/detectors/azure/vm/go.mod new file mode 100644 index 00000000000..236232ed620 --- /dev/null +++ b/detectors/azure/vm/go.mod @@ -0,0 +1,20 @@ +module go.opentelemetry.io/contrib/detectors/azure/vm + +go 1.21 + +require ( + github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/otel v1.25.0 + go.opentelemetry.io/otel/sdk v1.25.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + go.opentelemetry.io/otel/metric v1.25.0 // indirect + go.opentelemetry.io/otel/trace v1.25.0 // indirect + golang.org/x/sys v0.18.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/detectors/azure/vm/go.sum b/detectors/azure/vm/go.sum new file mode 100644 index 00000000000..c3341ed33f2 --- /dev/null +++ b/detectors/azure/vm/go.sum @@ -0,0 +1,24 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +go.opentelemetry.io/otel v1.25.0 h1:gldB5FfhRl7OJQbUHt/8s0a7cE8fbsPAtdpRaApKy4k= +go.opentelemetry.io/otel v1.25.0/go.mod h1:Wa2ds5NOXEMkCmUou1WA7ZBfLTHWIsp034OVD7AO+Vg= +go.opentelemetry.io/otel/metric v1.25.0 h1:LUKbS7ArpFL/I2jJHdJcqMGxkRdxpPHE0VU/D4NuEwA= +go.opentelemetry.io/otel/metric v1.25.0/go.mod h1:rkDLUSd2lC5lq2dFNrX9LGAbINP5B7WBkC78RXCpH5s= +go.opentelemetry.io/otel/sdk v1.25.0 h1:PDryEJPC8YJZQSyLY5eqLeafHtG+X7FWnf3aXMtxbqo= +go.opentelemetry.io/otel/sdk v1.25.0/go.mod h1:oFgzCM2zdsxKzz6zwpTZYLLQsFwc+K0daArPdIhuxkw= +go.opentelemetry.io/otel/trace v1.25.0 h1:tqukZGLwQYRIFtSQM2u2+yfMVTgGVeqRLPUYx1Dq6RM= +go.opentelemetry.io/otel/trace v1.25.0/go.mod h1:hCCs70XM/ljO+BeQkyFnbK28SBIJ/Emuha+ccrCRT7I= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/detectors/azure/vm/vm.go b/detectors/azure/vm/vm.go new file mode 100644 index 00000000000..73cc3895356 --- /dev/null +++ b/detectors/azure/vm/vm.go @@ -0,0 +1,142 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package vm // import "go.opentelemetry.io/contrib/detectors/azure/vm" + +import ( + "context" + "encoding/json" + "io" + "net/http" + + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/sdk/resource" + semconv "go.opentelemetry.io/otel/semconv/v1.24.0" +) + +type config struct { + client Client +} + +func newConfig(options ...Option) *config { + c := &config{&azureInstanceMetadataClient{}} + for _, option := range options { + option.apply(c) + } + + return c +} + +// Option applies an Azure VM detector configuration option. +type Option interface { + apply(*config) +} + +type optionFunc func(*config) + +func (fn optionFunc) apply(c *config) { + fn(c) +} + +// WithClient sets the client for obtaining a Azure instance metadata JSON. +func WithClient(t Client) Option { + return optionFunc(func(c *config) { + c.client = t + }) +} + +func (cfg *config) getClient() Client { + return cfg.client +} + +type resourceDetector struct { + client Client +} + +type vmMetadata struct { + VMId *string `json:"vmId"` + Location *string `json:"location"` + ResourceId *string `json:"resourceId"` + Name *string `json:"name"` + VMSize *string `json:"vmSize"` + OsType *string `json:"osType"` + Version *string `json:"version"` +} + +// NewResourceDetector returns a resource detector that will detect Azure VM resources. +func NewResourceDetector(opts ...Option) resource.Detector { + c := newConfig(opts...) + return &resourceDetector{c.getClient()} +} + +// Detect detects associated resources when running on an Azure VM. +func (detector *resourceDetector) Detect(ctx context.Context) (*resource.Resource, error) { + jsonMetadata, err := detector.client.GetJSONMetadata() + if err != nil { + return nil, err + } + + var metadata vmMetadata + err = json.Unmarshal(jsonMetadata, &metadata) + if err != nil { + return nil, err + } + + attributes := []attribute.KeyValue{ + semconv.CloudProviderAzure, + semconv.CloudPlatformAzureVM, + } + + if metadata.VMId != nil { + attributes = append(attributes, semconv.HostID(*metadata.VMId)) + } + if metadata.Location != nil { + attributes = append(attributes, semconv.CloudRegion(*metadata.Location)) + } + if metadata.ResourceId != nil { + attributes = append(attributes, semconv.CloudResourceID(*metadata.ResourceId)) + } + if metadata.Name != nil { + attributes = append(attributes, semconv.HostName(*metadata.Name)) + } + if metadata.VMSize != nil { + attributes = append(attributes, semconv.HostType(*metadata.VMSize)) + } + if metadata.OsType != nil { + attributes = append(attributes, semconv.OSTypeKey.String(*metadata.OsType)) + } + if metadata.Version != nil { + attributes = append(attributes, semconv.OSVersion(*metadata.Version)) + } + + return resource.NewWithAttributes(semconv.SchemaURL, attributes...), nil +} + +// Client is an interface that allows mocking for testing. +type Client interface { + GetJSONMetadata() ([]byte, error) +} + +type azureInstanceMetadataClient struct{} + +func (c *azureInstanceMetadataClient) GetJSONMetadata() ([]byte, error) { + PTransport := &http.Transport{Proxy: nil} + + client := http.Client{Transport: PTransport} + + req, err := http.NewRequest("GET", "http://169.254.169.254/metadata/instance/compute?api-version=2021-12-13&format=json", nil) + if err != nil { + return nil, err + } + + req.Header.Add("Metadata", "True") + + resp, err := client.Do(req) + if err != nil { + return nil, err + } + + defer resp.Body.Close() + + return io.ReadAll(resp.Body) +} diff --git a/detectors/azure/vm/vm_test.go b/detectors/azure/vm/vm_test.go new file mode 100644 index 00000000000..3e40e9c45f7 --- /dev/null +++ b/detectors/azure/vm/vm_test.go @@ -0,0 +1,103 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package vm + +import ( + "context" + "errors" + "testing" + + "github.com/stretchr/testify/assert" + + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/sdk/resource" + semconv "go.opentelemetry.io/otel/semconv/v1.24.0" +) + +func Test_Detect(t *testing.T) { + type input struct { + jsonMetadata string + err error + } + type expected struct { + resource *resource.Resource + err bool + } + type testCase struct { + input input + expected expected + } + + testTable := []testCase{ + { + input: input{ + jsonMetadata: `{ + "location": "us-west3", + "resourceId": "/subscriptions/sid/resourceGroups/rid/providers/pname/name", + "vmId": "43f65c49-8715-4639-88a9-be6d7eb749a5", + "name": "localhost-3", + "vmSize": "Standard_D2s_v3", + "osType": "linux", + "version": "6.5.0-26-generic" + }`, + err: nil, + }, + expected: expected{ + resource: resource.NewWithAttributes(semconv.SchemaURL, []attribute.KeyValue{ + semconv.CloudProviderAzure, + semconv.CloudPlatformAzureVM, + semconv.CloudRegion("us-west3"), + semconv.CloudResourceID("/subscriptions/sid/resourceGroups/rid/providers/pname/name"), + semconv.HostID("43f65c49-8715-4639-88a9-be6d7eb749a5"), + semconv.HostName("localhost-3"), + semconv.HostType("Standard_D2s_v3"), + semconv.OSTypeKey.String("linux"), + semconv.OSVersion("6.5.0-26-generic"), + }...), + err: false, + }, + }, + { + input: input{ + jsonMetadata: `{`, + err: nil, + }, + expected: expected{ + resource: nil, + err: true, + }, + }, + { + input: input{ + jsonMetadata: "", + err: errors.New("cannot get metadata"), + }, + expected: expected{ + resource: nil, + err: true, + }, + }, + } + + for _, tCase := range testTable { + detector := NewResourceDetector(WithClient(&mockClient{ + jsonMetadata: []byte(tCase.input.jsonMetadata), + err: tCase.input.err, + })) + + azureResource, err := detector.Detect(context.Background()) + + assert.Equal(t, err != nil, tCase.expected.err) + assert.Equal(t, tCase.expected.resource, azureResource) + } +} + +type mockClient struct { + jsonMetadata []byte + err error +} + +func (c *mockClient) GetJSONMetadata() ([]byte, error) { + return c.jsonMetadata, c.err +} From 643207b8ecdede8e4891eb36498189dcd7112f14 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 22 Apr 2024 16:26:46 +0200 Subject: [PATCH 02/26] Fix go.sum --- detectors/azure/vm/go.sum | 3 +++ 1 file changed, 3 insertions(+) diff --git a/detectors/azure/vm/go.sum b/detectors/azure/vm/go.sum index c3341ed33f2..c94c7b1876b 100644 --- a/detectors/azure/vm/go.sum +++ b/detectors/azure/vm/go.sum @@ -5,6 +5,8 @@ github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= @@ -19,6 +21,7 @@ go.opentelemetry.io/otel/trace v1.25.0 h1:tqukZGLwQYRIFtSQM2u2+yfMVTgGVeqRLPUYx1 go.opentelemetry.io/otel/trace v1.25.0/go.mod h1:hCCs70XM/ljO+BeQkyFnbK28SBIJ/Emuha+ccrCRT7I= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 859b363c5cf592ff1fd30d7cebdb7cf8ada280d2 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 22 Apr 2024 16:31:08 +0200 Subject: [PATCH 03/26] PR comments --- versions.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/versions.yaml b/versions.yaml index d11eba4e4fc..b6c97326cfb 100644 --- a/versions.yaml +++ b/versions.yaml @@ -20,6 +20,7 @@ module-sets: modules: - go.opentelemetry.io/contrib/bridges/prometheus - go.opentelemetry.io/contrib/detectors/aws/lambda + - go.opentelemetry.io/contrib/detectors/azure/vm - go.opentelemetry.io/contrib/exporters/autoexport - go.opentelemetry.io/contrib/propagators/autoprop - go.opentelemetry.io/contrib/propagators/opencensus From 15688a2d7994735f8e0b0fa1db3449217a27070f Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Tue, 23 Apr 2024 14:22:36 +0200 Subject: [PATCH 04/26] Change option handling --- detectors/azure/vm/vm.go | 24 +++++++++++++----------- detectors/azure/vm/vm_test.go | 4 ++-- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/detectors/azure/vm/vm.go b/detectors/azure/vm/vm.go index 73cc3895356..47896ed3b13 100644 --- a/detectors/azure/vm/vm.go +++ b/detectors/azure/vm/vm.go @@ -18,10 +18,10 @@ type config struct { client Client } -func newConfig(options ...Option) *config { - c := &config{&azureInstanceMetadataClient{}} +func newConfig(options ...Option) config { + c := config{&azureInstanceMetadataClient{}} for _, option := range options { - option.apply(c) + c = option.apply(c) } return c @@ -29,23 +29,25 @@ func newConfig(options ...Option) *config { // Option applies an Azure VM detector configuration option. type Option interface { - apply(*config) + apply(config) config } -type optionFunc func(*config) +type optionFunc func(config) config -func (fn optionFunc) apply(c *config) { - fn(c) +func (fn optionFunc) apply(c config) config { + return fn(c) } // WithClient sets the client for obtaining a Azure instance metadata JSON. func WithClient(t Client) Option { - return optionFunc(func(c *config) { + return optionFunc(func(c config) config { c.client = t + + return c }) } -func (cfg *config) getClient() Client { +func (cfg config) getClient() Client { return cfg.client } @@ -63,8 +65,8 @@ type vmMetadata struct { Version *string `json:"version"` } -// NewResourceDetector returns a resource detector that will detect Azure VM resources. -func NewResourceDetector(opts ...Option) resource.Detector { +// New returns a [resource.Detector] that will detect Azure VM resources. +func New(opts ...Option) resource.Detector { c := newConfig(opts...) return &resourceDetector{c.getClient()} } diff --git a/detectors/azure/vm/vm_test.go b/detectors/azure/vm/vm_test.go index 3e40e9c45f7..eb631ede2a1 100644 --- a/detectors/azure/vm/vm_test.go +++ b/detectors/azure/vm/vm_test.go @@ -15,7 +15,7 @@ import ( semconv "go.opentelemetry.io/otel/semconv/v1.24.0" ) -func Test_Detect(t *testing.T) { +func TestDetect(t *testing.T) { type input struct { jsonMetadata string err error @@ -81,7 +81,7 @@ func Test_Detect(t *testing.T) { } for _, tCase := range testTable { - detector := NewResourceDetector(WithClient(&mockClient{ + detector := New(WithClient(&mockClient{ jsonMetadata: []byte(tCase.input.jsonMetadata), err: tCase.input.err, })) From 80d0d1170a8ee5f6e7dab9c7c021ba56c6481288 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Tue, 23 Apr 2024 16:01:39 +0200 Subject: [PATCH 05/26] Add changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5e9d73b4bb..b51199d843d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -107,6 +107,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Added - `NewSDK` in `go.opentelemetry.io/contrib/config` now returns a configured SDK with a valid `MeterProvider`. (#4804) +- Add the new `go.opentelemetry.io/contrib/detectors/azure/vm` package to provide a resource detector for Azure VMs. (#5421) ### Changed From f1b2704a6f99e3545ef13866cfb784930fa6b11e Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Tue, 23 Apr 2024 16:06:18 +0200 Subject: [PATCH 06/26] Add README --- detectors/azure/vm/README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 detectors/azure/vm/README.md diff --git a/detectors/azure/vm/README.md b/detectors/azure/vm/README.md new file mode 100644 index 00000000000..5987b85b7ce --- /dev/null +++ b/detectors/azure/vm/README.md @@ -0,0 +1,28 @@ +# Azure VM Resource detector + +The Azure VM resource detector supports detecting attributes specific to Azure VMs. + +## Usage + +```golang +// Instantiate a new host resource detector +azureVmResourceDetector := vm.New() +resource, err := azureVmResourceDetector.Detect(context.Background()) +``` + +## Supported attributes + +According to semantic conventions for +[host](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/resource/host.md), +[cloud](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/resource/cloud.md), +and +[os](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/resource/os.md) +attributes, each of the following attributes is added if it is available: + +* `cloud.provider` +* `cloud.platform` +* `host.id` +* `host.name` +* `host.type` +* `os.type` +* `os.version` From 115b9413434fce3617ab6179966534157a8b5a51 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 27 May 2024 12:42:08 +0200 Subject: [PATCH 07/26] Add pyohannes as code owner for Azure resource detectors --- CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/CODEOWNERS b/CODEOWNERS index 23e7f61b6c8..3bc5ed551e4 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -33,6 +33,7 @@ bridges/otelzap/ @open-te config/ @open-telemetry/go-approvers @MadVikingGod @pellared @codeboten detectors/aws/ @open-telemetry/go-approvers +detectors/azure/ @open-telemetry/go-approvers @pyohannes detectors/gcp/ @open-telemetry/go-approvers @dashpole exporters/autoexport @open-telemetry/go-approvers @MikeGoldsmith @pellared From deaed2e87ed737c25da8301cd364a56a1a1cdd5c Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 27 May 2024 12:47:59 +0200 Subject: [PATCH 08/26] Add missing attributes --- detectors/azure/vm/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/detectors/azure/vm/README.md b/detectors/azure/vm/README.md index 5987b85b7ce..b1f92c62b84 100644 --- a/detectors/azure/vm/README.md +++ b/detectors/azure/vm/README.md @@ -21,6 +21,8 @@ attributes, each of the following attributes is added if it is available: * `cloud.provider` * `cloud.platform` +* `cloud.region` +* `cloud.resource_id` * `host.id` * `host.name` * `host.type` From dacbb2b835b34ed0ac61f0da13f984bc4b589e8c Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 27 May 2024 15:58:29 +0200 Subject: [PATCH 09/26] Fix changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b51199d843d..505d1fcd863 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Added - The `go.opentelemetry.io/contrib/config` add support to configure periodic reader interval and timeout. (#5661) +- Add the new `go.opentelemetry.io/contrib/detectors/azure/vm` package to provide a resource detector for Azure VMs. (#5422) ### Fixed @@ -107,7 +108,6 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Added - `NewSDK` in `go.opentelemetry.io/contrib/config` now returns a configured SDK with a valid `MeterProvider`. (#4804) -- Add the new `go.opentelemetry.io/contrib/detectors/azure/vm` package to provide a resource detector for Azure VMs. (#5421) ### Changed From 9837d40141bb98e7a02da2bf972f58dde4b69a24 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Wed, 29 May 2024 10:56:18 +0200 Subject: [PATCH 10/26] PR comments --- detectors/azure/vm/vm.go | 35 ++++++++++++++--------------------- detectors/azure/vm/vm_test.go | 33 ++++++++++++++++----------------- 2 files changed, 30 insertions(+), 38 deletions(-) diff --git a/detectors/azure/vm/vm.go b/detectors/azure/vm/vm.go index 47896ed3b13..b45f9b16589 100644 --- a/detectors/azure/vm/vm.go +++ b/detectors/azure/vm/vm.go @@ -14,12 +14,16 @@ import ( semconv "go.opentelemetry.io/otel/semconv/v1.24.0" ) +const ( + defaultAzureVmMetadataEndpoint = "http://169.254.169.254/metadata/instance/compute?api-version=2021-12-13&format=json" +) + type config struct { - client Client + endpoint string } func newConfig(options ...Option) config { - c := config{&azureInstanceMetadataClient{}} + c := config{defaultAzureVmMetadataEndpoint} for _, option := range options { c = option.apply(c) } @@ -38,21 +42,17 @@ func (fn optionFunc) apply(c config) config { return fn(c) } -// WithClient sets the client for obtaining a Azure instance metadata JSON. -func WithClient(t Client) Option { +// WithEndpoint sets the endpoint for obtaining a Azure instance metadata JSON. +func WithEndpoint(e string) Option { return optionFunc(func(c config) config { - c.client = t + c.endpoint = e return c }) } -func (cfg config) getClient() Client { - return cfg.client -} - type resourceDetector struct { - client Client + endpoint string } type vmMetadata struct { @@ -68,12 +68,12 @@ type vmMetadata struct { // New returns a [resource.Detector] that will detect Azure VM resources. func New(opts ...Option) resource.Detector { c := newConfig(opts...) - return &resourceDetector{c.getClient()} + return &resourceDetector{c.endpoint} } // Detect detects associated resources when running on an Azure VM. func (detector *resourceDetector) Detect(ctx context.Context) (*resource.Resource, error) { - jsonMetadata, err := detector.client.GetJSONMetadata() + jsonMetadata, err := detector.getJSONMetadata() if err != nil { return nil, err } @@ -114,19 +114,12 @@ func (detector *resourceDetector) Detect(ctx context.Context) (*resource.Resourc return resource.NewWithAttributes(semconv.SchemaURL, attributes...), nil } -// Client is an interface that allows mocking for testing. -type Client interface { - GetJSONMetadata() ([]byte, error) -} - -type azureInstanceMetadataClient struct{} - -func (c *azureInstanceMetadataClient) GetJSONMetadata() ([]byte, error) { +func (detector *resourceDetector) getJSONMetadata() ([]byte, error) { PTransport := &http.Transport{Proxy: nil} client := http.Client{Transport: PTransport} - req, err := http.NewRequest("GET", "http://169.254.169.254/metadata/instance/compute?api-version=2021-12-13&format=json", nil) + req, err := http.NewRequest("GET", detector.endpoint, nil) if err != nil { return nil, err } diff --git a/detectors/azure/vm/vm_test.go b/detectors/azure/vm/vm_test.go index eb631ede2a1..216694c3927 100644 --- a/detectors/azure/vm/vm_test.go +++ b/detectors/azure/vm/vm_test.go @@ -5,7 +5,9 @@ package vm import ( "context" - "errors" + "fmt" + "net/http" + "net/http/httptest" "testing" "github.com/stretchr/testify/assert" @@ -18,7 +20,7 @@ import ( func TestDetect(t *testing.T) { type input struct { jsonMetadata string - err error + statusCode int } type expected struct { resource *resource.Resource @@ -41,7 +43,7 @@ func TestDetect(t *testing.T) { "osType": "linux", "version": "6.5.0-26-generic" }`, - err: nil, + statusCode: http.StatusOK, }, expected: expected{ resource: resource.NewWithAttributes(semconv.SchemaURL, []attribute.KeyValue{ @@ -61,7 +63,7 @@ func TestDetect(t *testing.T) { { input: input{ jsonMetadata: `{`, - err: nil, + statusCode: http.StatusOK, }, expected: expected{ resource: nil, @@ -71,7 +73,7 @@ func TestDetect(t *testing.T) { { input: input{ jsonMetadata: "", - err: errors.New("cannot get metadata"), + statusCode: http.StatusNotFound, }, expected: expected{ resource: nil, @@ -81,10 +83,16 @@ func TestDetect(t *testing.T) { } for _, tCase := range testTable { - detector := New(WithClient(&mockClient{ - jsonMetadata: []byte(tCase.input.jsonMetadata), - err: tCase.input.err, + svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusInternalServerError) + + if r.Header.Get("Metadata") == "True" { + fmt.Fprintf(w, tCase.input.jsonMetadata) + } })) + defer svr.Close() + + detector := New(WithEndpoint(svr.URL)) azureResource, err := detector.Detect(context.Background()) @@ -92,12 +100,3 @@ func TestDetect(t *testing.T) { assert.Equal(t, tCase.expected.resource, azureResource) } } - -type mockClient struct { - jsonMetadata []byte - err error -} - -func (c *mockClient) GetJSONMetadata() ([]byte, error) { - return c.jsonMetadata, c.err -} From c268566cff3e10a0df2dc3888f07dd09e474c027 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Wed, 29 May 2024 11:07:12 +0200 Subject: [PATCH 11/26] Linter issues --- detectors/azure/vm/vm.go | 4 ++-- detectors/azure/vm/vm_test.go | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/detectors/azure/vm/vm.go b/detectors/azure/vm/vm.go index b45f9b16589..addb40d3f09 100644 --- a/detectors/azure/vm/vm.go +++ b/detectors/azure/vm/vm.go @@ -15,7 +15,7 @@ import ( ) const ( - defaultAzureVmMetadataEndpoint = "http://169.254.169.254/metadata/instance/compute?api-version=2021-12-13&format=json" + defaultAzureVMMetadataEndpoint = "http://169.254.169.254/metadata/instance/compute?api-version=2021-12-13&format=json" ) type config struct { @@ -23,7 +23,7 @@ type config struct { } func newConfig(options ...Option) config { - c := config{defaultAzureVmMetadataEndpoint} + c := config{defaultAzureVMMetadataEndpoint} for _, option := range options { c = option.apply(c) } diff --git a/detectors/azure/vm/vm_test.go b/detectors/azure/vm/vm_test.go index 216694c3927..67227f351e1 100644 --- a/detectors/azure/vm/vm_test.go +++ b/detectors/azure/vm/vm_test.go @@ -90,12 +90,13 @@ func TestDetect(t *testing.T) { fmt.Fprintf(w, tCase.input.jsonMetadata) } })) - defer svr.Close() detector := New(WithEndpoint(svr.URL)) azureResource, err := detector.Detect(context.Background()) + svr.Close() + assert.Equal(t, err != nil, tCase.expected.err) assert.Equal(t, tCase.expected.resource, azureResource) } From c157aa0d4f5ac7f8315ec171b261293050ccb071 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Wed, 29 May 2024 11:18:22 +0200 Subject: [PATCH 12/26] Linter issues --- detectors/azure/vm/vm_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/detectors/azure/vm/vm_test.go b/detectors/azure/vm/vm_test.go index 67227f351e1..6ceabb65363 100644 --- a/detectors/azure/vm/vm_test.go +++ b/detectors/azure/vm/vm_test.go @@ -43,7 +43,7 @@ func TestDetect(t *testing.T) { "osType": "linux", "version": "6.5.0-26-generic" }`, - statusCode: http.StatusOK, + statusCode: http.StatusOK, }, expected: expected{ resource: resource.NewWithAttributes(semconv.SchemaURL, []attribute.KeyValue{ @@ -63,7 +63,7 @@ func TestDetect(t *testing.T) { { input: input{ jsonMetadata: `{`, - statusCode: http.StatusOK, + statusCode: http.StatusOK, }, expected: expected{ resource: nil, @@ -73,7 +73,7 @@ func TestDetect(t *testing.T) { { input: input{ jsonMetadata: "", - statusCode: http.StatusNotFound, + statusCode: http.StatusNotFound, }, expected: expected{ resource: nil, From edb01a0cc3bfd119ab4577e5dc1ca475a6491ef1 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Thu, 30 May 2024 09:57:37 +0200 Subject: [PATCH 13/26] Update detectors/azure/vm/vm.go Co-authored-by: David Ashpole --- detectors/azure/vm/vm.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/detectors/azure/vm/vm.go b/detectors/azure/vm/vm.go index addb40d3f09..8b7f94d89da 100644 --- a/detectors/azure/vm/vm.go +++ b/detectors/azure/vm/vm.go @@ -115,9 +115,9 @@ func (detector *resourceDetector) Detect(ctx context.Context) (*resource.Resourc } func (detector *resourceDetector) getJSONMetadata() ([]byte, error) { - PTransport := &http.Transport{Proxy: nil} + pTransport := &http.Transport{Proxy: nil} - client := http.Client{Transport: PTransport} + client := http.Client{Transport: pTransport} req, err := http.NewRequest("GET", detector.endpoint, nil) if err != nil { From 6fc2bd82cf478e9e4fb8553f690f6d3dc00c43a8 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Thu, 30 May 2024 09:57:46 +0200 Subject: [PATCH 14/26] Update detectors/azure/vm/README.md Co-authored-by: David Ashpole --- detectors/azure/vm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detectors/azure/vm/README.md b/detectors/azure/vm/README.md index b1f92c62b84..2046c281fac 100644 --- a/detectors/azure/vm/README.md +++ b/detectors/azure/vm/README.md @@ -5,7 +5,7 @@ The Azure VM resource detector supports detecting attributes specific to Azure V ## Usage ```golang -// Instantiate a new host resource detector +// Instantiate a new azure vm resource detector azureVmResourceDetector := vm.New() resource, err := azureVmResourceDetector.Detect(context.Background()) ``` From 336463e49ff5b6dfb9c085fc330467d7295436aa Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Thu, 30 May 2024 10:00:02 +0200 Subject: [PATCH 15/26] PR comments --- CHANGELOG.md | 2 +- detectors/azure/{vm => azurevm}/README.md | 4 ++-- detectors/azure/{vm => azurevm}/go.mod | 2 +- detectors/azure/{vm => azurevm}/go.sum | 0 detectors/azure/{vm => azurevm}/vm.go | 9 +++++++-- detectors/azure/{vm => azurevm}/vm_test.go | 10 +++++----- versions.yaml | 2 +- 7 files changed, 17 insertions(+), 12 deletions(-) rename detectors/azure/{vm => azurevm}/README.md (89%) rename detectors/azure/{vm => azurevm}/go.mod (89%) rename detectors/azure/{vm => azurevm}/go.sum (100%) rename detectors/azure/{vm => azurevm}/vm.go (93%) rename detectors/azure/{vm => azurevm}/vm_test.go (94%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 505d1fcd863..32a8e204c4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ### Added - The `go.opentelemetry.io/contrib/config` add support to configure periodic reader interval and timeout. (#5661) -- Add the new `go.opentelemetry.io/contrib/detectors/azure/vm` package to provide a resource detector for Azure VMs. (#5422) +- Add the new `go.opentelemetry.io/contrib/detectors/azure/azurevm` package to provide a resource detector for Azure VMs. (#5422) ### Fixed diff --git a/detectors/azure/vm/README.md b/detectors/azure/azurevm/README.md similarity index 89% rename from detectors/azure/vm/README.md rename to detectors/azure/azurevm/README.md index 2046c281fac..4dab2fa308f 100644 --- a/detectors/azure/vm/README.md +++ b/detectors/azure/azurevm/README.md @@ -5,8 +5,8 @@ The Azure VM resource detector supports detecting attributes specific to Azure V ## Usage ```golang -// Instantiate a new azure vm resource detector -azureVmResourceDetector := vm.New() +// Instantiate a new Azure VM resource detector +azureVmResourceDetector := azurevm.New() resource, err := azureVmResourceDetector.Detect(context.Background()) ``` diff --git a/detectors/azure/vm/go.mod b/detectors/azure/azurevm/go.mod similarity index 89% rename from detectors/azure/vm/go.mod rename to detectors/azure/azurevm/go.mod index 236232ed620..1e6498d53fd 100644 --- a/detectors/azure/vm/go.mod +++ b/detectors/azure/azurevm/go.mod @@ -1,4 +1,4 @@ -module go.opentelemetry.io/contrib/detectors/azure/vm +module go.opentelemetry.io/contrib/detectors/azure/azurevm go 1.21 diff --git a/detectors/azure/vm/go.sum b/detectors/azure/azurevm/go.sum similarity index 100% rename from detectors/azure/vm/go.sum rename to detectors/azure/azurevm/go.sum diff --git a/detectors/azure/vm/vm.go b/detectors/azure/azurevm/vm.go similarity index 93% rename from detectors/azure/vm/vm.go rename to detectors/azure/azurevm/vm.go index 8b7f94d89da..a4b59289eb7 100644 --- a/detectors/azure/vm/vm.go +++ b/detectors/azure/azurevm/vm.go @@ -1,11 +1,12 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -package vm // import "go.opentelemetry.io/contrib/detectors/azure/vm" +package azurevm // import "go.opentelemetry.io/contrib/detectors/azure/azurevm" import ( "context" "encoding/json" + "errors" "io" "net/http" @@ -75,7 +76,7 @@ func New(opts ...Option) resource.Detector { func (detector *resourceDetector) Detect(ctx context.Context) (*resource.Resource, error) { jsonMetadata, err := detector.getJSONMetadata() if err != nil { - return nil, err + return resource.Empty(), nil } var metadata vmMetadata @@ -131,6 +132,10 @@ func (detector *resourceDetector) getJSONMetadata() ([]byte, error) { return nil, err } + if resp.StatusCode != http.StatusOK { + return nil, errors.New(http.StatusText(resp.StatusCode)) + } + defer resp.Body.Close() return io.ReadAll(resp.Body) diff --git a/detectors/azure/vm/vm_test.go b/detectors/azure/azurevm/vm_test.go similarity index 94% rename from detectors/azure/vm/vm_test.go rename to detectors/azure/azurevm/vm_test.go index 6ceabb65363..81c991c3202 100644 --- a/detectors/azure/vm/vm_test.go +++ b/detectors/azure/azurevm/vm_test.go @@ -1,7 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 -package vm +package azurevm import ( "context" @@ -72,19 +72,19 @@ func TestDetect(t *testing.T) { }, { input: input{ - jsonMetadata: "", + jsonMetadata: "{}", statusCode: http.StatusNotFound, }, expected: expected{ - resource: nil, - err: true, + resource: resource.Empty(), + err: false, }, }, } for _, tCase := range testTable { svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusInternalServerError) + w.WriteHeader(tCase.input.statusCode) if r.Header.Get("Metadata") == "True" { fmt.Fprintf(w, tCase.input.jsonMetadata) diff --git a/versions.yaml b/versions.yaml index b6c97326cfb..09e2f96f9f6 100644 --- a/versions.yaml +++ b/versions.yaml @@ -20,7 +20,7 @@ module-sets: modules: - go.opentelemetry.io/contrib/bridges/prometheus - go.opentelemetry.io/contrib/detectors/aws/lambda - - go.opentelemetry.io/contrib/detectors/azure/vm + - go.opentelemetry.io/contrib/detectors/azure/azurevm - go.opentelemetry.io/contrib/exporters/autoexport - go.opentelemetry.io/contrib/propagators/autoprop - go.opentelemetry.io/contrib/propagators/opencensus From 887a8dd784854e068fb60ed98ac85367a53279e9 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Fri, 31 May 2024 09:27:43 +0200 Subject: [PATCH 16/26] PR comments --- detectors/azure/azurevm/README.md | 29 +--------- detectors/azure/azurevm/doc.go | 24 ++++++++ detectors/azure/azurevm/example_new_test.go | 20 +++++++ detectors/azure/azurevm/vm.go | 63 ++++++--------------- detectors/azure/azurevm/vm_test.go | 15 ++++- 5 files changed, 76 insertions(+), 75 deletions(-) create mode 100644 detectors/azure/azurevm/doc.go create mode 100644 detectors/azure/azurevm/example_new_test.go diff --git a/detectors/azure/azurevm/README.md b/detectors/azure/azurevm/README.md index 4dab2fa308f..0a2b94da7ff 100644 --- a/detectors/azure/azurevm/README.md +++ b/detectors/azure/azurevm/README.md @@ -1,30 +1,3 @@ # Azure VM Resource detector -The Azure VM resource detector supports detecting attributes specific to Azure VMs. - -## Usage - -```golang -// Instantiate a new Azure VM resource detector -azureVmResourceDetector := azurevm.New() -resource, err := azureVmResourceDetector.Detect(context.Background()) -``` - -## Supported attributes - -According to semantic conventions for -[host](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/resource/host.md), -[cloud](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/resource/cloud.md), -and -[os](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/resource/os.md) -attributes, each of the following attributes is added if it is available: - -* `cloud.provider` -* `cloud.platform` -* `cloud.region` -* `cloud.resource_id` -* `host.id` -* `host.name` -* `host.type` -* `os.type` -* `os.version` +[![PkgGoDev](https://pkg.go.dev/badge/go.opentelemetry.io/contrib/detectors/azure/azurevm)](https://pkg.go.dev/go.opentelemetry.io/contrib/detectors/azure/azurevm) diff --git a/detectors/azure/azurevm/doc.go b/detectors/azure/azurevm/doc.go new file mode 100644 index 00000000000..d2c7ce71fb8 --- /dev/null +++ b/detectors/azure/azurevm/doc.go @@ -0,0 +1,24 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +/* +The Azure VM [resource.Detector] supports detecting attributes specific to Azure VMs. + +According to semantic conventions for [host], [cloud], and [os] attributes, +each of the following attributes is added if it is available: + + - cloud.provider + - cloud.platform + - cloud.region + - cloud.resource_id + - host.id + - host.name + - host.type + - os.type + - os.version + +[host]: https://github.com/open-telemetry/semantic-conventions/blob/main/docs/resource/host.md +[cloud]: https://github.com/open-telemetry/semantic-conventions/blob/main/docs/resource/cloud.md +[os]: https://github.com/open-telemetry/semantic-conventions/blob/main/docs/resource/os.md +*/ +package azurevm // import "go.opentelemetry.io/contrib/detectors/azure/azurevm" diff --git a/detectors/azure/azurevm/example_new_test.go b/detectors/azure/azurevm/example_new_test.go new file mode 100644 index 00000000000..891a619deec --- /dev/null +++ b/detectors/azure/azurevm/example_new_test.go @@ -0,0 +1,20 @@ +package azurevm_test + +import ( + "context" + "fmt" + + "go.opentelemetry.io/contrib/detectors/azure/azurevm" +) + +func ExampleNew() { + azureVmResourceDetector := azurevm.New() + resource, err := azureVmResourceDetector.Detect(context.Background()) + + if err != nil { + panic(err) + } + + // Now, you can use the resource (e.g. pass it to a tracer or meter provider). + fmt.Println(resource.SchemaURL()) +} diff --git a/detectors/azure/azurevm/vm.go b/detectors/azure/azurevm/vm.go index a4b59289eb7..4b0a8115663 100644 --- a/detectors/azure/azurevm/vm.go +++ b/detectors/azure/azurevm/vm.go @@ -19,39 +19,6 @@ const ( defaultAzureVMMetadataEndpoint = "http://169.254.169.254/metadata/instance/compute?api-version=2021-12-13&format=json" ) -type config struct { - endpoint string -} - -func newConfig(options ...Option) config { - c := config{defaultAzureVMMetadataEndpoint} - for _, option := range options { - c = option.apply(c) - } - - return c -} - -// Option applies an Azure VM detector configuration option. -type Option interface { - apply(config) config -} - -type optionFunc func(config) config - -func (fn optionFunc) apply(c config) config { - return fn(c) -} - -// WithEndpoint sets the endpoint for obtaining a Azure instance metadata JSON. -func WithEndpoint(e string) Option { - return optionFunc(func(c config) config { - c.endpoint = e - - return c - }) -} - type resourceDetector struct { endpoint string } @@ -67,16 +34,19 @@ type vmMetadata struct { } // New returns a [resource.Detector] that will detect Azure VM resources. -func New(opts ...Option) resource.Detector { - c := newConfig(opts...) - return &resourceDetector{c.endpoint} +func New() *resourceDetector { + return &resourceDetector{defaultAzureVMMetadataEndpoint} } // Detect detects associated resources when running on an Azure VM. func (detector *resourceDetector) Detect(ctx context.Context) (*resource.Resource, error) { - jsonMetadata, err := detector.getJSONMetadata() + jsonMetadata, err, runningInAzure := detector.getJSONMetadata() if err != nil { - return resource.Empty(), nil + if !runningInAzure { + return resource.Empty(), nil + } else { + return nil, err + } } var metadata vmMetadata @@ -115,28 +85,31 @@ func (detector *resourceDetector) Detect(ctx context.Context) (*resource.Resourc return resource.NewWithAttributes(semconv.SchemaURL, attributes...), nil } -func (detector *resourceDetector) getJSONMetadata() ([]byte, error) { +func (detector *resourceDetector) getJSONMetadata() ([]byte, error, bool) { pTransport := &http.Transport{Proxy: nil} client := http.Client{Transport: pTransport} req, err := http.NewRequest("GET", detector.endpoint, nil) if err != nil { - return nil, err + return nil, err, false } req.Header.Add("Metadata", "True") resp, err := client.Do(req) if err != nil { - return nil, err + return nil, err, false } - if resp.StatusCode != http.StatusOK { - return nil, errors.New(http.StatusText(resp.StatusCode)) + defer resp.Body.Close() + + if resp.StatusCode == http.StatusOK { + bytes, err := io.ReadAll(resp.Body) + return bytes, err, true } - defer resp.Body.Close() + runningInAzure := resp.StatusCode < 400 || resp.StatusCode > 499 - return io.ReadAll(resp.Body) + return nil, errors.New(http.StatusText(resp.StatusCode)), runningInAzure } diff --git a/detectors/azure/azurevm/vm_test.go b/detectors/azure/azurevm/vm_test.go index 81c991c3202..27143c354c1 100644 --- a/detectors/azure/azurevm/vm_test.go +++ b/detectors/azure/azurevm/vm_test.go @@ -72,7 +72,7 @@ func TestDetect(t *testing.T) { }, { input: input{ - jsonMetadata: "{}", + jsonMetadata: "", statusCode: http.StatusNotFound, }, expected: expected{ @@ -80,6 +80,16 @@ func TestDetect(t *testing.T) { err: false, }, }, + { + input: input{ + jsonMetadata: "", + statusCode: http.StatusInternalServerError, + }, + expected: expected{ + resource: nil, + err: true, + }, + }, } for _, tCase := range testTable { @@ -91,7 +101,8 @@ func TestDetect(t *testing.T) { } })) - detector := New(WithEndpoint(svr.URL)) + detector := New() + detector.endpoint = svr.URL azureResource, err := detector.Detect(context.Background()) From 39d8f62c007e50dc9076b14d066686545d4eab53 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Fri, 31 May 2024 09:33:38 +0200 Subject: [PATCH 17/26] Linter issues --- detectors/azure/azurevm/example_new_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/detectors/azure/azurevm/example_new_test.go b/detectors/azure/azurevm/example_new_test.go index 891a619deec..6bd35c597e0 100644 --- a/detectors/azure/azurevm/example_new_test.go +++ b/detectors/azure/azurevm/example_new_test.go @@ -1,3 +1,6 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + package azurevm_test import ( From 103dcb5776cddc727cbb789022214bfd305dc0c5 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Fri, 31 May 2024 09:58:30 +0200 Subject: [PATCH 18/26] Linter issues --- detectors/azure/azurevm/doc.go | 3 ++- detectors/azure/azurevm/example_new_test.go | 4 ++-- detectors/azure/azurevm/vm.go | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/detectors/azure/azurevm/doc.go b/detectors/azure/azurevm/doc.go index d2c7ce71fb8..779068e92d9 100644 --- a/detectors/azure/azurevm/doc.go +++ b/detectors/azure/azurevm/doc.go @@ -2,7 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 /* -The Azure VM [resource.Detector] supports detecting attributes specific to Azure VMs. +Package azurevm provides a [resource.Detector] which supports detecting +attributes specific to Azure VMs. According to semantic conventions for [host], [cloud], and [os] attributes, each of the following attributes is added if it is available: diff --git a/detectors/azure/azurevm/example_new_test.go b/detectors/azure/azurevm/example_new_test.go index 6bd35c597e0..1fcc62b7add 100644 --- a/detectors/azure/azurevm/example_new_test.go +++ b/detectors/azure/azurevm/example_new_test.go @@ -11,8 +11,8 @@ import ( ) func ExampleNew() { - azureVmResourceDetector := azurevm.New() - resource, err := azureVmResourceDetector.Detect(context.Background()) + azureVMResourceDetector := azurevm.New() + resource, err := azureVMResourceDetector.Detect(context.Background()) if err != nil { panic(err) diff --git a/detectors/azure/azurevm/vm.go b/detectors/azure/azurevm/vm.go index 4b0a8115663..f31957dd05a 100644 --- a/detectors/azure/azurevm/vm.go +++ b/detectors/azure/azurevm/vm.go @@ -44,9 +44,9 @@ func (detector *resourceDetector) Detect(ctx context.Context) (*resource.Resourc if err != nil { if !runningInAzure { return resource.Empty(), nil - } else { - return nil, err } + + return nil, err } var metadata vmMetadata From 8b0b366d62ab71991fc5a0b39f636dd543040c92 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Fri, 31 May 2024 09:59:50 +0200 Subject: [PATCH 19/26] Make struct public --- detectors/azure/azurevm/vm.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/detectors/azure/azurevm/vm.go b/detectors/azure/azurevm/vm.go index f31957dd05a..ce7de46fb5b 100644 --- a/detectors/azure/azurevm/vm.go +++ b/detectors/azure/azurevm/vm.go @@ -19,7 +19,7 @@ const ( defaultAzureVMMetadataEndpoint = "http://169.254.169.254/metadata/instance/compute?api-version=2021-12-13&format=json" ) -type resourceDetector struct { +type AzureVMResourceDetector struct { endpoint string } @@ -34,12 +34,12 @@ type vmMetadata struct { } // New returns a [resource.Detector] that will detect Azure VM resources. -func New() *resourceDetector { - return &resourceDetector{defaultAzureVMMetadataEndpoint} +func New() *AzureVMResourceDetector { + return &AzureVMResourceDetector{defaultAzureVMMetadataEndpoint} } // Detect detects associated resources when running on an Azure VM. -func (detector *resourceDetector) Detect(ctx context.Context) (*resource.Resource, error) { +func (detector *AzureVMResourceDetector) Detect(ctx context.Context) (*resource.Resource, error) { jsonMetadata, err, runningInAzure := detector.getJSONMetadata() if err != nil { if !runningInAzure { @@ -85,7 +85,7 @@ func (detector *resourceDetector) Detect(ctx context.Context) (*resource.Resourc return resource.NewWithAttributes(semconv.SchemaURL, attributes...), nil } -func (detector *resourceDetector) getJSONMetadata() ([]byte, error, bool) { +func (detector *AzureVMResourceDetector) getJSONMetadata() ([]byte, error, bool) { pTransport := &http.Transport{Proxy: nil} client := http.Client{Transport: pTransport} From 001940d4a145077d8ed7d48dcf311b6d19da15b9 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Fri, 31 May 2024 10:10:51 +0200 Subject: [PATCH 20/26] Add missing comment --- detectors/azure/azurevm/vm.go | 1 + 1 file changed, 1 insertion(+) diff --git a/detectors/azure/azurevm/vm.go b/detectors/azure/azurevm/vm.go index ce7de46fb5b..0b68bf39dea 100644 --- a/detectors/azure/azurevm/vm.go +++ b/detectors/azure/azurevm/vm.go @@ -19,6 +19,7 @@ const ( defaultAzureVMMetadataEndpoint = "http://169.254.169.254/metadata/instance/compute?api-version=2021-12-13&format=json" ) +// AzureVMResourceDetector collects resource information of Azure VMs. type AzureVMResourceDetector struct { endpoint string } From 507cdf6e6d1cc7e4316643d6b53361f34234225a Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Fri, 31 May 2024 10:33:59 +0200 Subject: [PATCH 21/26] Fix linter issues --- detectors/azure/azurevm/example_new_test.go | 3 +-- detectors/azure/azurevm/vm.go | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/detectors/azure/azurevm/example_new_test.go b/detectors/azure/azurevm/example_new_test.go index 1fcc62b7add..a5f34f34ada 100644 --- a/detectors/azure/azurevm/example_new_test.go +++ b/detectors/azure/azurevm/example_new_test.go @@ -6,14 +6,13 @@ package azurevm_test import ( "context" "fmt" - + "go.opentelemetry.io/contrib/detectors/azure/azurevm" ) func ExampleNew() { azureVMResourceDetector := azurevm.New() resource, err := azureVMResourceDetector.Detect(context.Background()) - if err != nil { panic(err) } diff --git a/detectors/azure/azurevm/vm.go b/detectors/azure/azurevm/vm.go index 0b68bf39dea..7a645e986a0 100644 --- a/detectors/azure/azurevm/vm.go +++ b/detectors/azure/azurevm/vm.go @@ -20,7 +20,7 @@ const ( ) // AzureVMResourceDetector collects resource information of Azure VMs. -type AzureVMResourceDetector struct { +type ResourceDetector struct { endpoint string } @@ -35,13 +35,13 @@ type vmMetadata struct { } // New returns a [resource.Detector] that will detect Azure VM resources. -func New() *AzureVMResourceDetector { - return &AzureVMResourceDetector{defaultAzureVMMetadataEndpoint} +func New() *ResourceDetector { + return &ResourceDetector{defaultAzureVMMetadataEndpoint} } // Detect detects associated resources when running on an Azure VM. -func (detector *AzureVMResourceDetector) Detect(ctx context.Context) (*resource.Resource, error) { - jsonMetadata, err, runningInAzure := detector.getJSONMetadata() +func (detector *ResourceDetector) Detect(ctx context.Context) (*resource.Resource, error) { + jsonMetadata, runningInAzure, err := detector.getJSONMetadata() if err != nil { if !runningInAzure { return resource.Empty(), nil @@ -86,31 +86,31 @@ func (detector *AzureVMResourceDetector) Detect(ctx context.Context) (*resource. return resource.NewWithAttributes(semconv.SchemaURL, attributes...), nil } -func (detector *AzureVMResourceDetector) getJSONMetadata() ([]byte, error, bool) { +func (detector *ResourceDetector) getJSONMetadata() ([]byte, bool, error) { pTransport := &http.Transport{Proxy: nil} client := http.Client{Transport: pTransport} req, err := http.NewRequest("GET", detector.endpoint, nil) if err != nil { - return nil, err, false + return nil, false, err } req.Header.Add("Metadata", "True") resp, err := client.Do(req) if err != nil { - return nil, err, false + return nil, false, err } defer resp.Body.Close() if resp.StatusCode == http.StatusOK { bytes, err := io.ReadAll(resp.Body) - return bytes, err, true + return bytes, true, err } runningInAzure := resp.StatusCode < 400 || resp.StatusCode > 499 - return nil, errors.New(http.StatusText(resp.StatusCode)), runningInAzure + return nil, runningInAzure, errors.New(http.StatusText(resp.StatusCode)) } From 930f84cdcb1d8fe30a613fc390685b0abbe62a89 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 3 Jun 2024 12:53:52 +0200 Subject: [PATCH 22/26] Comment broken link --- detectors/azure/azurevm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detectors/azure/azurevm/README.md b/detectors/azure/azurevm/README.md index 0a2b94da7ff..f5b09e28f89 100644 --- a/detectors/azure/azurevm/README.md +++ b/detectors/azure/azurevm/README.md @@ -1,3 +1,3 @@ # Azure VM Resource detector -[![PkgGoDev](https://pkg.go.dev/badge/go.opentelemetry.io/contrib/detectors/azure/azurevm)](https://pkg.go.dev/go.opentelemetry.io/contrib/detectors/azure/azurevm) + From c8b1212d3b15a7fc2b06d591731f0644dc519099 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 3 Jun 2024 16:17:23 +0200 Subject: [PATCH 23/26] Use context in HTTP request --- detectors/azure/azurevm/vm.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/detectors/azure/azurevm/vm.go b/detectors/azure/azurevm/vm.go index 7a645e986a0..2286b6c0e2c 100644 --- a/detectors/azure/azurevm/vm.go +++ b/detectors/azure/azurevm/vm.go @@ -41,7 +41,7 @@ func New() *ResourceDetector { // Detect detects associated resources when running on an Azure VM. func (detector *ResourceDetector) Detect(ctx context.Context) (*resource.Resource, error) { - jsonMetadata, runningInAzure, err := detector.getJSONMetadata() + jsonMetadata, runningInAzure, err := detector.getJSONMetadata(ctx) if err != nil { if !runningInAzure { return resource.Empty(), nil @@ -86,12 +86,12 @@ func (detector *ResourceDetector) Detect(ctx context.Context) (*resource.Resourc return resource.NewWithAttributes(semconv.SchemaURL, attributes...), nil } -func (detector *ResourceDetector) getJSONMetadata() ([]byte, bool, error) { +func (detector *ResourceDetector) getJSONMetadata(ctx context.Context) ([]byte, bool, error) { pTransport := &http.Transport{Proxy: nil} client := http.Client{Transport: pTransport} - req, err := http.NewRequest("GET", detector.endpoint, nil) + req, err := http.NewRequestWithContext(ctx, "GET", detector.endpoint, nil) if err != nil { return nil, false, err } From 2c4b80e5e58339aba45cadc5b5e4cb8ed1ee751e Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 3 Jun 2024 17:24:14 +0200 Subject: [PATCH 24/26] Apply suggestions from code review Co-authored-by: Tyler Yahn --- detectors/azure/azurevm/vm.go | 10 ++++------ detectors/azure/azurevm/vm_test.go | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/detectors/azure/azurevm/vm.go b/detectors/azure/azurevm/vm.go index 2286b6c0e2c..7787427ea08 100644 --- a/detectors/azure/azurevm/vm.go +++ b/detectors/azure/azurevm/vm.go @@ -12,14 +12,12 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/sdk/resource" - semconv "go.opentelemetry.io/otel/semconv/v1.24.0" + semconv "go.opentelemetry.io/otel/semconv/v1.25.0" ) -const ( - defaultAzureVMMetadataEndpoint = "http://169.254.169.254/metadata/instance/compute?api-version=2021-12-13&format=json" -) +const defaultAzureVMMetadataEndpoint = "http://169.254.169.254/metadata/instance/compute?api-version=2021-12-13&format=json" -// AzureVMResourceDetector collects resource information of Azure VMs. +// ResourceDetector collects resource information of Azure VMs. type ResourceDetector struct { endpoint string } @@ -34,7 +32,7 @@ type vmMetadata struct { Version *string `json:"version"` } -// New returns a [resource.Detector] that will detect Azure VM resources. +// New returns a [ResourceDetector] that will detect Azure VM resources. func New() *ResourceDetector { return &ResourceDetector{defaultAzureVMMetadataEndpoint} } diff --git a/detectors/azure/azurevm/vm_test.go b/detectors/azure/azurevm/vm_test.go index 27143c354c1..035ca6e318d 100644 --- a/detectors/azure/azurevm/vm_test.go +++ b/detectors/azure/azurevm/vm_test.go @@ -14,7 +14,7 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/sdk/resource" - semconv "go.opentelemetry.io/otel/semconv/v1.24.0" + semconv "go.opentelemetry.io/otel/semconv/v1.25.0" ) func TestDetect(t *testing.T) { From 2972ad2768e4be7f3254d3b881b272f60f120afc Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 3 Jun 2024 17:33:58 +0200 Subject: [PATCH 25/26] Update module files --- detectors/azure/azurevm/go.mod | 6 +++--- detectors/azure/azurevm/go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/detectors/azure/azurevm/go.mod b/detectors/azure/azurevm/go.mod index 1e6498d53fd..56931217416 100644 --- a/detectors/azure/azurevm/go.mod +++ b/detectors/azure/azurevm/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/stretchr/testify v1.9.0 - go.opentelemetry.io/otel v1.25.0 + go.opentelemetry.io/otel v1.27.0 go.opentelemetry.io/otel/sdk v1.25.0 ) @@ -13,8 +13,8 @@ require ( github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - go.opentelemetry.io/otel/metric v1.25.0 // indirect - go.opentelemetry.io/otel/trace v1.25.0 // indirect + go.opentelemetry.io/otel/metric v1.27.0 // indirect + go.opentelemetry.io/otel/trace v1.27.0 // indirect golang.org/x/sys v0.18.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/detectors/azure/azurevm/go.sum b/detectors/azure/azurevm/go.sum index c94c7b1876b..377a5231a9f 100644 --- a/detectors/azure/azurevm/go.sum +++ b/detectors/azure/azurevm/go.sum @@ -11,14 +11,14 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -go.opentelemetry.io/otel v1.25.0 h1:gldB5FfhRl7OJQbUHt/8s0a7cE8fbsPAtdpRaApKy4k= -go.opentelemetry.io/otel v1.25.0/go.mod h1:Wa2ds5NOXEMkCmUou1WA7ZBfLTHWIsp034OVD7AO+Vg= -go.opentelemetry.io/otel/metric v1.25.0 h1:LUKbS7ArpFL/I2jJHdJcqMGxkRdxpPHE0VU/D4NuEwA= -go.opentelemetry.io/otel/metric v1.25.0/go.mod h1:rkDLUSd2lC5lq2dFNrX9LGAbINP5B7WBkC78RXCpH5s= +go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg= +go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ= +go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik= +go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak= go.opentelemetry.io/otel/sdk v1.25.0 h1:PDryEJPC8YJZQSyLY5eqLeafHtG+X7FWnf3aXMtxbqo= go.opentelemetry.io/otel/sdk v1.25.0/go.mod h1:oFgzCM2zdsxKzz6zwpTZYLLQsFwc+K0daArPdIhuxkw= -go.opentelemetry.io/otel/trace v1.25.0 h1:tqukZGLwQYRIFtSQM2u2+yfMVTgGVeqRLPUYx1Dq6RM= -go.opentelemetry.io/otel/trace v1.25.0/go.mod h1:hCCs70XM/ljO+BeQkyFnbK28SBIJ/Emuha+ccrCRT7I= +go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw= +go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= From 315ae577dcd0a4820e36ab9428aba656f14248c3 Mon Sep 17 00:00:00 2001 From: Johannes Tax Date: Mon, 3 Jun 2024 22:09:55 +0200 Subject: [PATCH 26/26] Add Azure VM detector with version v0.0.1 --- versions.yaml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/versions.yaml b/versions.yaml index 09e2f96f9f6..26e0311c742 100644 --- a/versions.yaml +++ b/versions.yaml @@ -20,7 +20,6 @@ module-sets: modules: - go.opentelemetry.io/contrib/bridges/prometheus - go.opentelemetry.io/contrib/detectors/aws/lambda - - go.opentelemetry.io/contrib/detectors/azure/azurevm - go.opentelemetry.io/contrib/exporters/autoexport - go.opentelemetry.io/contrib/propagators/autoprop - go.opentelemetry.io/contrib/propagators/opencensus @@ -83,6 +82,10 @@ module-sets: version: v0.0.1 modules: - go.opentelemetry.io/contrib/processors/baggage/baggagetrace + experimental-detectors: + version: v0.0.1 + modules: + - go.opentelemetry.io/contrib/detectors/azure/azurevm excluded-modules: - go.opentelemetry.io/contrib/bridges/otelzap - go.opentelemetry.io/contrib/instrgen