Skip to content

Commit

Permalink
[exporter/logging] Add exporter.logging.CreateLoggerFromCore featur…
Browse files Browse the repository at this point in the history
…e gate
  • Loading branch information
mx-psi committed Jul 12, 2022
1 parent 6133c82 commit 16b18ad
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### 💡 Enhancements 💡

- Add `linux-ppc64le` architecture to cross build tests in CI
- Add `exporter.logging.CreateLoggerFromCore` feature gate, to create the exporter's logger from the service's logger (#5677)

### 🧰 Bug fixes 🧰

Expand Down
6 changes: 6 additions & 0 deletions exporter/loggingexporter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ exporters:
sampling_thereafter: 200
```
## Feature gates
The following feature gates are available:
- `exporter.logging.CreateLoggerFromCore` ([alpha stability](../../service/featuregate#feature-lifecycle)): Create the logger from the service logger's core. This makes the logging exporter follow the `telemetry::logs` configuration. This will make the exporter fail to start if the `loglevel` is set lower than `telemetry::logs::level`.

[contrib]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol-contrib
[core]: https://github.com/open-telemetry/opentelemetry-collector-releases/tree/main/distributions/otelcol
[In development]: https://github.com/open-telemetry/opentelemetry-collector#in-development
62 changes: 58 additions & 4 deletions exporter/loggingexporter/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,39 @@ package loggingexporter // import "go.opentelemetry.io/collector/exporter/loggin

import (
"context"
"fmt"
"sync"
"time"

"go.uber.org/zap"
"go.uber.org/zap/zapcore"

"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/config"
"go.opentelemetry.io/collector/service/featuregate"
)

const (
// The value of "type" key in configuration.
typeStr = "logging"
defaultSamplingInitial = 2
defaultSamplingThereafter = 500

// CreateLoggerFromCoreFeatureGate is a feature gate that, when enabled will create the logger from the service logger's core.
CreateLoggerFromCoreFeatureGate = "exporter.logging.CreateLoggerFromCore"
)

func init() {
featuregate.GetRegistry().Register(featuregate.Gate{
ID: CreateLoggerFromCoreFeatureGate,
Description: "Use the service logger's core to build the logging exporter logger. When doing this, the `loglevel` field must not be lower than `telemetry::logs::level`.",
Enabled: false,
})
}

// onceWarnFailedBuild is used to warn users about the future change to create the logger from core.
var onceWarnFailedBuild sync.Once

// NewFactory creates a factory for Logging exporter
func NewFactory() component.ExporterFactory {
return component.NewExporterFactory(
Expand All @@ -54,7 +72,7 @@ func createDefaultConfig() config.Exporter {
func createTracesExporter(_ context.Context, set component.ExporterCreateSettings, config config.Exporter) (component.TracesExporter, error) {
cfg := config.(*Config)

exporterLogger, err := createLogger(cfg)
exporterLogger, err := createLogger(cfg, set.TelemetrySettings.Logger)
if err != nil {
return nil, err
}
Expand All @@ -65,7 +83,7 @@ func createTracesExporter(_ context.Context, set component.ExporterCreateSetting
func createMetricsExporter(_ context.Context, set component.ExporterCreateSettings, config config.Exporter) (component.MetricsExporter, error) {
cfg := config.(*Config)

exporterLogger, err := createLogger(cfg)
exporterLogger, err := createLogger(cfg, set.TelemetrySettings.Logger)
if err != nil {
return nil, err
}
Expand All @@ -76,15 +94,15 @@ func createMetricsExporter(_ context.Context, set component.ExporterCreateSettin
func createLogsExporter(_ context.Context, set component.ExporterCreateSettings, config config.Exporter) (component.LogsExporter, error) {
cfg := config.(*Config)

exporterLogger, err := createLogger(cfg)
exporterLogger, err := createLogger(cfg, set.TelemetrySettings.Logger)
if err != nil {
return nil, err
}

return newLogsExporter(config, exporterLogger, set)
}

func createLogger(cfg *Config) (*zap.Logger, error) {
func createIndependentLogger(cfg *Config) (*zap.Logger, error) {
// We take development config as the base since it matches the purpose
// of logging exporter being used for debugging reasons (so e.g. console encoder)
conf := zap.NewDevelopmentConfig()
Expand All @@ -100,3 +118,39 @@ func createLogger(cfg *Config) (*zap.Logger, error) {
}
return logginglogger, nil
}

func createLoggerFromCore(cfg *Config, logger *zap.Logger) (*zap.Logger, error) {
core := zapcore.NewSamplerWithOptions(
logger.Core(),
1*time.Second,
cfg.SamplingInitial,
cfg.SamplingThereafter,
)

core, err := zapcore.NewIncreaseLevelCore(core, cfg.LogLevel)
if err != nil {
return nil, fmt.Errorf("failed to increase log level: %w", err)
}

return zap.New(core), nil
}

func createLogger(cfg *Config, logger *zap.Logger) (*zap.Logger, error) {
// Always create the logger from core, to check if it would fail to build.
loggerFromCore, err := createLoggerFromCore(cfg, logger)

if featuregate.GetRegistry().IsEnabled(CreateLoggerFromCoreFeatureGate) {
return loggerFromCore, err
}

onceWarnFailedBuild.Do(func() {
if err != nil {
logger.Warn(
"This exporter will fail to start with the current configuration in a future version.",
zap.Error(err),
zap.String("related feature gate", CreateLoggerFromCoreFeatureGate),
)
}
})
return createIndependentLogger(cfg)
}

0 comments on commit 16b18ad

Please sign in to comment.