1// The Test package is used for testing logrus.
2// It provides a simple hooks which register logged messages.
3package test
4
5import (
6	"io/ioutil"
7	"sync"
8
9	"github.com/sirupsen/logrus"
10)
11
12// Hook is a hook designed for dealing with logs in test scenarios.
13type Hook struct {
14	// Entries is an array of all entries that have been received by this hook.
15	// For safe access, use the AllEntries() method, rather than reading this
16	// value directly.
17	Entries []logrus.Entry
18	mu      sync.RWMutex
19}
20
21// NewGlobal installs a test hook for the global logger.
22func NewGlobal() *Hook {
23
24	hook := new(Hook)
25	logrus.AddHook(hook)
26
27	return hook
28
29}
30
31// NewLocal installs a test hook for a given local logger.
32func NewLocal(logger *logrus.Logger) *Hook {
33
34	hook := new(Hook)
35	logger.Hooks.Add(hook)
36
37	return hook
38
39}
40
41// NewNullLogger creates a discarding logger and installs the test hook.
42func NewNullLogger() (*logrus.Logger, *Hook) {
43
44	logger := logrus.New()
45	logger.Out = ioutil.Discard
46
47	return logger, NewLocal(logger)
48
49}
50
51func (t *Hook) Fire(e *logrus.Entry) error {
52	t.mu.Lock()
53	defer t.mu.Unlock()
54	t.Entries = append(t.Entries, *e)
55	return nil
56}
57
58func (t *Hook) Levels() []logrus.Level {
59	return logrus.AllLevels
60}
61
62// LastEntry returns the last entry that was logged or nil.
63func (t *Hook) LastEntry() *logrus.Entry {
64	t.mu.RLock()
65	defer t.mu.RUnlock()
66	i := len(t.Entries) - 1
67	if i < 0 {
68		return nil
69	}
70	return &t.Entries[i]
71}
72
73// AllEntries returns all entries that were logged.
74func (t *Hook) AllEntries() []*logrus.Entry {
75	t.mu.RLock()
76	defer t.mu.RUnlock()
77	// Make a copy so the returned value won't race with future log requests
78	entries := make([]*logrus.Entry, len(t.Entries))
79	for i := 0; i < len(t.Entries); i++ {
80		// Make a copy, for safety
81		entries[i] = &t.Entries[i]
82	}
83	return entries
84}
85
86// Reset removes all Entries from this test hook.
87func (t *Hook) Reset() {
88	t.mu.Lock()
89	defer t.mu.Unlock()
90	t.Entries = make([]logrus.Entry, 0)
91}
92