File: stdlog.go

package info (click to toggle)
golang-github-alexcesaro-log 0.0~git20150915.61e6862-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 128 kB
  • sloc: makefile: 2
file content (140 lines) | stat: -rw-r--r-- 4,140 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Package stdlog provides simple and fast logging to the standard output
// (stdout) and is optimized for programs launched via a shell or cron. It can
// also be used to log to a file by redirecting the standard output to a file.
// This package is thread-safe.
//
// Basic examples:
//
//     logger := stdlog.GetFromFlags()
//     logger.Info("Connecting to the server...")
//     logger.Errorf("Connection failed: %q", err)
//
// Will output:
//
//     2014-04-02 18:09:15.862 INFO Connecting to the API...
//     2014-04-02 18:10:14.347 ERROR Connection failed (Server is unavailable).
//
// Log*() functions can be used to avoid evaluating arguments when it is
// expensive and unnecessary:
//
//     logger.Debug("Memory usage: %s", getMemoryUsage())
//     if LogDebug() { logger.Debug("Memory usage: %s", getMemoryUsage()) }
//
// If debug logging is off the getMemoryUsage() will be executed on the first
// line while it will not be executed on the second line.
//
// List of command-line arguments:
//
//     -log=info
//         Log events at or above this level are logged.
//     -stderr=false
//         Logs are written to standard error (stderr) instead of standard
//         output.
//     -flushlog=none
//         Until this level is reached nothing is output and logs are stored
//         in the memory. Once a log event is at or above this level, it
//         outputs all logs in memory as well as the future log events. This
//         feature should not be used with long-running processes.
//
// The available levels are the eight ones described in RFC 5424 (debug, info,
// notice, warning, error, critical, alert, emergency) and none.
//
// Some use cases:
//    - By default, all logs except debug ones are output to the stdout. Which
//      is useful to follow the execution of a program launched via a shell.
//    - A program launched by a crontab where the variable `MAILTO` is set
//      with `-debug -flushlog=error` will send all logs generated by the
//      program only if an error happens. When there is no error the email
//      will not be sent.
//    - `my_program > /var/log/my_program/my_program-$(date+%Y-%m-%d-%H%M%S).log`
//      will create a log file in /var/log/my_program each time it is run.
package stdlog

import (
	"flag"
	"fmt"
	"io"
	"os"

	"github.com/alexcesaro/log"
	"github.com/alexcesaro/log/buflog"
	"github.com/alexcesaro/log/golog"
)

var (
	logger             log.Logger
	thresholdName      *string
	logToStderr        *bool
	flushThresholdName *string
)

// GetFromFlags returns the logger defined by the command-line flags. This
// function runs flag.Parse() if it has not been run yet.
func GetFromFlags() log.Logger {
	if logger != nil {
		return logger
	}
	if !flag.Parsed() {
		flag.Parse()
	}

	threshold := getLevelFromName(*thresholdName)
	thresholdName = nil

	out := getStream(*logToStderr)
	logToStderr = nil

	flushThreshold := getLevelFromName(*flushThresholdName)
	flushThresholdName = nil

	if flushThreshold == log.None {
		logger = golog.New(out, threshold)
	} else {
		logger = buflog.New(out, threshold, flushThreshold)
	}

	return logger
}

func init() {
	thresholdName = flag.String("log", "info", "sets the logging threshold")
	logToStderr = flag.Bool("stderr", false, "outputs to standard error (stderr)")
	flushThresholdName = flag.String("flushlog", "none", "sets the flush trigger level")
}

func getLevelFromName(levelName string) (level log.Level) {
	switch levelName {
	case "debug":
		level = log.Debug
	case "info":
		level = log.Info
	case "notice":
		level = log.Notice
	case "warning":
		level = log.Warning
	case "error":
		level = log.Error
	case "critical":
		level = log.Critical
	case "alert":
		level = log.Alert
	case "emergency":
		level = log.Emergency
	case "none":
		level = log.None
	default:
		fmt.Fprintf(os.Stderr, "Invalid level value %q, allowed values are: debug, info, notice, warning, error, critical, alert, emergency and none\n", levelName)
		os.Exit(2)
	}

	return
}

// Stubbed out for testing.
var getStream = func(logToStderr bool) io.Writer {
	if logToStderr {
		return os.Stderr
	}

	return os.Stdout
}