mirror of
https://github.com/nabbar/golib.git
synced 2025-11-01 19:42:35 +08:00
Fix logger :
- issue #106 - fix bug with color linux / win - fix bug with color between std, file and syslog
This commit is contained in:
@@ -44,13 +44,14 @@ type HookFile interface {
|
|||||||
|
|
||||||
type _HookFile struct {
|
type _HookFile struct {
|
||||||
f *os.File
|
f *os.File
|
||||||
|
r logrus.Formatter
|
||||||
l []logrus.Level
|
l []logrus.Level
|
||||||
s bool
|
s bool
|
||||||
d bool
|
d bool
|
||||||
t bool
|
t bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHookFile(opt OptionsFile) (HookFile, error) {
|
func NewHookFile(opt OptionsFile, format logrus.Formatter) (HookFile, error) {
|
||||||
if opt.Filepath == "" {
|
if opt.Filepath == "" {
|
||||||
return nil, fmt.Errorf("missing file path")
|
return nil, fmt.Errorf("missing file path")
|
||||||
}
|
}
|
||||||
@@ -92,6 +93,7 @@ func NewHookFile(opt OptionsFile) (HookFile, error) {
|
|||||||
|
|
||||||
return &_HookFile{
|
return &_HookFile{
|
||||||
f: hdl,
|
f: hdl,
|
||||||
|
r: format,
|
||||||
l: LVLs,
|
l: LVLs,
|
||||||
s: opt.DisableStack,
|
s: opt.DisableStack,
|
||||||
d: opt.DisableTimestamp,
|
d: opt.DisableTimestamp,
|
||||||
@@ -125,7 +127,7 @@ func (o *_HookFile) Fire(entry *logrus.Entry) error {
|
|||||||
ent.Data = o.filterKey(ent.Data, FieldLine)
|
ent.Data = o.filterKey(ent.Data, FieldLine)
|
||||||
}
|
}
|
||||||
|
|
||||||
if p, err := ent.Bytes(); err != nil {
|
if p, err := o.r.Format(ent); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if _, err = o.Write(p); err != nil {
|
} else if _, err = o.Write(p); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -30,10 +30,20 @@ package logger
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/mattn/go-colorable"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type StdWriter uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
StdOut StdWriter = iota
|
||||||
|
StdErr
|
||||||
|
)
|
||||||
|
|
||||||
type HookStandard interface {
|
type HookStandard interface {
|
||||||
logrus.Hook
|
logrus.Hook
|
||||||
io.WriteCloser
|
io.WriteCloser
|
||||||
@@ -48,11 +58,29 @@ type _HookStd struct {
|
|||||||
t bool // Disable Trace
|
t bool // Disable Trace
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHookStandard(opt Options, w io.Writer, lvls []logrus.Level) HookFile {
|
func NewHookStandard(opt Options, s StdWriter, lvls []logrus.Level) HookFile {
|
||||||
if len(lvls) < 1 {
|
if len(lvls) < 1 {
|
||||||
lvls = logrus.AllLevels
|
lvls = logrus.AllLevels
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var w io.Writer
|
||||||
|
|
||||||
|
if opt.DisableColor {
|
||||||
|
switch s {
|
||||||
|
case StdErr:
|
||||||
|
w = os.Stderr
|
||||||
|
default:
|
||||||
|
w = os.Stdout
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch s {
|
||||||
|
case StdErr:
|
||||||
|
w = colorable.NewColorableStderr()
|
||||||
|
default:
|
||||||
|
w = colorable.NewColorableStderr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &_HookStd{
|
return &_HookStd{
|
||||||
w: w,
|
w: w,
|
||||||
l: lvls,
|
l: lvls,
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ package logger
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log/syslog"
|
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
@@ -41,18 +40,32 @@ type HookSyslog interface {
|
|||||||
RegisterHook(log *logrus.Logger)
|
RegisterHook(log *logrus.Logger)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type syslogWrapper interface {
|
||||||
|
io.WriteCloser
|
||||||
|
|
||||||
|
Panic(p []byte) (n int, err error)
|
||||||
|
Fatal(p []byte) (n int, err error)
|
||||||
|
Error(p []byte) (n int, err error)
|
||||||
|
Warning(p []byte) (n int, err error)
|
||||||
|
Info(p []byte) (n int, err error)
|
||||||
|
Debug(p []byte) (n int, err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type FuncFormatter func() logrus.Formatter
|
||||||
|
|
||||||
type _HookSyslog struct {
|
type _HookSyslog struct {
|
||||||
w *syslog.Writer
|
w syslogWrapper
|
||||||
|
f logrus.Formatter
|
||||||
l []logrus.Level
|
l []logrus.Level
|
||||||
s bool
|
s bool
|
||||||
d bool
|
d bool
|
||||||
t bool
|
t bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHookSyslog(opt OptionsSyslog) (HookSyslog, error) {
|
func NewHookSyslog(opt OptionsSyslog, format logrus.Formatter) (HookSyslog, error) {
|
||||||
var (
|
var (
|
||||||
LVLs = make([]logrus.Level, 0)
|
LVLs = make([]logrus.Level, 0)
|
||||||
sys *syslog.Writer
|
sys syslogWrapper
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -64,12 +77,13 @@ func NewHookSyslog(opt OptionsSyslog) (HookSyslog, error) {
|
|||||||
LVLs = logrus.AllLevels
|
LVLs = logrus.AllLevels
|
||||||
}
|
}
|
||||||
|
|
||||||
if sys, err = syslog.Dial(opt.Network.String(), opt.Host, opt.Priority, opt.Tag); err != nil {
|
if sys, err = newSyslog(MakeNetwork(opt.Network), opt.Host, opt.Tag, MakeSeverity(opt.Severity), MakeFacility(opt.Facility)); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &_HookSyslog{
|
return &_HookSyslog{
|
||||||
w: sys,
|
w: sys,
|
||||||
|
f: format,
|
||||||
l: LVLs,
|
l: LVLs,
|
||||||
s: opt.DisableStack,
|
s: opt.DisableStack,
|
||||||
d: opt.DisableTimestamp,
|
d: opt.DisableTimestamp,
|
||||||
@@ -103,13 +117,28 @@ func (o *_HookSyslog) Fire(entry *logrus.Entry) error {
|
|||||||
ent.Data = o.filterKey(ent.Data, FieldLine)
|
ent.Data = o.filterKey(ent.Data, FieldLine)
|
||||||
}
|
}
|
||||||
|
|
||||||
if p, err := ent.Bytes(); err != nil {
|
if p, err := o.f.Format(ent); err != nil {
|
||||||
return err
|
|
||||||
} else if _, err = o.Write(p); err != nil {
|
|
||||||
return err
|
return err
|
||||||
|
} else {
|
||||||
|
switch ent.Level {
|
||||||
|
case logrus.PanicLevel:
|
||||||
|
_, err = o.w.Panic(p)
|
||||||
|
case logrus.FatalLevel:
|
||||||
|
_, err = o.w.Fatal(p)
|
||||||
|
case logrus.ErrorLevel:
|
||||||
|
_, err = o.w.Error(p)
|
||||||
|
case logrus.WarnLevel:
|
||||||
|
_, err = o.w.Warning(p)
|
||||||
|
case logrus.InfoLevel:
|
||||||
|
_, err = o.w.Info(p)
|
||||||
|
case logrus.DebugLevel:
|
||||||
|
_, err = o.w.Debug(p)
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *_HookSyslog) Write(p []byte) (n int, err error) {
|
func (o *_HookSyslog) Write(p []byte) (n int, err error) {
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
|
||||||
"path"
|
"path"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
@@ -42,8 +41,6 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mattn/go-colorable"
|
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -66,14 +63,10 @@ type logger struct {
|
|||||||
c *atomic.Value
|
c *atomic.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *logger) defaultFormatter(opt *Options) *logrus.TextFormatter {
|
func defaultFormatter() logrus.TextFormatter {
|
||||||
if opt == nil {
|
return logrus.TextFormatter{
|
||||||
opt = &Options{}
|
ForceColors: false,
|
||||||
}
|
DisableColors: false,
|
||||||
|
|
||||||
return &logrus.TextFormatter{
|
|
||||||
ForceColors: true,
|
|
||||||
DisableColors: opt.DisableColor,
|
|
||||||
ForceQuote: false,
|
ForceQuote: false,
|
||||||
DisableQuote: false,
|
DisableQuote: false,
|
||||||
EnvironmentOverrideColors: false,
|
EnvironmentOverrideColors: false,
|
||||||
@@ -90,6 +83,29 @@ func (l *logger) defaultFormatter(opt *Options) *logrus.TextFormatter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *logger) defaultFormatter(opt *Options) logrus.Formatter {
|
||||||
|
f := defaultFormatter()
|
||||||
|
|
||||||
|
if opt != nil && opt.DisableColor {
|
||||||
|
f.ForceColors = false
|
||||||
|
f.EnvironmentOverrideColors = false
|
||||||
|
f.DisableColors = true
|
||||||
|
} else {
|
||||||
|
f.ForceColors = true
|
||||||
|
f.DisableColors = false
|
||||||
|
}
|
||||||
|
|
||||||
|
return &f
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *logger) defaultFormatterNoColor() logrus.Formatter {
|
||||||
|
f := defaultFormatter()
|
||||||
|
f.ForceColors = false
|
||||||
|
f.EnvironmentOverrideColors = false
|
||||||
|
f.DisableColors = true
|
||||||
|
return &f
|
||||||
|
}
|
||||||
|
|
||||||
func (l *logger) closeAdd(clo io.Closer) {
|
func (l *logger) closeAdd(clo io.Closer) {
|
||||||
lst := append(l.closeGet(), clo)
|
lst := append(l.closeGet(), clo)
|
||||||
|
|
||||||
@@ -259,23 +275,13 @@ func (l *logger) setOptionsMutex(ctx context.Context, opt *Options) error {
|
|||||||
obj.SetOutput(ioutil.Discard) // Send all logs to nowhere by default
|
obj.SetOutput(ioutil.Discard) // Send all logs to nowhere by default
|
||||||
|
|
||||||
if !opt.DisableStandard {
|
if !opt.DisableStandard {
|
||||||
var (
|
obj.AddHook(NewHookStandard(*opt, StdOut, []logrus.Level{
|
||||||
o io.Writer = os.Stdout
|
|
||||||
e io.Writer = os.Stderr
|
|
||||||
)
|
|
||||||
|
|
||||||
if opt.DisableColor {
|
|
||||||
o = colorable.NewColorableStdout()
|
|
||||||
e = colorable.NewColorableStderr()
|
|
||||||
}
|
|
||||||
|
|
||||||
obj.AddHook(NewHookStandard(*opt, o, []logrus.Level{
|
|
||||||
logrus.InfoLevel,
|
logrus.InfoLevel,
|
||||||
logrus.DebugLevel,
|
logrus.DebugLevel,
|
||||||
logrus.TraceLevel,
|
logrus.TraceLevel,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
obj.AddHook(NewHookStandard(*opt, e, []logrus.Level{
|
obj.AddHook(NewHookStandard(*opt, StdErr, []logrus.Level{
|
||||||
logrus.PanicLevel,
|
logrus.PanicLevel,
|
||||||
logrus.FatalLevel,
|
logrus.FatalLevel,
|
||||||
logrus.ErrorLevel,
|
logrus.ErrorLevel,
|
||||||
@@ -285,7 +291,7 @@ func (l *logger) setOptionsMutex(ctx context.Context, opt *Options) error {
|
|||||||
|
|
||||||
if len(opt.LogFile) > 0 {
|
if len(opt.LogFile) > 0 {
|
||||||
for _, fopt := range opt.LogFile {
|
for _, fopt := range opt.LogFile {
|
||||||
if hook, err := NewHookFile(fopt); err != nil {
|
if hook, err := NewHookFile(fopt, l.defaultFormatterNoColor()); err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
l.closeAdd(hook)
|
l.closeAdd(hook)
|
||||||
@@ -296,7 +302,7 @@ func (l *logger) setOptionsMutex(ctx context.Context, opt *Options) error {
|
|||||||
|
|
||||||
if len(opt.LogSyslog) > 0 {
|
if len(opt.LogSyslog) > 0 {
|
||||||
for _, lopt := range opt.LogSyslog {
|
for _, lopt := range opt.LogSyslog {
|
||||||
if hook, err := NewHookSyslog(lopt); err != nil {
|
if hook, err := NewHookSyslog(lopt, l.defaultFormatterNoColor()); err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
l.closeAdd(hook)
|
l.closeAdd(hook)
|
||||||
|
|||||||
@@ -28,8 +28,8 @@
|
|||||||
package logger
|
package logger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log/syslog"
|
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FuncCustomConfig func(log Logger)
|
type FuncCustomConfig func(log Logger)
|
||||||
@@ -53,6 +53,17 @@ func (n NetworkType) String() string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MakeNetwork(net string) NetworkType {
|
||||||
|
switch strings.ToLower(net) {
|
||||||
|
case NetworkTCP.String():
|
||||||
|
return NetworkTCP
|
||||||
|
case NetworkUDP.String():
|
||||||
|
return NetworkUDP
|
||||||
|
default:
|
||||||
|
return NetworkEmpty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type OptionsFile struct {
|
type OptionsFile struct {
|
||||||
// LogLevel define the allowed level of log for this file.
|
// LogLevel define the allowed level of log for this file.
|
||||||
LogLevel []string
|
LogLevel []string
|
||||||
@@ -86,17 +97,21 @@ type OptionsSyslog struct {
|
|||||||
// LogLevel define the allowed level of log for this syslog.
|
// LogLevel define the allowed level of log for this syslog.
|
||||||
LogLevel []string
|
LogLevel []string
|
||||||
|
|
||||||
// Network define the network used to connect to this syslog.
|
// Network define the network used to connect to this syslog (tcp, udp, or any other to a local connection).
|
||||||
Network NetworkType
|
Network string
|
||||||
|
|
||||||
// Host define the remote syslog to use.
|
// Host define the remote syslog to use.
|
||||||
// If Host and Network are empty, local syslog will be used.
|
// If Host and Network are empty, local syslog will be used.
|
||||||
Host string
|
Host string
|
||||||
|
|
||||||
// Priority define the priority used for this syslog.
|
// Severity define the severity syslog to be used.
|
||||||
Priority syslog.Priority
|
Severity string
|
||||||
|
|
||||||
// Tag define the syslog tag used for log message.
|
// Facility define the facility syslog to be used.
|
||||||
|
Facility string
|
||||||
|
|
||||||
|
// Tag define the syslog tag used in linux syslog system or name of logger for windows event logger.
|
||||||
|
// For window, this value must be unic for each syslog config
|
||||||
Tag string
|
Tag string
|
||||||
|
|
||||||
// DisableStack allow to disable the goroutine id before each message.
|
// DisableStack allow to disable the goroutine id before each message.
|
||||||
|
|||||||
208
logger/sys_priority.go
Normal file
208
logger/sys_priority.go
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
/***********************************************************************************************************************
|
||||||
|
*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
**********************************************************************************************************************/
|
||||||
|
|
||||||
|
package logger
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
type SyslogSeverity uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
SyslogSeverityEmerg SyslogSeverity = iota + 1
|
||||||
|
SyslogSeverityAlert
|
||||||
|
SyslogSeverityCrit
|
||||||
|
SyslogSeverityErr
|
||||||
|
SyslogSeverityWarning
|
||||||
|
SyslogSeverityNotice
|
||||||
|
SyslogSeverityInfo
|
||||||
|
SyslogSeverityDebug
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s SyslogSeverity) String() string {
|
||||||
|
switch s {
|
||||||
|
case SyslogSeverityEmerg:
|
||||||
|
return "EMERG"
|
||||||
|
case SyslogSeverityAlert:
|
||||||
|
return "ALERT"
|
||||||
|
case SyslogSeverityCrit:
|
||||||
|
return "CRIT"
|
||||||
|
case SyslogSeverityErr:
|
||||||
|
return "ERR"
|
||||||
|
case SyslogSeverityWarning:
|
||||||
|
return "WARNING"
|
||||||
|
case SyslogSeverityNotice:
|
||||||
|
return "NOTICE"
|
||||||
|
case SyslogSeverityInfo:
|
||||||
|
return "INFO"
|
||||||
|
case SyslogSeverityDebug:
|
||||||
|
return "DEBUG"
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeSeverity(severity string) SyslogSeverity {
|
||||||
|
switch strings.ToUpper(severity) {
|
||||||
|
case SyslogSeverityEmerg.String():
|
||||||
|
return SyslogSeverityEmerg
|
||||||
|
case SyslogSeverityAlert.String():
|
||||||
|
return SyslogSeverityAlert
|
||||||
|
case SyslogSeverityCrit.String():
|
||||||
|
return SyslogSeverityCrit
|
||||||
|
case SyslogSeverityErr.String():
|
||||||
|
return SyslogSeverityErr
|
||||||
|
case SyslogSeverityWarning.String():
|
||||||
|
return SyslogSeverityWarning
|
||||||
|
case SyslogSeverityNotice.String():
|
||||||
|
return SyslogSeverityNotice
|
||||||
|
case SyslogSeverityInfo.String():
|
||||||
|
return SyslogSeverityInfo
|
||||||
|
case SyslogSeverityDebug.String():
|
||||||
|
return SyslogSeverityDebug
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type SyslogFacility uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
SyslogFacilityKern SyslogFacility = iota + 1
|
||||||
|
SyslogFacilityUser
|
||||||
|
SyslogFacilityMail
|
||||||
|
SyslogFacilityDaemon
|
||||||
|
SyslogFacilityAuth
|
||||||
|
SyslogFacilitySyslog
|
||||||
|
SyslogFacilityLpr
|
||||||
|
SyslogFacilityNews
|
||||||
|
SyslogFacilityUucp
|
||||||
|
SyslogFacilityCron
|
||||||
|
SyslogFacilityAuthPriv
|
||||||
|
SyslogFacilityFTP
|
||||||
|
SyslogFacilityLocal0
|
||||||
|
SyslogFacilityLocal1
|
||||||
|
SyslogFacilityLocal2
|
||||||
|
SyslogFacilityLocal3
|
||||||
|
SyslogFacilityLocal4
|
||||||
|
SyslogFacilityLocal5
|
||||||
|
SyslogFacilityLocal6
|
||||||
|
SyslogFacilityLocal7
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s SyslogFacility) String() string {
|
||||||
|
switch s {
|
||||||
|
case SyslogFacilityKern:
|
||||||
|
return "KERN"
|
||||||
|
case SyslogFacilityUser:
|
||||||
|
return "USER"
|
||||||
|
case SyslogFacilityMail:
|
||||||
|
return "MAIL"
|
||||||
|
case SyslogFacilityDaemon:
|
||||||
|
return "DAEMON"
|
||||||
|
case SyslogFacilityAuth:
|
||||||
|
return "AUTH"
|
||||||
|
case SyslogFacilitySyslog:
|
||||||
|
return "SYSLOG"
|
||||||
|
case SyslogFacilityLpr:
|
||||||
|
return "LPR"
|
||||||
|
case SyslogFacilityNews:
|
||||||
|
return "NEWS"
|
||||||
|
case SyslogFacilityUucp:
|
||||||
|
return "UUCP"
|
||||||
|
case SyslogFacilityCron:
|
||||||
|
return "CRON"
|
||||||
|
case SyslogFacilityAuthPriv:
|
||||||
|
return "AUTHPRIV"
|
||||||
|
case SyslogFacilityFTP:
|
||||||
|
return "FTP"
|
||||||
|
case SyslogFacilityLocal0:
|
||||||
|
return "LOCAL0"
|
||||||
|
case SyslogFacilityLocal1:
|
||||||
|
return "LOCAL1"
|
||||||
|
case SyslogFacilityLocal2:
|
||||||
|
return "LOCAL2"
|
||||||
|
case SyslogFacilityLocal3:
|
||||||
|
return "LOCAL3"
|
||||||
|
case SyslogFacilityLocal4:
|
||||||
|
return "LOCAL4"
|
||||||
|
case SyslogFacilityLocal5:
|
||||||
|
return "LOCAL5"
|
||||||
|
case SyslogFacilityLocal6:
|
||||||
|
return "LOCAL6"
|
||||||
|
case SyslogFacilityLocal7:
|
||||||
|
return "LOCAL7"
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeFacility(facility string) SyslogFacility {
|
||||||
|
switch strings.ToUpper(facility) {
|
||||||
|
case SyslogFacilityKern.String():
|
||||||
|
return SyslogFacilityKern
|
||||||
|
case SyslogFacilityUser.String():
|
||||||
|
return SyslogFacilityUser
|
||||||
|
case SyslogFacilityMail.String():
|
||||||
|
return SyslogFacilityMail
|
||||||
|
case SyslogFacilityDaemon.String():
|
||||||
|
return SyslogFacilityDaemon
|
||||||
|
case SyslogFacilityAuth.String():
|
||||||
|
return SyslogFacilityAuth
|
||||||
|
case SyslogFacilitySyslog.String():
|
||||||
|
return SyslogFacilitySyslog
|
||||||
|
case SyslogFacilityLpr.String():
|
||||||
|
return SyslogFacilityLpr
|
||||||
|
case SyslogFacilityNews.String():
|
||||||
|
return SyslogFacilityNews
|
||||||
|
case SyslogFacilityUucp.String():
|
||||||
|
return SyslogFacilityUucp
|
||||||
|
case SyslogFacilityCron.String():
|
||||||
|
return SyslogFacilityCron
|
||||||
|
case SyslogFacilityAuthPriv.String():
|
||||||
|
return SyslogFacilityAuthPriv
|
||||||
|
case SyslogFacilityFTP.String():
|
||||||
|
return SyslogFacilityFTP
|
||||||
|
case SyslogFacilityLocal0.String():
|
||||||
|
return SyslogFacilityLocal0
|
||||||
|
case SyslogFacilityLocal1.String():
|
||||||
|
return SyslogFacilityLocal1
|
||||||
|
case SyslogFacilityLocal2.String():
|
||||||
|
return SyslogFacilityLocal2
|
||||||
|
case SyslogFacilityLocal3.String():
|
||||||
|
return SyslogFacilityLocal3
|
||||||
|
case SyslogFacilityLocal4.String():
|
||||||
|
return SyslogFacilityLocal4
|
||||||
|
case SyslogFacilityLocal5.String():
|
||||||
|
return SyslogFacilityLocal5
|
||||||
|
case SyslogFacilityLocal6.String():
|
||||||
|
return SyslogFacilityLocal6
|
||||||
|
case SyslogFacilityLocal7.String():
|
||||||
|
return SyslogFacilityLocal7
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
164
logger/sys_syslog.go
Normal file
164
logger/sys_syslog.go
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
// +build !windows
|
||||||
|
|
||||||
|
/***********************************************************************************************************************
|
||||||
|
*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
**********************************************************************************************************************/
|
||||||
|
|
||||||
|
package logger
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log/syslog"
|
||||||
|
)
|
||||||
|
|
||||||
|
func makePriority(severity SyslogSeverity, facility SyslogFacility) syslog.Priority {
|
||||||
|
return makePriorotySeverity(severity) | makePriorotyFacility(facility)
|
||||||
|
}
|
||||||
|
|
||||||
|
func makePriorotySeverity(sev SyslogSeverity) syslog.Priority {
|
||||||
|
switch sev {
|
||||||
|
case SyslogSeverityEmerg:
|
||||||
|
return syslog.LOG_EMERG
|
||||||
|
case SyslogSeverityAlert:
|
||||||
|
return syslog.LOG_ALERT
|
||||||
|
case SyslogSeverityCrit:
|
||||||
|
return syslog.LOG_CRIT
|
||||||
|
case SyslogSeverityErr:
|
||||||
|
return syslog.LOG_ERR
|
||||||
|
case SyslogSeverityWarning:
|
||||||
|
return syslog.LOG_WARNING
|
||||||
|
case SyslogSeverityNotice:
|
||||||
|
return syslog.LOG_NOTICE
|
||||||
|
case SyslogSeverityInfo:
|
||||||
|
return syslog.LOG_INFO
|
||||||
|
case SyslogSeverityDebug:
|
||||||
|
return syslog.LOG_DEBUG
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func makePriorotyFacility(fac SyslogFacility) syslog.Priority {
|
||||||
|
switch fac {
|
||||||
|
case SyslogFacilityKern:
|
||||||
|
return syslog.LOG_KERN
|
||||||
|
case SyslogFacilityUser:
|
||||||
|
return syslog.LOG_USER
|
||||||
|
case SyslogFacilityMail:
|
||||||
|
return syslog.LOG_MAIL
|
||||||
|
case SyslogFacilityDaemon:
|
||||||
|
return syslog.LOG_DAEMON
|
||||||
|
case SyslogFacilityAuth:
|
||||||
|
return syslog.LOG_AUTH
|
||||||
|
case SyslogFacilitySyslog:
|
||||||
|
return syslog.LOG_SYSLOG
|
||||||
|
case SyslogFacilityLpr:
|
||||||
|
return syslog.LOG_LPR
|
||||||
|
case SyslogFacilityNews:
|
||||||
|
return syslog.LOG_NEWS
|
||||||
|
case SyslogFacilityUucp:
|
||||||
|
return syslog.LOG_UUCP
|
||||||
|
case SyslogFacilityCron:
|
||||||
|
return syslog.LOG_CRON
|
||||||
|
case SyslogFacilityAuthPriv:
|
||||||
|
return syslog.LOG_AUTHPRIV
|
||||||
|
case SyslogFacilityFTP:
|
||||||
|
return syslog.LOG_FTP
|
||||||
|
case SyslogFacilityLocal0:
|
||||||
|
return syslog.LOG_LOCAL0
|
||||||
|
case SyslogFacilityLocal1:
|
||||||
|
return syslog.LOG_LOCAL1
|
||||||
|
case SyslogFacilityLocal2:
|
||||||
|
return syslog.LOG_LOCAL2
|
||||||
|
case SyslogFacilityLocal3:
|
||||||
|
return syslog.LOG_LOCAL3
|
||||||
|
case SyslogFacilityLocal4:
|
||||||
|
return syslog.LOG_LOCAL4
|
||||||
|
case SyslogFacilityLocal5:
|
||||||
|
return syslog.LOG_LOCAL5
|
||||||
|
case SyslogFacilityLocal6:
|
||||||
|
return syslog.LOG_LOCAL6
|
||||||
|
case SyslogFacilityLocal7:
|
||||||
|
return syslog.LOG_LOCAL7
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type _Syslog struct {
|
||||||
|
w *syslog.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSyslog(net NetworkType, host, tag string, severity SyslogSeverity, facility SyslogFacility) (syslogWrapper, error) {
|
||||||
|
var (
|
||||||
|
sys *syslog.Writer
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if sys, err = syslog.Dial(net.String(), host, makePriority(severity, facility), tag); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &_Syslog{
|
||||||
|
w: sys,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *_Syslog) Write(p []byte) (n int, err error) {
|
||||||
|
if o.w == nil {
|
||||||
|
return 0, fmt.Errorf("logrus.hooksyslog: connection not setup")
|
||||||
|
}
|
||||||
|
|
||||||
|
return o.w.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *_Syslog) Close() error {
|
||||||
|
err := o.w.Close()
|
||||||
|
o.w = nil
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *_Syslog) Panic(p []byte) (n int, err error) {
|
||||||
|
return o.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *_Syslog) Fatal(p []byte) (n int, err error) {
|
||||||
|
return o.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *_Syslog) Error(p []byte) (n int, err error) {
|
||||||
|
return o.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *_Syslog) Warning(p []byte) (n int, err error) {
|
||||||
|
return o.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *_Syslog) Info(p []byte) (n int, err error) {
|
||||||
|
return o.Write(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *_Syslog) Debug(p []byte) (n int, err error) {
|
||||||
|
return o.Write(p)
|
||||||
|
}
|
||||||
196
logger/sys_winlog.go
Normal file
196
logger/sys_winlog.go
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
// +build windows
|
||||||
|
|
||||||
|
/***********************************************************************************************************************
|
||||||
|
*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
**********************************************************************************************************************/
|
||||||
|
|
||||||
|
package logger
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows/svc/eventlog"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _registred *atomic.Value
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// register a function to clean event on stopping application to clean Windows Registry Database
|
||||||
|
go func() {
|
||||||
|
// clean all registered event
|
||||||
|
defer func() {
|
||||||
|
if _registred == nil {
|
||||||
|
_registred = new(atomic.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
i interface{}
|
||||||
|
o []string
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
|
|
||||||
|
if i = _registred.Load(); i == nil {
|
||||||
|
i = make([]string, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if o, ok = i.([]string); !ok {
|
||||||
|
o = make([]string, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
_registred.Store(make([]string, 0))
|
||||||
|
|
||||||
|
for _, s := range o {
|
||||||
|
if err := eventlog.Remove(s); err != nil {
|
||||||
|
println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
for {
|
||||||
|
// only wait the stopping process
|
||||||
|
time.Sleep(200 * time.Millisecond)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func windowsRegister(source string) error {
|
||||||
|
if _registred == nil {
|
||||||
|
_registred = new(atomic.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
i interface{}
|
||||||
|
o []string
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
|
|
||||||
|
if i = _registred.Load(); i == nil {
|
||||||
|
i = make([]string, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if o, ok = i.([]string); !ok {
|
||||||
|
o = make([]string, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range o {
|
||||||
|
if s == source {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := eventlog.InstallAsEventCreate(source, eventlog.Error|eventlog.Warning|eventlog.Info); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
o = append(o, source)
|
||||||
|
_registred.Store(o)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
_ErrorId uint32 = iota + 1
|
||||||
|
_WarningId
|
||||||
|
_InfoId
|
||||||
|
)
|
||||||
|
|
||||||
|
type _WinLog struct {
|
||||||
|
r bool
|
||||||
|
s string
|
||||||
|
w *eventlog.Log
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSyslog(net NetworkType, host, tag string, severity SyslogSeverity, facility SyslogFacility) (syslogWrapper, error) {
|
||||||
|
var (
|
||||||
|
sys *eventlog.Log
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if net != NetworkEmpty {
|
||||||
|
sys, err = eventlog.OpenRemote(host, tag)
|
||||||
|
} else {
|
||||||
|
if err = windowsRegister(tag); err != nil {
|
||||||
|
println(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
sys, err = eventlog.Open(tag)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &_WinLog{
|
||||||
|
r: net != NetworkEmpty,
|
||||||
|
s: tag,
|
||||||
|
w: sys,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *_WinLog) Close() error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
err = o.w.Close()
|
||||||
|
o.w = nil
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *_WinLog) Write(p []byte) (n int, err error) {
|
||||||
|
return o.Info(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *_WinLog) Panic(p []byte) (n int, err error) {
|
||||||
|
return o.Error(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *_WinLog) Fatal(p []byte) (n int, err error) {
|
||||||
|
return o.Error(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *_WinLog) Error(p []byte) (n int, err error) {
|
||||||
|
err = o.w.Error(_ErrorId*100, string(p))
|
||||||
|
return len(p), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *_WinLog) Warning(p []byte) (n int, err error) {
|
||||||
|
err = o.w.Warning(_WarningId*100, string(p))
|
||||||
|
return len(p), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *_WinLog) Info(p []byte) (n int, err error) {
|
||||||
|
err = o.w.Info(_InfoId*100, string(p))
|
||||||
|
return len(p), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *_WinLog) Debug(p []byte) (n int, err error) {
|
||||||
|
return o.Info(p)
|
||||||
|
}
|
||||||
202
test/test-httpserver-syslog/main.go
Normal file
202
test/test-httpserver-syslog/main.go
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
/***********************************************************************************************************************
|
||||||
|
*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 Nicolas JUHEL
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
**********************************************************************************************************************/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
liblog "github.com/nabbar/golib/logger"
|
||||||
|
|
||||||
|
libtls "github.com/nabbar/golib/certificates"
|
||||||
|
liberr "github.com/nabbar/golib/errors"
|
||||||
|
libsrv "github.com/nabbar/golib/httpserver"
|
||||||
|
)
|
||||||
|
|
||||||
|
var tlsConfigSrv = libtls.Config{
|
||||||
|
InheritDefault: true,
|
||||||
|
VersionMin: "1.2",
|
||||||
|
}
|
||||||
|
|
||||||
|
var cfgSrv01 = libsrv.ServerConfig{
|
||||||
|
Name: "test-01",
|
||||||
|
Listen: "0.0.0.0:61001",
|
||||||
|
Expose: "0.0.0.0:61000",
|
||||||
|
TLSMandatory: false,
|
||||||
|
TLS: tlsConfigSrv,
|
||||||
|
}
|
||||||
|
|
||||||
|
var cfgSrv02 = libsrv.ServerConfig{
|
||||||
|
Name: "test-02",
|
||||||
|
Listen: "0.0.0.0:61002",
|
||||||
|
Expose: "0.0.0.0:61000",
|
||||||
|
TLSMandatory: false,
|
||||||
|
TLS: tlsConfigSrv,
|
||||||
|
}
|
||||||
|
|
||||||
|
var cfgSrv03 = libsrv.ServerConfig{
|
||||||
|
Name: "test-03",
|
||||||
|
Listen: "0.0.0.0:61003",
|
||||||
|
Expose: "0.0.0.0:61000",
|
||||||
|
TLSMandatory: true,
|
||||||
|
TLS: tlsConfigSrv,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
cfgPool libsrv.PoolServerConfig
|
||||||
|
ctx context.Context
|
||||||
|
cnl context.CancelFunc
|
||||||
|
log = liblog.New()
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
liberr.SetModeReturnError(liberr.ErrorReturnCodeErrorTraceFull)
|
||||||
|
|
||||||
|
ctx, cnl = context.WithCancel(context.Background())
|
||||||
|
|
||||||
|
log.SetLevel(liblog.DebugLevel)
|
||||||
|
if err := log.SetOptions(ctx, &liblog.Options{
|
||||||
|
DisableStandard: false,
|
||||||
|
DisableStack: false,
|
||||||
|
DisableTimestamp: false,
|
||||||
|
EnableTrace: true,
|
||||||
|
TraceFilter: "",
|
||||||
|
DisableColor: false,
|
||||||
|
LogSyslog: []liblog.OptionsSyslog{
|
||||||
|
{
|
||||||
|
LogLevel: nil,
|
||||||
|
Network: "",
|
||||||
|
Host: "",
|
||||||
|
Severity: "",
|
||||||
|
Facility: "USER",
|
||||||
|
Tag: "test-http-server",
|
||||||
|
DisableStack: false,
|
||||||
|
DisableTimestamp: false,
|
||||||
|
EnableTrace: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cfgPool = libsrv.PoolServerConfig{cfgSrv01, cfgSrv02, cfgSrv03}
|
||||||
|
cfgPool.MapUpdate(func(cfg libsrv.ServerConfig) libsrv.ServerConfig {
|
||||||
|
cfg.SetParentContext(func() context.Context {
|
||||||
|
return ctx
|
||||||
|
})
|
||||||
|
return cfg
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var (
|
||||||
|
pool libsrv.PoolServer
|
||||||
|
lerr liberr.Error
|
||||||
|
)
|
||||||
|
|
||||||
|
if pool, lerr = cfgPool.PoolServer(); lerr != nil {
|
||||||
|
panic(lerr)
|
||||||
|
} else {
|
||||||
|
pool.SetLogger(getLogger)
|
||||||
|
}
|
||||||
|
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/hello", hello)
|
||||||
|
mux.HandleFunc("/headers", headers)
|
||||||
|
|
||||||
|
if lerr = pool.Listen(mux); lerr != nil {
|
||||||
|
panic(lerr)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
pool.Shutdown()
|
||||||
|
cnl()
|
||||||
|
}()
|
||||||
|
|
||||||
|
go pool.WaitNotify(ctx, cnl)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
l := getLogger()
|
||||||
|
for {
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pool.MapRun(func(srv libsrv.Server) {
|
||||||
|
n, v, _ := srv.StatusInfo()
|
||||||
|
e := l.Entry(liblog.ErrorLevel, "status message")
|
||||||
|
e = e.FieldAdd("server_name", n).FieldAdd("server_release", v)
|
||||||
|
e.ErrorAdd(true, srv.StatusHealth())
|
||||||
|
e.Check(liblog.InfoLevel)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
var i = 0
|
||||||
|
for {
|
||||||
|
|
||||||
|
l := getLogger()
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
i++
|
||||||
|
|
||||||
|
if i%3 == 0 {
|
||||||
|
for s := range pool.List(libsrv.FieldBind, libsrv.FieldName, "", ".*") {
|
||||||
|
l.Entry(liblog.InfoLevel, "Restarting server...").FieldAdd("server_name", s).Log()
|
||||||
|
}
|
||||||
|
pool.Restart()
|
||||||
|
i = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func hello(w http.ResponseWriter, req *http.Request) {
|
||||||
|
_, _ = fmt.Fprintf(w, "hello\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
func headers(w http.ResponseWriter, req *http.Request) {
|
||||||
|
for name, headers := range req.Header {
|
||||||
|
for _, h := range headers {
|
||||||
|
_, _ = fmt.Fprintf(w, "%v: %v\n", name, h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLogger() liblog.Logger {
|
||||||
|
l, _ := log.Clone(ctx)
|
||||||
|
return l
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user