You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

logger_golog.go 8.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. // Copyright (c) 2016-2019 Couchbase, Inc.
  2. // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
  3. // except in compliance with the License. You may obtain a copy of the License at
  4. // http://www.apache.org/licenses/LICENSE-2.0
  5. // Unless required by applicable law or agreed to in writing, software distributed under the
  6. // License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
  7. // either express or implied. See the License for the specific language governing permissions
  8. // and limitations under the License.
  9. package logging
  10. import (
  11. "bytes"
  12. "encoding/json"
  13. "fmt"
  14. "io"
  15. "log"
  16. "time"
  17. )
  18. type goLogger struct {
  19. logger *log.Logger
  20. level Level
  21. entryFormatter formatter
  22. }
  23. const (
  24. _LEVEL = "_level"
  25. _MSG = "_msg"
  26. _TIME = "_time"
  27. _RLEVEL = "_rlevel"
  28. )
  29. func NewLogger(out io.Writer, lvl Level, fmtLogging LogEntryFormatter, fmtArgs ...interface{}) *goLogger {
  30. logger := &goLogger{
  31. logger: log.New(out, "", 0),
  32. level: lvl,
  33. }
  34. if fmtLogging == JSONFORMATTER {
  35. logger.entryFormatter = &jsonFormatter{}
  36. } else if fmtLogging == KVFORMATTER {
  37. logger.entryFormatter = &keyvalueFormatter{}
  38. } else if fmtLogging == UNIFORMFORMATTER {
  39. logger.entryFormatter = &uniformFormatter{
  40. callback: fmtArgs[0].(ComponentCallback),
  41. }
  42. } else {
  43. logger.entryFormatter = &textFormatter{}
  44. }
  45. return logger
  46. }
  47. func (gl *goLogger) Logp(level Level, msg string, kv ...Pair) {
  48. if gl.logger == nil {
  49. return
  50. }
  51. if level <= gl.level {
  52. e := newLogEntry(msg, level)
  53. copyPairs(e, kv)
  54. gl.log(e)
  55. }
  56. }
  57. func (gl *goLogger) Debugp(msg string, kv ...Pair) {
  58. gl.Logp(DEBUG, msg, kv...)
  59. }
  60. func (gl *goLogger) Tracep(msg string, kv ...Pair) {
  61. gl.Logp(TRACE, msg, kv...)
  62. }
  63. func (gl *goLogger) Requestp(rlevel Level, msg string, kv ...Pair) {
  64. if gl.logger == nil {
  65. return
  66. }
  67. if REQUEST <= gl.level {
  68. e := newLogEntry(msg, REQUEST)
  69. e.Rlevel = rlevel
  70. copyPairs(e, kv)
  71. gl.log(e)
  72. }
  73. }
  74. func (gl *goLogger) Infop(msg string, kv ...Pair) {
  75. gl.Logp(INFO, msg, kv...)
  76. }
  77. func (gl *goLogger) Warnp(msg string, kv ...Pair) {
  78. gl.Logp(WARN, msg, kv...)
  79. }
  80. func (gl *goLogger) Errorp(msg string, kv ...Pair) {
  81. gl.Logp(ERROR, msg, kv...)
  82. }
  83. func (gl *goLogger) Severep(msg string, kv ...Pair) {
  84. gl.Logp(SEVERE, msg, kv...)
  85. }
  86. func (gl *goLogger) Fatalp(msg string, kv ...Pair) {
  87. gl.Logp(FATAL, msg, kv...)
  88. }
  89. func (gl *goLogger) Logm(level Level, msg string, kv Map) {
  90. if gl.logger == nil {
  91. return
  92. }
  93. if level <= gl.level {
  94. e := newLogEntry(msg, level)
  95. e.Data = kv
  96. gl.log(e)
  97. }
  98. }
  99. func (gl *goLogger) Debugm(msg string, kv Map) {
  100. gl.Logm(DEBUG, msg, kv)
  101. }
  102. func (gl *goLogger) Tracem(msg string, kv Map) {
  103. gl.Logm(TRACE, msg, kv)
  104. }
  105. func (gl *goLogger) Requestm(rlevel Level, msg string, kv Map) {
  106. if gl.logger == nil {
  107. return
  108. }
  109. if REQUEST <= gl.level {
  110. e := newLogEntry(msg, REQUEST)
  111. e.Rlevel = rlevel
  112. e.Data = kv
  113. gl.log(e)
  114. }
  115. }
  116. func (gl *goLogger) Infom(msg string, kv Map) {
  117. gl.Logm(INFO, msg, kv)
  118. }
  119. func (gl *goLogger) Warnm(msg string, kv Map) {
  120. gl.Logm(WARN, msg, kv)
  121. }
  122. func (gl *goLogger) Errorm(msg string, kv Map) {
  123. gl.Logm(ERROR, msg, kv)
  124. }
  125. func (gl *goLogger) Severem(msg string, kv Map) {
  126. gl.Logm(SEVERE, msg, kv)
  127. }
  128. func (gl *goLogger) Fatalm(msg string, kv Map) {
  129. gl.Logm(FATAL, msg, kv)
  130. }
  131. func (gl *goLogger) Logf(level Level, format string, args ...interface{}) {
  132. if gl.logger == nil {
  133. return
  134. }
  135. if level <= gl.level {
  136. e := newLogEntry(fmt.Sprintf(format, args...), level)
  137. gl.log(e)
  138. }
  139. }
  140. func (gl *goLogger) Debugf(format string, args ...interface{}) {
  141. gl.Logf(DEBUG, format, args...)
  142. }
  143. func (gl *goLogger) Tracef(format string, args ...interface{}) {
  144. gl.Logf(TRACE, format, args...)
  145. }
  146. func (gl *goLogger) Requestf(rlevel Level, format string, args ...interface{}) {
  147. if gl.logger == nil {
  148. return
  149. }
  150. if REQUEST <= gl.level {
  151. e := newLogEntry(fmt.Sprintf(format, args...), REQUEST)
  152. e.Rlevel = rlevel
  153. gl.log(e)
  154. }
  155. }
  156. func (gl *goLogger) Infof(format string, args ...interface{}) {
  157. gl.Logf(INFO, format, args...)
  158. }
  159. func (gl *goLogger) Warnf(format string, args ...interface{}) {
  160. gl.Logf(WARN, format, args...)
  161. }
  162. func (gl *goLogger) Errorf(format string, args ...interface{}) {
  163. gl.Logf(ERROR, format, args...)
  164. }
  165. func (gl *goLogger) Severef(format string, args ...interface{}) {
  166. gl.Logf(SEVERE, format, args...)
  167. }
  168. func (gl *goLogger) Fatalf(format string, args ...interface{}) {
  169. gl.Logf(FATAL, format, args...)
  170. }
  171. func (gl *goLogger) Level() Level {
  172. return gl.level
  173. }
  174. func (gl *goLogger) SetLevel(level Level) {
  175. gl.level = level
  176. }
  177. func (gl *goLogger) log(newEntry *logEntry) {
  178. s := gl.entryFormatter.format(newEntry)
  179. gl.logger.Print(s)
  180. }
  181. type logEntry struct {
  182. Time string
  183. Level Level
  184. Rlevel Level
  185. Message string
  186. Data Map
  187. }
  188. func newLogEntry(msg string, level Level) *logEntry {
  189. return &logEntry{
  190. Time: time.Now().Format("2006-01-02T15:04:05.000-07:00"), // time.RFC3339 with milliseconds
  191. Level: level,
  192. Rlevel: NONE,
  193. Message: msg,
  194. }
  195. }
  196. func copyPairs(newEntry *logEntry, pairs []Pair) {
  197. newEntry.Data = make(Map, len(pairs))
  198. for _, p := range pairs {
  199. newEntry.Data[p.Name] = p.Value
  200. }
  201. }
  202. type formatter interface {
  203. format(*logEntry) string
  204. }
  205. type textFormatter struct {
  206. }
  207. // ex. 2016-02-10T09:15:25.498-08:00 [INFO] This is a message from test in text format
  208. func (*textFormatter) format(newEntry *logEntry) string {
  209. b := &bytes.Buffer{}
  210. appendValue(b, newEntry.Time)
  211. if newEntry.Rlevel != NONE {
  212. fmt.Fprintf(b, "[%s,%s] ", newEntry.Level.String(), newEntry.Rlevel.String())
  213. } else {
  214. fmt.Fprintf(b, "[%s] ", newEntry.Level.String())
  215. }
  216. appendValue(b, newEntry.Message)
  217. for key, value := range newEntry.Data {
  218. appendKeyValue(b, key, value)
  219. }
  220. b.WriteByte('\n')
  221. s := bytes.NewBuffer(b.Bytes())
  222. return s.String()
  223. }
  224. func appendValue(b *bytes.Buffer, value interface{}) {
  225. if _, ok := value.(string); ok {
  226. fmt.Fprintf(b, "%s ", value)
  227. } else {
  228. fmt.Fprintf(b, "%v ", value)
  229. }
  230. }
  231. type keyvalueFormatter struct {
  232. }
  233. // ex. _time=2016-02-10T09:15:25.498-08:00 _level=INFO _msg=This is a message from test in key-value format
  234. func (*keyvalueFormatter) format(newEntry *logEntry) string {
  235. b := &bytes.Buffer{}
  236. appendKeyValue(b, _TIME, newEntry.Time)
  237. appendKeyValue(b, _LEVEL, newEntry.Level.String())
  238. if newEntry.Rlevel != NONE {
  239. appendKeyValue(b, _RLEVEL, newEntry.Rlevel.String())
  240. }
  241. appendKeyValue(b, _MSG, newEntry.Message)
  242. for key, value := range newEntry.Data {
  243. appendKeyValue(b, key, value)
  244. }
  245. b.WriteByte('\n')
  246. s := bytes.NewBuffer(b.Bytes())
  247. return s.String()
  248. }
  249. func appendKeyValue(b *bytes.Buffer, key, value interface{}) {
  250. if _, ok := value.(string); ok {
  251. fmt.Fprintf(b, "%v=%s ", key, value)
  252. } else {
  253. fmt.Fprintf(b, "%v=%v ", key, value)
  254. }
  255. }
  256. type jsonFormatter struct {
  257. }
  258. // ex. {"_level":"INFO","_msg":"This is a message from test in json format","_time":"2016-02-10T09:12:59.518-08:00"}
  259. func (*jsonFormatter) format(newEntry *logEntry) string {
  260. if newEntry.Data == nil {
  261. newEntry.Data = make(Map, 5)
  262. }
  263. newEntry.Data[_TIME] = newEntry.Time
  264. newEntry.Data[_LEVEL] = newEntry.Level.String()
  265. if newEntry.Rlevel != NONE {
  266. newEntry.Data[_RLEVEL] = newEntry.Rlevel.String()
  267. }
  268. newEntry.Data[_MSG] = newEntry.Message
  269. serialized, _ := json.Marshal(newEntry.Data)
  270. s := bytes.NewBuffer(append(serialized, '\n'))
  271. return s.String()
  272. }
  273. type ComponentCallback func() string
  274. type uniformFormatter struct {
  275. callback ComponentCallback
  276. }
  277. // ex. 2019-03-15T11:28:07.652-04:00 DEBU COMPONENT.subcomponent This is a message from test in uniform format
  278. var _LEVEL_UNIFORM = []string{
  279. DEBUG: "DEBU",
  280. TRACE: "TRAC",
  281. REQUEST: "REQU",
  282. INFO: "INFO",
  283. WARN: "WARN",
  284. ERROR: "ERRO",
  285. SEVERE: "SEVE",
  286. FATAL: "FATA",
  287. NONE: "NONE",
  288. }
  289. func (level Level) UniformString() string {
  290. return _LEVEL_UNIFORM[level]
  291. }
  292. func (uf *uniformFormatter) format(newEntry *logEntry) string {
  293. b := &bytes.Buffer{}
  294. appendValue(b, newEntry.Time)
  295. component := uf.callback()
  296. if newEntry.Rlevel != NONE {
  297. // not really any accommodation for a composite level in the uniform standard; just output as abbr,abbr
  298. fmt.Fprintf(b, "%s,%s %s ", newEntry.Level.UniformString(), newEntry.Rlevel.UniformString(), component)
  299. } else {
  300. fmt.Fprintf(b, "%s %s ", newEntry.Level.UniformString(), component)
  301. }
  302. appendValue(b, newEntry.Message)
  303. for key, value := range newEntry.Data {
  304. appendKeyValue(b, key, value)
  305. }
  306. b.WriteByte('\n')
  307. s := bytes.NewBuffer(b.Bytes())
  308. return s.String()
  309. }