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