]> Cypherpunks.ru repositories - govpn.git/blob - src/cypherpunks.ru/govpn/logger.go
Simplify operations with arrays and maps
[govpn.git] / src / cypherpunks.ru / govpn / logger.go
1 // +build !windows
2
3 /*
4 GoVPN -- simple secure free software virtual private network daemon
5 Copyright (C) 2014-2017 Sergey Matveev <stargrave@stargrave.org>
6               2016-2017 Bruno Clermont <bruno@robotinfra.com>
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 package govpn
23
24 import (
25         "bytes"
26         "fmt"
27         logsyslog "log/syslog"
28         "os"
29         "sort"
30         "time"
31
32         "github.com/Sirupsen/logrus"
33         "github.com/Sirupsen/logrus/hooks/syslog"
34         "github.com/pkg/errors"
35 )
36
37 // syslogFormatter is a syslog friendly formatter
38 type syslogFormatter struct{}
39
40 // Format converts a log entry into a list of bytes
41 func (sf *syslogFormatter) Format(entry *logrus.Entry) ([]byte, error) {
42         var buf bytes.Buffer
43         var err error
44         keys := make([]string, 0, len(entry.Data))
45         for k := range entry.Data {
46                 keys = append(keys, k)
47         }
48         sort.Strings(keys)
49
50         for _, k := range keys {
51                 if _, err = buf.WriteString(fmt.Sprintf("[%s]%+v ", k, entry.Data[k])); err != nil {
52                         return nil, errors.Wrapf(err, "buf.WriteString %s", k)
53                 }
54         }
55         if _, err = buf.WriteString(entry.Message); err != nil {
56                 return nil, errors.Wrap(err, "buf.WriteString message")
57         }
58         return buf.Bytes(), nil
59 }
60
61 // NewLogger returns a logger for specified level. Syslog or Windows Events can be turned on.
62 func NewLogger(level string, syslog bool) (*logrus.Logger, error) {
63         var logger *logrus.Logger
64         logLevel, err := logrus.ParseLevel(level)
65         if err != nil {
66                 return nil, errors.Wrap(err, "logrus.ParseLevel")
67         }
68
69         if syslog {
70                 syslogHook, err := logrus_syslog.NewSyslogHook("", "", logsyslog.LOG_INFO, "GoVPN")
71                 if err != nil {
72                         return nil, errors.Wrap(err, "logrus_syslog.NewSyslogHook")
73                 }
74                 logger = &logrus.Logger{
75                         Formatter: &syslogFormatter{},
76                         Hooks:     make(logrus.LevelHooks),
77                 }
78                 logger.Hooks.Add(syslogHook)
79         } else {
80                 logger = &logrus.Logger{
81                         Formatter: &logrus.TextFormatter{
82                                 ForceColors:      true,
83                                 DisableColors:    false,
84                                 DisableTimestamp: false,
85                                 FullTimestamp:    true,
86                                 TimestampFormat:  time.RFC3339Nano,
87                                 DisableSorting:   false,
88                         },
89                         Hooks: make(logrus.LevelHooks),
90                 }
91         }
92         logger.Out = os.Stderr
93         logger.Level = logLevel
94         logger.WithFields(logrus.Fields{
95                 "version": VersionGet(),
96                 "level":   logLevel.String(),
97         }).Info("Initialize logging")
98         return logger, nil
99 }
100
101 // ExtendLogFields adds batch of log Fields to existing fields ones
102 func ExtendLogFields(input *logrus.Fields, add logrus.Fields) {
103         i := *input
104         for k, v := range add {
105                 i[k] = v
106         }
107 }
108
109 // MergeLogFields combines multiple log fields into a single one
110 func MergeLogFields(fields ...logrus.Fields) (output logrus.Fields) {
111         output = logrus.Fields{}
112         for _, f := range fields {
113                 ExtendLogFields(&output, f)
114         }
115         return
116 }