1// Copyright (C) MongoDB, Inc. 2014-present. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); you may 4// not use this file except in compliance with the License. You may obtain 5// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 6 7// Package log provides a utility to log timestamped messages to an io.Writer. 8package log 9 10import ( 11 "fmt" 12 "io" 13 "os" 14 "sync" 15 "time" 16) 17 18// Tool Logger verbosity constants 19const ( 20 Always = iota 21 Info 22 DebugLow 23 DebugHigh 24) 25 26const ( 27 ToolTimeFormat = "2006-01-02T15:04:05.000-0700" 28) 29 30//// Tool Logger Definition 31 32type ToolLogger struct { 33 mutex *sync.Mutex 34 writer io.Writer 35 format string 36 verbosity int 37} 38 39type VerbosityLevel interface { 40 Level() int 41 IsQuiet() bool 42} 43 44func (tl *ToolLogger) SetVerbosity(level VerbosityLevel) { 45 if level == nil { 46 tl.verbosity = 0 47 return 48 } 49 50 if level.IsQuiet() { 51 tl.verbosity = -1 52 } else { 53 tl.verbosity = level.Level() 54 } 55} 56 57func (tl *ToolLogger) SetWriter(writer io.Writer) { 58 tl.writer = writer 59} 60 61func (tl *ToolLogger) SetDateFormat(dateFormat string) { 62 tl.format = dateFormat 63} 64 65func (tl *ToolLogger) Logvf(minVerb int, format string, a ...interface{}) { 66 if minVerb < 0 { 67 panic("cannot set a minimum log verbosity that is less than 0") 68 } 69 70 if minVerb <= tl.verbosity { 71 tl.mutex.Lock() 72 defer tl.mutex.Unlock() 73 tl.log(fmt.Sprintf(format, a...)) 74 } 75} 76 77func (tl *ToolLogger) Logv(minVerb int, msg string) { 78 if minVerb < 0 { 79 panic("cannot set a minimum log verbosity that is less than 0") 80 } 81 82 if minVerb <= tl.verbosity { 83 tl.mutex.Lock() 84 defer tl.mutex.Unlock() 85 tl.log(msg) 86 } 87} 88 89func (tl *ToolLogger) log(msg string) { 90 fmt.Fprintf(tl.writer, "%v\t%v\n", time.Now().Format(tl.format), msg) 91} 92 93func NewToolLogger(verbosity VerbosityLevel) *ToolLogger { 94 tl := &ToolLogger{ 95 mutex: &sync.Mutex{}, 96 writer: os.Stderr, // default to stderr 97 format: ToolTimeFormat, 98 } 99 tl.SetVerbosity(verbosity) 100 return tl 101} 102 103//// Log Writer Interface 104 105// toolLogWriter is an io.Writer wrapping a tool logger. It is a private 106// type meant for creation with the ToolLogger.Writer(...) method. 107type toolLogWriter struct { 108 logger *ToolLogger 109 minVerbosity int 110} 111 112func (tlw *toolLogWriter) Write(message []byte) (int, error) { 113 tlw.logger.Logv(tlw.minVerbosity, string(message)) 114 return len(message), nil 115} 116 117// Writer returns an io.Writer that writes to the logger with 118// the given verbosity 119func (tl *ToolLogger) Writer(minVerb int) io.Writer { 120 return &toolLogWriter{tl, minVerb} 121} 122 123//// Global Logging 124 125var globalToolLogger *ToolLogger 126 127func init() { 128 if globalToolLogger == nil { 129 // initialize tool logger with verbosity level = 0 130 globalToolLogger = NewToolLogger(nil) 131 } 132} 133 134// IsInVerbosity returns true if the current verbosity level setting is 135// greater than or equal to the given level. 136func IsInVerbosity(minVerb int) bool { 137 return minVerb <= globalToolLogger.verbosity 138} 139 140func Logvf(minVerb int, format string, a ...interface{}) { 141 globalToolLogger.Logvf(minVerb, format, a...) 142} 143 144func Logv(minVerb int, msg string) { 145 globalToolLogger.Logv(minVerb, msg) 146} 147 148func SetVerbosity(verbosity VerbosityLevel) { 149 globalToolLogger.SetVerbosity(verbosity) 150} 151 152func SetWriter(writer io.Writer) { 153 globalToolLogger.SetWriter(writer) 154} 155 156func SetDateFormat(dateFormat string) { 157 globalToolLogger.SetDateFormat(dateFormat) 158} 159 160func Writer(minVerb int) io.Writer { 161 return globalToolLogger.Writer(minVerb) 162} 163