~ubuntu-branches/ubuntu/trusty/juju-core/trusty-proposed

« back to all changes in this revision

Viewing changes to src/launchpad.net/loggo/writer.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-02-03 09:22:46 UTC
  • mfrom: (1.1.17)
  • Revision ID: package-import@ubuntu.com-20140203092246-e03vg402vztzo4qa
Tags: 1.17.2-0ubuntu1
New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
package loggo
2
 
 
3
 
import (
4
 
        "fmt"
5
 
        "io"
6
 
        "os"
7
 
        "sync"
8
 
        "time"
9
 
)
10
 
 
11
 
// Writer is implemented by any recipient of log messages.
12
 
type Writer interface {
13
 
        // Write writes a message to the Writer with the given
14
 
        // level and module name. The filename and line hold
15
 
        // the file name and line number of the code that is
16
 
        // generating the log message; the time stamp holds
17
 
        // the time the log message was generated, and
18
 
        // message holds the log message itself.
19
 
        Write(level Level, name, filename string, line int, timestamp time.Time, message string)
20
 
}
21
 
 
22
 
type registeredWriter struct {
23
 
        writer Writer
24
 
        level  Level
25
 
}
26
 
 
27
 
// defaultName is the name of a writer that is registered
28
 
// by default that writes to stderr.
29
 
const defaultName = "default"
30
 
 
31
 
var (
32
 
        writerMutex sync.Mutex
33
 
        writers     = map[string]*registeredWriter{
34
 
                defaultName: &registeredWriter{
35
 
                        writer: NewSimpleWriter(os.Stderr, &DefaultFormatter{}),
36
 
                        level:  TRACE,
37
 
                },
38
 
        }
39
 
        globalMinLevel = TRACE
40
 
)
41
 
 
42
 
// ResetWriters puts the list of writers back into the initial state.
43
 
func ResetWriters() {
44
 
        writerMutex.Lock()
45
 
        defer writerMutex.Unlock()
46
 
        writers = map[string]*registeredWriter{
47
 
                "default": &registeredWriter{
48
 
                        writer: NewSimpleWriter(os.Stderr, &DefaultFormatter{}),
49
 
                        level:  TRACE,
50
 
                },
51
 
        }
52
 
        findMinLevel()
53
 
}
54
 
 
55
 
// ReplaceDefaultWriter is a convenience method that does the equivalent of
56
 
// RemoveWriter and then RegisterWriter with the name "default".  The previous
57
 
// default writer, if any is returned.
58
 
func ReplaceDefaultWriter(writer Writer) (Writer, error) {
59
 
        if writer == nil {
60
 
                return nil, fmt.Errorf("Writer cannot be nil")
61
 
        }
62
 
        writerMutex.Lock()
63
 
        defer writerMutex.Unlock()
64
 
        reg, found := writers[defaultName]
65
 
        if !found {
66
 
                return nil, fmt.Errorf("there is no %q writer", defaultName)
67
 
        }
68
 
        oldWriter := reg.writer
69
 
        reg.writer = writer
70
 
        return oldWriter, nil
71
 
 
72
 
}
73
 
 
74
 
// RegisterWriter adds the writer to the list of writers that get notified
75
 
// when logging.  When registering, the caller specifies the minimum logging
76
 
// level that will be written, and a name for the writer.  If there is already
77
 
// a registered writer with that name, an error is returned.
78
 
func RegisterWriter(name string, writer Writer, minLevel Level) error {
79
 
        if writer == nil {
80
 
                return fmt.Errorf("Writer cannot be nil")
81
 
        }
82
 
        writerMutex.Lock()
83
 
        defer writerMutex.Unlock()
84
 
        if _, found := writers[name]; found {
85
 
                return fmt.Errorf("there is already a Writer registered with the name %q", name)
86
 
        }
87
 
        writers[name] = &registeredWriter{writer: writer, level: minLevel}
88
 
        findMinLevel()
89
 
        return nil
90
 
}
91
 
 
92
 
// RemoveWriter removes the Writer identified by 'name' and returns it.
93
 
// If the Writer is not found, an error is returned.
94
 
func RemoveWriter(name string) (Writer, Level, error) {
95
 
        writerMutex.Lock()
96
 
        defer writerMutex.Unlock()
97
 
        registered, found := writers[name]
98
 
        if !found {
99
 
                return nil, UNSPECIFIED, fmt.Errorf("Writer %q is not registered", name)
100
 
        }
101
 
        delete(writers, name)
102
 
        findMinLevel()
103
 
        return registered.writer, registered.level, nil
104
 
}
105
 
 
106
 
func findMinLevel() {
107
 
        // We assume the lock is already held
108
 
        minLevel := CRITICAL
109
 
        for _, registered := range writers {
110
 
                if registered.level < minLevel {
111
 
                        minLevel = registered.level
112
 
                }
113
 
        }
114
 
        globalMinLevel.set(minLevel)
115
 
}
116
 
 
117
 
// WillWrite returns whether there are any writers registered
118
 
// at or above the given severity level. If it returns
119
 
// false, a log message at the given level will be discarded.
120
 
func WillWrite(level Level) bool {
121
 
        return level >= globalMinLevel.get()
122
 
}
123
 
 
124
 
func writeToWriters(level Level, module, filename string, line int, timestamp time.Time, message string) {
125
 
        writerMutex.Lock()
126
 
        defer writerMutex.Unlock()
127
 
        for _, registered := range writers {
128
 
                if level >= registered.level {
129
 
                        registered.writer.Write(level, module, filename, line, timestamp, message)
130
 
                }
131
 
        }
132
 
}
133
 
 
134
 
type simpleWriter struct {
135
 
        writer    io.Writer
136
 
        formatter Formatter
137
 
}
138
 
 
139
 
// NewSimpleWriter returns a new writer that writes
140
 
// log messages to the given io.Writer formatting the
141
 
// messages with the given formatter.
142
 
func NewSimpleWriter(writer io.Writer, formatter Formatter) Writer {
143
 
        return &simpleWriter{writer, formatter}
144
 
}
145
 
 
146
 
func (simple *simpleWriter) Write(level Level, module, filename string, line int, timestamp time.Time, message string) {
147
 
        logLine := simple.formatter.Format(level, module, filename, line, timestamp, message)
148
 
        fmt.Fprintln(simple.writer, logLine)
149
 
}