| // Copyright 2020 The Monogon Project Authors. | 
 | // | 
 | // SPDX-License-Identifier: Apache-2.0 | 
 | // | 
 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
 | // you may not use this file except in compliance with the License. | 
 | // You may obtain a copy of the License at | 
 | // | 
 | //     http://www.apache.org/licenses/LICENSE-2.0 | 
 | // | 
 | // Unless required by applicable law or agreed to in writing, software | 
 | // distributed under the License is distributed on an "AS IS" BASIS, | 
 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | // See the License for the specific language governing permissions and | 
 | // limitations under the License. | 
 |  | 
 | package logtree | 
 |  | 
 | import ( | 
 | 	"fmt" | 
 |  | 
 | 	apb "source.monogon.dev/metropolis/proto/api" | 
 | ) | 
 |  | 
 | // LeveledLogger is a generic interface for glog-style logging. There are four hardcoded log severities, in increasing | 
 | // order: INFO, WARNING, ERROR, FATAL. Logging at a certain severity level logs not only to consumers expecting data | 
 | // at that severity level, but also all lower severity levels. For example, an ERROR log will also be passed to | 
 | // consumers looking at INFO or WARNING logs. | 
 | type LeveledLogger interface { | 
 | 	// Info logs at the INFO severity. Arguments are handled in the manner of fmt.Print, a terminating newline is added | 
 | 	// if missing. | 
 | 	Info(args ...interface{}) | 
 | 	// Infof logs at the INFO severity. Arguments are handled in the manner of fmt.Printf, a terminating newline is | 
 | 	// added if missing. | 
 | 	Infof(format string, args ...interface{}) | 
 |  | 
 | 	// Warning logs at the WARNING severity. Arguments are handled in the manner of fmt.Print, a terminating newline is | 
 | 	// added if missing. | 
 | 	Warning(args ...interface{}) | 
 | 	// Warningf logs at the WARNING severity. Arguments are handled in the manner of fmt.Printf, a terminating newline | 
 | 	// is added if missing. | 
 | 	Warningf(format string, args ...interface{}) | 
 |  | 
 | 	// Error logs at the ERROR severity. Arguments are handled in the manner of fmt.Print, a terminating newline is | 
 | 	// added if missing. | 
 | 	Error(args ...interface{}) | 
 | 	// Errorf logs at the ERROR severity. Arguments are handled in the manner of fmt.Printf, a terminating newline is | 
 | 	// added if missing. | 
 | 	Errorf(format string, args ...interface{}) | 
 |  | 
 | 	// Fatal logs at the FATAL severity and aborts the current program. Arguments are handled in the manner of | 
 | 	// fmt.Print, a terminating newline is added if missing. | 
 | 	Fatal(args ...interface{}) | 
 | 	// Fatalf logs at the FATAL severity and aborts the current program. Arguments are handled in the manner of | 
 | 	// fmt.Printf, a terminating newline is added if missing. | 
 | 	Fatalf(format string, args ...interface{}) | 
 |  | 
 | 	// V returns a VerboseLeveledLogger at a given verbosity level. These verbosity levels can be dynamically set and | 
 | 	// unset on a package-granular level by consumers of the LeveledLogger logs. The returned value represents whether | 
 | 	// logging at the given verbosity level was active at that time, and as such should not be a long-lived object | 
 | 	// in programs. | 
 | 	// This construct is further refered to as 'V-logs'. | 
 | 	V(level VerbosityLevel) VerboseLeveledLogger | 
 | } | 
 |  | 
 | // VerbosityLevel is a verbosity level defined for V-logs. This can be changed programmatically per Go package. When | 
 | // logging at a given VerbosityLevel V, the current level must be equal or higher to V for the logs to be recorded. | 
 | // Conversely, enabling a V-logging at a VerbosityLevel V also enables all logging at lower levels [Int32Min .. (V-1)]. | 
 | type VerbosityLevel int32 | 
 |  | 
 | type VerboseLeveledLogger interface { | 
 | 	// Enabled returns if this level was enabled. If not enabled, all logging into this logger will be discarded | 
 | 	// immediately. | 
 | 	// Thus, Enabled() can be used to check the verbosity level before performing any logging: | 
 | 	//    if l.V(3).Enabled() { l.Info("V3 is enabled") } | 
 | 	// or, in simple cases, the convenience function .Info can be used: | 
 | 	//    l.V(3).Info("V3 is enabled") | 
 | 	// The second form is shorter and more convenient, but more expensive, as its arguments are always evaluated. | 
 | 	Enabled() bool | 
 | 	// Info is the equivalent of a LeveledLogger's Info call, guarded by whether this VerboseLeveledLogger is enabled. | 
 | 	Info(args ...interface{}) | 
 | 	// Infof is the equivalent of a LeveledLogger's Infof call, guarded by whether this VerboseLeveledLogger is enabled. | 
 | 	Infof(format string, args ...interface{}) | 
 | } | 
 |  | 
 | // Severity is one of the severities as described in LeveledLogger. | 
 | type Severity string | 
 |  | 
 | const ( | 
 | 	INFO    Severity = "I" | 
 | 	WARNING Severity = "W" | 
 | 	ERROR   Severity = "E" | 
 | 	FATAL   Severity = "F" | 
 | ) | 
 |  | 
 | var ( | 
 | 	// SeverityAtLeast maps a given severity to a list of severities that at that severity or higher. In other words, | 
 | 	// SeverityAtLeast[X] returns a list of severities that might be seen in a log at severity X. | 
 | 	SeverityAtLeast = map[Severity][]Severity{ | 
 | 		INFO:    {INFO, WARNING, ERROR, FATAL}, | 
 | 		WARNING: {WARNING, ERROR, FATAL}, | 
 | 		ERROR:   {ERROR, FATAL}, | 
 | 		FATAL:   {FATAL}, | 
 | 	} | 
 | ) | 
 |  | 
 | func (s Severity) AtLeast(other Severity) bool { | 
 | 	for _, el := range SeverityAtLeast[other] { | 
 | 		if el == s { | 
 | 			return true | 
 | 		} | 
 | 	} | 
 | 	return false | 
 | } | 
 |  | 
 | func SeverityFromProto(s apb.LeveledLogSeverity) (Severity, error) { | 
 | 	switch s { | 
 | 	case apb.LeveledLogSeverity_INFO: | 
 | 		return INFO, nil | 
 | 	case apb.LeveledLogSeverity_WARNING: | 
 | 		return WARNING, nil | 
 | 	case apb.LeveledLogSeverity_ERROR: | 
 | 		return ERROR, nil | 
 | 	case apb.LeveledLogSeverity_FATAL: | 
 | 		return FATAL, nil | 
 | 	default: | 
 | 		return "", fmt.Errorf("unknown severity value %d", s) | 
 | 	} | 
 | } | 
 |  | 
 | func (s Severity) ToProto() apb.LeveledLogSeverity { | 
 | 	switch s { | 
 | 	case INFO: | 
 | 		return apb.LeveledLogSeverity_INFO | 
 | 	case WARNING: | 
 | 		return apb.LeveledLogSeverity_WARNING | 
 | 	case ERROR: | 
 | 		return apb.LeveledLogSeverity_ERROR | 
 | 	case FATAL: | 
 | 		return apb.LeveledLogSeverity_FATAL | 
 | 	default: | 
 | 		return apb.LeveledLogSeverity_INVALID | 
 | 	} | 
 | } |