1
1
// Copyright The OpenTelemetry Authors
2
2
// SPDX-License-Identifier: Apache-2.0
3
3
4
- package componentattribute_test
4
+ package componentattribute
5
5
6
6
import (
7
7
"testing"
8
+ "time"
8
9
9
10
"github.com/stretchr/testify/assert"
10
11
"github.com/stretchr/testify/require"
@@ -14,7 +15,6 @@ import (
14
15
"go.uber.org/zap/zapcore"
15
16
"go.uber.org/zap/zaptest/observer"
16
17
17
- "go.opentelemetry.io/collector/internal/telemetry/componentattribute"
18
18
"go.opentelemetry.io/collector/pipeline"
19
19
)
20
20
@@ -31,7 +31,7 @@ type test struct {
31
31
func createZapCore () (zapcore.Core , * observer.ObservedLogs ) {
32
32
core , observed := observer .New (zap .DebugLevel )
33
33
core = core .With ([]zapcore.Field {zap .String ("preexisting" , "value" )})
34
- core = componentattribute . NewConsoleCoreWithAttributes (core , attribute .NewSet ())
34
+ core = NewConsoleCoreWithAttributes (core , attribute .NewSet ())
35
35
return core , observed
36
36
}
37
37
@@ -40,13 +40,13 @@ func checkZapLogs(t *testing.T, observed *observer.ObservedLogs) {
40
40
require .Len (t , observedLogs , 3 )
41
41
42
42
parentContext := map [string ]string {
43
- "preexisting" : "value" ,
44
- componentattribute . SignalKey : pipeline .SignalLogs .String (),
45
- componentattribute . ComponentIDKey : "filelog" ,
43
+ "preexisting" : "value" ,
44
+ SignalKey : pipeline .SignalLogs .String (),
45
+ ComponentIDKey : "filelog" ,
46
46
}
47
47
childContext := map [string ]string {
48
- "preexisting" : "value" ,
49
- componentattribute . ComponentIDKey : "filelog" ,
48
+ "preexisting" : "value" ,
49
+ ComponentIDKey : "filelog" ,
50
50
}
51
51
52
52
require .Equal (t , "test parent before child" , observedLogs [0 ].Message )
@@ -70,8 +70,8 @@ func checkZapLogs(t *testing.T, observed *observer.ObservedLogs) {
70
70
71
71
func TestCore (t * testing.T ) {
72
72
attrs := attribute .NewSet (
73
- attribute .String (componentattribute . SignalKey , pipeline .SignalLogs .String ()),
74
- attribute .String (componentattribute . ComponentIDKey , "filelog" ),
73
+ attribute .String (SignalKey , pipeline .SignalLogs .String ()),
74
+ attribute .String (ComponentIDKey , "filelog" ),
75
75
)
76
76
77
77
tests := []test {
@@ -90,7 +90,7 @@ func TestCore(t *testing.T) {
90
90
createLogger : func () (* zap.Logger , logRecorder ) {
91
91
core , observed := createZapCore ()
92
92
recorder := logtest .NewRecorder ()
93
- core = componentattribute . NewOTelTeeCoreWithAttributes (core , recorder , "testinstr" , zap .DebugLevel , attribute .NewSet (), func ( c zapcore. Core ) zapcore. Core { return c } )
93
+ core = NewOTelTeeCoreWithAttributes (core , recorder , "testinstr" , zap .DebugLevel , attribute .NewSet ())
94
94
return zap .New (core ), logRecorder {zapLogs : observed , otelLogs : recorder }
95
95
},
96
96
check : func (t * testing.T , rec logRecorder ) {
@@ -107,7 +107,7 @@ func TestCore(t *testing.T) {
107
107
}
108
108
109
109
childAttrs := attribute .NewSet (
110
- attribute .String (componentattribute . ComponentIDKey , "filelog" ),
110
+ attribute .String (ComponentIDKey , "filelog" ),
111
111
)
112
112
113
113
assert .Equal (t , map [string ]attribute.Set {
@@ -122,13 +122,110 @@ func TestCore(t *testing.T) {
122
122
t .Run (test .name , func (t * testing.T ) {
123
123
logger , state := test .createLogger ()
124
124
125
- parent := componentattribute . ZapLoggerWithAttributes (logger , attrs )
125
+ parent := ZapLoggerWithAttributes (logger , attrs )
126
126
parent .Info ("test parent before child" )
127
- child := componentattribute . ZapLoggerWithAttributes (parent , componentattribute . RemoveAttributes (attrs , componentattribute . SignalKey ))
127
+ child := ZapLoggerWithAttributes (parent , RemoveAttributes (attrs , SignalKey ))
128
128
child .Info ("test child" )
129
129
parent .Info ("test parent after child" )
130
130
131
131
test .check (t , state )
132
132
})
133
133
}
134
134
}
135
+
136
+ func TestSamplerCore (t * testing.T ) {
137
+ tick := time .Second
138
+ // Drop identical messages after the first two
139
+ first := 2
140
+ thereafter := 0
141
+
142
+ type testCase struct {
143
+ name string
144
+ withAttributes func (inner zapcore.Core , sampler zapcore.Core , attrs attribute.Set ) zapcore.Core
145
+ expectedAttrs []string
146
+ }
147
+ testCases := []testCase {
148
+ {
149
+ name : "new-sampler" ,
150
+ withAttributes : func (inner zapcore.Core , _ zapcore.Core , attrs attribute.Set ) zapcore.Core {
151
+ return zapcore .NewSamplerWithOptions (tryWithAttributeSet (inner , attrs ), tick , first , thereafter )
152
+ },
153
+ expectedAttrs : []string {"foo" , "bar" , "foo" , "bar" },
154
+ },
155
+ {
156
+ name : "cloned-sampler" ,
157
+ withAttributes : func (_ zapcore.Core , sampler zapcore.Core , attrs attribute.Set ) zapcore.Core {
158
+ return tryWithAttributeSet (sampler , attrs )
159
+ },
160
+ expectedAttrs : []string {"foo" , "bar" },
161
+ },
162
+ }
163
+ for _ , tc := range testCases {
164
+ t .Run (tc .name , func (t * testing.T ) {
165
+ inner , obs := observer .New (zapcore .DebugLevel )
166
+ inner = NewConsoleCoreWithAttributes (inner , attribute .NewSet (attribute .String ("test" , "foo" )))
167
+
168
+ sampler1 := NewSamplerCoreWithAttributes (inner , tick , first , thereafter )
169
+ loggerFoo := zap .New (sampler1 )
170
+
171
+ sampler2 := tc .withAttributes (inner , sampler1 , attribute .NewSet (attribute .String ("test" , "bar" )))
172
+ loggerBar := zap .New (sampler2 )
173
+
174
+ // If the two samplers share their counters, only the first two messages will go through.
175
+ // If they are independent, the first three and the fifth will go through.
176
+ loggerFoo .Info ("test" )
177
+ loggerBar .Info ("test" )
178
+ loggerFoo .Info ("test" )
179
+ loggerFoo .Info ("test" )
180
+ loggerBar .Info ("test" )
181
+ loggerBar .Info ("test" )
182
+
183
+ var attrs []string
184
+ for _ , log := range obs .All () {
185
+ var fooValue string
186
+ for _ , field := range log .Context {
187
+ if field .Key == "test" {
188
+ fooValue = field .String
189
+ }
190
+ }
191
+ attrs = append (attrs , fooValue )
192
+ }
193
+ assert .Equal (t , tc .expectedAttrs , attrs )
194
+ })
195
+ }
196
+ }
197
+
198
+ // Worst case scenario for the reflect spell in samplerCoreWithAttributes
199
+ type crazySampler struct {
200
+ Core int
201
+ }
202
+
203
+ var _ zapcore.Core = (* crazySampler )(nil )
204
+
205
+ func (s * crazySampler ) Enabled (zapcore.Level ) bool {
206
+ return true
207
+ }
208
+
209
+ func (s * crazySampler ) With ([]zapcore.Field ) zapcore.Core {
210
+ return s
211
+ }
212
+
213
+ func (s * crazySampler ) Check (_ zapcore.Entry , ce * zapcore.CheckedEntry ) * zapcore.CheckedEntry {
214
+ return ce
215
+ }
216
+
217
+ func (s * crazySampler ) Write (zapcore.Entry , []zapcore.Field ) error {
218
+ return nil
219
+ }
220
+
221
+ func (s * crazySampler ) Sync () error {
222
+ return nil
223
+ }
224
+
225
+ func TestSamplerCorePanic (t * testing.T ) {
226
+ sampler := NewSamplerCoreWithAttributes (zapcore .NewNopCore (), 1 , 1 , 1 )
227
+ sampler .(* samplerCoreWithAttributes ).Core = & crazySampler {}
228
+ assert .PanicsWithValue (t , "Unexpected Zap sampler type; see github.com/open-telemetry/opentelemetry-collector/issues/13014" , func () {
229
+ tryWithAttributeSet (sampler , attribute .NewSet ())
230
+ })
231
+ }
0 commit comments