Skip to content

Commit f6dc72e

Browse files
committed
feat: add file exporter tests
Signed-off-by: Bence Csati <bence.csati@axoflow.com>
1 parent e36e27c commit f6dc72e

File tree

1 file changed

+363
-0
lines changed

1 file changed

+363
-0
lines changed
Lines changed: 363 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,363 @@
1+
// Copyright © 2025 Kube logging authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package exporter
16+
17+
import (
18+
"context"
19+
"testing"
20+
"time"
21+
22+
"github.com/stretchr/testify/assert"
23+
"go.opentelemetry.io/collector/component"
24+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25+
26+
"github.com/kube-logging/telemetry-controller/api/telemetry/v1alpha1"
27+
"github.com/kube-logging/telemetry-controller/pkg/resources/otel_conf_gen/pipeline/components"
28+
"github.com/kube-logging/telemetry-controller/pkg/sdk/utils"
29+
)
30+
31+
func TestGenerateFileExporter(t *testing.T) {
32+
tests := []struct {
33+
name string
34+
resourceRelations components.ResourceRelations
35+
expectedResult map[string]any
36+
}{
37+
{
38+
name: "Basic file exporter with path only",
39+
resourceRelations: components.ResourceRelations{
40+
OutputsWithSecretData: []components.OutputWithSecretData{
41+
{
42+
Output: v1alpha1.Output{
43+
ObjectMeta: metav1.ObjectMeta{
44+
Name: "output1",
45+
Namespace: "default",
46+
},
47+
Spec: v1alpha1.OutputSpec{
48+
File: &v1alpha1.File{
49+
Path: "/tmp/logs.json",
50+
},
51+
},
52+
},
53+
},
54+
},
55+
},
56+
expectedResult: map[string]any{
57+
"file/default_output1": map[string]any{
58+
"path": "/tmp/logs.json",
59+
},
60+
},
61+
},
62+
{
63+
name: "File exporter with append mode",
64+
resourceRelations: components.ResourceRelations{
65+
OutputsWithSecretData: []components.OutputWithSecretData{
66+
{
67+
Output: v1alpha1.Output{
68+
ObjectMeta: metav1.ObjectMeta{
69+
Name: "output2",
70+
Namespace: "test-ns",
71+
},
72+
Spec: v1alpha1.OutputSpec{
73+
File: &v1alpha1.File{
74+
Path: "/var/log/telemetry.log",
75+
Append: true,
76+
},
77+
},
78+
},
79+
},
80+
},
81+
},
82+
expectedResult: map[string]any{
83+
"file/test-ns_output2": map[string]any{
84+
"path": "/var/log/telemetry.log",
85+
"append": true,
86+
},
87+
},
88+
},
89+
{
90+
name: "File exporter with rotation settings",
91+
resourceRelations: components.ResourceRelations{
92+
OutputsWithSecretData: []components.OutputWithSecretData{
93+
{
94+
Output: v1alpha1.Output{
95+
ObjectMeta: metav1.ObjectMeta{
96+
Name: "output3",
97+
Namespace: "default",
98+
},
99+
Spec: v1alpha1.OutputSpec{
100+
File: &v1alpha1.File{
101+
Path: "/tmp/rotating.log",
102+
Rotation: &v1alpha1.Rotation{
103+
MaxMegabytes: 100,
104+
MaxDays: 7,
105+
MaxBackups: 5,
106+
LocalTime: utils.ToPtr(true),
107+
},
108+
},
109+
},
110+
},
111+
},
112+
},
113+
},
114+
expectedResult: map[string]any{
115+
"file/default_output3": map[string]any{
116+
"path": "/tmp/rotating.log",
117+
"rotation": map[string]any{
118+
"max_megabytes": float64(100),
119+
"max_days": float64(7),
120+
"max_backups": float64(5),
121+
"localtime": true,
122+
},
123+
},
124+
},
125+
},
126+
{
127+
name: "File exporter with format type and compression",
128+
resourceRelations: components.ResourceRelations{
129+
OutputsWithSecretData: []components.OutputWithSecretData{
130+
{
131+
Output: v1alpha1.Output{
132+
ObjectMeta: metav1.ObjectMeta{
133+
Name: "output4",
134+
Namespace: "default",
135+
},
136+
Spec: v1alpha1.OutputSpec{
137+
File: &v1alpha1.File{
138+
Path: "/tmp/logs.proto",
139+
FormatType: "proto",
140+
Compression: "zstd",
141+
},
142+
},
143+
},
144+
},
145+
},
146+
},
147+
expectedResult: map[string]any{
148+
"file/default_output4": map[string]any{
149+
"path": "/tmp/logs.proto",
150+
"format": "proto",
151+
"compression": "zstd",
152+
},
153+
},
154+
},
155+
{
156+
name: "File exporter with flush interval",
157+
resourceRelations: components.ResourceRelations{
158+
OutputsWithSecretData: []components.OutputWithSecretData{
159+
{
160+
Output: v1alpha1.Output{
161+
ObjectMeta: metav1.ObjectMeta{
162+
Name: "output5",
163+
Namespace: "default",
164+
},
165+
Spec: v1alpha1.OutputSpec{
166+
File: &v1alpha1.File{
167+
Path: "/tmp/logs.json",
168+
FlushInterval: 5 * time.Second,
169+
},
170+
},
171+
},
172+
},
173+
},
174+
},
175+
expectedResult: map[string]any{
176+
"file/default_output5": map[string]any{
177+
"path": "/tmp/logs.json",
178+
"flush_interval": float64(5 * time.Second),
179+
},
180+
},
181+
},
182+
{
183+
name: "File exporter with group by settings",
184+
resourceRelations: components.ResourceRelations{
185+
OutputsWithSecretData: []components.OutputWithSecretData{
186+
{
187+
Output: v1alpha1.Output{
188+
ObjectMeta: metav1.ObjectMeta{
189+
Name: "output6",
190+
Namespace: "default",
191+
},
192+
Spec: v1alpha1.OutputSpec{
193+
File: &v1alpha1.File{
194+
Path: "/tmp/logs/*.json",
195+
GroupBy: &v1alpha1.GroupBy{
196+
Enabled: true,
197+
ResourceAttribute: "service.name",
198+
MaxOpenFiles: 50,
199+
},
200+
},
201+
},
202+
},
203+
},
204+
},
205+
},
206+
expectedResult: map[string]any{
207+
"file/default_output6": map[string]any{
208+
"path": "/tmp/logs/*.json",
209+
"group_by": map[string]any{
210+
"enabled": true,
211+
"resource_attribute": "service.name",
212+
"max_open_files": float64(50),
213+
},
214+
},
215+
},
216+
},
217+
{
218+
name: "File exporter with custom encoding",
219+
resourceRelations: components.ResourceRelations{
220+
OutputsWithSecretData: []components.OutputWithSecretData{
221+
{
222+
Output: v1alpha1.Output{
223+
ObjectMeta: metav1.ObjectMeta{
224+
Name: "output7",
225+
Namespace: "default",
226+
},
227+
Spec: v1alpha1.OutputSpec{
228+
File: &v1alpha1.File{
229+
Path: "/tmp/logs.txt",
230+
Encoding: utils.ToPtr(component.MustNewID("json")),
231+
},
232+
},
233+
},
234+
},
235+
},
236+
},
237+
expectedResult: map[string]any{
238+
"file/default_output7": map[string]any{
239+
"path": "/tmp/logs.txt",
240+
"encoding": "json",
241+
},
242+
},
243+
},
244+
{
245+
name: "File exporter with all options",
246+
resourceRelations: components.ResourceRelations{
247+
OutputsWithSecretData: []components.OutputWithSecretData{
248+
{
249+
Output: v1alpha1.Output{
250+
ObjectMeta: metav1.ObjectMeta{
251+
Name: "output-all",
252+
Namespace: "prod",
253+
},
254+
Spec: v1alpha1.OutputSpec{
255+
File: &v1alpha1.File{
256+
Path: "/var/log/telemetry/output.json",
257+
Append: true,
258+
FormatType: "json",
259+
Compression: "zstd",
260+
FlushInterval: 10 * time.Second,
261+
Rotation: &v1alpha1.Rotation{
262+
MaxMegabytes: 200,
263+
MaxDays: 14,
264+
MaxBackups: 10,
265+
LocalTime: utils.ToPtr(false),
266+
},
267+
},
268+
},
269+
},
270+
},
271+
},
272+
},
273+
expectedResult: map[string]any{
274+
"file/prod_output-all": map[string]any{
275+
"path": "/var/log/telemetry/output.json",
276+
"append": true,
277+
"format": "json",
278+
"compression": "zstd",
279+
"flush_interval": float64(10 * time.Second),
280+
"rotation": map[string]any{
281+
"max_megabytes": float64(200),
282+
"max_days": float64(14),
283+
"max_backups": float64(10),
284+
"localtime": false,
285+
},
286+
},
287+
},
288+
},
289+
{
290+
name: "Multiple file exporters",
291+
resourceRelations: components.ResourceRelations{
292+
OutputsWithSecretData: []components.OutputWithSecretData{
293+
{
294+
Output: v1alpha1.Output{
295+
ObjectMeta: metav1.ObjectMeta{
296+
Name: "output1",
297+
Namespace: "ns1",
298+
},
299+
Spec: v1alpha1.OutputSpec{
300+
File: &v1alpha1.File{
301+
Path: "/tmp/output1.json",
302+
},
303+
},
304+
},
305+
},
306+
{
307+
Output: v1alpha1.Output{
308+
ObjectMeta: metav1.ObjectMeta{
309+
Name: "output2",
310+
Namespace: "ns2",
311+
},
312+
Spec: v1alpha1.OutputSpec{
313+
File: &v1alpha1.File{
314+
Path: "/tmp/output2.log",
315+
Append: true,
316+
},
317+
},
318+
},
319+
},
320+
},
321+
},
322+
expectedResult: map[string]any{
323+
"file/ns1_output1": map[string]any{
324+
"path": "/tmp/output1.json",
325+
},
326+
"file/ns2_output2": map[string]any{
327+
"path": "/tmp/output2.log",
328+
"append": true,
329+
},
330+
},
331+
},
332+
{
333+
name: "No file exporters",
334+
resourceRelations: components.ResourceRelations{
335+
OutputsWithSecretData: []components.OutputWithSecretData{
336+
{
337+
Output: v1alpha1.Output{
338+
ObjectMeta: metav1.ObjectMeta{
339+
Name: "output1",
340+
Namespace: "default",
341+
},
342+
Spec: v1alpha1.OutputSpec{
343+
OTLPGRPC: &v1alpha1.OTLPGRPC{
344+
GRPCClientConfig: v1alpha1.GRPCClientConfig{
345+
Endpoint: utils.ToPtr("http://example.com"),
346+
},
347+
},
348+
},
349+
},
350+
},
351+
},
352+
},
353+
expectedResult: map[string]any{},
354+
},
355+
}
356+
357+
for _, tt := range tests {
358+
ttp := tt
359+
t.Run(ttp.name, func(t *testing.T) {
360+
assert.Equal(t, ttp.expectedResult, GenerateFileExporter(context.TODO(), ttp.resourceRelations))
361+
})
362+
}
363+
}

0 commit comments

Comments
 (0)