blob: 02243ac71454d7c3936ea09ca000972f5b2671bf [file] [log] [blame]
Serge Bazanski5faa2fc2020-09-07 14:09:30 +02001// Copyright 2020 The Monogon Project Authors.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17package logtree
18
19import (
20 "fmt"
21 "runtime"
22 "strings"
23 "time"
24)
25
26// LeveledFor returns a LeveledLogger publishing interface for a given DN. An error may be returned if the DN is
27// malformed.
28func (l *LogTree) LeveledFor(dn DN) (LeveledLogger, error) {
29 return l.nodeByDN(dn)
30}
31
32// MustLeveledFor returns a LeveledLogger publishing interface for a given DN, or panics if the given DN is invalid.
33func (l *LogTree) MustLeveledFor(dn DN) LeveledLogger {
34 leveled, err := l.LeveledFor(dn)
35 if err != nil {
36 panic(fmt.Errorf("LeveledFor returned: %w", err))
37 }
38 return leveled
39}
40
41// SetVerbosity sets the verbosity for a given DN (non-recursively, ie. for that DN only, not its children).
42func (l *LogTree) SetVerbosity(dn DN, level VerbosityLevel) error {
43 node, err := l.nodeByDN(dn)
44 if err != nil {
45 return err
46 }
47 node.verbosity = level
48 return nil
49}
50
51// log builds a Payload and entry for a given message, including all related metadata, and appends it to the journal,
52// notifying all pertinent subscribers.
53func (n *node) log(depth int, severity Severity, msg string) {
54 _, file, line, ok := runtime.Caller(2 + depth)
55 if !ok {
56 file = "???"
57 line = 1
58 } else {
59 slash := strings.LastIndex(file, "/")
60 if slash >= 0 {
61 file = file[slash+1:]
62 }
63 }
64 p := &Payload{
65 timestamp: time.Now(),
66 severity: severity,
67 message: msg,
68 file: file,
69 line: line,
70 }
71 e := &entry{
72 origin: n.dn,
73 payload: p,
74 }
75 n.tree.journal.append(e)
76 n.tree.journal.notify(e)
77}
78
79// Info implements the LeveledLogger interface.
80func (n *node) Info(args ...interface{}) {
81 n.log(0, INFO, fmt.Sprint(args...))
82}
83
84// Infof implements the LeveledLogger interface.
85func (n *node) Infof(format string, args ...interface{}) {
86 n.log(0, INFO, fmt.Sprintf(format, args...))
87}
88
89// Warning implements the LeveledLogger interface.
90func (n *node) Warning(args ...interface{}) {
91 n.log(0, WARNING, fmt.Sprint(args...))
92}
93
94// Warningf implements the LeveledLogger interface.
95func (n *node) Warningf(format string, args ...interface{}) {
96 n.log(0, WARNING, fmt.Sprintf(format, args...))
97}
98
99// Error implements the LeveledLogger interface.
100func (n *node) Error(args ...interface{}) {
101 n.log(0, ERROR, fmt.Sprint(args...))
102}
103
104// Errorf implements the LeveledLogger interface.
105func (n *node) Errorf(format string, args ...interface{}) {
106 n.log(0, ERROR, fmt.Sprintf(format, args...))
107}
108
109// Fatal implements the LeveledLogger interface.
110func (n *node) Fatal(args ...interface{}) {
111 n.log(0, FATAL, fmt.Sprint(args...))
112}
113
114// Fatalf implements the LeveledLogger interface.
115func (n *node) Fatalf(format string, args ...interface{}) {
116 n.log(0, FATAL, fmt.Sprintf(format, args...))
117}
118
119// V implements the LeveledLogger interface.
120func (n *node) V(v VerbosityLevel) VerboseLeveledLogger {
121 return &verbose{
122 node: n,
123 enabled: n.verbosity >= v,
124 }
125}
126
127// verbose implements the VerboseLeveledLogger interface. It is a thin wrapper around node, with an 'enabled' bool. This
128// means that V(n)-returned VerboseLeveledLoggers must be short lived, as a changed in verbosity will not affect all
129// already existing VerboseLeveledLoggers.
130type verbose struct {
131 node *node
132 enabled bool
133}
134
135func (v *verbose) Enabled() bool {
136 return v.enabled
137}
138
139func (v *verbose) Info(args ...interface{}) {
140 if !v.enabled {
141 return
142 }
143 v.node.log(0, INFO, fmt.Sprint(args...))
144}
145
146func (v *verbose) Infof(format string, args ...interface{}) {
147 if !v.enabled {
148 return
149 }
150 v.node.log(0, INFO, fmt.Sprintf(format, args...))
151}