mirror of
https://github.com/DNSCrypt/dnscrypt-proxy.git
synced 2025-04-04 05:37:38 +03:00
Logs can now be sent to files or syslog in addition to stderr
This commit is contained in:
parent
b0f6a04dc4
commit
0a63975d48
14 changed files with 518 additions and 10 deletions
8
Gopkg.lock
generated
8
Gopkg.lock
generated
|
@ -43,6 +43,12 @@
|
|||
packages = ["."]
|
||||
revision = "59b67882ec612f43b9d4c4fd97cebd507be4b3ee"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/go-syslog"
|
||||
packages = ["."]
|
||||
revision = "326bf4a7f709d263f964a6a96558676b103f3534"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/golang-lru"
|
||||
|
@ -56,7 +62,7 @@
|
|||
branch = "master"
|
||||
name = "github.com/jedisct1/dlog"
|
||||
packages = ["."]
|
||||
revision = "8c253f4161c5b23a5fedd1d1ccee28d7ea312c6c"
|
||||
revision = "fcbcc457e6a2b4eab2325a0902fd3d0a7d17e548"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
|
|
|
@ -69,7 +69,6 @@ The current 2.0.0 beta version includes all the major features from dnscrypt-pro
|
|||
* New super simple (to copy&paste), extensible format for servers parameters: "stamps"
|
||||
* Offline responses
|
||||
* Local DNSSEC validation
|
||||
* Flexible logging
|
||||
* [DNS-over-HTTP2 (DoH)](https://datatracker.ietf.org/wg/doh/about/), the successor to DNS-over-TLS
|
||||
* Support for the V1 plugin API
|
||||
* Real documentation
|
||||
|
|
|
@ -51,7 +51,7 @@ type App struct {
|
|||
}
|
||||
|
||||
func main() {
|
||||
dlog.Init("dnscrypt-proxy", dlog.SeverityNotice)
|
||||
dlog.Init("dnscrypt-proxy", dlog.SeverityNotice, "DAEMON")
|
||||
cdLocal()
|
||||
|
||||
svcConfig := &service.Config{
|
||||
|
|
22
vendor/github.com/hashicorp/go-syslog/.gitignore
generated
vendored
Normal file
22
vendor/github.com/hashicorp/go-syslog/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
20
vendor/github.com/hashicorp/go-syslog/LICENSE
generated
vendored
Normal file
20
vendor/github.com/hashicorp/go-syslog/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Armon Dadgar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
11
vendor/github.com/hashicorp/go-syslog/README.md
generated
vendored
Normal file
11
vendor/github.com/hashicorp/go-syslog/README.md
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
go-syslog
|
||||
=========
|
||||
|
||||
This repository provides a very simple `gsyslog` package. The point of this
|
||||
package is to allow safe importing of syslog without introducing cross-compilation
|
||||
issues. The stdlib `log/syslog` cannot be imported on Windows systems, and without
|
||||
conditional compilation this adds complications.
|
||||
|
||||
Instead, `gsyslog` provides a very simple wrapper around `log/syslog` but returns
|
||||
a runtime error if attempting to initialize on a non Linux or OSX system.
|
||||
|
214
vendor/github.com/hashicorp/go-syslog/builtin.go
generated
vendored
Normal file
214
vendor/github.com/hashicorp/go-syslog/builtin.go
generated
vendored
Normal file
|
@ -0,0 +1,214 @@
|
|||
// This file is taken from the log/syslog in the standard lib.
|
||||
// However, there is a bug with overwhelming syslog that causes writes
|
||||
// to block indefinitely. This is fixed by adding a write deadline.
|
||||
//
|
||||
// +build !windows,!nacl,!plan9
|
||||
|
||||
package gsyslog
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/syslog"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const severityMask = 0x07
|
||||
const facilityMask = 0xf8
|
||||
const localDeadline = 20 * time.Millisecond
|
||||
const remoteDeadline = 50 * time.Millisecond
|
||||
|
||||
// A builtinWriter is a connection to a syslog server.
|
||||
type builtinWriter struct {
|
||||
priority syslog.Priority
|
||||
tag string
|
||||
hostname string
|
||||
network string
|
||||
raddr string
|
||||
|
||||
mu sync.Mutex // guards conn
|
||||
conn serverConn
|
||||
}
|
||||
|
||||
// This interface and the separate syslog_unix.go file exist for
|
||||
// Solaris support as implemented by gccgo. On Solaris you can not
|
||||
// simply open a TCP connection to the syslog daemon. The gccgo
|
||||
// sources have a syslog_solaris.go file that implements unixSyslog to
|
||||
// return a type that satisfies this interface and simply calls the C
|
||||
// library syslog function.
|
||||
type serverConn interface {
|
||||
writeString(p syslog.Priority, hostname, tag, s, nl string) error
|
||||
close() error
|
||||
}
|
||||
|
||||
type netConn struct {
|
||||
local bool
|
||||
conn net.Conn
|
||||
}
|
||||
|
||||
// New establishes a new connection to the system log daemon. Each
|
||||
// write to the returned writer sends a log message with the given
|
||||
// priority and prefix.
|
||||
func newBuiltin(priority syslog.Priority, tag string) (w *builtinWriter, err error) {
|
||||
return dialBuiltin("", "", priority, tag)
|
||||
}
|
||||
|
||||
// Dial establishes a connection to a log daemon by connecting to
|
||||
// address raddr on the specified network. Each write to the returned
|
||||
// writer sends a log message with the given facility, severity and
|
||||
// tag.
|
||||
// If network is empty, Dial will connect to the local syslog server.
|
||||
func dialBuiltin(network, raddr string, priority syslog.Priority, tag string) (*builtinWriter, error) {
|
||||
if priority < 0 || priority > syslog.LOG_LOCAL7|syslog.LOG_DEBUG {
|
||||
return nil, errors.New("log/syslog: invalid priority")
|
||||
}
|
||||
|
||||
if tag == "" {
|
||||
tag = os.Args[0]
|
||||
}
|
||||
hostname, _ := os.Hostname()
|
||||
|
||||
w := &builtinWriter{
|
||||
priority: priority,
|
||||
tag: tag,
|
||||
hostname: hostname,
|
||||
network: network,
|
||||
raddr: raddr,
|
||||
}
|
||||
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
|
||||
err := w.connect()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return w, err
|
||||
}
|
||||
|
||||
// connect makes a connection to the syslog server.
|
||||
// It must be called with w.mu held.
|
||||
func (w *builtinWriter) connect() (err error) {
|
||||
if w.conn != nil {
|
||||
// ignore err from close, it makes sense to continue anyway
|
||||
w.conn.close()
|
||||
w.conn = nil
|
||||
}
|
||||
|
||||
if w.network == "" {
|
||||
w.conn, err = unixSyslog()
|
||||
if w.hostname == "" {
|
||||
w.hostname = "localhost"
|
||||
}
|
||||
} else {
|
||||
var c net.Conn
|
||||
c, err = net.DialTimeout(w.network, w.raddr, remoteDeadline)
|
||||
if err == nil {
|
||||
w.conn = &netConn{conn: c}
|
||||
if w.hostname == "" {
|
||||
w.hostname = c.LocalAddr().String()
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Write sends a log message to the syslog daemon.
|
||||
func (w *builtinWriter) Write(b []byte) (int, error) {
|
||||
return w.writeAndRetry(w.priority, string(b))
|
||||
}
|
||||
|
||||
// Close closes a connection to the syslog daemon.
|
||||
func (w *builtinWriter) Close() error {
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
|
||||
if w.conn != nil {
|
||||
err := w.conn.close()
|
||||
w.conn = nil
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *builtinWriter) writeAndRetry(p syslog.Priority, s string) (int, error) {
|
||||
pr := (w.priority & facilityMask) | (p & severityMask)
|
||||
|
||||
w.mu.Lock()
|
||||
defer w.mu.Unlock()
|
||||
|
||||
if w.conn != nil {
|
||||
if n, err := w.write(pr, s); err == nil {
|
||||
return n, err
|
||||
}
|
||||
}
|
||||
if err := w.connect(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return w.write(pr, s)
|
||||
}
|
||||
|
||||
// write generates and writes a syslog formatted string. The
|
||||
// format is as follows: <PRI>TIMESTAMP HOSTNAME TAG[PID]: MSG
|
||||
func (w *builtinWriter) write(p syslog.Priority, msg string) (int, error) {
|
||||
// ensure it ends in a \n
|
||||
nl := ""
|
||||
if !strings.HasSuffix(msg, "\n") {
|
||||
nl = "\n"
|
||||
}
|
||||
|
||||
err := w.conn.writeString(p, w.hostname, w.tag, msg, nl)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
// Note: return the length of the input, not the number of
|
||||
// bytes printed by Fprintf, because this must behave like
|
||||
// an io.Writer.
|
||||
return len(msg), nil
|
||||
}
|
||||
|
||||
func (n *netConn) writeString(p syslog.Priority, hostname, tag, msg, nl string) error {
|
||||
if n.local {
|
||||
// Compared to the network form below, the changes are:
|
||||
// 1. Use time.Stamp instead of time.RFC3339.
|
||||
// 2. Drop the hostname field from the Fprintf.
|
||||
timestamp := time.Now().Format(time.Stamp)
|
||||
n.conn.SetWriteDeadline(time.Now().Add(localDeadline))
|
||||
_, err := fmt.Fprintf(n.conn, "<%d>%s %s[%d]: %s%s",
|
||||
p, timestamp,
|
||||
tag, os.Getpid(), msg, nl)
|
||||
return err
|
||||
}
|
||||
timestamp := time.Now().Format(time.RFC3339)
|
||||
n.conn.SetWriteDeadline(time.Now().Add(remoteDeadline))
|
||||
_, err := fmt.Fprintf(n.conn, "<%d>%s %s %s[%d]: %s%s",
|
||||
p, timestamp, hostname,
|
||||
tag, os.Getpid(), msg, nl)
|
||||
return err
|
||||
}
|
||||
|
||||
func (n *netConn) close() error {
|
||||
return n.conn.Close()
|
||||
}
|
||||
|
||||
// unixSyslog opens a connection to the syslog daemon running on the
|
||||
// local machine using a Unix domain socket.
|
||||
func unixSyslog() (conn serverConn, err error) {
|
||||
logTypes := []string{"unixgram", "unix"}
|
||||
logPaths := []string{"/dev/log", "/var/run/syslog", "/var/run/log"}
|
||||
for _, network := range logTypes {
|
||||
for _, path := range logPaths {
|
||||
conn, err := net.DialTimeout(network, path, localDeadline)
|
||||
if err != nil {
|
||||
continue
|
||||
} else {
|
||||
return &netConn{conn: conn, local: true}, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, errors.New("Unix syslog delivery error")
|
||||
}
|
27
vendor/github.com/hashicorp/go-syslog/syslog.go
generated
vendored
Normal file
27
vendor/github.com/hashicorp/go-syslog/syslog.go
generated
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
package gsyslog
|
||||
|
||||
// Priority maps to the syslog priority levels
|
||||
type Priority int
|
||||
|
||||
const (
|
||||
LOG_EMERG Priority = iota
|
||||
LOG_ALERT
|
||||
LOG_CRIT
|
||||
LOG_ERR
|
||||
LOG_WARNING
|
||||
LOG_NOTICE
|
||||
LOG_INFO
|
||||
LOG_DEBUG
|
||||
)
|
||||
|
||||
// Syslogger interface is used to write log messages to syslog
|
||||
type Syslogger interface {
|
||||
// WriteLevel is used to write a message at a given level
|
||||
WriteLevel(Priority, []byte) error
|
||||
|
||||
// Write is used to write a message at the default level
|
||||
Write([]byte) (int, error)
|
||||
|
||||
// Close is used to close the connection to the logger
|
||||
Close() error
|
||||
}
|
123
vendor/github.com/hashicorp/go-syslog/unix.go
generated
vendored
Normal file
123
vendor/github.com/hashicorp/go-syslog/unix.go
generated
vendored
Normal file
|
@ -0,0 +1,123 @@
|
|||
// +build linux darwin dragonfly freebsd netbsd openbsd solaris
|
||||
|
||||
package gsyslog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/syslog"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// builtinLogger wraps the Golang implementation of a
|
||||
// syslog.Writer to provide the Syslogger interface
|
||||
type builtinLogger struct {
|
||||
*builtinWriter
|
||||
}
|
||||
|
||||
// NewLogger is used to construct a new Syslogger
|
||||
func NewLogger(p Priority, facility, tag string) (Syslogger, error) {
|
||||
fPriority, err := facilityPriority(facility)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
priority := syslog.Priority(p) | fPriority
|
||||
l, err := newBuiltin(priority, tag)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &builtinLogger{l}, nil
|
||||
}
|
||||
|
||||
// DialLogger is used to construct a new Syslogger that establishes connection to remote syslog server
|
||||
func DialLogger(network, raddr string, p Priority, facility, tag string) (Syslogger, error) {
|
||||
fPriority, err := facilityPriority(facility)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
priority := syslog.Priority(p) | fPriority
|
||||
|
||||
l, err := dialBuiltin(network, raddr, priority, tag)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &builtinLogger{l}, nil
|
||||
}
|
||||
|
||||
// WriteLevel writes out a message at the given priority
|
||||
func (b *builtinLogger) WriteLevel(p Priority, buf []byte) error {
|
||||
var err error
|
||||
m := string(buf)
|
||||
switch p {
|
||||
case LOG_EMERG:
|
||||
_, err = b.writeAndRetry(syslog.LOG_EMERG, m)
|
||||
case LOG_ALERT:
|
||||
_, err = b.writeAndRetry(syslog.LOG_ALERT, m)
|
||||
case LOG_CRIT:
|
||||
_, err = b.writeAndRetry(syslog.LOG_CRIT, m)
|
||||
case LOG_ERR:
|
||||
_, err = b.writeAndRetry(syslog.LOG_ERR, m)
|
||||
case LOG_WARNING:
|
||||
_, err = b.writeAndRetry(syslog.LOG_WARNING, m)
|
||||
case LOG_NOTICE:
|
||||
_, err = b.writeAndRetry(syslog.LOG_NOTICE, m)
|
||||
case LOG_INFO:
|
||||
_, err = b.writeAndRetry(syslog.LOG_INFO, m)
|
||||
case LOG_DEBUG:
|
||||
_, err = b.writeAndRetry(syslog.LOG_DEBUG, m)
|
||||
default:
|
||||
err = fmt.Errorf("Unknown priority: %v", p)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// facilityPriority converts a facility string into
|
||||
// an appropriate priority level or returns an error
|
||||
func facilityPriority(facility string) (syslog.Priority, error) {
|
||||
facility = strings.ToUpper(facility)
|
||||
switch facility {
|
||||
case "KERN":
|
||||
return syslog.LOG_KERN, nil
|
||||
case "USER":
|
||||
return syslog.LOG_USER, nil
|
||||
case "MAIL":
|
||||
return syslog.LOG_MAIL, nil
|
||||
case "DAEMON":
|
||||
return syslog.LOG_DAEMON, nil
|
||||
case "AUTH":
|
||||
return syslog.LOG_AUTH, nil
|
||||
case "SYSLOG":
|
||||
return syslog.LOG_SYSLOG, nil
|
||||
case "LPR":
|
||||
return syslog.LOG_LPR, nil
|
||||
case "NEWS":
|
||||
return syslog.LOG_NEWS, nil
|
||||
case "UUCP":
|
||||
return syslog.LOG_UUCP, nil
|
||||
case "CRON":
|
||||
return syslog.LOG_CRON, nil
|
||||
case "AUTHPRIV":
|
||||
return syslog.LOG_AUTHPRIV, nil
|
||||
case "FTP":
|
||||
return syslog.LOG_FTP, nil
|
||||
case "LOCAL0":
|
||||
return syslog.LOG_LOCAL0, nil
|
||||
case "LOCAL1":
|
||||
return syslog.LOG_LOCAL1, nil
|
||||
case "LOCAL2":
|
||||
return syslog.LOG_LOCAL2, nil
|
||||
case "LOCAL3":
|
||||
return syslog.LOG_LOCAL3, nil
|
||||
case "LOCAL4":
|
||||
return syslog.LOG_LOCAL4, nil
|
||||
case "LOCAL5":
|
||||
return syslog.LOG_LOCAL5, nil
|
||||
case "LOCAL6":
|
||||
return syslog.LOG_LOCAL6, nil
|
||||
case "LOCAL7":
|
||||
return syslog.LOG_LOCAL7, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("invalid syslog facility: %s", facility)
|
||||
}
|
||||
}
|
17
vendor/github.com/hashicorp/go-syslog/unsupported.go
generated
vendored
Normal file
17
vendor/github.com/hashicorp/go-syslog/unsupported.go
generated
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
// +build windows plan9 nacl
|
||||
|
||||
package gsyslog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// NewLogger is used to construct a new Syslogger
|
||||
func NewLogger(p Priority, facility, tag string) (Syslogger, error) {
|
||||
return nil, fmt.Errorf("Platform does not support syslog")
|
||||
}
|
||||
|
||||
// DialLogger is used to construct a new Syslogger that establishes connection to remote syslog server
|
||||
func DialLogger(network, raddr string, p Priority, facility, tag string) (Syslogger, error) {
|
||||
return nil, fmt.Errorf("Platform does not support syslog")
|
||||
}
|
15
vendor/github.com/jedisct1/dlog/Gopkg.lock
generated
vendored
Normal file
15
vendor/github.com/jedisct1/dlog/Gopkg.lock
generated
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/go-syslog"
|
||||
packages = ["."]
|
||||
revision = "326bf4a7f709d263f964a6a96558676b103f3534"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "47c6ffc1a8ae6fd34bff3832f6d38cf0e950ca98e55fb4af939dfb80e61f0409"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
3
vendor/github.com/jedisct1/dlog/Gopkg.toml
generated
vendored
Normal file
3
vendor/github.com/jedisct1/dlog/Gopkg.toml
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/hashicorp/go-syslog"
|
4
vendor/github.com/jedisct1/dlog/README.md
generated
vendored
4
vendor/github.com/jedisct1/dlog/README.md
generated
vendored
|
@ -4,6 +4,8 @@ Go's standard logger is fairly limited. As result, kazilion alternatives loggers
|
|||
|
||||
All of these are wonderful. They can make your logs look colorful and pretty, format them for ElasticSearch, and more.
|
||||
|
||||
Cool, but all I wanted is something super dumb, that just exposes `log.Info()`, `log.Error()` and a couple other standard levels. I don't need a super flexible kitchen sink. Just something super basic and trivial to use.
|
||||
Cool, but all I wanted is something super dumb, that just exposes `log.Info()`, `log.Error()` and a couple other standard levels.
|
||||
|
||||
I don't need a super flexible kitchen sink. Just something super basic and trivial to use. I just want it to handle different log levels, and be able to write simple logs to `stderr`, to a local file or to `syslog`.
|
||||
|
||||
So, here's one more logging library for Go. The dumbest of them all. Enjoy.
|
||||
|
|
61
vendor/github.com/jedisct1/dlog/dlog.go
generated
vendored
61
vendor/github.com/jedisct1/dlog/dlog.go
generated
vendored
|
@ -9,14 +9,21 @@ import (
|
|||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-syslog"
|
||||
)
|
||||
|
||||
type Severity int32
|
||||
|
||||
type globals struct {
|
||||
sync.Mutex
|
||||
logLevel Severity
|
||||
appName string
|
||||
logLevel Severity
|
||||
useSyslog *bool
|
||||
appName string
|
||||
syslogFacility string
|
||||
syslogger *gsyslog.Syslogger
|
||||
fileName *string
|
||||
outFd *os.File
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -47,6 +54,16 @@ var SeverityName = []string{
|
|||
SeverityFatal: "FATAL",
|
||||
}
|
||||
|
||||
var severityToSyslogPriority = []gsyslog.Priority{
|
||||
SeverityDebug: gsyslog.LOG_DEBUG,
|
||||
SeverityInfo: gsyslog.LOG_INFO,
|
||||
SeverityNotice: gsyslog.LOG_NOTICE,
|
||||
SeverityWarning: gsyslog.LOG_WARNING,
|
||||
SeverityError: gsyslog.LOG_ERR,
|
||||
SeverityCritical: gsyslog.LOG_CRIT,
|
||||
SeverityFatal: gsyslog.LOG_ALERT,
|
||||
}
|
||||
|
||||
func Debugf(format string, args ...interface{}) {
|
||||
logf(SeverityDebug, format, args...)
|
||||
}
|
||||
|
@ -125,9 +142,18 @@ func (s *Severity) Set(strVal string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func Init(appName string, logLevel Severity) {
|
||||
func Init(appName string, logLevel Severity, syslogFacility string) error {
|
||||
_globals.logLevel.set(logLevel)
|
||||
|
||||
if len(syslogFacility) == 0 {
|
||||
syslogFacility = "DAEMON"
|
||||
}
|
||||
_globals.appName = appName
|
||||
_globals.syslogFacility = syslogFacility
|
||||
_globals.useSyslog = flag.Bool("syslog", false, "Send logs to the local system logger")
|
||||
_globals.fileName = flag.String("logfile", "", "Write logs to file")
|
||||
flag.Var(&_globals.logLevel, "loglevel", fmt.Sprintf("Log level (%d-%d)", SeverityDebug, SeverityFatal))
|
||||
return nil
|
||||
}
|
||||
|
||||
func logf(severity Severity, format string, args ...interface{}) {
|
||||
|
@ -142,10 +168,33 @@ func logf(severity Severity, format string, args ...interface{}) {
|
|||
if len(message) <= 0 {
|
||||
return
|
||||
}
|
||||
line := fmt.Sprintf("[%d-%02d-%02d %02d:%02d:%02d] [%s] [%s] %s\n", year, int(month), day, hour, minute, second, _globals.appName, SeverityName[severity], message)
|
||||
_globals.Lock()
|
||||
os.Stderr.WriteString(line)
|
||||
_globals.Unlock()
|
||||
defer _globals.Unlock()
|
||||
if *_globals.useSyslog && _globals.syslogger == nil {
|
||||
syslogger, err := gsyslog.NewLogger(gsyslog.LOG_INFO, _globals.syslogFacility, _globals.appName)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_globals.syslogger = &syslogger
|
||||
}
|
||||
if _globals.fileName != nil && len(*_globals.fileName) > 0 && _globals.outFd == nil {
|
||||
outFd, err := os.OpenFile(*_globals.fileName, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
_globals.outFd = outFd
|
||||
}
|
||||
if _globals.syslogger != nil {
|
||||
(*_globals.syslogger).WriteLevel(severityToSyslogPriority[severity], []byte(message))
|
||||
} else {
|
||||
line := fmt.Sprintf("[%d-%02d-%02d %02d:%02d:%02d] [%s] [%s] %s\n", year, int(month), day, hour, minute, second, _globals.appName, SeverityName[severity], message)
|
||||
if _globals.outFd != nil {
|
||||
_globals.outFd.WriteString(line)
|
||||
_globals.outFd.Sync()
|
||||
} else {
|
||||
os.Stderr.WriteString(line)
|
||||
}
|
||||
}
|
||||
if severity >= SeverityFatal {
|
||||
os.Exit(255)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue