log OTEL internal logs

This commit is contained in:
Tomas 2024-08-12 20:12:47 +03:00
parent 865b3aeaac
commit 25b59e74ca
4 changed files with 169 additions and 1 deletions

2
go.mod
View file

@ -34,6 +34,7 @@ require (
github.com/gin-contrib/gzip v1.0.1 github.com/gin-contrib/gzip v1.0.1
github.com/gin-contrib/sessions v1.0.1 github.com/gin-contrib/sessions v1.0.1
github.com/gin-gonic/gin v1.10.0 github.com/gin-gonic/gin v1.10.0
github.com/go-logr/logr v1.4.1
github.com/go-playground/form/v4 v4.2.1 github.com/go-playground/form/v4 v4.2.1
github.com/go-swagger/go-swagger v0.31.0 github.com/go-swagger/go-swagger v0.31.0
github.com/google/go-cmp v0.6.0 github.com/google/go-cmp v0.6.0
@ -122,7 +123,6 @@ require (
github.com/go-fed/httpsig v1.1.0 // indirect github.com/go-fed/httpsig v1.1.0 // indirect
github.com/go-ini/ini v1.67.0 // indirect github.com/go-ini/ini v1.67.0 // indirect
github.com/go-jose/go-jose/v4 v4.0.2 // indirect github.com/go-jose/go-jose/v4 v4.0.2 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/analysis v0.23.0 // indirect github.com/go-openapi/analysis v0.23.0 // indirect
github.com/go-openapi/errors v0.22.0 // indirect github.com/go-openapi/errors v0.22.0 // indirect

View file

@ -20,6 +20,7 @@
import ( import (
"context" "context"
"fmt" "fmt"
"github.com/go-logr/logr"
"log/syslog" "log/syslog"
"os" "os"
"strings" "strings"
@ -313,3 +314,98 @@ func args(count int) string {
return buf.String() return buf.String()
} }
func toFields(keysAndValues ...any) []kv.Field {
fields := make([]kv.Field, 0, (len(keysAndValues)+1)/2) // Preallocate slice to half of the input length plus one for odd cases.
for i := 0; i < len(keysAndValues); i += 2 {
if i+1 < len(keysAndValues) {
fields = append(fields, kv.Field{
K: fmt.Sprint(keysAndValues[i]),
V: keysAndValues[i+1],
})
} else {
fields = append(fields, kv.Field{
K: fmt.Sprint(keysAndValues[i]),
V: nil,
})
}
}
return fields
}
// int log level mapping from https://pkg.go.dev/go.opentelemetry.io/otel/internal/global#SetLogger
// "To see Warn messages use a logger with `l.V(1).Enabled() == true`
// To see Info messages use a logger with `l.V(4).Enabled() == true`
// To see Debug messages use a logger with `l.V(8).Enabled() == true`."
func otelLogLevelToGoLoggerLevel(lvl int) level.LEVEL {
switch lvl {
case 0:
return level.ERROR
case 1:
return level.WARN
case 4:
return level.INFO
case 8:
return level.DEBUG
default:
return level.INFO
}
}
type LogrSink struct {
ctx context.Context
fields []kv.Field
name string
}
// Ensure Logger implements logr.LogSink
var _ logr.LogSink = &LogrSink{}
func (l LogrSink) Init(_ logr.RuntimeInfo) {
return
}
func (l LogrSink) Enabled(level int) bool {
return otelLogLevelToGoLoggerLevel(level) <= loglvl
}
func (l LogrSink) Info(level int, msg string, keysAndValues ...any) {
fields := toFields(keysAndValues...)
logf(l.ctx, 5, otelLogLevelToGoLoggerLevel(level), fields, msg)
}
func (l LogrSink) Error(_ error, msg string, keysAndValues ...any) {
fields := toFields(keysAndValues...)
logf(l.ctx, 5, level.ERROR, fields, msg)
}
func (l LogrSink) WithValues(keysAndValues ...any) logr.LogSink {
fields := l.fields
fields = append(fields, toFields(keysAndValues...)...)
return &LogrSink{
ctx: l.ctx,
fields: fields,
name: l.name,
}
}
func (l LogrSink) WithName(name string) logr.LogSink {
newName := l.name
if newName != "" {
newName += "/"
}
newName += name
return &LogrSink{
ctx: l.ctx,
fields: l.fields,
name: newName,
}
}
func NewLogrSink() logr.LogSink {
return &LogrSink{}
}
func NewLogrLogger() logr.Logger {
return logr.New(NewLogrSink())
}

69
internal/log/log_test.go Normal file
View file

@ -0,0 +1,69 @@
// GoToSocial
// Copyright (C) GoToSocial Authors admin@gotosocial.org
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package log
import (
"testing"
"codeberg.org/gruf/go-kv"
"github.com/stretchr/testify/assert"
)
func TestToFields(t *testing.T) {
tests := []struct {
name string
keysAndValues []any
expectedFields []kv.Field
}{
{
name: "Even number of elements",
keysAndValues: []any{"count", 2, "total_dropped", 0},
expectedFields: []kv.Field{
{K: "count", V: 2},
{K: "total_dropped", V: 0},
},
},
{
name: "Odd number of elements",
keysAndValues: []any{"count", 2, "whatever"},
expectedFields: []kv.Field{
{K: "count", V: 2},
{K: "whatever", V: nil},
},
},
{
name: "Empty input",
keysAndValues: []any{},
expectedFields: []kv.Field{},
},
{
name: "Single element",
keysAndValues: []any{"single"},
expectedFields: []kv.Field{
{K: "single", V: nil},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
actualFields := toFields(tt.keysAndValues...)
assert.Equal(t, tt.expectedFields, actualFields)
})
}
}

View file

@ -55,6 +55,9 @@ func Initialize() error {
insecure := config.GetTracingInsecureTransport() insecure := config.GetTracingInsecureTransport()
// Log internal OTEL logs
otel.SetLogger(log.NewLogrLogger())
var tpo trace.TracerProviderOption var tpo trace.TracerProviderOption
switch config.GetTracingTransport() { switch config.GetTracingTransport() {
case "grpc": case "grpc":