]> Cypherpunks.ru repositories - govpn.git/blob - src/cypherpunks.ru/govpn/logger.go
967b8434b6071c870f32134a307df2d36830b89b
[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 formatter that is syslog friendly
38 type syslogFormatter struct {
39 }
40
41 // Format convert a log entry into a list of bytes
42 func (sf *syslogFormatter) Format(entry *logrus.Entry) ([]byte, error) {
43         buf := bytes.NewBuffer(nil)
44         var (
45                 err   error
46                 index int
47         )
48         keys := make([]string, len(entry.Data))
49         for k := range entry.Data {
50                 keys[index] = k
51                 index++
52         }
53         sort.Strings(keys)
54
55         for index = range keys {
56                 k := keys[index]
57                 v := entry.Data[k]
58                 if _, err = buf.WriteString(fmt.Sprintf("[%s]%+v ", k, v)); err != nil {
59                         return nil, errors.Wrapf(err, "buf.WriteString %s", k)
60                 }
61         }
62         if _, err = buf.WriteString(entry.Message); err != nil {
63                 return nil, errors.Wrap(err, "buf.WriteString message")
64         }
65         return buf.Bytes(), nil
66 }
67
68 // NewLogger return a logger for specified level. Syslog or Windows Events can be turned on.
69 func NewLogger(level string, syslog bool) (*logrus.Logger, error) {
70         var logger *logrus.Logger
71         logLevel, err := logrus.ParseLevel(level)
72         if err != nil {
73                 return nil, errors.Wrap(err, "logrus.ParseLevel")
74         }
75
76         if syslog {
77                 syslogHook, err := logrus_syslog.NewSyslogHook("", "", logsyslog.LOG_INFO, "GoVPN")
78                 if err != nil {
79                         return nil, errors.Wrap(err, "logrus_syslog.NewSyslogHook")
80                 }
81                 logger = &logrus.Logger{
82                         Formatter: &syslogFormatter{},
83                         Hooks:     make(logrus.LevelHooks),
84                 }
85                 logger.Hooks.Add(syslogHook)
86         } else {
87                 logger = &logrus.Logger{
88                         Formatter: &logrus.TextFormatter{
89                                 ForceColors:      true,
90                                 DisableColors:    false,
91                                 DisableTimestamp: false,
92                                 FullTimestamp:    true,
93                                 TimestampFormat:  time.RFC3339Nano,
94                                 DisableSorting:   false,
95                         },
96                         Hooks: make(logrus.LevelHooks),
97                 }
98         }
99         logger.Out = os.Stderr
100         logger.Level = logLevel
101         logger.WithFields(logrus.Fields{
102                 "version": VersionGet(),
103                 "level":   logLevel.String(),
104         }).Info("Initialize logging")
105         return logger, nil
106 }
107
108 // ExtendLogFields add to existing fields a new batch of log Fields
109 func ExtendLogFields(input *logrus.Fields, add logrus.Fields) {
110         i := *input
111         for k, v := range add {
112                 i[k] = v
113         }
114 }
115
116 // MergeLogFields combine multiple log fields into a single one
117 func MergeLogFields(fields ...logrus.Fields) (output logrus.Fields) {
118         output = logrus.Fields{}
119         for _, f := range fields {
120                 ExtendLogFields(&output, f)
121         }
122         return
123 }