mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-02-05 07:37:02 +01:00
log OTEL internal logs
This commit is contained in:
parent
865b3aeaac
commit
25b59e74ca
4 changed files with 169 additions and 1 deletions
2
go.mod
2
go.mod
|
@ -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
|
||||||
|
|
|
@ -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
69
internal/log/log_test.go
Normal 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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -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":
|
||||||
|
|
Loading…
Reference in a new issue