Skip to content

Commit

Permalink
refactor: exporter config (#214)
Browse files Browse the repository at this point in the history
* refactor: exporter config

* refactor: add common exporter config struct instead of multiple returns
* docs: add missing docs for exporter config

Signed-off-by: lvlcn-t <[email protected]>

* chore: simplified if guard

Merged the two ifs into one.

* docs: add certpath hint

Signed-off-by: lvlcn-t <[email protected]>

---------

Signed-off-by: lvlcn-t <[email protected]>
Co-authored-by: Bruno Bressi <[email protected]>
  • Loading branch information
lvlcn-t and puffitos authored Nov 7, 2024
1 parent 52d6213 commit da02b0e
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 47 deletions.
35 changes: 21 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,14 @@ The binary is available for several distributions. To install the binary, use a
Replace `${RELEASE_VERSION}` with the desired release version:

```sh
curl https://github.com/caas-team/sparrow/releases/download/v${RELEASE_VERSION}/sparrow_${RELEASE_VERSION}_linux_amd64.tar.gz -Lo sparrow.tar.gz
curl https://github.com/caas-team/sparrow/releases/download/v${RELEASE_VERSION}/sparrow_${RELEASE_VERSION}_checksums.txt -Lo checksums.txt
export RELEASE_VERSION=0.5.0
```

For example, for release `v0.3.1`:
Download the binary:

```sh
curl https://github.com/caas-team/sparrow/releases/download/v0.3.1/sparrow_0.3.1_linux_amd64.tar.gz -Lo sparrow.tar.gz
curl https://github.com/caas-team/sparrow/releases/download/v0.3.1/sparrow_0.3.1_checksums.txt -Lo checksums.txt
curl https://github.com/caas-team/sparrow/releases/download/v${RELEASE_VERSION}/sparrow_${RELEASE_VERSION}_linux_amd64.tar.gz -Lo sparrow.tar.gz
curl https://github.com/caas-team/sparrow/releases/download/v${RELEASE_VERSION}/sparrow_${RELEASE_VERSION}_checksums.txt -Lo checksums.txt
```

Extract the binary:
Expand Down Expand Up @@ -291,9 +290,13 @@ telemetry:
# The token to use for authentication.
# If the exporter does not require a token, this can be left empty.
token: ""
# The path to the tls certificate to use.
# To disable tls, either set this to an empty string or set it to insecure.
certPath: ""
# Configures tls for the telemetry exporter
tls:
# Enable or disable TLS
enabled: true
# The path to the tls certificate to use.
# Only required if your otel endpoint uses custom TLS certificates
certPath: ""
```

#### Loader
Expand Down Expand Up @@ -644,17 +647,21 @@ Replace `<sparrow_instance_address>` with the actual address of your `sparrow` i

The `sparrow` supports exporting telemetry data using the OpenTelemetry Protocol (OTLP). This allows users to choose their preferred telemetry provider and collector. The following configuration options are available for setting up telemetry:

| Field | Type | Description |
| ---------- | -------- | ------------------------------------------------------------------------ |
| `exporter` | `string` | The telemetry exporter to use. Options: `grpc`, `http`, `stdout`, `noop` |
| `url` | `string` | The address to export telemetry to |
| `token` | `string` | The token to use for authentication |
| `certPath` | `string` | The path to the TLS certificate to use |
| Field | Type | Description |
| -------------- | -------- | --------------------------------------------------------------------------- |
| `enabled` | `bool` | Whether to enable telemetry. Default: `false` |
| `exporter` | `string` | The telemetry exporter to use. Options: `grpc`, `http`, `stdout`, `noop` |
| `url` | `string` | The address to export telemetry to. |
| `token` | `string` | The token to use for authentication. |
| `tls.enabled` | `bool` | Enable or disable TLS. |
| `tls.certPath` | `string` | The path to the TLS certificate to use. Only required if custom TLS is used |

For example, to export telemetry data using OTLP via gRPC, you can add the following configuration to your [startup configuration](#startup):

```yaml
telemetry:
# Whether to enable telemetry. (default: false)
enabled: true
# The telemetry exporter to use.
# Options:
# grpc: Exports telemetry using OTLP via gRPC.
Expand Down
19 changes: 10 additions & 9 deletions pkg/sparrow/metrics/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,17 @@ type Config struct {
// Url is the Url of the collector to which the traces are exported
Url string `yaml:"url" mapstructure:"url"`
// Token is the token used to authenticate with the collector
Token string `yaml:"token" mapstructure:"token"`
Tls TLSConfig `yaml:"tls" mapstructure:"tls"`
Token string `yaml:"token" mapstructure:"token"`
// TLS holds the tls configuration
TLS TLSConfig `yaml:"tls" mapstructure:"tls"`
}

type TLSConfig struct {
// CertPath is the path to the tls certificate file
// Enabled is a flag to enable or disable the tls
Enabled bool `yaml:"enabled" mapstructure:"enabled"`
// CertPath is the path to the tls certificate file.
// This is only required if the otel backend uses custom TLS certificates.
CertPath string `yaml:"certPath" mapstructure:"certPath"`
Enabled bool `yaml:"enabled" mapstructure:"enabled"`
}

func (c *Config) Validate(ctx context.Context) error {
Expand All @@ -51,11 +54,9 @@ func (c *Config) Validate(ctx context.Context) error {
return err
}

if c.Exporter.IsExporting() {
if c.Url == "" {
log.ErrorContext(ctx, "Url is required for otlp exporter", "exporter", c.Exporter)
return fmt.Errorf("url is required for otlp exporter %q", c.Exporter)
}
if c.Exporter.IsExporting() && c.Url == "" {
log.ErrorContext(ctx, "Url is required for otlp exporter", "exporter", c.Exporter)
return fmt.Errorf("url is required for otlp exporter %q", c.Exporter)
}
return nil
}
60 changes: 36 additions & 24 deletions pkg/sparrow/metrics/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,44 +91,44 @@ func (e Exporter) Create(ctx context.Context, config *Config) (sdktrace.SpanExpo

// newHTTPExporter creates a new HTTP exporter
func newHTTPExporter(ctx context.Context, config *Config) (sdktrace.SpanExporter, error) {
headers, tlsCfg, err := getCommonConfig(config)
cfg, err := newExporterConfig(config)
if err != nil {
return nil, err
}

opts := []otlptracehttp.Option{
otlptracehttp.WithEndpoint(config.Url),
otlptracehttp.WithHeaders(headers),
otlptracehttp.WithHeaders(cfg.headers),
}
if config.Tls.Enabled {
if tlsCfg != nil {
opts = append(opts, otlptracehttp.WithTLSClientConfig(tlsCfg))
}
} else {
if !config.TLS.Enabled {
opts = append(opts, otlptracehttp.WithInsecure())
return otlptracehttp.New(ctx, opts...)
}
if cfg.tls != nil {
opts = append(opts, otlptracehttp.WithTLSClientConfig(cfg.tls))
}

return otlptracehttp.New(ctx, opts...)
}

// newGRPCExporter creates a new gRPC exporter
func newGRPCExporter(ctx context.Context, config *Config) (sdktrace.SpanExporter, error) {
headers, tlsCfg, err := getCommonConfig(config)
cfg, err := newExporterConfig(config)
if err != nil {
return nil, err
}

opts := []otlptracegrpc.Option{
otlptracegrpc.WithEndpoint(config.Url),
otlptracegrpc.WithHeaders(headers),
otlptracegrpc.WithHeaders(cfg.headers),
}

if !config.Tls.Enabled {
if !config.TLS.Enabled {
opts = append(opts, otlptracegrpc.WithInsecure())
return otlptracegrpc.New(ctx, opts...)
}
if tlsCfg != nil {
opts = append(opts, otlptracegrpc.WithTLSCredentials(credentials.NewTLS(tlsCfg)))
if cfg.tls != nil {
opts = append(opts, otlptracegrpc.WithTLSCredentials(credentials.NewTLS(cfg.tls)))
}

return otlptracegrpc.New(ctx, opts...)
Expand All @@ -144,22 +144,36 @@ func newNoopExporter(_ context.Context, _ *Config) (sdktrace.SpanExporter, error
return nil, nil
}

// getCommonConfig returns the common configuration for the exporters
func getCommonConfig(config *Config) (map[string]string, *tls.Config, error) {
headers := make(map[string]string)
// exporterConfig contains the common configuration for the exporters
type exporterConfig struct {
// headers contains the headers to send with spans
headers map[string]string
// tls contains the TLS configuration for the exporter
tls *tls.Config
}

// newExporterConfig returns the common configuration for the exporters
func newExporterConfig(config *Config) (exporterConfig, error) {
headers := map[string]string{}
if config.Token != "" {
headers["Authorization"] = fmt.Sprintf("Bearer %s", config.Token)
}

if config.Tls.Enabled {
tlsCfg, err := getTLSConfig(config.Tls.CertPath)
if config.TLS.Enabled {
tlsCfg, err := getTLSConfig(config.TLS.CertPath)
if err != nil {
return nil, nil, fmt.Errorf("failed to create TLS configuration: %w", err)
return exporterConfig{}, fmt.Errorf("failed to create TLS configuration: %w", err)
}
return headers, tlsCfg, nil
return exporterConfig{
headers: headers,
tls: tlsCfg,
}, nil
}

return headers, nil, nil
return exporterConfig{
headers: headers,
tls: nil,
}, nil
}

// FileOpener is the function used to open a file
Expand All @@ -172,7 +186,7 @@ var openFile FileOpener = func() FileOpener {
}
}()

func getTLSConfig(certFile string) (conf *tls.Config, err error) {
func getTLSConfig(certFile string) (*tls.Config, error) {
if certFile == "" {
return nil, nil
}
Expand All @@ -182,9 +196,7 @@ func getTLSConfig(certFile string) (conf *tls.Config, err error) {
return nil, fmt.Errorf("failed to open certificate file: %w", err)
}
defer func() {
if cErr := file.Close(); cErr != nil {
err = errors.Join(err, cErr)
}
err = errors.Join(err, file.Close())
}()

b, err := io.ReadAll(file)
Expand Down

0 comments on commit da02b0e

Please sign in to comment.