Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpAMP Agent Extension #16594

Merged
merged 70 commits into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
df750c9
opamp agent extension, hello world
portertech Dec 2, 2022
952cff6
opamp agent extension, agent id and description
portertech Dec 2, 2022
185e8c3
opamp agent extension, update agent id
portertech Dec 2, 2022
27740ad
opamp agent extension, compose effective config
portertech Dec 2, 2022
fc6beb3
opamp agent extension, start and shutdown
portertech Dec 2, 2022
c816932
opamp agent extension, changelog
portertech Dec 2, 2022
9b4e0da
opamp agent extension, config doc nit
portertech Dec 2, 2022
9a2619b
opamp agent extension, improved uid validation, use shutdown ctx
portertech Dec 29, 2022
3437a4a
opamp agent extension, removed ReportsEffectiveConfig capability
portertech Aug 3, 2023
5d6b34b
Merge branch 'main' into feature/opamp-extension
portertech Aug 3, 2023
c8a8c3e
opamp agent extension, upgraded collector to v0.82.0 and opamp-go to …
portertech Aug 3, 2023
029360a
Merge branch 'main' into feature/opamp-extension
portertech Aug 8, 2023
48428d2
Merge branch 'main' into feature/opamp-extension
portertech Sep 28, 2023
92f1488
opamp agent extension, dropped unnecessary logger interface
portertech Sep 28, 2023
859736d
opamp agent extension, report agent status capability
portertech Sep 28, 2023
c3ae9e6
opamp agent extension, go 1.20
portertech Sep 28, 2023
390621e
opamp agent extension, use buildinfo and resource
portertech Sep 28, 2023
3d6d560
opamp agent extension, attempt to get agent type and version from
portertech Sep 29, 2023
1659320
opamp agent extension, support http client settings
portertech Sep 29, 2023
924ed2d
opamp agent extension, apply http headers and tls
portertech Sep 29, 2023
fe2278d
Merge branch 'main' into feature/opamp-extension
portertech Sep 29, 2023
9f86052
Merge branch 'main' into feature/opamp-extension
portertech Sep 29, 2023
911382d
opamp agent extension, metadata.yaml
portertech Sep 29, 2023
afce5a6
opamp agent extension, github codeowners and readme
portertech Sep 29, 2023
6f36984
opamp agent extension, github issue templates
portertech Sep 29, 2023
8d78a13
opamp agent extension, added to versions.yaml
portertech Sep 29, 2023
a2f32ab
opamp agent extension, pr make commands
portertech Sep 29, 2023
ee3e513
opamp agent extension, make checkdoc
portertech Sep 29, 2023
524bccc
Merge branch 'main' into feature/opamp-extension
portertech Sep 29, 2023
5ea9924
Update extension/opampextension/opamp_agent.go
portertech Oct 3, 2023
cd17ed1
opamp agent extension, update todos to reference #27293
portertech Oct 3, 2023
198e84d
Update extension/opampextension/opamp_agent.go
portertech Oct 3, 2023
0489a97
Update extension/opampextension/opamp_agent.go
portertech Oct 3, 2023
ca1d1d5
opamp agent extension, use LoadTLSConfig()
portertech Oct 3, 2023
52d83f1
opamp agent extension, return on new agent identity parse error
portertech Oct 3, 2023
84f6ec2
Update extension/opampextension/factory_test.go
portertech Oct 3, 2023
1b17172
Update extension/opampextension/config_test.go
portertech Oct 3, 2023
00d7b67
opamp agent extension, config instance_uid is optional
portertech Oct 3, 2023
e5c5c64
opamp agent extension, mutually exclusive instance uid, more attribut…
portertech Oct 3, 2023
72229c3
Update extension/opampextension/factory_test.go
portertech Oct 3, 2023
8743c3a
opamp agent extension, align with supervisor config
portertech Oct 3, 2023
e84b7fd
opamp agent extension, use semconv for identifying attributes
portertech Oct 3, 2023
096e856
opamp agent extension, added basic configuration and status to readme
portertech Oct 3, 2023
db3530b
Merge branch 'main' into feature/opamp-extension
portertech Oct 4, 2023
25e78ff
Merge branch 'main' into feature/opamp-extension
portertech Oct 5, 2023
61492fb
Merge branch 'main' into feature/opamp-extension
portertech Oct 6, 2023
572614a
opamp extension, service id uuid to agent ulid
portertech Oct 13, 2023
ec237bc
Merge branch 'main' into feature/opamp-extension
portertech Oct 13, 2023
30273a9
opamp agent extension, updated collector dep and license headers
portertech Oct 13, 2023
6f9b304
opamp agent extension, header opaque strings and lint fixes
portertech Oct 13, 2023
2b39482
Merge branch 'main' into feature/opamp-extension
portertech Oct 19, 2023
05ec3a2
opamp agent extension, gofmt for lint errors
portertech Oct 19, 2023
50c78af
opamp agent extension, go mod tidy and lint fix
portertech Oct 20, 2023
d277c16
opamp agent extension, component upgrade and lint fixes
portertech Oct 20, 2023
b581611
opamp agent extension, go mod tidy
portertech Oct 21, 2023
5ab82c2
Merge branch 'main' into feature/opamp-extension
portertech Oct 21, 2023
c271773
opamp agent extension, attempt to make the linter happy
portertech Oct 21, 2023
8c86826
Merge branch 'main' into feature/opamp-extension
portertech Oct 23, 2023
c6b3c39
opamp agent extension, collector bump and lint fix
portertech Oct 23, 2023
a340f99
opamp agent extension, one more collector version bump
portertech Oct 23, 2023
1f33f74
opamp agent extension, go mod tidy
portertech Oct 23, 2023
f3968e6
opamp agent extension, make gendependabot
portertech Oct 23, 2023
2d41a78
Merge branch 'main' into feature/opamp-extension
portertech Oct 24, 2023
301b838
opamp agent extension, make gendependabot
portertech Oct 24, 2023
02ff11f
Merge branch 'main' into feature/opamp-extension
portertech Oct 24, 2023
86351c5
Update extension/opampextension/opamp_agent.go
portertech Oct 25, 2023
2204190
Merge branch 'main' into feature/opamp-extension
portertech Oct 25, 2023
c3aaddb
opamp agent extension, use semconv os.type and host.arch as attributes
portertech Oct 25, 2023
3688953
opamp agent extension, make gendependabot
portertech Oct 25, 2023
4555060
Merge branch 'main' into feature/opamp-extension
portertech Oct 26, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .chloggen/add-opamp-agent-extension.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
change_type: new_component
portertech marked this conversation as resolved.
Show resolved Hide resolved

# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
component: extension/opampextension

# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
note: Add a new extension that implements an OpAMP agent for reporting the collector's health and effective configuration.

# One or more tracking issues related to the change
issues: [16462]

# (Optional) One or more lines of additional information to render under the primary note.
# These lines will be padded with 2 spaces and then inserted directly into the document.
# Use pipe (|) for multiline entries.
subtext:
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ extension/observer/ecstaskobserver/ @open-te
extension/observer/hostobserver/ @open-telemetry/collector-contrib-approvers @MovieStoreGuy
extension/observer/k8sobserver/ @open-telemetry/collector-contrib-approvers @rmfitzpatrick @dmitryax
extension/oidcauthextension/ @open-telemetry/collector-contrib-approvers @jpkrohling
extension/opampextension/ @open-telemetry/collector-contrib-approvers @portertech @evan-bradley @tigrannajaryan
extension/pprofextension/ @open-telemetry/collector-contrib-approvers @MovieStoreGuy
extension/sigv4authextension/ @open-telemetry/collector-contrib-approvers @Aneurysm9 @erichsueh3
extension/storage/ @open-telemetry/collector-contrib-approvers @dmitryax @atoulme @djaglowski
Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ body:
- extension/observer/hostobserver
- extension/observer/k8sobserver
- extension/oidcauth
- extension/opamp
- extension/pprof
- extension/sigv4auth
- extension/storage
Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ body:
- extension/observer/hostobserver
- extension/observer/k8sobserver
- extension/oidcauth
- extension/opamp
- extension/pprof
- extension/sigv4auth
- extension/storage
Expand Down
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/other.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ body:
- extension/observer/hostobserver
- extension/observer/k8sobserver
- extension/oidcauth
- extension/opamp
- extension/pprof
- extension/sigv4auth
- extension/storage
Expand Down
22 changes: 11 additions & 11 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@ updates:
interval: "weekly"
day: "wednesday"
- package-ecosystem: "gomod"
directory: "/cmd/githubgen"
directory: "/cmd/otelcontribcol"
schedule:
interval: "weekly"
day: "wednesday"
- package-ecosystem: "gomod"
directory: "/cmd/oteltestbedcol"
schedule:
interval: "weekly"
day: "wednesday"
Expand Down Expand Up @@ -302,11 +307,6 @@ updates:
schedule:
interval: "weekly"
day: "wednesday"
- package-ecosystem: "gomod"
directory: "/extension/encoding/jaegerencodingextension"
schedule:
interval: "weekly"
day: "wednesday"
- package-ecosystem: "gomod"
directory: "/extension/headerssetterextension"
schedule:
Expand Down Expand Up @@ -1012,11 +1012,6 @@ updates:
schedule:
interval: "weekly"
day: "wednesday"
- package-ecosystem: "gomod"
directory: "/receiver/splunkenterprisereceiver"
schedule:
interval: "weekly"
day: "wednesday"
- package-ecosystem: "gomod"
directory: "/receiver/splunkhecreceiver"
schedule:
Expand Down Expand Up @@ -1067,6 +1062,11 @@ updates:
schedule:
interval: "weekly"
day: "wednesday"
- package-ecosystem: "gomod"
directory: "/receiver/webhookeventreceiver"
schedule:
interval: "weekly"
day: "wednesday"
- package-ecosystem: "gomod"
directory: "/receiver/windowseventlogreceiver"
schedule:
Expand Down
1 change: 1 addition & 0 deletions extension/opampextension/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include ../../Makefile.Common
46 changes: 46 additions & 0 deletions extension/opampextension/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# OpAMP Agent Extension
<!-- status autogenerated section -->
| Status | |
| ------------- |-----------|
| Stability | [development] |
| Distributions | [] |
| Issues | [![Open issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aopen%20label%3Aextension%2Fopamp%20&label=open&color=orange&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aopen+is%3Aissue+label%3Aextension%2Fopamp) [![Closed issues](https://img.shields.io/github/issues-search/open-telemetry/opentelemetry-collector-contrib?query=is%3Aissue%20is%3Aclosed%20label%3Aextension%2Fopamp%20&label=closed&color=blue&logo=opentelemetry)](https://github.com/open-telemetry/opentelemetry-collector-contrib/issues?q=is%3Aclosed+is%3Aissue+label%3Aextension%2Fopamp) |
| [Code Owners](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/CONTRIBUTING.md#becoming-a-code-owner) | [@portertech](https://www.github.com/portertech), [@evan-bradley](https://www.github.com/evan-bradley), [@tigrannajaryan](https://www.github.com/tigrannajaryan) |

[development]: https://github.com/open-telemetry/opentelemetry-collector#development
<!-- end autogenerated section -->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we please get some more details into the README beyond the auto-generated stuff? How about the config options as a list and at least one basic usage example? Bonus point for calling out limitations and/or security considerations.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mhausenblas The readme has been updated, could you take another look?


## Configuration

The following settings are required:

- `server`: The OpAMP server connection settings.
- `ws`: The OpAMP websocket transport settings.
- `endpoint` (no default): The OpAMP server websocket endpoint (URL).

The following settings are optional:

- `server`: The OpAMP server connection settings.
- `ws`: The OpAMP websocket transport settings.
- `tls`: TLS settings.
- `headers`: HTTP headers to set.
- `instance_uid`: A ULID formatted as a 26 character string in canonical
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ULID?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe link to https://github.com/ulid/spec to disambiguate?

representation. Auto-generated on start if missing. Setting this ensures the
instance UID remains constant across process restarts.

### Example

``` yaml
extensions:
opamp:
server:
ws:
endpoint: wss://127.0.0.1:4320/v1/opamp
```

## Status

This OpenTelemetry OpAMP agent extension is intended to support the [OpAMP
Supervisor][supervisor].

[supervisor]: https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/cmd/opampsupervisor
50 changes: 50 additions & 0 deletions extension/opampextension/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package opampextension // import "github.com/open-telemetry/opentelemetry-collector-contrib/extension/opampextension"

import (
"errors"

"github.com/oklog/ulid/v2"
"go.opentelemetry.io/collector/config/configopaque"
"go.opentelemetry.io/collector/config/configtls"
)

// Config contains the configuration for the opamp extension. Trying to mirror
// the OpAMP supervisor config for some consistency.
type Config struct {
Server *OpAMPServer `mapstructure:"server"`

// InstanceUID is a ULID formatted as a 26 character string in canonical
// representation. Auto-generated on start if missing.
InstanceUID string `mapstructure:"instance_uid"`
}

// OpAMPServer contains the OpAMP transport configuration.
type OpAMPServer struct {
WS *OpAMPWebsocket `mapstructure:"ws"`
}

// OpAMPWebsocket contains the OpAMP websocket transport configuration.
type OpAMPWebsocket struct {
Endpoint string `mapstructure:"endpoint"`
TLSSetting configtls.TLSClientSetting `mapstructure:"tls,omitempty"`
Headers map[string]configopaque.String `mapstructure:"headers,omitempty"`
}

// Validate checks if the extension configuration is valid
func (cfg *Config) Validate() error {
if cfg.Server.WS.Endpoint == "" {
return errors.New("opamp server websocket endpoint must be provided")
}

if cfg.InstanceUID != "" {
_, err := ulid.ParseStrict(cfg.InstanceUID)
if err != nil {
return errors.New("opamp instance_uid is invalid")
}
}

return nil
}
57 changes: 57 additions & 0 deletions extension/opampextension/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package opampextension

import (
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/confmap"
"go.opentelemetry.io/collector/confmap/confmaptest"
)

func TestUnmarshalDefaultConfig(t *testing.T) {
factory := NewFactory()
cfg := factory.CreateDefaultConfig()
assert.NoError(t, component.UnmarshalConfig(confmap.New(), cfg))
assert.Equal(t, factory.CreateDefaultConfig(), cfg)
}

func TestUnmarshalConfig(t *testing.T) {
cm, err := confmaptest.LoadConf(filepath.Join("testdata", "config.yaml"))
require.NoError(t, err)
factory := NewFactory()
cfg := factory.CreateDefaultConfig()
assert.NoError(t, component.UnmarshalConfig(cm, cfg))
assert.Equal(t,
&Config{
Server: &OpAMPServer{
WS: &OpAMPWebsocket{
Endpoint: "wss://127.0.0.1:4320/v1/opamp",
},
},
InstanceUID: "01BX5ZZKBKACTAV9WEVGEMMVRZ",
}, cfg)
}

func TestConfigValidate(t *testing.T) {
cfg := &Config{
Server: &OpAMPServer{
WS: &OpAMPWebsocket{},
},
}
err := cfg.Validate()
assert.Equal(t, "opamp server websocket endpoint must be provided", err.Error())
cfg.Server.WS.Endpoint = "wss://127.0.0.1:4320/v1/opamp"
assert.NoError(t, cfg.Validate())
cfg.InstanceUID = "01BX5ZZKBKACTAV9WEVGEMMVRZFAIL"
err = cfg.Validate()
require.Error(t, err)
assert.Equal(t, "opamp instance_uid is invalid", err.Error())
portertech marked this conversation as resolved.
Show resolved Hide resolved
cfg.InstanceUID = "01BX5ZZKBKACTAV9WEVGEMMVRZ"
require.NoError(t, cfg.Validate())
}
portertech marked this conversation as resolved.
Show resolved Hide resolved
6 changes: 6 additions & 0 deletions extension/opampextension/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

//go:generate mdatagen metadata.yaml

package opampextension // import "github.com/open-telemetry/opentelemetry-collector-contrib/extension/opampextension"
34 changes: 34 additions & 0 deletions extension/opampextension/factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package opampextension // import "github.com/open-telemetry/opentelemetry-collector-contrib/extension/opampextension"

import (
"context"

"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/extension"

"github.com/open-telemetry/opentelemetry-collector-contrib/extension/opampextension/internal/metadata"
)

func NewFactory() extension.Factory {
return extension.NewFactory(
metadata.Type,
createDefaultConfig,
createExtension,
metadata.ExtensionStability,
)
}

func createDefaultConfig() component.Config {
return &Config{
Server: &OpAMPServer{
WS: &OpAMPWebsocket{},
},
}
}

func createExtension(_ context.Context, set extension.CreateSettings, cfg component.Config) (extension.Extension, error) {
return newOpampAgent(cfg.(*Config), set.Logger, set.BuildInfo, set.Resource)
}
31 changes: 31 additions & 0 deletions extension/opampextension/factory_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

package opampextension

import (
"context"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/component/componenttest"
"go.opentelemetry.io/collector/extension/extensiontest"
)

func TestFactory_CreateDefaultConfig(t *testing.T) {
cfg := NewFactory().CreateDefaultConfig()
assert.Equal(t, createDefaultConfig().(*Config), cfg)

assert.NoError(t, componenttest.CheckConfigStruct(cfg))
ext, err := createExtension(context.Background(), extensiontest.NewNopCreateSettings(), cfg)
require.NoError(t, err)
require.NotNil(t, ext)
}

func TestFactory_CreateExtension(t *testing.T) {
cfg := NewFactory().CreateDefaultConfig()
ext, err := createExtension(context.Background(), extensiontest.NewNopCreateSettings(), cfg)
require.NoError(t, err)
require.NotNil(t, ext)
}
47 changes: 47 additions & 0 deletions extension/opampextension/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
module github.com/open-telemetry/opentelemetry-collector-contrib/extension/opampextension

go 1.20

require (
github.com/google/uuid v1.3.1
github.com/oklog/ulid/v2 v2.1.0
github.com/open-telemetry/opamp-go v0.9.0
github.com/stretchr/testify v1.8.4
go.opentelemetry.io/collector/component v0.88.0
go.opentelemetry.io/collector/config/configopaque v0.88.0
go.opentelemetry.io/collector/config/configtls v0.88.0
go.opentelemetry.io/collector/confmap v0.88.0
go.opentelemetry.io/collector/extension v0.88.0
go.opentelemetry.io/collector/pdata v1.0.0-rcv0017
go.opentelemetry.io/collector/semconv v0.88.0
go.uber.org/zap v1.26.0
)

require (
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/knadh/koanf v1.5.0 // indirect
github.com/knadh/koanf/v2 v2.0.1 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/mapstructure v1.5.1-0.20220423185008-bf980b35cac4 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
go.opentelemetry.io/collector/config/configtelemetry v0.88.0 // indirect
go.opentelemetry.io/collector/featuregate v1.0.0-rcv0017 // indirect
go.opentelemetry.io/otel v1.19.0 // indirect
go.opentelemetry.io/otel/metric v1.19.0 // indirect
go.opentelemetry.io/otel/trace v1.19.0 // indirect
go.uber.org/goleak v1.2.1 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/grpc v1.59.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
Loading