Skip to content

Commit

Permalink
Merge branch 'main' into mx-psi/decouple-loglevel-from-log-level
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex Boten authored Jul 13, 2022
2 parents b380c5f + d48e930 commit 43d8912
Show file tree
Hide file tree
Showing 11 changed files with 196 additions and 53 deletions.
11 changes: 10 additions & 1 deletion .github/ISSUE_TEMPLATE/release.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,19 @@ assignees: ''

Like #4522, but for vX.X.X

**Performed by collector release manager**

- [ ] Prepare core release vX.X.X
- [ ] Tag and release core vX.X.X
- [ ] Prepare contrib release vX.X.X
- [ ] Tag and release contrib vX.X.X
- [ ] Prepare otelcol-releases vX.X.X
- [ ] Release binaries and container images vX.X.X
- [ ] Release the operator vX.X.X

**Performed by operator maintainers**

- [ ] Release the operator vX.X.X

**Performed by helm chart maintainers**

- [ ] Update the opentelemetry-collector helm chart to use vX.X.X docker image
2 changes: 2 additions & 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
- `client`: perform case insensitive lookups in case the requested metadata value isn't found (#5646)
- `loggingexporter`: Decouple `loglevel` field from level of logged messages (#5678)

### 🧰 Bug fixes 🧰
Expand Down Expand Up @@ -33,6 +34,7 @@
- `component.WithTracesProcessor` -> `component.WithTracesProcessorAndStabilityLevel`
- `component.WithMetricsProcessor` -> `component.WithMetricsProcessorAndStabilityLevel`
- `component.WithLogsProcessor` -> `component.WithLogsProcessorAndStabilityLevel`
- Deprecate `Registry.Apply` in `service.featuregate` (#5660)

### 💡 Enhancements 💡

Expand Down
15 changes: 14 additions & 1 deletion client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ package client // import "go.opentelemetry.io/collector/client"
import (
"context"
"net"
"strings"
)

type ctxKey struct{}
Expand Down Expand Up @@ -160,7 +161,19 @@ func NewMetadata(md map[string][]string) Metadata {
func (m Metadata) Get(key string) []string {
vals := m.data[key]
if len(vals) == 0 {
return nil
// we didn't find the key, but perhaps it just has different cases?
for k, v := range m.data {
if strings.EqualFold(key, k) {
vals = v
// we optimize for the next lookup
m.data[key] = v
}
}

// if it's still not found, it's really not here
if len(vals) == 0 {
return nil
}
}

ret := make([]string, len(vals))
Expand Down
1 change: 1 addition & 0 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ func TestMetadata(t *testing.T) {
source := map[string][]string{"test-key": {"test-val"}}
md := NewMetadata(source)
assert.Equal(t, []string{"test-val"}, md.Get("test-key"))
assert.Equal(t, []string{"test-val"}, md.Get("test-KEY")) // case insensitive lookup

// test if copy. In regular use, source cannot change
val := md.Get("test-key")
Expand Down
18 changes: 18 additions & 0 deletions component/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,24 @@ func (sl StabilityLevel) String() string {
return "undefined"
}

func (sl StabilityLevel) LogMessage() string {
switch sl {
case StabilityLevelUnmaintained:
return "Unmaintained component. Actively looking for contributors. Component will become deprecated after 6 months of remaining unmaintained."
case StabilityLevelDeprecated:
return "Deprecated component. Will be removed in future releases."
case StabilityLevelInDevelopment:
return "In development component. May change in the future."
case StabilityLevelAlpha:
return "Alpha component. May change in the future."
case StabilityLevelBeta:
return "Beta component. May change in the future."
case StabilityLevelStable:
return "Stable component."
}
return "Stability level of component is undefined"
}

// Factory is implemented by all component factories.
//
// This interface cannot be directly implemented. Implementations must
Expand Down
16 changes: 16 additions & 0 deletions service/featuregate/gates.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ type Registry struct {

// Apply a configuration in the form of a map of Gate identifiers to boolean values.
// Sets only those values provided in the map, other gate values are not changed.
// Deprecated: [v0.56.0] Use MustApply instead.
func (r *Registry) Apply(cfg map[string]bool) {
r.mu.Lock()
defer r.mu.Unlock()
Expand All @@ -57,6 +58,21 @@ func (r *Registry) Apply(cfg map[string]bool) {
}
}

// MustApply a configuration in the form of a map of Gate identifiers to boolean values.
// Sets only those values provided in the map, other gate values are not changed.
func (r *Registry) MustApply(cfg map[string]bool) {
r.mu.Lock()
defer r.mu.Unlock()
for id, val := range cfg {
if g, ok := r.gates[id]; ok {
g.Enabled = val
r.gates[g.ID] = g
} else {
panic(fmt.Sprintf("feature gate %s is unregistered", id))
}
}
}

// IsEnabled returns true if a registered feature gate is enabled and false otherwise.
func (r *Registry) IsEnabled(id string) bool {
r.mu.RLock()
Expand Down
44 changes: 44 additions & 0 deletions service/featuregate/gates_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,47 @@ func TestRegistry(t *testing.T) {
r.MustRegister(gate)
})
}

func TestRegistryWithMustApply(t *testing.T) {
r := Registry{gates: map[string]Gate{}}
gate := Gate{
ID: "foo",
Description: "Test Gate",
Enabled: true,
}
assert.NoError(t, r.Register(gate))

tests := []struct {
name string
gate string
enabled bool
shouldError bool
}{
{
name: "existing_gate",
gate: "foo",
enabled: false,
shouldError: false,
},
{
name: "none_existing_gate",
gate: "bar",
enabled: false,
shouldError: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.shouldError {
assert.Panics(t, func() {
r.MustApply(map[string]bool{tt.gate: tt.enabled})
})
} else {
r.MustApply(map[string]bool{tt.gate: tt.enabled})
assert.Equal(t, tt.enabled, r.IsEnabled(tt.gate))
}

})
}
}
32 changes: 32 additions & 0 deletions service/internal/components/components.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package components // import "go.opentelemetry.io/collector/service/internal/components"

import (
"go.uber.org/zap"

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

// LogStabilityLevel logs the stability level of a component. The log level is set to info for
// undefined, unmaintained, deprecated and in development. The log level is set to debug
// for alpha, beta and stable.
func LogStabilityLevel(logger *zap.Logger, sl component.StabilityLevel) {
if sl >= component.StabilityLevelAlpha {
logger.Debug(sl.LogMessage(), zap.String(ZapStabilityKey, sl.String()))
} else {
logger.Info(sl.LogMessage(), zap.String(ZapStabilityKey, sl.String()))
}
}
56 changes: 56 additions & 0 deletions service/internal/components/components_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package components // import "go.opentelemetry.io/collector/service/internal/components"

import (
"testing"

"github.com/stretchr/testify/require"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"go.uber.org/zap/zaptest/observer"

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

func TestLogStabilityLevel(t *testing.T) {
tests := []struct {
level zapcore.Level
expectedLogs int
}{
{
level: zapcore.DebugLevel,
expectedLogs: 7,
},
{
level: zapcore.InfoLevel,
expectedLogs: 4,
},
}

for _, tt := range tests {
observed, logs := observer.New(tt.level)
logger := zap.New(observed)
// ensure log levels are set correctly for each stability level
LogStabilityLevel(logger, component.StabilityLevelUndefined)
LogStabilityLevel(logger, component.StabilityLevelUnmaintained)
LogStabilityLevel(logger, component.StabilityLevelDeprecated)
LogStabilityLevel(logger, component.StabilityLevelInDevelopment)
LogStabilityLevel(logger, component.StabilityLevelAlpha)
LogStabilityLevel(logger, component.StabilityLevelBeta)
LogStabilityLevel(logger, component.StabilityLevelStable)
require.Equal(t, tt.expectedLogs, logs.Len())
}
}
21 changes: 3 additions & 18 deletions service/internal/pipelines/pipelines.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,21 +331,6 @@ func Build(ctx context.Context, set Settings) (*Pipelines, error) {
return exps, nil
}

func logStabilityMessage(logger *zap.Logger, sl component.StabilityLevel) {
switch sl {
case component.StabilityLevelDeprecated:
logger.Info("Component has been deprecated and will be removed in future releases.", zap.String(components.ZapStabilityKey, sl.String()))
case component.StabilityLevelUnmaintained:
logger.Info("Component is unmaintained and actively looking for contributors. This component will become deprecated after 6 months of remaining unmaintained", zap.String(components.ZapStabilityKey, sl.String()))
case component.StabilityLevelInDevelopment:
logger.Info("Component is under development.", zap.String(components.ZapStabilityKey, sl.String()))
case component.StabilityLevelAlpha, component.StabilityLevelBeta, component.StabilityLevelStable:
logger.Debug("Stability level", zap.String(components.ZapStabilityKey, sl.String()))
default:
logger.Debug("Stability level of component undefined", zap.String(components.ZapStabilityKey, sl.String()))
}
}

func buildExporter(
ctx context.Context,
settings component.TelemetrySettings,
Expand All @@ -370,7 +355,7 @@ func buildExporter(
BuildInfo: buildInfo,
}
set.TelemetrySettings.Logger = exporterLogger(settings.Logger, id, pipelineID.Type())
logStabilityMessage(set.TelemetrySettings.Logger, factory.StabilityLevel(pipelineID.Type()))
components.LogStabilityLevel(set.TelemetrySettings.Logger, factory.StabilityLevel(pipelineID.Type()))

exp, err := createExporter(ctx, set, cfg, id, pipelineID, factory)
if err != nil {
Expand Down Expand Up @@ -452,7 +437,7 @@ func buildProcessor(ctx context.Context,
BuildInfo: buildInfo,
}
set.TelemetrySettings.Logger = processorLogger(settings.Logger, id, pipelineID)
logStabilityMessage(set.TelemetrySettings.Logger, factory.StabilityLevel(pipelineID.Type()))
components.LogStabilityLevel(set.TelemetrySettings.Logger, factory.StabilityLevel(pipelineID.Type()))

proc, err := createProcessor(ctx, set, procCfg, id, pipelineID, next, factory)
if err != nil {
Expand Down Expand Up @@ -506,7 +491,7 @@ func buildReceiver(ctx context.Context,
BuildInfo: buildInfo,
}
set.TelemetrySettings.Logger = receiverLogger(settings.Logger, id, pipelineID.Type())
logStabilityMessage(set.TelemetrySettings.Logger, factory.StabilityLevel(pipelineID.Type()))
components.LogStabilityLevel(set.TelemetrySettings.Logger, factory.StabilityLevel(pipelineID.Type()))

recv, err := createReceiver(ctx, set, cfg, id, pipelineID, nexts, factory)
if err != nil {
Expand Down
33 changes: 0 additions & 33 deletions service/internal/pipelines/pipelines_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@ import (

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"go.uber.org/zap/zaptest/observer"

"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/component/componenttest"
Expand Down Expand Up @@ -348,36 +345,6 @@ func TestFailToStartAndShutdown(t *testing.T) {
}
}

func TestLogStabilityLevle(t *testing.T) {
tests := []struct {
level zapcore.Level
expectedLogs int
}{
{
level: zapcore.DebugLevel,
expectedLogs: 7,
},
{
level: zapcore.InfoLevel,
expectedLogs: 3,
},
}

for _, tt := range tests {
observed, logs := observer.New(tt.level)
logger := zap.New(observed)
// ensure log levels are set correctly for each stability level
logStabilityMessage(logger, component.StabilityLevelUndefined)
logStabilityMessage(logger, component.StabilityLevelUnmaintained)
logStabilityMessage(logger, component.StabilityLevelDeprecated)
logStabilityMessage(logger, component.StabilityLevelInDevelopment)
logStabilityMessage(logger, component.StabilityLevelAlpha)
logStabilityMessage(logger, component.StabilityLevelBeta)
logStabilityMessage(logger, component.StabilityLevelStable)
require.Equal(t, tt.expectedLogs, logs.Len())
}
}

func newBadReceiverFactory() component.ReceiverFactory {
return component.NewReceiverFactory("bf", func() config.Receiver {
return &struct {
Expand Down

0 comments on commit 43d8912

Please sign in to comment.