mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 02:02:25 -05: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 @@ package log | ||||||
| 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…
	
	Add table
		Add a link
		
	
		Reference in a new issue