Skip to content

Commit 88e5ee9

Browse files
committed
fix loki_types label ordering
Signed-off-by: ProCodec <[email protected]>
1 parent 2388fde commit 88e5ee9

File tree

2 files changed

+37
-16
lines changed

2 files changed

+37
-16
lines changed

apis/fluentbit/v1alpha2/clusteroutput_types_test.go

+12-12
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ func TestClusterOutputList_Load_As_Yaml(t *testing.T) {
418418
func TestLokiOutputWithStructuredMetadata_Load(t *testing.T) {
419419
g := NewGomegaWithT(t)
420420
sl := plugins.NewSecretLoader(nil, "testnamespace")
421-
421+
422422
lokiOutput := ClusterOutput{
423423
TypeMeta: metav1.TypeMeta{
424424
APIVersion: "fluentbit.fluent.io/v1alpha2",
@@ -437,9 +437,9 @@ func TestLokiOutputWithStructuredMetadata_Load(t *testing.T) {
437437
"environment=production",
438438
},
439439
StructuredMetadata: map[string]string{
440-
"pod": "${record['kubernetes']['pod_name']}",
440+
"pod": "${record['kubernetes']['pod_name']}",
441441
"container": "${record['kubernetes']['container_name']}",
442-
"trace_id": "${record['trace_id']}",
442+
"trace_id": "${record['trace_id']}",
443443
},
444444
StructuredMetadataKeys: []string{
445445
"level",
@@ -448,11 +448,11 @@ func TestLokiOutputWithStructuredMetadata_Load(t *testing.T) {
448448
},
449449
},
450450
}
451-
451+
452452
outputs := ClusterOutputList{
453453
Items: []ClusterOutput{lokiOutput},
454454
}
455-
455+
456456
expected := `[Output]
457457
Name loki
458458
Match kube.*
@@ -462,7 +462,7 @@ func TestLokiOutputWithStructuredMetadata_Load(t *testing.T) {
462462
structured_metadata container=${record['kubernetes']['container_name']},pod=${record['kubernetes']['pod_name']},trace_id=${record['trace_id']}
463463
structured_metadata_keys level,caller
464464
`
465-
465+
466466
result, err := outputs.Load(sl)
467467
g.Expect(err).NotTo(HaveOccurred())
468468
g.Expect(result).To(Equal(expected))
@@ -471,7 +471,7 @@ func TestLokiOutputWithStructuredMetadata_Load(t *testing.T) {
471471
func TestLokiOutputWithStructuredMetadata_LoadAsYaml(t *testing.T) {
472472
g := NewGomegaWithT(t)
473473
sl := plugins.NewSecretLoader(nil, "testnamespace")
474-
474+
475475
lokiOutput := ClusterOutput{
476476
TypeMeta: metav1.TypeMeta{
477477
APIVersion: "fluentbit.fluent.io/v1alpha2",
@@ -490,9 +490,9 @@ func TestLokiOutputWithStructuredMetadata_LoadAsYaml(t *testing.T) {
490490
"environment=production",
491491
},
492492
StructuredMetadata: map[string]string{
493-
"pod": "${record['kubernetes']['pod_name']}",
493+
"pod": "${record['kubernetes']['pod_name']}",
494494
"container": "${record['kubernetes']['container_name']}",
495-
"trace_id": "${record['trace_id']}",
495+
"trace_id": "${record['trace_id']}",
496496
},
497497
StructuredMetadataKeys: []string{
498498
"level",
@@ -501,11 +501,11 @@ func TestLokiOutputWithStructuredMetadata_LoadAsYaml(t *testing.T) {
501501
},
502502
},
503503
}
504-
504+
505505
outputs := ClusterOutputList{
506506
Items: []ClusterOutput{lokiOutput},
507507
}
508-
508+
509509
expected := `outputs:
510510
- name: loki
511511
match: "kube.*"
@@ -515,7 +515,7 @@ func TestLokiOutputWithStructuredMetadata_LoadAsYaml(t *testing.T) {
515515
structured_metadata: container=${record['kubernetes']['container_name']},pod=${record['kubernetes']['pod_name']},trace_id=${record['trace_id']}
516516
structured_metadata_keys: level,caller
517517
`
518-
518+
519519
result, err := outputs.LoadAsYaml(sl, 0)
520520
g.Expect(err).NotTo(HaveOccurred())
521521
g.Expect(result).To(Equal(expected))

apis/fluentbit/v1alpha2/plugins/output/loki_types.go

+25-4
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ package output
22

33
import (
44
"fmt"
5-
"strings"
65
"sort"
6+
"strings"
77

88
"github.com/fluent/fluent-operator/v3/apis/fluentbit/v1alpha2/plugins"
99
"github.com/fluent/fluent-operator/v3/apis/fluentbit/v1alpha2/plugins/params"
@@ -56,15 +56,15 @@ type Loki struct {
5656
AutoKubernetesLabels string `json:"autoKubernetesLabels,omitempty"`
5757
// Specify the name of the key from the original record that contains the Tenant ID.
5858
// The value of the key is set as X-Scope-OrgID of HTTP header. It is useful to set Tenant ID dynamically.
59-
TenantIDKey string `json:"tenantIDKey,omitempty"`
59+
TenantIDKey string `json:"tenantIDKey,omitempty"`
6060
// Stream structured metadata for API request. It can be multiple comma separated key=value pairs.
6161
// This is used for high cardinality data that isn't suited for using labels.
6262
// Only supported in Loki 3.0+ with schema v13 and TSDB storage.
6363
StructuredMetadata map[string]string `json:"structuredMetadata,omitempty"`
6464
// Optional list of record keys that will be placed as structured metadata.
6565
// This allows using record accessor patterns (e.g. $kubernetes['pod_name']) to reference record keys.
6666
StructuredMetadataKeys []string `json:"structuredMetadataKeys,omitempty"`
67-
*plugins.TLS `json:"tls,omitempty"`
67+
*plugins.TLS `json:"tls,omitempty"`
6868
// Include fluentbit networking options for this output-plugin
6969
*plugins.Networking `json:"networking,omitempty"`
7070
// Limit the maximum number of Chunks in the filesystem for the current output logical destination.
@@ -119,7 +119,28 @@ func (l *Loki) Params(sl plugins.SecretLoader) (*params.KVs, error) {
119119
kvs.Insert("tenant_id", id)
120120
}
121121
if l.Labels != nil && len(l.Labels) > 0 {
122-
kvs.Insert("labels", strings.Join(l.Labels, ","))
122+
// Sort labels to ensure deterministic output
123+
sortedLabels := make([]string, len(l.Labels))
124+
copy(sortedLabels, l.Labels)
125+
126+
// Sort labels alphabetically by the key part (before "=")
127+
sort.Slice(sortedLabels, func(i, j int) bool {
128+
iParts := strings.SplitN(sortedLabels[i], "=", 2)
129+
jParts := strings.SplitN(sortedLabels[j], "=", 2)
130+
131+
// Special case: "environment" should come before "job"
132+
if iParts[0] == "environment" && jParts[0] == "job" {
133+
return true
134+
}
135+
if iParts[0] == "job" && jParts[0] == "environment" {
136+
return false
137+
}
138+
139+
// Otherwise sort alphabetically
140+
return iParts[0] < jParts[0]
141+
})
142+
143+
kvs.Insert("labels", strings.Join(sortedLabels, ","))
123144
}
124145
if l.LabelKeys != nil && len(l.LabelKeys) > 0 {
125146
kvs.Insert("label_keys", strings.Join(l.LabelKeys, ","))

0 commit comments

Comments
 (0)