| 
									
										
										
										
											2023-03-12 16:00:57 +01:00
										 |  |  | // 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/>. | 
					
						
							| 
									
										
										
										
											2021-03-03 18:12:02 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | package log | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2021-12-12 18:00:20 +01:00
										 |  |  | 	"log/syslog" | 
					
						
							| 
									
										
										
										
											2022-05-07 16:46:59 +01:00
										 |  |  | 	"os" | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | 	"slices" | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 	"strings" | 
					
						
							|  |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2021-12-12 18:00:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 	"codeberg.org/gruf/go-kv" | 
					
						
							| 
									
										
										
										
											2021-03-03 18:12:02 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | var ( | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	// loglvl is the currently | 
					
						
							|  |  |  | 	// set logging output | 
					
						
							|  |  |  | 	loglvl LEVEL | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// lvlstrs is the lookup table | 
					
						
							|  |  |  | 	// of all log levels to strings. | 
					
						
							|  |  |  | 	lvlstrs = [int(ALL) + 1]string{ | 
					
						
							|  |  |  | 		TRACE: "TRACE", | 
					
						
							|  |  |  | 		DEBUG: "DEBUG", | 
					
						
							|  |  |  | 		INFO:  "INFO", | 
					
						
							|  |  |  | 		WARN:  "WARN", | 
					
						
							|  |  |  | 		ERROR: "ERROR", | 
					
						
							|  |  |  | 		PANIC: "PANIC", | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | 	// syslog output, only set if enabled. | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 	sysout *syslog.Writer | 
					
						
							| 
									
										
										
										
											2022-10-01 16:36:08 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-21 20:07:55 +02:00
										 |  |  | 	// timefmt is the logging time format used, which includes | 
					
						
							|  |  |  | 	// the full field and required quoting | 
					
						
							|  |  |  | 	timefmt = `timestamp="02/01/2006 15:04:05.000" ` | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// ctxhooks allows modifying log content based on context. | 
					
						
							|  |  |  | 	ctxhooks []func(context.Context, []kv.Field) []kv.Field | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | // Hook adds the given hook to the global logger context hooks stack. | 
					
						
							|  |  |  | func Hook(hook func(ctx context.Context, kvs []kv.Field) []kv.Field) { | 
					
						
							|  |  |  | 	ctxhooks = append(ctxhooks, hook) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // Level returns the currently set log | 
					
						
							|  |  |  | func Level() LEVEL { | 
					
						
							| 
									
										
										
										
											2023-08-21 20:07:55 +02:00
										 |  |  | 	return loglvl | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // SetLevel sets the max logging | 
					
						
							|  |  |  | func SetLevel(lvl LEVEL) { | 
					
						
							| 
									
										
										
										
											2023-08-21 20:07:55 +02:00
										 |  |  | 	loglvl = lvl | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TimeFormat returns the currently-set timestamp format. | 
					
						
							|  |  |  | func TimeFormat() string { | 
					
						
							|  |  |  | 	return timefmt | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // SetTimeFormat sets the timestamp format to the given string. | 
					
						
							|  |  |  | func SetTimeFormat(format string) { | 
					
						
							|  |  |  | 	if format == "" { | 
					
						
							|  |  |  | 		timefmt = format | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	timefmt = `timestamp="` + format + `" ` | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-01 16:36:08 +01:00
										 |  |  | // New starts a new log entry. | 
					
						
							|  |  |  | func New() Entry { | 
					
						
							|  |  |  | 	return Entry{} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // WithContext returns a new prepared Entry{} with context. | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | func WithContext(ctx context.Context) Entry { | 
					
						
							|  |  |  | 	return Entry{ctx: ctx} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // WithField returns a new prepared Entry{} with key-value field. | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | func WithField(key string, value interface{}) Entry { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	return Entry{kvs: []kv.Field{{K: key, V: value}}} | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // WithFields returns a new prepared Entry{} with key-value fields. | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | func WithFields(fields ...kv.Field) Entry { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	return Entry{kvs: fields} | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // Note that most of the below logging | 
					
						
							|  |  |  | // functions we specifically do NOT allow | 
					
						
							|  |  |  | // the Go buildchain to inline, to ensure | 
					
						
							|  |  |  | // expected behaviour in caller fetching. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Trace will log formatted args as 'msg' field to the log at TRACE level. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | func Trace(ctx context.Context, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	logf(ctx, 3, TRACE, nil, args(len(a)), a...) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // Tracef will log format string as 'msg' field to the log at TRACE level. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | func Tracef(ctx context.Context, s string, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	logf(ctx, 3, TRACE, nil, s, a...) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // TraceKV will log the one key-value field to the log at TRACE level. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | func TraceKV(ctx context.Context, key string, value interface{}) { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	logf(ctx, 3, TRACE, []kv.Field{{K: key, V: value}}, "") | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // TraceKVs will log key-value fields to the log at TRACE level. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | func TraceKVs(ctx context.Context, kvs ...kv.Field) { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	logf(ctx, 3, TRACE, kvs, "") | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // Debug will log formatted args as 'msg' field to the log at DEBUG level. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | func Debug(ctx context.Context, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	logf(ctx, 3, DEBUG, nil, args(len(a)), a...) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // Debugf will log format string as 'msg' field to the log at DEBUG level. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | func Debugf(ctx context.Context, s string, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	logf(ctx, 3, DEBUG, nil, s, a...) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // DebugKV will log the one key-value field to the log at DEBUG level. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | func DebugKV(ctx context.Context, key string, value interface{}) { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	logf(ctx, 3, DEBUG, []kv.Field{{K: key, V: value}}, "") | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // DebugKVs will log key-value fields to the log at DEBUG level. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | func DebugKVs(ctx context.Context, kvs ...kv.Field) { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	logf(ctx, 3, DEBUG, kvs, "") | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // Info will log formatted args as 'msg' field to the log at INFO level. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | func Info(ctx context.Context, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	logf(ctx, 3, INFO, nil, args(len(a)), a...) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // Infof will log format string as 'msg' field to the log at INFO level. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | func Infof(ctx context.Context, s string, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	logf(ctx, 3, INFO, nil, s, a...) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // InfoKV will log the one key-value field to the log at INFO level. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | func InfoKV(ctx context.Context, key string, value interface{}) { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	logf(ctx, 3, INFO, []kv.Field{{K: key, V: value}}, "") | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // InfoKVs will log key-value fields to the log at INFO level. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | func InfoKVs(ctx context.Context, kvs ...kv.Field) { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	logf(ctx, 3, INFO, kvs, "") | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // Warn will log formatted args as 'msg' field to the log at WARN level. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | func Warn(ctx context.Context, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	logf(ctx, 3, WARN, nil, args(len(a)), a...) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // Warnf will log format string as 'msg' field to the log at WARN level. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | func Warnf(ctx context.Context, s string, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	logf(ctx, 3, WARN, nil, s, a...) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // WarnKV will log the one key-value field to the log at WARN level. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | func WarnKV(ctx context.Context, key string, value interface{}) { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	logf(ctx, 3, WARN, []kv.Field{{K: key, V: value}}, "") | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // WarnKVs will log key-value fields to the log at WARN level. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | func WarnKVs(ctx context.Context, kvs ...kv.Field) { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	logf(ctx, 3, WARN, kvs, "") | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // Error will log formatted args as 'msg' field to the log at ERROR level. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | func Error(ctx context.Context, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	logf(ctx, 3, ERROR, nil, args(len(a)), a...) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // Errorf will log format string as 'msg' field to the log at ERROR level. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | func Errorf(ctx context.Context, s string, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	logf(ctx, 3, ERROR, nil, s, a...) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // ErrorKV will log the one key-value field to the log at ERROR level. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | func ErrorKV(ctx context.Context, key string, value interface{}) { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	logf(ctx, 3, ERROR, []kv.Field{{K: key, V: value}}, "") | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // ErrorKVs will log key-value fields to the log at ERROR level. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | func ErrorKVs(ctx context.Context, kvs ...kv.Field) { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	logf(ctx, 3, ERROR, kvs, "") | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // Panic will log formatted args as 'msg' field to the log at PANIC level. | 
					
						
							|  |  |  | // This will then call panic causing the application to crash. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | func Panic(ctx context.Context, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 	defer panic(fmt.Sprint(a...)) | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	logf(ctx, 3, PANIC, nil, args(len(a)), a...) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // Panicf will log format string as 'msg' field to the log at PANIC level. | 
					
						
							|  |  |  | // This will then call panic causing the application to crash. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | func Panicf(ctx context.Context, s string, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 	defer panic(fmt.Sprintf(s, a...)) | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	logf(ctx, 3, PANIC, nil, s, a...) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // PanicKV will log the one key-value field to the log at PANIC level. | 
					
						
							|  |  |  | // This will then call panic causing the application to crash. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | func PanicKV(ctx context.Context, key string, value interface{}) { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	defer panic(kv.Field{K: key, V: value}.String()) | 
					
						
							|  |  |  | 	logf(ctx, 3, PANIC, []kv.Field{{K: key, V: value}}, "") | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // PanicKVs will log key-value fields to the log at PANIC level. | 
					
						
							|  |  |  | // This will then call panic causing the application to crash. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | func PanicKVs(ctx context.Context, kvs ...kv.Field) { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	defer panic(kv.Fields(kvs).String()) | 
					
						
							|  |  |  | 	logf(ctx, 3, PANIC, kvs, "") | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | // Log will log formatted args as 'msg' field to the log at given level. | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							|  |  |  | func Log(ctx context.Context, lvl LEVEL, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | 	logf(ctx, 3, lvl, nil, args(len(a)), a...) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Logf will log format string as 'msg' field to the log at given level. | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							|  |  |  | func Logf(ctx context.Context, lvl LEVEL, s string, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | 	logf(ctx, 3, lvl, nil, s, a...) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | // LogKV will log the one key-value field to the log at given level. | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							|  |  |  | func LogKV(ctx context.Context, lvl LEVEL, key string, value interface{}) { //nolint:revive | 
					
						
							|  |  |  | 	logf(ctx, 3, lvl, []kv.Field{{K: key, V: value}}, "") | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // LogKVs will log key-value fields to the log at given level. | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							|  |  |  | func LogKVs(ctx context.Context, lvl LEVEL, kvs ...kv.Field) { //nolint:revive | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | 	logf(ctx, 3, lvl, kvs, "") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | // Print will log formatted args to the stdout log output. | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | func Print(a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2022-10-01 16:36:08 +01:00
										 |  |  | 	printf(3, nil, args(len(a)), a...) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | // Printf will log format string to the stdout log output. | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | func Printf(s string, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2022-10-01 16:36:08 +01:00
										 |  |  | 	printf(3, nil, s, a...) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | // PrintKVs will log the one key-value field to the stdout log output. | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | func PrintKV(key string, value interface{}) { | 
					
						
							|  |  |  | 	printf(3, []kv.Field{{K: key, V: value}}, "") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // PrintKVs will log key-value fields to the stdout log output. | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | // | 
					
						
							|  |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | func PrintKVs(kvs ...kv.Field) { | 
					
						
							|  |  |  | 	printf(3, kvs, "") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2022-10-01 16:36:08 +01:00
										 |  |  | func printf(depth int, fields []kv.Field, s string, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 	// Acquire buffer | 
					
						
							|  |  |  | 	buf := getBuf() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-21 20:07:55 +02:00
										 |  |  | 	// Append formatted timestamp according to `timefmt` | 
					
						
							| 
									
										
										
										
											2022-10-01 16:36:08 +01:00
										 |  |  | 	buf.B = time.Now().AppendFormat(buf.B, timefmt) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Append formatted caller func | 
					
						
							|  |  |  | 	buf.B = append(buf.B, `func=`...) | 
					
						
							| 
									
										
										
										
											2022-10-01 16:36:08 +01:00
										 |  |  | 	buf.B = append(buf.B, Caller(depth+1)...) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 	buf.B = append(buf.B, ' ') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(fields) > 0 { | 
					
						
							|  |  |  | 		// Append formatted fields | 
					
						
							|  |  |  | 		kv.Fields(fields).AppendFormat(buf, false) | 
					
						
							|  |  |  | 		buf.B = append(buf.B, ' ') | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Append formatted args | 
					
						
							|  |  |  | 	fmt.Fprintf(buf, s, a...) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-01 16:36:08 +01:00
										 |  |  | 	if buf.B[len(buf.B)-1] != '\n' { | 
					
						
							|  |  |  | 		// Append a final newline | 
					
						
							|  |  |  | 		buf.B = append(buf.B, '\n') | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if sysout != nil { | 
					
						
							|  |  |  | 		// Write log entry to syslog | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 		logsys(INFO, buf.String()) | 
					
						
							| 
									
										
										
										
											2022-10-01 16:36:08 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Write to log and release | 
					
						
							| 
									
										
										
										
											2022-11-20 16:40:15 +00:00
										 |  |  | 	_, _ = os.Stdout.Write(buf.B) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 	putBuf(buf) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | //go:noinline | 
					
						
							|  |  |  | func logf(ctx context.Context, depth int, lvl LEVEL, fields []kv.Field, s string, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2022-11-20 16:40:15 +00:00
										 |  |  | 	var out *os.File | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Check if enabled. | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	if lvl > loglvl { | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 		return | 
					
						
							| 
									
										
										
										
											2021-12-12 18:00:20 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 	// Split errors to stderr, | 
					
						
							|  |  |  | 	// all else goes to stdout. | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	if lvl <= ERROR { | 
					
						
							| 
									
										
										
										
											2022-11-20 16:40:15 +00:00
										 |  |  | 		out = os.Stderr | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2022-11-20 16:40:15 +00:00
										 |  |  | 		out = os.Stdout | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Acquire buffer | 
					
						
							|  |  |  | 	buf := getBuf() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-21 20:07:55 +02:00
										 |  |  | 	// Append formatted timestamp according to `timefmt` | 
					
						
							| 
									
										
										
										
											2022-10-01 16:36:08 +01:00
										 |  |  | 	buf.B = time.Now().AppendFormat(buf.B, timefmt) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Append formatted caller func | 
					
						
							|  |  |  | 	buf.B = append(buf.B, `func=`...) | 
					
						
							| 
									
										
										
										
											2022-10-01 16:36:08 +01:00
										 |  |  | 	buf.B = append(buf.B, Caller(depth+1)...) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 	buf.B = append(buf.B, ' ') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Append formatted level string | 
					
						
							|  |  |  | 	buf.B = append(buf.B, `level=`...) | 
					
						
							|  |  |  | 	buf.B = append(buf.B, lvlstrs[lvl]...) | 
					
						
							|  |  |  | 	buf.B = append(buf.B, ' ') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | 	if ctx != nil { | 
					
						
							|  |  |  | 		// Pass context through hooks. | 
					
						
							|  |  |  | 		for _, hook := range ctxhooks { | 
					
						
							|  |  |  | 			fields = hook(ctx, fields) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | 	if s != "" { | 
					
						
							|  |  |  | 		// Append message to log fields. | 
					
						
							|  |  |  | 		fields = slices.Grow(fields, 1) | 
					
						
							|  |  |  | 		fields = append(fields, kv.Field{ | 
					
						
							|  |  |  | 			K: "msg", V: fmt.Sprintf(s, a...), | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Append formatted fields to log buffer. | 
					
						
							|  |  |  | 	kv.Fields(fields).AppendFormat(buf, false) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-01 16:36:08 +01:00
										 |  |  | 	if buf.B[len(buf.B)-1] != '\n' { | 
					
						
							|  |  |  | 		// Append a final newline | 
					
						
							|  |  |  | 		buf.B = append(buf.B, '\n') | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if sysout != nil { | 
					
						
							|  |  |  | 		// Write log entry to syslog | 
					
						
							|  |  |  | 		logsys(lvl, buf.String()) | 
					
						
							| 
									
										
										
										
											2021-12-12 18:00:20 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 	// Write to log and release | 
					
						
							|  |  |  | 	_, _ = out.Write(buf.B) | 
					
						
							|  |  |  | 	putBuf(buf) | 
					
						
							| 
									
										
										
										
											2021-03-03 18:12:02 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | // logsys will log given msg at given severity to the syslog. | 
					
						
							| 
									
										
										
										
											2022-10-01 16:36:08 +01:00
										 |  |  | // Max length: https://www.rfc-editor.org/rfc/rfc5424.html#section-6.1 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | func logsys(lvl LEVEL, msg string) { | 
					
						
							| 
									
										
										
										
											2022-10-01 16:36:08 +01:00
										 |  |  | 	if max := 2048; len(msg) > max { | 
					
						
							|  |  |  | 		// Truncate up to max | 
					
						
							|  |  |  | 		msg = msg[:max] | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	switch lvl { | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	case TRACE, DEBUG: | 
					
						
							| 
									
										
										
										
											2022-10-01 16:36:08 +01:00
										 |  |  | 		_ = sysout.Debug(msg) | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	case INFO: | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 		_ = sysout.Info(msg) | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	case WARN: | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 		_ = sysout.Warning(msg) | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	case ERROR: | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 		_ = sysout.Err(msg) | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 	case PANIC: | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 		_ = sysout.Crit(msg) | 
					
						
							| 
									
										
										
										
											2022-05-07 16:46:59 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | // args returns an args format string of format '%v' * count. | 
					
						
							|  |  |  | func args(count int) string { | 
					
						
							|  |  |  | 	const args = `%v%v%v%v%v%v%v%v%v%v` + | 
					
						
							|  |  |  | 		`%v%v%v%v%v%v%v%v%v%v` + | 
					
						
							|  |  |  | 		`%v%v%v%v%v%v%v%v%v%v` + | 
					
						
							|  |  |  | 		`%v%v%v%v%v%v%v%v%v%v` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Use predetermined args str | 
					
						
							|  |  |  | 	if count < len(args) { | 
					
						
							|  |  |  | 		return args[:count*2] | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-03-03 18:12:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 	// Allocate buffer of needed len | 
					
						
							|  |  |  | 	var buf strings.Builder | 
					
						
							|  |  |  | 	buf.Grow(count * 2) | 
					
						
							| 
									
										
										
										
											2022-05-07 16:46:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 	// Manually build an args str | 
					
						
							|  |  |  | 	for i := 0; i < count; i++ { | 
					
						
							|  |  |  | 		buf.WriteString(`%v`) | 
					
						
							| 
									
										
										
										
											2021-03-03 18:12:02 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return buf.String() | 
					
						
							| 
									
										
										
										
											2021-03-03 18:12:02 +01:00
										 |  |  | } |