Skip to content

Commit dfcd49a

Browse files
Resource Detection processor (#309)
* Add resourcedetection processor * Add env and gce resource detectors * Resource Detection Processor: increase test coverage & fix README * Cache detected resource against processor name to avoid running resource detection code more than once * Refactor resources detection processor to use resource provider
1 parent 9905ab0 commit dfcd49a

23 files changed

+3277
-0
lines changed

cmd/otelcontribcol/components.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import (
3636
"github.com/open-telemetry/opentelemetry-collector-contrib/exporter/stackdriverexporter"
3737
"github.com/open-telemetry/opentelemetry-collector-contrib/extension/observer/k8sobserver"
3838
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/k8sprocessor"
39+
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor"
3940
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/carbonreceiver"
4041
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/collectdreceiver"
4142
"github.com/open-telemetry/opentelemetry-collector-contrib/receiver/jaegerlegacyreceiver"
@@ -118,6 +119,7 @@ func components() (config.Factories, error) {
118119

119120
processors := []component.ProcessorFactoryBase{
120121
&k8sprocessor.Factory{},
122+
resourcedetectionprocessor.NewFactory(),
121123
}
122124
for _, pr := range factories.Processors {
123125
processors = append(processors, pr)

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ require (
2323
github.com/open-telemetry/opentelemetry-collector-contrib/exporter/stackdriverexporter v0.0.0
2424
github.com/open-telemetry/opentelemetry-collector-contrib/extension/observer/k8sobserver v0.0.0
2525
github.com/open-telemetry/opentelemetry-collector-contrib/processor/k8sprocessor v0.0.0
26+
github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor v0.0.0
2627
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/carbonreceiver v0.0.0
2728
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/collectdreceiver v0.0.0
2829
github.com/open-telemetry/opentelemetry-collector-contrib/receiver/jaegerlegacyreceiver v0.0.0
@@ -109,4 +110,6 @@ replace github.com/open-telemetry/opentelemetry-collector-contrib/receiver/zipki
109110

110111
replace github.com/open-telemetry/opentelemetry-collector-contrib/processor/k8sprocessor => ./processor/k8sprocessor/
111112

113+
replace github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor => ./processor/resourcedetectionprocessor/
114+
112115
replace k8s.io/client-go => k8s.io/client-go v0.0.0-20190620085101-78d2af792bab
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include ../../Makefile.Common
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Resource Detection Processor
2+
3+
Supported pipeline types: metrics, traces
4+
5+
The resource detection processor can be used to detect resource information from the host,
6+
in a format that conforms to the OpenTelemetry resource semantic conventions, and append or
7+
override the resource value in traces and metrics with this information.
8+
9+
Currently supported detectors include:
10+
11+
* Environment Variable: Reads resource information from the `OTEL_RESOURCE` environment
12+
variable. This is expected to be in the format `<key1>=<value1>,<key2>=<value2>,...`, the
13+
details of which are currently pending confirmation in the OpenTelemetry specification.
14+
15+
* GCE Metadata: Uses the [Google Cloud Client Libraries for Go](https://github.com/googleapis/google-cloud-go)
16+
to read resource information from the GCE metadata server as documented by
17+
https://cloud.google.com/compute/docs/storing-retrieving-metadata
18+
19+
## Configuration
20+
21+
```yaml
22+
# a list of resource detectors to run, valid options are: "env", "gce"
23+
detectors: [ <string> ]
24+
# determines if existing resource attributes should be overridden or preserved, defaults to true
25+
override: <bool>
26+
```
27+
28+
The full list of settings exposed for this extension are documented [here](./config.go)
29+
with detailed sample configurations [here](./testdata/config.yaml).
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright The OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package resourcedetectionprocessor
16+
17+
import (
18+
"time"
19+
20+
"go.opentelemetry.io/collector/config/configmodels"
21+
)
22+
23+
// Config defines configuration for Resource processor.
24+
type Config struct {
25+
configmodels.ProcessorSettings `mapstructure:",squash"`
26+
// Detectors is an ordered list of named detectors that should be
27+
// run to attempt to detect resource information.
28+
Detectors []string `mapstructure:"detectors"`
29+
// Timeout specifies the maximum amount of time that we will wait
30+
// before assuming a detector has failed. Defaults to 5s.
31+
Timeout time.Duration `mapstructure:"timeout"`
32+
// Override indicates whether any existing resource attributes
33+
// should be overridden or preserved. Defaults to true.
34+
Override bool `mapstructure:"override"`
35+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Copyright The OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package resourcedetectionprocessor
16+
17+
import (
18+
"path"
19+
"testing"
20+
"time"
21+
22+
"github.com/stretchr/testify/assert"
23+
"go.opentelemetry.io/collector/config"
24+
"go.opentelemetry.io/collector/config/configmodels"
25+
)
26+
27+
func TestLoadConfig(t *testing.T) {
28+
factories, err := config.ExampleComponents()
29+
assert.NoError(t, err)
30+
31+
factory := &Factory{}
32+
factories.Processors[typeStr] = &Factory{}
33+
34+
cfg, err := config.LoadConfigFile(t, path.Join(".", "testdata", "config.yaml"), factories)
35+
assert.NoError(t, err)
36+
assert.NotNil(t, cfg)
37+
38+
p1 := cfg.Processors["resourcedetection"]
39+
assert.Equal(t, p1, factory.CreateDefaultConfig())
40+
41+
p2 := cfg.Processors["resourcedetection/2"]
42+
assert.Equal(t, p2, &Config{
43+
ProcessorSettings: configmodels.ProcessorSettings{
44+
TypeVal: "resourcedetection",
45+
NameVal: "resourcedetection/2",
46+
},
47+
Detectors: []string{"env", "gce"},
48+
Timeout: 2 * time.Second,
49+
Override: false,
50+
})
51+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright The OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// package resourcedetectionprocessor implements a processor for specifying resource
16+
// labels to be added to OpenCensus trace data and metrics data.
17+
package resourcedetectionprocessor
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
// Copyright The OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package resourcedetectionprocessor
16+
17+
import (
18+
"context"
19+
"strings"
20+
"sync"
21+
"time"
22+
23+
"go.opentelemetry.io/collector/component"
24+
"go.opentelemetry.io/collector/config/configmodels"
25+
"go.opentelemetry.io/collector/consumer"
26+
"go.uber.org/zap"
27+
28+
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal"
29+
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/env"
30+
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp/gce"
31+
)
32+
33+
const (
34+
// The value of "type" key in configuration.
35+
typeStr = "resourcedetection"
36+
)
37+
38+
// Factory is the factory for resourcedetection processor.
39+
type Factory struct {
40+
resourceProviderFactory *internal.ResourceProviderFactory
41+
42+
// providers stores a provider for each named processor that
43+
// may a different set of detectors configured.
44+
providers map[string]*internal.ResourceProvider
45+
lock sync.Mutex
46+
}
47+
48+
// NewFactory creates a new factory for resourcedetection processor.
49+
func NewFactory() *Factory {
50+
resourceProviderFactory := internal.NewProviderFactory(map[internal.DetectorType]internal.Detector{
51+
env.TypeStr: &env.Detector{},
52+
gce.TypeStr: gce.NewDetector(),
53+
})
54+
55+
return &Factory{
56+
resourceProviderFactory: resourceProviderFactory,
57+
providers: map[string]*internal.ResourceProvider{},
58+
}
59+
}
60+
61+
// Type gets the type of the Option config created by this factory.
62+
func (*Factory) Type() configmodels.Type {
63+
return typeStr
64+
}
65+
66+
// CreateDefaultConfig creates the default configuration for processor.
67+
func (*Factory) CreateDefaultConfig() configmodels.Processor {
68+
return &Config{
69+
ProcessorSettings: configmodels.ProcessorSettings{
70+
TypeVal: typeStr,
71+
NameVal: typeStr,
72+
},
73+
Detectors: []string{env.TypeStr},
74+
Timeout: 5 * time.Second,
75+
Override: true,
76+
}
77+
}
78+
79+
// CreateTraceProcessor creates a trace processor based on this config.
80+
func (f *Factory) CreateTraceProcessor(
81+
ctx context.Context,
82+
params component.ProcessorCreateParams,
83+
nextConsumer consumer.TraceConsumer,
84+
cfg configmodels.Processor,
85+
) (component.TraceProcessor, error) {
86+
oCfg := cfg.(*Config)
87+
88+
provider, err := f.getResourceProvider(ctx, params.Logger, cfg.Name(), oCfg.Timeout, oCfg.Detectors)
89+
if err != nil {
90+
return nil, err
91+
}
92+
93+
return newResourceTraceProcessor(ctx, nextConsumer, provider, oCfg.Override), nil
94+
}
95+
96+
// CreateMetricsProcessor creates a metrics processor based on this config.
97+
func (f *Factory) CreateMetricsProcessor(
98+
ctx context.Context,
99+
params component.ProcessorCreateParams,
100+
nextConsumer consumer.MetricsConsumer,
101+
cfg configmodels.Processor,
102+
) (component.MetricsProcessor, error) {
103+
oCfg := cfg.(*Config)
104+
105+
provider, err := f.getResourceProvider(ctx, params.Logger, cfg.Name(), oCfg.Timeout, oCfg.Detectors)
106+
if err != nil {
107+
return nil, err
108+
}
109+
110+
return newResourceMetricProcessor(ctx, nextConsumer, provider, oCfg.Override), nil
111+
}
112+
113+
func (f *Factory) getResourceProvider(
114+
ctx context.Context,
115+
logger *zap.Logger,
116+
processorName string,
117+
timeout time.Duration,
118+
configuredDetectors []string,
119+
) (*internal.ResourceProvider, error) {
120+
f.lock.Lock()
121+
defer f.lock.Unlock()
122+
123+
if provider, ok := f.providers[processorName]; ok {
124+
return provider, nil
125+
}
126+
127+
detectorTypes := make([]internal.DetectorType, 0, len(configuredDetectors))
128+
for _, key := range configuredDetectors {
129+
detectorTypes = append(detectorTypes, internal.DetectorType(strings.TrimSpace(key)))
130+
}
131+
132+
provider, err := f.resourceProviderFactory.CreateResourceProvider(logger, timeout, detectorTypes...)
133+
if err != nil {
134+
return nil, err
135+
}
136+
137+
f.providers[processorName] = provider
138+
return provider, nil
139+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright The OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package resourcedetectionprocessor
16+
17+
import (
18+
"context"
19+
"testing"
20+
21+
"github.com/stretchr/testify/assert"
22+
"go.opentelemetry.io/collector/component"
23+
"go.opentelemetry.io/collector/config/configcheck"
24+
)
25+
26+
func TestCreateDefaultConfig(t *testing.T) {
27+
var factory Factory
28+
cfg := factory.CreateDefaultConfig()
29+
assert.NoError(t, configcheck.ValidateConfig(cfg))
30+
assert.NotNil(t, cfg)
31+
}
32+
33+
func TestCreateProcessor(t *testing.T) {
34+
factory := NewFactory()
35+
cfg := factory.CreateDefaultConfig()
36+
37+
tp, err := factory.CreateTraceProcessor(context.Background(), component.ProcessorCreateParams{}, nil, cfg)
38+
assert.NoError(t, err)
39+
assert.NotNil(t, tp)
40+
41+
mp, err := factory.CreateMetricsProcessor(context.Background(), component.ProcessorCreateParams{}, nil, cfg)
42+
assert.NoError(t, err)
43+
assert.NotNil(t, mp)
44+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor
2+
3+
go 1.14
4+
5+
require (
6+
cloud.google.com/go v0.45.1
7+
github.com/census-instrumentation/opencensus-proto v0.2.1
8+
github.com/opentracing/opentracing-go v1.1.1-0.20190913142402-a7454ce5950e // indirect
9+
github.com/stretchr/testify v1.5.1
10+
go.opentelemetry.io/collector v0.4.1-0.20200622191610-a8db6271f90a
11+
go.uber.org/atomic v1.5.1
12+
go.uber.org/zap v1.13.0
13+
)

0 commit comments

Comments
 (0)