| 
									
										
										
										
											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" | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	"runtime" | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2021-12-12 18:00:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	"code.superseriousbusiness.org/gotosocial/internal/log/format" | 
					
						
							|  |  |  | 	"code.superseriousbusiness.org/gotosocial/internal/log/level" | 
					
						
							| 
									
										
										
										
											2025-04-26 15:34:10 +02:00
										 |  |  | 	"code.superseriousbusiness.org/gotosocial/internal/util/xslices" | 
					
						
							| 
									
										
										
										
											2025-07-29 09:23:20 +02:00
										 |  |  | 	"codeberg.org/gruf/go-kv/v2" | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	// set logging output. | 
					
						
							|  |  |  | 	loglvl = level.UNSET | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// appendFormat stores log | 
					
						
							|  |  |  | 	// entry formatting function. | 
					
						
							|  |  |  | 	appendFormat = (&format.Logfmt{ | 
					
						
							|  |  |  | 		Base: format.Base{TimeFormat: timefmt}, | 
					
						
							|  |  |  | 	}).Format | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	// timefmt is the logging time format used. | 
					
						
							|  |  |  | 	timefmt = `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) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | // Level returns the currently set log. | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | func Level() LEVEL { | 
					
						
							| 
									
										
										
										
											2023-08-21 20:07:55 +02:00
										 |  |  | 	return loglvl | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | // SetLevel sets the max logging. | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | 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) { | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	timefmt = format | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // SetJSON enables / disables JSON log output formatting. | 
					
						
							|  |  |  | func SetJSON(enabled bool) { | 
					
						
							|  |  |  | 	if enabled { | 
					
						
							|  |  |  | 		var fmt format.JSON | 
					
						
							|  |  |  | 		fmt.TimeFormat = timefmt | 
					
						
							|  |  |  | 		appendFormat = fmt.Format | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		var fmt format.Logfmt | 
					
						
							|  |  |  | 		fmt.TimeFormat = timefmt | 
					
						
							|  |  |  | 		appendFormat = fmt.Format | 
					
						
							| 
									
										
										
										
											2023-08-21 20:07:55 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											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
										 |  |  | // Trace will log formatted args as 'msg' field to the log at TRACE level. | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | func Trace(ctx context.Context, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if TRACE > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, TRACE, nil, "", 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. | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | func Tracef(ctx context.Context, s string, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if TRACE > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, 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. | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | func TraceKV(ctx context.Context, key string, value interface{}) { | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if TRACE > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, 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. | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | func TraceKVs(ctx context.Context, kvs ...kv.Field) { | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if TRACE > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, 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. | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | func Debug(ctx context.Context, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if DEBUG > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, DEBUG, nil, "", 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. | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | func Debugf(ctx context.Context, s string, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if DEBUG > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, 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. | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | func DebugKV(ctx context.Context, key string, value interface{}) { | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if DEBUG > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, 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. | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | func DebugKVs(ctx context.Context, kvs ...kv.Field) { | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if DEBUG > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, 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. | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | func Info(ctx context.Context, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if INFO > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, INFO, nil, "", 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. | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | func Infof(ctx context.Context, s string, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if INFO > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, 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. | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | func InfoKV(ctx context.Context, key string, value interface{}) { | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if INFO > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, 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. | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | func InfoKVs(ctx context.Context, kvs ...kv.Field) { | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if INFO > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, 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. | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | func Warn(ctx context.Context, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if WARN > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, WARN, nil, "", 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. | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | func Warnf(ctx context.Context, s string, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if WARN > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, 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. | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | func WarnKV(ctx context.Context, key string, value interface{}) { | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if WARN > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, 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. | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | func WarnKVs(ctx context.Context, kvs ...kv.Field) { | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if WARN > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, 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. | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | func Error(ctx context.Context, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if ERROR > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, ERROR, nil, "", 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. | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | func Errorf(ctx context.Context, s string, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if ERROR > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, 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. | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | func ErrorKV(ctx context.Context, key string, value interface{}) { | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if ERROR > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, 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. | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | func ErrorKVs(ctx context.Context, kvs ...kv.Field) { | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if ERROR > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, 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. | 
					
						
							| 
									
										
										
										
											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...)) | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if PANIC > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, PANIC, nil, "", 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. | 
					
						
							| 
									
										
										
										
											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...)) | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if PANIC > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, 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. | 
					
						
							| 
									
										
										
										
											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()) | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if PANIC > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, 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. | 
					
						
							| 
									
										
										
										
											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()) | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if PANIC > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, 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. | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | func Log(ctx context.Context, lvl LEVEL, a ...interface{}) { //nolint:revive | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if lvl > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, lvl, nil, "", a...) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Logf will log format string as 'msg' field to the log at given level. | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | func Logf(ctx context.Context, lvl LEVEL, s string, a ...interface{}) { //nolint:revive | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if lvl > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, 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
										 |  |  | func LogKV(ctx context.Context, lvl LEVEL, key string, value interface{}) { //nolint:revive | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if lvl > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, 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
										 |  |  | func LogKVs(ctx context.Context, lvl LEVEL, kvs ...kv.Field) { //nolint:revive | 
					
						
							| 
									
										
										
										
											2025-09-07 14:47:45 +02:00
										 |  |  | 	if lvl > loglvl { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(ctx, lvl, kvs, "") | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | // Print will log formatted args to the stdout log output. | 
					
						
							|  |  |  | func Print(a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(context.Background(), UNSET, nil, "", 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. | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | func Printf(s string, a ...interface{}) { | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	logf(context.Background(), UNSET, nil, s, a...) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-20 13:30:33 +00:00
										 |  |  | //go:noinline | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | func logf(ctx context.Context, lvl LEVEL, fields []kv.Field, msg string, args ...interface{}) { | 
					
						
							| 
									
										
										
										
											2022-11-20 16:40:15 +00:00
										 |  |  | 	var out *os.File | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	// Get log stamp. | 
					
						
							|  |  |  | 	now := time.Now() | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	// Get caller information. | 
					
						
							|  |  |  | 	pcs := make([]uintptr, 1) | 
					
						
							|  |  |  | 	_ = runtime.Callers(3, pcs) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	// Acquire buffer. | 
					
						
							|  |  |  | 	buf := getBuf() | 
					
						
							|  |  |  | 	defer putBuf(buf) | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	if ctx != nil { | 
					
						
							|  |  |  | 		// Ensure fields have space for context hooks. | 
					
						
							|  |  |  | 		fields = xslices.GrowJust(fields, len(ctxhooks)) | 
					
						
							| 
									
										
										
										
											2024-11-11 15:45:19 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-17 12:02:29 +01:00
										 |  |  | 		// Pass context through hooks. | 
					
						
							|  |  |  | 		for _, hook := range ctxhooks { | 
					
						
							|  |  |  | 			fields = hook(ctx, fields) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	// If no args, use placeholders. | 
					
						
							|  |  |  | 	if msg == "" && len(args) > 0 { | 
					
						
							|  |  |  | 		const argstr = `%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` | 
					
						
							|  |  |  | 		msg = argstr[:2*len(args)] | 
					
						
							| 
									
										
										
										
											2024-09-17 19:35:47 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	if msg != "" { | 
					
						
							|  |  |  | 		// Format the message string. | 
					
						
							|  |  |  | 		msg = fmt.Sprintf(msg, args...) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	// Append formatted | 
					
						
							|  |  |  | 	// entry to buffer. | 
					
						
							|  |  |  | 	appendFormat(buf, | 
					
						
							|  |  |  | 		now, | 
					
						
							|  |  |  | 		pcs[0], | 
					
						
							|  |  |  | 		lvl, | 
					
						
							|  |  |  | 		fields, | 
					
						
							|  |  |  | 		msg, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Ensure a final new-line char. | 
					
						
							| 
									
										
										
										
											2022-10-01 16:36:08 +01:00
										 |  |  | 	if buf.B[len(buf.B)-1] != '\n' { | 
					
						
							|  |  |  | 		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
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-08-09 16:23:00 +02:00
										 |  |  | 	// Write to output file. | 
					
						
							| 
									
										
										
										
											2022-07-19 09:47:55 +01:00
										 |  |  | 	_, _ = out.Write(buf.B) | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 	} | 
					
						
							|  |  |  | } |