Skip to content

Commit 8802361

Browse files
authored
Merge branch 'main' into add-beholder-v2-auth-header-func
2 parents ceb9056 + 20bf958 commit 8802361

File tree

4 files changed

+130
-18
lines changed

4 files changed

+130
-18
lines changed

observability-lib/grafana/panels.go

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -202,14 +202,15 @@ func setDefaults(options *PanelOptions) {
202202

203203
type StatPanelOptions struct {
204204
*PanelOptions
205-
TextSize float64
206-
ValueSize float64
207-
JustifyMode common.BigValueJustifyMode
208-
ColorMode common.BigValueColorMode
209-
GraphMode common.BigValueGraphMode
210-
TextMode common.BigValueTextMode
211-
Orientation common.VizOrientation
212-
Mappings []dashboard.ValueMapping
205+
TextSize float64
206+
ValueSize float64
207+
JustifyMode common.BigValueJustifyMode
208+
ColorMode common.BigValueColorMode
209+
GraphMode common.BigValueGraphMode
210+
TextMode common.BigValueTextMode
211+
Orientation common.VizOrientation
212+
Mappings []dashboard.ValueMapping
213+
ReduceOptions *common.ReduceDataOptionsBuilder
213214
}
214215

215216
func NewStatPanel(options *StatPanelOptions) *Panel {
@@ -231,6 +232,10 @@ func NewStatPanel(options *StatPanelOptions) *Panel {
231232
options.Orientation = common.VizOrientationAuto
232233
}
233234

235+
if options.ReduceOptions == nil {
236+
options.ReduceOptions = common.NewReduceDataOptionsBuilder().Calcs([]string{"last"})
237+
}
238+
234239
newPanel := stat.NewPanelBuilder().
235240
Datasource(datasourceRef(options.Datasource)).
236241
Title(*options.Title).
@@ -247,7 +252,7 @@ func NewStatPanel(options *StatPanelOptions) *Panel {
247252
Orientation(options.Orientation).
248253
JustifyMode(options.JustifyMode).
249254
Mappings(options.Mappings).
250-
ReduceOptions(common.NewReduceDataOptionsBuilder().Calcs([]string{"last"}))
255+
ReduceOptions(options.ReduceOptions)
251256

252257
if options.Interval != "" {
253258
newPanel.Interval(options.Interval)

pkg/logger/otelzap/otelzap.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,13 @@ func (o OtelZapCore) Write(entry zapcore.Entry, fields []zapcore.Field) error {
105105
// Start with encoder attributes
106106
attributes := encoder.attributes
107107

108-
// Add exception metadata
108+
// Add caller information if available
109+
if entry.Caller.Defined {
110+
attributes = append(attributes, attribute.String("caller", entry.Caller.String()))
111+
}
112+
113+
// Add exception metadata for error levels
109114
if entry.Level > zapcore.InfoLevel {
110-
if entry.Caller.Defined {
111-
attributes = append(attributes, semconv.ExceptionType(entry.Caller.String()))
112-
}
113115
if entry.Stack != "" {
114116
attributes = append(attributes, semconv.ExceptionStacktrace(entry.Stack))
115117
}

pkg/logger/otelzap/otelzap_test.go

Lines changed: 105 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package otelzap
22

33
import (
44
"bytes"
5+
"context"
56
"encoding/json"
67
"errors"
8+
"fmt"
79
"math"
810
"testing"
911
"time"
@@ -228,7 +230,7 @@ func TestOtelZapCore_Write(t *testing.T) {
228230
wantMessage: "fail",
229231
wantAttrs: map[string]string{
230232
"err": "fail",
231-
"exception.type": "file.go:42",
233+
"caller": "file.go:42",
232234
"exception.stacktrace": "stacktrace",
233235
},
234236
},
@@ -490,3 +492,105 @@ func (t *testMixedArray) MarshalLogArray(enc zapcore.ArrayEncoder) error {
490492
}
491493
return nil
492494
}
495+
496+
func TestCallerInfo(t *testing.T) {
497+
// Setup OTEL exporter
498+
var buf bytes.Buffer
499+
exporter, err := stdoutlog.New(stdoutlog.WithWriter(&buf))
500+
require.NoError(t, err)
501+
502+
// Setup OTEL provider
503+
provider := sdklog.NewLoggerProvider(sdklog.WithProcessor(sdklog.NewBatchProcessor(exporter)))
504+
505+
// Create otel zap core
506+
logger := provider.Logger("test")
507+
core := NewCore(logger)
508+
509+
tests := []struct {
510+
name string
511+
level zapcore.Level
512+
caller zapcore.EntryCaller
513+
wantCaller bool
514+
}{
515+
{
516+
name: "info with caller",
517+
level: zapcore.InfoLevel,
518+
caller: zapcore.EntryCaller{Defined: true, File: "test.go", Line: 123, Function: "TestFunc"},
519+
wantCaller: true,
520+
},
521+
{
522+
name: "error with caller",
523+
level: zapcore.ErrorLevel,
524+
caller: zapcore.EntryCaller{Defined: true, File: "error.go", Line: 456, Function: "ErrorFunc"},
525+
wantCaller: true,
526+
},
527+
{
528+
name: "debug without caller",
529+
level: zapcore.DebugLevel,
530+
caller: zapcore.EntryCaller{Defined: false},
531+
wantCaller: false,
532+
},
533+
}
534+
535+
for _, tt := range tests {
536+
t.Run(tt.name, func(t *testing.T) {
537+
buf.Reset()
538+
539+
entry := zapcore.Entry{
540+
Message: "test message",
541+
Level: tt.level,
542+
Time: time.Now(),
543+
Caller: tt.caller,
544+
}
545+
546+
err := core.Write(entry, nil)
547+
require.NoError(t, err)
548+
549+
// Force flush
550+
require.NoError(t, provider.ForceFlush(context.Background()))
551+
552+
if !tt.wantCaller {
553+
// If no caller expected, we just check that no caller attributes exist
554+
var logEntry struct {
555+
Attributes []struct {
556+
Key string `json:"key"`
557+
Value struct {
558+
Value interface{} `json:"value"`
559+
} `json:"value"`
560+
} `json:"attributes"`
561+
}
562+
err = json.Unmarshal(buf.Bytes(), &logEntry)
563+
require.NoError(t, err)
564+
565+
for _, attr := range logEntry.Attributes {
566+
assert.NotContains(t, []string{"caller", "source.file", "source.line", "source.function"}, attr.Key)
567+
}
568+
return
569+
}
570+
571+
// Parse JSON output and check for caller attributes
572+
var logEntry struct {
573+
Attributes []struct {
574+
Key string `json:"key"`
575+
Value struct {
576+
Value string `json:"value"`
577+
} `json:"value"`
578+
} `json:"attributes"`
579+
}
580+
err = json.Unmarshal(buf.Bytes(), &logEntry)
581+
require.NoError(t, err, "failed to parse OTEL JSON log output")
582+
583+
got := map[string]string{}
584+
for _, attr := range logEntry.Attributes {
585+
got[attr.Key] = attr.Value.Value
586+
}
587+
588+
// Check required caller attributes
589+
assert.Contains(t, got, "caller")
590+
591+
expectedCaller := fmt.Sprintf("%s:%d", tt.caller.File, tt.caller.Line)
592+
assert.Equal(t, expectedCaller, fmt.Sprintf("%v", got["caller"]))
593+
594+
})
595+
}
596+
}

pkg/nodeauth/jwt/node_jwt_authenticator.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package jwt
33
import (
44
"context"
55
"crypto/ed25519"
6+
"encoding/hex"
67
"fmt"
78
"log/slog"
89

@@ -62,21 +63,21 @@ func (v *NodeJWTAuthenticator) AuthenticateJWT(ctx context.Context, tokenString
6263
isValid, err := v.nodeAuthProvider.IsNodePubKeyTrusted(ctx, publicKey)
6364
if err != nil {
6465
v.logger.Error("Node validation failed",
65-
"csaPubKey", publicKey,
66+
"csaPubKey", hex.EncodeToString(publicKey),
6667
"error", err,
6768
)
6869
return false, claims, fmt.Errorf("node validation failed: %w", err)
6970
}
7071

7172
if !isValid {
7273
v.logger.Warn("Unauthorized node attempted access",
73-
"csaPubKey", publicKey,
74+
"csaPubKey", hex.EncodeToString(publicKey),
7475
)
75-
return false, claims, fmt.Errorf("unauthorized node: %s", publicKey)
76+
return false, claims, fmt.Errorf("unauthorized node: %s", hex.EncodeToString(publicKey))
7677
}
7778

7879
v.logger.Debug("JWT validation successful",
79-
"csaPubKey", publicKey,
80+
"csaPubKey", hex.EncodeToString(publicKey),
8081
)
8182

8283
return true, claims, nil

0 commit comments

Comments
 (0)