1// Copyright 2013-2020 Aerospike, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package logger
16
17import (
18	"fmt"
19	"log"
20	"os"
21	"sync"
22)
23
24// LogPriority specifies the logging level for the client
25type LogPriority int
26
27const (
28	DEBUG LogPriority = iota - 1
29	INFO
30	WARNING
31	ERR
32	OFF LogPriority = 999
33)
34
35type genericLogger interface {
36	Printf(format string, v ...interface{})
37}
38
39type logger struct {
40	Logger genericLogger
41
42	level LogPriority
43	mutex sync.RWMutex
44}
45
46// Logger is the default logger instance
47var Logger = newLogger()
48
49func newLogger() *logger {
50	return &logger{
51		Logger: log.New(os.Stdout, "", log.LstdFlags),
52		level:  OFF,
53	}
54}
55
56// SetLogger sets the *log.Logger object where log messages should be sent to.
57func (lgr *logger) SetLogger(l genericLogger) {
58	lgr.mutex.Lock()
59	defer lgr.mutex.Unlock()
60
61	lgr.Logger = l
62}
63
64// SetLevel sets logging level. Default is ERR.
65func (lgr *logger) SetLevel(level LogPriority) {
66	lgr.mutex.Lock()
67	defer lgr.mutex.Unlock()
68
69	lgr.level = level
70}
71
72// Error logs a message if log level allows to do so.
73func (lgr *logger) LogAtLevel(level LogPriority, format string, v ...interface{}) {
74	switch level {
75	case DEBUG:
76		lgr.Debug(format, v...)
77	case INFO:
78		lgr.Info(format, v...)
79	case WARNING:
80		lgr.Warn(format, v...)
81	case ERR:
82		lgr.Error(format, v...)
83	}
84}
85
86// Debug logs a message if log level allows to do so.
87func (lgr *logger) Debug(format string, v ...interface{}) {
88	lgr.mutex.RLock()
89	defer lgr.mutex.RUnlock()
90
91	if lgr.level <= DEBUG {
92		if l, ok := lgr.Logger.(*log.Logger); ok {
93			l.Output(2, fmt.Sprintf(format, v...))
94		} else {
95			lgr.Logger.Printf(format, v...)
96		}
97	}
98}
99
100// Info logs a message if log level allows to do so.
101func (lgr *logger) Info(format string, v ...interface{}) {
102	lgr.mutex.RLock()
103	defer lgr.mutex.RUnlock()
104
105	if lgr.level <= INFO {
106		if l, ok := lgr.Logger.(*log.Logger); ok {
107			l.Output(2, fmt.Sprintf(format, v...))
108		} else {
109			lgr.Logger.Printf(format, v...)
110		}
111	}
112}
113
114// Warn logs a message if log level allows to do so.
115func (lgr *logger) Warn(format string, v ...interface{}) {
116	lgr.mutex.RLock()
117	defer lgr.mutex.RUnlock()
118
119	if lgr.level <= WARNING {
120		if l, ok := lgr.Logger.(*log.Logger); ok {
121			l.Output(2, fmt.Sprintf(format, v...))
122		} else {
123			lgr.Logger.Printf(format, v...)
124		}
125	}
126}
127
128// Error logs a message if log level allows to do so.
129func (lgr *logger) Error(format string, v ...interface{}) {
130	lgr.mutex.RLock()
131	defer lgr.mutex.RUnlock()
132
133	if lgr.level <= ERR {
134		if l, ok := lgr.Logger.(*log.Logger); ok {
135			l.Output(2, fmt.Sprintf(format, v...))
136		} else {
137			lgr.Logger.Printf(format, v...)
138		}
139	}
140}
141