Skip to content

Commit 9ebe108

Browse files
author
Alex Boten
authored
[processor/coldstart] add coldstart processor (aws-observability#346)
Follow up to aws-observability#345 This processor associates cold start timing information generated by the telemetryapireceiver with the first span processed by the Collector extension containing a faas.execution attribute. Signed-off-by: Alex Boten [email protected]
1 parent 4777fff commit 9ebe108

File tree

16 files changed

+1517
-0
lines changed

16 files changed

+1517
-0
lines changed

collector/go.mod

+3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ go 1.18
44

55
replace github.com/open-telemetry/opentelemetry-lambda/collector/lambdacomponents => ./lambdacomponents
66

7+
replace github.com/open-telemetry/opentelemetry-lambda/collector/processor/coldstartprocessor => ./processor/coldstartprocessor
8+
79
replace github.com/open-telemetry/opentelemetry-lambda/collector/receiver/telemetryapireceiver => ./receiver/telemetryapireceiver
810

911
// fixes ambiguous import error: found package cloud.google.com/go/compute/metadata in multiple modules:
@@ -88,6 +90,7 @@ require (
8890
github.com/open-telemetry/opentelemetry-collector-contrib/processor/probabilisticsamplerprocessor v0.69.0 // indirect
8991
github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourceprocessor v0.69.0 // indirect
9092
github.com/open-telemetry/opentelemetry-collector-contrib/processor/spanprocessor v0.69.0 // indirect
93+
github.com/open-telemetry/opentelemetry-lambda/collector/processor/coldstartprocessor v0.69.0 // indirect
9194
github.com/open-telemetry/opentelemetry-lambda/collector/receiver/telemetryapireceiver v0.69.0 // indirect
9295
github.com/pmezard/go-difflib v1.0.0 // indirect
9396
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect

collector/go.sum

+1
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInq
440440
github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
441441
github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
442442
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
443+
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
443444
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
444445
github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM=
445446
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=

collector/lambdacomponents/default.go

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import (
3535
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourceprocessor"
3636
"github.com/open-telemetry/opentelemetry-collector-contrib/processor/spanprocessor"
3737

38+
"github.com/open-telemetry/opentelemetry-lambda/collector/processor/coldstartprocessor"
3839
"github.com/open-telemetry/opentelemetry-lambda/collector/receiver/telemetryapireceiver"
3940
)
4041

@@ -66,6 +67,7 @@ func Components(extensionID string) (otelcol.Factories, error) {
6667
probabilisticsamplerprocessor.NewFactory(),
6768
resourceprocessor.NewFactory(),
6869
spanprocessor.NewFactory(),
70+
coldstartprocessor.NewFactory(),
6971
)
7072
if err != nil {
7173
errs = append(errs, err)

collector/lambdacomponents/go.mod

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ require (
1010
github.com/open-telemetry/opentelemetry-collector-contrib/processor/probabilisticsamplerprocessor v0.69.0
1111
github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourceprocessor v0.69.0
1212
github.com/open-telemetry/opentelemetry-collector-contrib/processor/spanprocessor v0.69.0
13+
github.com/open-telemetry/opentelemetry-lambda/collector/processor/coldstartprocessor v0.69.0
1314
github.com/open-telemetry/opentelemetry-lambda/collector/receiver/telemetryapireceiver v0.69.0
1415
go.opentelemetry.io/collector v0.69.1
1516
go.opentelemetry.io/collector/exporter/loggingexporter v0.69.1
@@ -129,4 +130,6 @@ replace cloud.google.com/go => cloud.google.com/go v0.107.0
129130

130131
replace github.com/open-telemetry/opentelemetry-lambda/collector => ../
131132

133+
replace github.com/open-telemetry/opentelemetry-lambda/collector/processor/coldstartprocessor => ../processor/coldstartprocessor
134+
132135
replace github.com/open-telemetry/opentelemetry-lambda/collector/receiver/telemetryapireceiver => ../receiver/telemetryapireceiver

collector/lambdacomponents/go.sum

+1
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,7 @@ github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInq
426426
github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
427427
github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
428428
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
429+
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
429430
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
430431
github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM=
431432
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include ../../Makefile.Common
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Coldstart Processor
2+
3+
| Status | |
4+
| ------------------------ |-----------------|
5+
| Stability | [in development]|
6+
| Supported pipeline types | traces |
7+
| Distributions | [extension] |
8+
9+
This processor associates cold start information generated by the [telemetryapireceiver](../../receiver/telemetryapireceiver) with incoming span data processed by
10+
the Collector extension. It reads the following of incoming Lambda execution spans identified by the `faas.execution` attribute:
11+
12+
- trace ID
13+
- parent span ID
14+
- span scope
15+
- resource attributes
16+
17+
This information is stored until the first coldstart span identified by the `faas.coldstart` attribute
18+
is received. That span's trace ID, parent span ID are updated to match the execution span. This
19+
allows the coldstart span to be part of the same trace as the operation that triggered the cold start. Additionally,
20+
the span scope and resource attributes of the span scope containing the coldstart span
21+
are replaced with the span scope and resource attributes of the execution span as
22+
they contain more details.
23+
24+
There are currently no configuration parameters available for this processor. It can be enabled via the following configuration:
25+
26+
```yaml
27+
processors:
28+
coldstart:
29+
```
30+
31+
[in development]: https://github.com/open-telemetry/opentelemetry-collector#development
32+
[extension]: https://github.com/open-telemetry/opentelemetry-lambda/collector
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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 coldstartprocessor // import "github.com/open-telemetry/opentelemetry-lambda/collector/processor/coldstartprocessor"
16+
17+
// Config defines the configuration for the various elements of the processor.
18+
type Config struct{}
19+
20+
// Validate validates the configuration by checking for missing or invalid fields
21+
func (cfg *Config) Validate() error {
22+
return nil
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
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 coldstartprocessor // import "github.com/open-telemetry/opentelemetry-lambda/collector/processor/coldstartprocessor"
16+
17+
import (
18+
"testing"
19+
20+
"github.com/stretchr/testify/require"
21+
)
22+
23+
func TestValidate(t *testing.T) {
24+
testCases := []struct {
25+
desc string
26+
cfg *Config
27+
expectedErr error
28+
}{
29+
{
30+
desc: "valid config",
31+
cfg: &Config{},
32+
expectedErr: nil,
33+
},
34+
}
35+
36+
for _, tc := range testCases {
37+
t.Run(tc.desc, func(t *testing.T) {
38+
actualErr := tc.cfg.Validate()
39+
if tc.expectedErr != nil {
40+
require.EqualError(t, actualErr, tc.expectedErr.Error())
41+
} else {
42+
require.NoError(t, actualErr)
43+
}
44+
45+
})
46+
}
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
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 coldstartprocessor correlates cold start information generated by the telemetryapireceiver
16+
// with incoming span data.
17+
//
18+
// It reads the following of incoming Lambda execution spans identified by the faas.execution attribute:
19+
//
20+
// - trace ID
21+
// - parent span ID
22+
// - span scope
23+
// - resource attributes
24+
//
25+
// This information is stored until the first coldstart span identified by the faas.coldstart attribute
26+
// is received. That span's trace ID, parent span ID are updated to match the execution span. This
27+
// allows the coldstart span to be part of the same trace as the operation that triggered the cold start. Additionally,
28+
// the span scope and resource attributes of the span scope containing the coldstart span
29+
// are replaced with the span scope and resource attributes of the execution span as
30+
// they contain more details.
31+
package coldstartprocessor // import "github.com/open-telemetry/opentelemetry-lambda/collector/processor/coldstartprocessor"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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 coldstartprocessor // import "github.com/open-telemetry/opentelemetry-lambda/collector/processor/coldstartprocessor"
16+
17+
import (
18+
"context"
19+
"errors"
20+
21+
"go.opentelemetry.io/collector/component"
22+
"go.opentelemetry.io/collector/consumer"
23+
"go.opentelemetry.io/collector/processor"
24+
"go.opentelemetry.io/collector/processor/processorhelper"
25+
)
26+
27+
const (
28+
typeStr = "coldstart"
29+
stability = component.StabilityLevelDevelopment
30+
)
31+
32+
var (
33+
errConfigNotColdstart = errors.New("config was not a Coldstart processor config")
34+
processorCapabilities = consumer.Capabilities{MutatesData: true}
35+
)
36+
37+
func NewFactory() processor.Factory {
38+
return processor.NewFactory(
39+
typeStr,
40+
createDefaultConfig,
41+
processor.WithTraces(createTracesProcessor, stability),
42+
)
43+
}
44+
45+
func createDefaultConfig() component.Config {
46+
return &Config{}
47+
}
48+
49+
func createTracesProcessor(ctx context.Context, params processor.CreateSettings, rConf component.Config, next consumer.Traces) (processor.Traces, error) {
50+
cfg, ok := rConf.(*Config)
51+
if !ok {
52+
return nil, errConfigNotColdstart
53+
}
54+
55+
cp, err := newColdstartProcessor(cfg, next, params)
56+
if err != nil {
57+
return nil, err
58+
}
59+
return processorhelper.NewTracesProcessor(
60+
ctx,
61+
params,
62+
cfg,
63+
next,
64+
cp.processTraces,
65+
processorhelper.WithCapabilities(processorCapabilities),
66+
)
67+
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
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 coldstartprocessor // import "github.com/open-telemetry/opentelemetry-lambda/collector/processor/coldstartprocessor"
16+
17+
import (
18+
"context"
19+
"testing"
20+
21+
"github.com/stretchr/testify/require"
22+
"go.opentelemetry.io/collector/consumer/consumertest"
23+
"go.opentelemetry.io/collector/processor/processortest"
24+
)
25+
26+
func TestNewFactory(t *testing.T) {
27+
testCases := []struct {
28+
desc string
29+
testFunc func(*testing.T)
30+
}{
31+
{
32+
desc: "creates a new factory with correct type",
33+
testFunc: func(t *testing.T) {
34+
factory := NewFactory()
35+
require.EqualValues(t, typeStr, factory.Type())
36+
},
37+
},
38+
{
39+
desc: "creates a new factory and CreateTracesProcessor returns no error",
40+
testFunc: func(t *testing.T) {
41+
factory := NewFactory()
42+
cfg := factory.CreateDefaultConfig()
43+
_, err := factory.CreateTracesProcessor(
44+
context.Background(),
45+
processortest.NewNopCreateSettings(),
46+
cfg,
47+
consumertest.NewNop(),
48+
)
49+
require.NoError(t, err)
50+
},
51+
},
52+
{
53+
desc: "creates a new factory and CreateTracesProcessor returns error with incorrect config",
54+
testFunc: func(t *testing.T) {
55+
factory := NewFactory()
56+
_, err := factory.CreateTracesProcessor(
57+
context.Background(),
58+
processortest.NewNopCreateSettings(),
59+
nil,
60+
consumertest.NewNop(),
61+
)
62+
require.ErrorIs(t, err, errConfigNotColdstart)
63+
},
64+
},
65+
}
66+
67+
for _, tc := range testCases {
68+
t.Run(tc.desc, tc.testFunc)
69+
}
70+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
module github.com/open-telemetry/opentelemetry-lambda/collector/processor/coldstartprocessor
2+
3+
go 1.19
4+
5+
require (
6+
github.com/cespare/xxhash v1.1.0
7+
github.com/stretchr/testify v1.8.1
8+
go.opentelemetry.io/collector v0.69.1
9+
go.opentelemetry.io/collector/component v0.69.1
10+
go.opentelemetry.io/collector/consumer v0.69.1
11+
go.opentelemetry.io/collector/pdata v1.0.0-rc3
12+
go.opentelemetry.io/collector/semconv v0.69.1
13+
go.uber.org/multierr v1.9.0
14+
go.uber.org/zap v1.24.0
15+
)
16+
17+
require (
18+
github.com/davecgh/go-spew v1.1.1 // indirect
19+
github.com/gogo/protobuf v1.3.2 // indirect
20+
github.com/golang/protobuf v1.5.2 // indirect
21+
github.com/json-iterator/go v1.1.12 // indirect
22+
github.com/knadh/koanf v1.4.4 // indirect
23+
github.com/mitchellh/copystructure v1.2.0 // indirect
24+
github.com/mitchellh/mapstructure v1.5.0 // indirect
25+
github.com/mitchellh/reflectwalk v1.0.2 // indirect
26+
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
27+
github.com/modern-go/reflect2 v1.0.2 // indirect
28+
github.com/pmezard/go-difflib v1.0.0 // indirect
29+
go.opencensus.io v0.24.0 // indirect
30+
go.opentelemetry.io/collector/confmap v0.69.1 // indirect
31+
go.opentelemetry.io/collector/featuregate v0.69.1 // indirect
32+
go.opentelemetry.io/otel v1.11.2 // indirect
33+
go.opentelemetry.io/otel/metric v0.34.0 // indirect
34+
go.opentelemetry.io/otel/trace v1.11.2 // indirect
35+
go.uber.org/atomic v1.10.0 // indirect
36+
golang.org/x/net v0.4.0 // indirect
37+
golang.org/x/sys v0.3.0 // indirect
38+
golang.org/x/text v0.5.0 // indirect
39+
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa // indirect
40+
google.golang.org/grpc v1.51.0 // indirect
41+
google.golang.org/protobuf v1.28.1 // indirect
42+
gopkg.in/yaml.v3 v3.0.1 // indirect
43+
)

0 commit comments

Comments
 (0)