[TASK] refactory to input and output
This commit is contained in:
parent
d3318177aa
commit
a9039fa290
|
@ -1,11 +1,13 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/NYTimes/gziphandler"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
|
@ -13,11 +15,11 @@ import (
|
|||
"dev.sum7.eu/genofire/golang-lib/worker"
|
||||
"dev.sum7.eu/genofire/logmania/bot"
|
||||
"dev.sum7.eu/genofire/logmania/database"
|
||||
"dev.sum7.eu/genofire/logmania/input"
|
||||
allInput "dev.sum7.eu/genofire/logmania/input/all"
|
||||
"dev.sum7.eu/genofire/logmania/lib"
|
||||
"dev.sum7.eu/genofire/logmania/notify"
|
||||
allNotify "dev.sum7.eu/genofire/logmania/notify/all"
|
||||
"dev.sum7.eu/genofire/logmania/receive"
|
||||
allReceiver "dev.sum7.eu/genofire/logmania/receive/all"
|
||||
"dev.sum7.eu/genofire/logmania/output"
|
||||
allOutput "dev.sum7.eu/genofire/logmania/output/all"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -25,8 +27,8 @@ var (
|
|||
config *lib.Config
|
||||
db *database.DB
|
||||
dbSaveWorker *worker.Worker
|
||||
notifier notify.Notifier
|
||||
receiver receive.Receiver
|
||||
out output.Output
|
||||
in input.Input
|
||||
logChannel chan *log.Entry
|
||||
logmaniaBot *bot.Bot
|
||||
)
|
||||
|
@ -51,24 +53,40 @@ var serverCmd = &cobra.Command{
|
|||
|
||||
logmaniaBot = bot.NewBot(db)
|
||||
|
||||
notifier = allNotify.Init(&config.Notify, db, logmaniaBot)
|
||||
out = allOutput.Init(config.Output, db, logmaniaBot)
|
||||
logChannel = make(chan *log.Entry)
|
||||
|
||||
go func() {
|
||||
for a := range logChannel {
|
||||
notifier.Send(a, nil)
|
||||
out.Send(a, nil)
|
||||
}
|
||||
}()
|
||||
|
||||
if config.Notify.AlertCheck.Duration > time.Duration(time.Second) {
|
||||
go db.Alert(config.Notify.AlertCheck.Duration, notifier.Send)
|
||||
if config.AlertCheck.Duration > time.Duration(time.Second) {
|
||||
go db.Alert(config.AlertCheck.Duration, out.Send)
|
||||
}
|
||||
|
||||
log.Info("starting logmania")
|
||||
|
||||
receiver = allReceiver.Init(&config.Receive, logChannel)
|
||||
if config.HTTPAddress != "" {
|
||||
if config.Webroot != "" {
|
||||
http.Handle("/", gziphandler.GzipHandler(http.FileServer(http.Dir(config.Webroot))))
|
||||
}
|
||||
|
||||
go receiver.Listen()
|
||||
srv := &http.Server{
|
||||
Addr: config.HTTPAddress,
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := srv.ListenAndServe(); err != http.ErrServerClosed {
|
||||
log.Panic(err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
in = allInput.Init(config.Input, logChannel)
|
||||
|
||||
go in.Listen()
|
||||
|
||||
// Wait for system signal
|
||||
sigchan := make(chan os.Signal, 1)
|
||||
|
@ -92,8 +110,8 @@ var serverCmd = &cobra.Command{
|
|||
func quit() {
|
||||
dbSaveWorker.Close()
|
||||
file.SaveJSON(config.DB, db)
|
||||
receiver.Close()
|
||||
notifier.Close()
|
||||
in.Close()
|
||||
out.Close()
|
||||
log.Info("quit of logmania")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
@ -106,12 +124,12 @@ func reload() {
|
|||
log.Errorf("reload: could not load '%s' for new configuration. Skip reload.", configPath)
|
||||
return
|
||||
}
|
||||
receiver.Close()
|
||||
receiver = allReceiver.Init(&config.Receive, logChannel)
|
||||
go receiver.Listen()
|
||||
in.Close()
|
||||
in = allInput.Init(config.Input, logChannel)
|
||||
go in.Listen()
|
||||
|
||||
notifier.Close()
|
||||
notifier = allNotify.Init(&config.Notify, db, logmaniaBot)
|
||||
out.Close()
|
||||
out = allOutput.Init(config.Output, db, logmaniaBot)
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
|
|
@ -76,10 +76,10 @@ func (db *DB) Alert(expired time.Duration, send func(e *log.Entry, n *Notify) bo
|
|||
for range c {
|
||||
now := time.Now()
|
||||
for _, h := range db.Hosts {
|
||||
if !h.Lastseen.Before(now.Add(expired * -2)) {
|
||||
if h.Lastseen.Before(now.Add(expired * -1)) {
|
||||
continue
|
||||
}
|
||||
if h.LastseenNotify.Year() <= 1 && h.Lastseen.Before(h.LastseenNotify) {
|
||||
if h.Lastseen.After(h.LastseenNotify) {
|
||||
continue
|
||||
}
|
||||
h.LastseenNotify = now
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
package all
|
||||
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"dev.sum7.eu/genofire/logmania/input"
|
||||
)
|
||||
|
||||
type Input struct {
|
||||
input.Input
|
||||
list []input.Input
|
||||
}
|
||||
|
||||
func Init(configInterface interface{}, exportChannel chan *log.Entry) input.Input {
|
||||
config := configInterface.(map[string]interface{})
|
||||
|
||||
var list []input.Input
|
||||
for inputType, init := range input.Register {
|
||||
configForItem := config[inputType]
|
||||
if configForItem == nil {
|
||||
log.Warnf("the input type '%s' has no configuration\n", inputType)
|
||||
continue
|
||||
}
|
||||
input := init(configForItem, exportChannel)
|
||||
|
||||
if input == nil {
|
||||
continue
|
||||
}
|
||||
list = append(list, input)
|
||||
}
|
||||
return &Input{
|
||||
list: list,
|
||||
}
|
||||
}
|
||||
|
||||
func (in *Input) Listen() {
|
||||
for _, item := range in.list {
|
||||
go item.Listen()
|
||||
}
|
||||
}
|
||||
|
||||
func (in *Input) Close() {
|
||||
for _, item := range in.list {
|
||||
item.Close()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package all
|
||||
|
||||
import (
|
||||
_ "dev.sum7.eu/genofire/logmania/input/journald_json"
|
||||
_ "dev.sum7.eu/genofire/logmania/input/logrus"
|
||||
_ "dev.sum7.eu/genofire/logmania/input/syslog"
|
||||
)
|
|
@ -0,0 +1,77 @@
|
|||
package journald_json
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"dev.sum7.eu/genofire/logmania/input"
|
||||
)
|
||||
|
||||
const inputType = "journald_json"
|
||||
|
||||
var logger = log.WithField("input", inputType)
|
||||
|
||||
type Input struct {
|
||||
input.Input
|
||||
exportChannel chan *log.Entry
|
||||
serverSocket *net.UDPConn
|
||||
}
|
||||
|
||||
type InputConfig struct {
|
||||
Type string `mapstructure:"type"`
|
||||
Address string `mapstructure:"address"`
|
||||
}
|
||||
|
||||
func Init(configInterface interface{}, exportChannel chan *log.Entry) input.Input {
|
||||
var config InputConfig
|
||||
if err := mapstructure.Decode(configInterface, &config); err != nil {
|
||||
logger.Warnf("not able to decode data: %s", err)
|
||||
return nil
|
||||
}
|
||||
addr, err := net.ResolveUDPAddr(config.Type, config.Address)
|
||||
ln, err := net.ListenUDP(config.Type, addr)
|
||||
|
||||
if err != nil {
|
||||
logger.Error("init ", err)
|
||||
return nil
|
||||
}
|
||||
in := &Input{
|
||||
serverSocket: ln,
|
||||
exportChannel: exportChannel,
|
||||
}
|
||||
|
||||
logger.Info("init")
|
||||
|
||||
return in
|
||||
}
|
||||
|
||||
const maxDataGramSize = 8192
|
||||
|
||||
func (in *Input) Listen() {
|
||||
logger.Info("listen")
|
||||
for {
|
||||
buf := make([]byte, maxDataGramSize)
|
||||
n, src, err := in.serverSocket.ReadFromUDP(buf)
|
||||
if err != nil {
|
||||
logger.Warn("failed to accept connection", err)
|
||||
continue
|
||||
}
|
||||
|
||||
raw := make([]byte, n)
|
||||
copy(raw, buf)
|
||||
entry := toLogEntry(raw, src.IP.String())
|
||||
if entry != nil {
|
||||
in.exportChannel <- entry
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (in *Input) Close() {
|
||||
in.serverSocket.Close()
|
||||
}
|
||||
|
||||
func init() {
|
||||
input.Add(inputType, Init)
|
||||
}
|
|
@ -4,7 +4,7 @@ import (
|
|||
"io"
|
||||
|
||||
websocketLib "dev.sum7.eu/genofire/golang-lib/websocket"
|
||||
"dev.sum7.eu/genofire/logmania/receive/logrus"
|
||||
"dev.sum7.eu/genofire/logmania/input/logrus"
|
||||
"github.com/google/uuid"
|
||||
"github.com/gorilla/websocket"
|
||||
log "github.com/sirupsen/logrus"
|
|
@ -6,28 +6,28 @@ import (
|
|||
"dev.sum7.eu/genofire/golang-lib/websocket"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"dev.sum7.eu/genofire/logmania/lib"
|
||||
"dev.sum7.eu/genofire/logmania/receive"
|
||||
"dev.sum7.eu/genofire/logmania/input"
|
||||
)
|
||||
|
||||
const inputType = "logrus"
|
||||
const WS_LOG_ENTRY = "log"
|
||||
|
||||
var logger = log.WithField("receive", "logrus")
|
||||
var logger = log.WithField("input", inputType)
|
||||
|
||||
type Receiver struct {
|
||||
receive.Receiver
|
||||
type Input struct {
|
||||
input.Input
|
||||
input chan *websocket.Message
|
||||
exportChannel chan *log.Entry
|
||||
serverSocket *websocket.Server
|
||||
}
|
||||
|
||||
func Init(config *lib.ReceiveConfig, exportChannel chan *log.Entry) receive.Receiver {
|
||||
func Init(config interface{}, exportChannel chan *log.Entry) input.Input {
|
||||
inputMsg := make(chan *websocket.Message)
|
||||
ws := websocket.NewServer(inputMsg, websocket.NewSessionManager())
|
||||
|
||||
http.HandleFunc("/receiver", ws.Handler)
|
||||
http.HandleFunc("/input/"+inputType, ws.Handler)
|
||||
|
||||
recv := &Receiver{
|
||||
input := &Input{
|
||||
input: inputMsg,
|
||||
serverSocket: ws,
|
||||
exportChannel: exportChannel,
|
||||
|
@ -35,21 +35,21 @@ func Init(config *lib.ReceiveConfig, exportChannel chan *log.Entry) receive.Rece
|
|||
|
||||
logger.Info("init")
|
||||
|
||||
return recv
|
||||
return input
|
||||
}
|
||||
|
||||
func (rc *Receiver) Listen() {
|
||||
func (in *Input) Listen() {
|
||||
logger.Info("listen")
|
||||
for msg := range rc.input {
|
||||
for msg := range in.input {
|
||||
if event, ok := msg.Body.(log.Entry); ok {
|
||||
rc.exportChannel <- &event
|
||||
in.exportChannel <- &event
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (rc *Receiver) Close() {
|
||||
func (in *Input) Close() {
|
||||
}
|
||||
|
||||
func init() {
|
||||
receive.AddReceiver("websocket", Init)
|
||||
input.Add(inputType, Init)
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package input
|
||||
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var Register = make(map[string]Init)
|
||||
|
||||
type Input interface {
|
||||
Listen()
|
||||
Close()
|
||||
}
|
||||
|
||||
type Init func(interface{}, chan *log.Entry) Input
|
||||
|
||||
func Add(name string, init Init) {
|
||||
Register[name] = init
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package syslog
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"dev.sum7.eu/genofire/logmania/input"
|
||||
)
|
||||
|
||||
const inputType = "syslog"
|
||||
|
||||
var logger = log.WithField("input", inputType)
|
||||
|
||||
type Input struct {
|
||||
input.Input
|
||||
exportChannel chan *log.Entry
|
||||
serverSocket *net.UDPConn
|
||||
}
|
||||
|
||||
type InputConfig struct {
|
||||
Type string `mapstructure:"type"`
|
||||
Address string `mapstructure:"address"`
|
||||
}
|
||||
|
||||
func Init(configInterface interface{}, exportChannel chan *log.Entry) input.Input {
|
||||
var config InputConfig
|
||||
if err := mapstructure.Decode(configInterface, &config); err != nil {
|
||||
logger.Warnf("not able to decode data: %s", err)
|
||||
return nil
|
||||
}
|
||||
addr, err := net.ResolveUDPAddr(config.Type, config.Address)
|
||||
ln, err := net.ListenUDP(config.Type, addr)
|
||||
|
||||
if err != nil {
|
||||
logger.Error("init ", err)
|
||||
return nil
|
||||
}
|
||||
input := &Input{
|
||||
serverSocket: ln,
|
||||
exportChannel: exportChannel,
|
||||
}
|
||||
|
||||
logger.Info("init")
|
||||
|
||||
return input
|
||||
}
|
||||
|
||||
const maxDataGramSize = 8192
|
||||
|
||||
func (in *Input) Listen() {
|
||||
logger.Info("listen")
|
||||
for {
|
||||
buf := make([]byte, maxDataGramSize)
|
||||
n, src, err := in.serverSocket.ReadFromUDP(buf)
|
||||
if err != nil {
|
||||
logger.Warn("failed to accept connection", err)
|
||||
continue
|
||||
}
|
||||
|
||||
raw := make([]byte, n)
|
||||
copy(raw, buf)
|
||||
entry := toLogEntry(raw, src.IP.String())
|
||||
if entry != nil {
|
||||
in.exportChannel <- entry
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (in *Input) Close() {
|
||||
in.serverSocket.Close()
|
||||
}
|
||||
|
||||
func init() {
|
||||
input.Add(inputType, Init)
|
||||
}
|
|
@ -3,37 +3,10 @@ package lib
|
|||
// Struct of the configuration
|
||||
// e.g. under dev.sum7.eu/genofire/logmania/logmania_example.conf
|
||||
type Config struct {
|
||||
Notify NotifyConfig `toml:"notify"`
|
||||
Receive ReceiveConfig `toml:"receive"`
|
||||
DB string `toml:"database"`
|
||||
}
|
||||
|
||||
type NotifyConfig struct {
|
||||
AlertCheck Duration `toml:"alert_check"`
|
||||
Console bool `toml:"debug"`
|
||||
XMPP struct {
|
||||
JID string `toml:"jid"`
|
||||
Password string `toml:"password"`
|
||||
Defaults map[string]bool `toml:"default"`
|
||||
} `toml:"xmpp"`
|
||||
Websocket struct {
|
||||
Address string `toml:"address"`
|
||||
HTTPAddress string `toml:"http_address"`
|
||||
Webroot string `toml:"webroot"`
|
||||
Default string `toml:"default"`
|
||||
} `toml:"websocket"`
|
||||
File struct {
|
||||
Directory string `toml:"directory"`
|
||||
Default string `toml:"default"`
|
||||
} `toml:"file"`
|
||||
}
|
||||
|
||||
type ReceiveConfig struct {
|
||||
Syslog struct {
|
||||
Type string `toml:"type"`
|
||||
Address string `toml:"address"`
|
||||
} `toml:"syslog"`
|
||||
JournaldJSON struct {
|
||||
Type string `toml:"type"`
|
||||
Address string `toml:"address"`
|
||||
} `toml:"journald_json"`
|
||||
AlertCheck Duration `toml:"alert_check"`
|
||||
Output map[string]interface{} `toml:"output"`
|
||||
Input map[string]interface{} `toml:"input"`
|
||||
}
|
||||
|
|
|
@ -1,26 +1,37 @@
|
|||
[receive.syslog]
|
||||
database = "/tmp/logmania.state.json"
|
||||
|
||||
# have to be mote then a minute
|
||||
alert_check = "5m"
|
||||
|
||||
# webserver
|
||||
http_address = ":8080"
|
||||
webroot = "./webroot/"
|
||||
|
||||
#########
|
||||
# Input #
|
||||
#########
|
||||
|
||||
[input.syslog]
|
||||
type = "udp"
|
||||
address = ":10001"
|
||||
|
||||
[receive.journald_json]
|
||||
[input.journald_json]
|
||||
type = "udp"
|
||||
address = ":10002"
|
||||
|
||||
[notify]
|
||||
state_file = "/tmp/logmania.state.json"
|
||||
debug = true
|
||||
##########
|
||||
# Output #
|
||||
##########
|
||||
|
||||
[file]
|
||||
[output.file]
|
||||
directory = "/tmp/"
|
||||
default = "raw"
|
||||
|
||||
[notify.xmpp]
|
||||
[output.xmpp]
|
||||
jid = "user@example.org"
|
||||
password = "password"
|
||||
# if boolean is true for muc either user chat
|
||||
default = { "log-raw@conference.example.org" = true, "person@example.org" = false }
|
||||
|
||||
[notify.websocket]
|
||||
address = ":8080"
|
||||
webroot = "./webroot/"
|
||||
[output.websocket]
|
||||
default = "raw"
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
package all
|
||||
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"dev.sum7.eu/genofire/logmania/bot"
|
||||
"dev.sum7.eu/genofire/logmania/database"
|
||||
"dev.sum7.eu/genofire/logmania/lib"
|
||||
"dev.sum7.eu/genofire/logmania/notify"
|
||||
)
|
||||
|
||||
var logger = log.WithField("notify", "all")
|
||||
|
||||
type Notifier struct {
|
||||
notify.Notifier
|
||||
list []notify.Notifier
|
||||
db *database.DB
|
||||
channelNotify chan *log.Entry
|
||||
}
|
||||
|
||||
func Init(config *lib.NotifyConfig, db *database.DB, bot *bot.Bot) notify.Notifier {
|
||||
var list []notify.Notifier
|
||||
var defaults []*database.Notify
|
||||
for _, init := range notify.NotifyRegister {
|
||||
notify := init(config, db, bot)
|
||||
|
||||
if notify == nil {
|
||||
continue
|
||||
}
|
||||
list = append(list, notify)
|
||||
def := notify.Default()
|
||||
if def != nil {
|
||||
continue
|
||||
}
|
||||
defaults = append(defaults, def...)
|
||||
}
|
||||
|
||||
db.DefaultNotify = defaults
|
||||
|
||||
n := &Notifier{
|
||||
db: db,
|
||||
list: list,
|
||||
channelNotify: make(chan *log.Entry),
|
||||
}
|
||||
go n.sender()
|
||||
return n
|
||||
}
|
||||
|
||||
func (n *Notifier) sender() {
|
||||
for c := range n.channelNotify {
|
||||
e, _, tos := n.db.SendTo(c)
|
||||
for _, to := range tos {
|
||||
send := false
|
||||
for _, item := range n.list {
|
||||
send = item.Send(e, to)
|
||||
if send {
|
||||
break
|
||||
}
|
||||
}
|
||||
if !send {
|
||||
logger.Warnf("notify not send to %s: [%s] %s", to.Address(), c.Level.String(), c.Message)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Notifier) Send(e *log.Entry, to *database.Notify) bool {
|
||||
n.channelNotify <- e
|
||||
return true
|
||||
}
|
||||
|
||||
func (n *Notifier) Close() {
|
||||
for _, item := range n.list {
|
||||
item.Close()
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
package all
|
||||
|
||||
import (
|
||||
_ "dev.sum7.eu/genofire/logmania/notify/file"
|
||||
_ "dev.sum7.eu/genofire/logmania/notify/websocket"
|
||||
_ "dev.sum7.eu/genofire/logmania/notify/xmpp"
|
||||
)
|
|
@ -1,23 +0,0 @@
|
|||
package notify
|
||||
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"dev.sum7.eu/genofire/logmania/bot"
|
||||
"dev.sum7.eu/genofire/logmania/database"
|
||||
"dev.sum7.eu/genofire/logmania/lib"
|
||||
)
|
||||
|
||||
var NotifyRegister []NotifyInit
|
||||
|
||||
type Notifier interface {
|
||||
Default() []*database.Notify
|
||||
Send(entry *log.Entry, to *database.Notify) bool
|
||||
Close()
|
||||
}
|
||||
|
||||
type NotifyInit func(*lib.NotifyConfig, *database.DB, *bot.Bot) Notifier
|
||||
|
||||
func AddNotifier(n NotifyInit) {
|
||||
NotifyRegister = append(NotifyRegister, n)
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package all
|
||||
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"dev.sum7.eu/genofire/logmania/bot"
|
||||
"dev.sum7.eu/genofire/logmania/database"
|
||||
"dev.sum7.eu/genofire/logmania/output"
|
||||
)
|
||||
|
||||
var logger = log.WithField("notify", "all")
|
||||
|
||||
type Output struct {
|
||||
output.Output
|
||||
list []output.Output
|
||||
db *database.DB
|
||||
channelNotify chan *log.Entry
|
||||
}
|
||||
|
||||
func Init(configInterface interface{}, db *database.DB, bot *bot.Bot) output.Output {
|
||||
config := configInterface.(map[string]interface{})
|
||||
|
||||
var list []output.Output
|
||||
var defaults []*database.Notify
|
||||
for outputType, init := range output.Register {
|
||||
configForItem := config[outputType]
|
||||
if configForItem == nil {
|
||||
log.Warnf("the input type '%s' has no configuration\n", outputType)
|
||||
continue
|
||||
}
|
||||
notify := init(configForItem, db, bot)
|
||||
|
||||
if notify == nil {
|
||||
continue
|
||||
}
|
||||
list = append(list, notify)
|
||||
def := notify.Default()
|
||||
if def != nil {
|
||||
continue
|
||||
}
|
||||
defaults = append(defaults, def...)
|
||||
}
|
||||
|
||||
db.DefaultNotify = defaults
|
||||
|
||||
out := &Output{
|
||||
db: db,
|
||||
list: list,
|
||||
channelNotify: make(chan *log.Entry),
|
||||
}
|
||||
go out.sender()
|
||||
return out
|
||||
}
|
||||
|
||||
func (out *Output) sender() {
|
||||
for c := range out.channelNotify {
|
||||
e, _, tos := out.db.SendTo(c)
|
||||
for _, to := range tos {
|
||||
send := false
|
||||
for _, item := range out.list {
|
||||
send = item.Send(e, to)
|
||||
if send {
|
||||
break
|
||||
}
|
||||
}
|
||||
if !send {
|
||||
logger.Warnf("notify not send to %s: [%s] %s", to.Address(), c.Level.String(), c.Message)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (out *Output) Send(e *log.Entry, to *database.Notify) bool {
|
||||
out.channelNotify <- e
|
||||
return true
|
||||
}
|
||||
|
||||
func (out *Output) Close() {
|
||||
for _, item := range out.list {
|
||||
item.Close()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package all
|
||||
|
||||
import (
|
||||
_ "dev.sum7.eu/genofire/logmania/output/file"
|
||||
_ "dev.sum7.eu/genofire/logmania/output/websocket"
|
||||
_ "dev.sum7.eu/genofire/logmania/output/xmpp"
|
||||
)
|
|
@ -5,82 +5,92 @@ import (
|
|||
"path"
|
||||
"regexp"
|
||||
|
||||
"github.com/mitchellh/mapstructure"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"dev.sum7.eu/genofire/logmania/bot"
|
||||
"dev.sum7.eu/genofire/logmania/database"
|
||||
"dev.sum7.eu/genofire/logmania/lib"
|
||||
"dev.sum7.eu/genofire/logmania/notify"
|
||||
"dev.sum7.eu/genofire/logmania/output"
|
||||
)
|
||||
|
||||
const (
|
||||
proto = "file"
|
||||
)
|
||||
|
||||
var logger = log.WithField("notify", proto)
|
||||
var logger = log.WithField("output", proto)
|
||||
|
||||
type Notifier struct {
|
||||
notify.Notifier
|
||||
type Output struct {
|
||||
output.Output
|
||||
defaults []*database.Notify
|
||||
files map[string]*os.File
|
||||
formatter log.Formatter
|
||||
path string
|
||||
}
|
||||
|
||||
func Init(config *lib.NotifyConfig, db *database.DB, bot *bot.Bot) notify.Notifier {
|
||||
if config.File.Directory == "" {
|
||||
type OutputConfig struct {
|
||||
Directory string `mapstructure:"directory"`
|
||||
Default string `mapstructure:"default"`
|
||||
}
|
||||
|
||||
func Init(configInterface interface{}, db *database.DB, bot *bot.Bot) output.Output {
|
||||
var config OutputConfig
|
||||
if err := mapstructure.Decode(configInterface, &config); err != nil {
|
||||
logger.Warnf("not able to decode data: %s", err)
|
||||
return nil
|
||||
}
|
||||
logger.WithField("directory", config.File.Directory).Info("startup")
|
||||
if config.Directory == "" {
|
||||
return nil
|
||||
}
|
||||
logger.WithField("directory", config.Directory).Info("startup")
|
||||
|
||||
var defaults []*database.Notify
|
||||
if config.File.Default != "" {
|
||||
if config.Default != "" {
|
||||
defaults = append(defaults, &database.Notify{
|
||||
Protocol: proto,
|
||||
To: config.File.Default,
|
||||
To: config.Default,
|
||||
})
|
||||
}
|
||||
|
||||
return &Notifier{
|
||||
return &Output{
|
||||
defaults: defaults,
|
||||
files: make(map[string]*os.File),
|
||||
formatter: &log.JSONFormatter{},
|
||||
path: config.File.Directory,
|
||||
path: config.Directory,
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Notifier) Default() []*database.Notify {
|
||||
return n.defaults
|
||||
func (out *Output) Default() []*database.Notify {
|
||||
return out.defaults
|
||||
}
|
||||
|
||||
func (n *Notifier) getFile(name string) *os.File {
|
||||
if file, ok := n.files[name]; ok {
|
||||
func (out *Output) getFile(name string) *os.File {
|
||||
if file, ok := out.files[name]; ok {
|
||||
return file
|
||||
}
|
||||
if m, err := regexp.MatchString(`^[0-9A-Za-z_-]*$`, name); err != nil || !m {
|
||||
logger.Errorf("not allowed to use '%s:%s'", proto, name)
|
||||
return nil
|
||||
}
|
||||
filename := path.Join(n.path, name+".json")
|
||||
filename := path.Join(out.path, name+".json")
|
||||
file, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
|
||||
if err != nil {
|
||||
logger.Errorf("could not open file: %s", err.Error())
|
||||
return nil
|
||||
}
|
||||
n.files[name] = file
|
||||
out.files[name] = file
|
||||
return file
|
||||
}
|
||||
|
||||
func (n *Notifier) Send(e *log.Entry, to *database.Notify) bool {
|
||||
func (out *Output) Send(e *log.Entry, to *database.Notify) bool {
|
||||
if to.Protocol != proto {
|
||||
return false
|
||||
}
|
||||
byteText, err := n.formatter.Format(e)
|
||||
byteText, err := out.formatter.Format(e)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
text := to.RunReplace(string(byteText))
|
||||
file := n.getFile(to.To)
|
||||
file := out.getFile(to.To)
|
||||
if file == nil {
|
||||
return false
|
||||
}
|
||||
|
@ -89,5 +99,5 @@ func (n *Notifier) Send(e *log.Entry, to *database.Notify) bool {
|
|||
}
|
||||
|
||||
func init() {
|
||||
notify.AddNotifier(Init)
|
||||
output.Add(proto, Init)
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package output
|
||||
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"dev.sum7.eu/genofire/logmania/bot"
|
||||
"dev.sum7.eu/genofire/logmania/database"
|
||||
)
|
||||
|
||||
var Register = make(map[string]Init)
|
||||
|
||||
type Output interface {
|
||||
Default() []*database.Notify
|
||||
Send(entry *log.Entry, to *database.Notify) bool
|
||||
Close()
|
||||
}
|
||||
|
||||
type Init func(interface{}, *database.DB, *bot.Bot) Output
|
||||
|
||||
func Add(name string, init Init) {
|
||||
Register[name] = init
|
||||
}
|
|
@ -4,33 +4,41 @@ import (
|
|||
"net/http"
|
||||
|
||||
"dev.sum7.eu/genofire/golang-lib/websocket"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"dev.sum7.eu/genofire/logmania/bot"
|
||||
"dev.sum7.eu/genofire/logmania/database"
|
||||
"dev.sum7.eu/genofire/logmania/lib"
|
||||
"dev.sum7.eu/genofire/logmania/notify"
|
||||
"dev.sum7.eu/genofire/logmania/output"
|
||||
)
|
||||
|
||||
const (
|
||||
proto = "ws"
|
||||
)
|
||||
|
||||
var logger = log.WithField("notify", proto)
|
||||
var logger = log.WithField("output", proto)
|
||||
|
||||
type Notifier struct {
|
||||
notify.Notifier
|
||||
type Output struct {
|
||||
output.Output
|
||||
defaults []*database.Notify
|
||||
ws *websocket.Server
|
||||
formatter log.Formatter
|
||||
}
|
||||
|
||||
func Init(config *lib.NotifyConfig, db *database.DB, bot *bot.Bot) notify.Notifier {
|
||||
type OutputConfig struct {
|
||||
Default string `mapstructure:"default"`
|
||||
}
|
||||
|
||||
func Init(configInterface interface{}, db *database.DB, bot *bot.Bot) output.Output {
|
||||
var config OutputConfig
|
||||
if err := mapstructure.Decode(configInterface, &config); err != nil {
|
||||
logger.Warnf("not able to decode data: %s", err)
|
||||
return nil
|
||||
}
|
||||
inputMSG := make(chan *websocket.Message)
|
||||
ws := websocket.NewServer(inputMSG, nil)
|
||||
|
||||
http.HandleFunc("/ws", ws.Handler)
|
||||
http.Handle("/", http.FileServer(http.Dir(config.Websocket.Webroot)))
|
||||
http.HandleFunc("/output/ws", ws.Handler)
|
||||
|
||||
go func() {
|
||||
for msg := range inputMSG {
|
||||
|
@ -44,26 +52,16 @@ func Init(config *lib.NotifyConfig, db *database.DB, bot *bot.Bot) notify.Notifi
|
|||
}
|
||||
}()
|
||||
|
||||
srv := &http.Server{
|
||||
Addr: config.Websocket.Address,
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := srv.ListenAndServe(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
logger.WithField("http-socket", config.Websocket.Address).Info("startup")
|
||||
logger.Info("startup")
|
||||
|
||||
var defaults []*database.Notify
|
||||
if config.Websocket.Default != "" {
|
||||
if config.Default != "" {
|
||||
defaults = append(defaults, &database.Notify{
|
||||
Protocol: proto,
|
||||
To: config.Websocket.Default,
|
||||
To: config.Default,
|
||||
})
|
||||
}
|
||||
return &Notifier{
|
||||
return &Output{
|
||||
defaults: defaults,
|
||||
ws: ws,
|
||||
formatter: &log.TextFormatter{
|
||||
|
@ -72,16 +70,16 @@ func Init(config *lib.NotifyConfig, db *database.DB, bot *bot.Bot) notify.Notifi
|
|||
}
|
||||
}
|
||||
|
||||
func (n *Notifier) Default() []*database.Notify {
|
||||
return n.defaults
|
||||
func (out *Output) Default() []*database.Notify {
|
||||
return out.defaults
|
||||
}
|
||||
|
||||
func (n *Notifier) Send(e *log.Entry, to *database.Notify) bool {
|
||||
func (out *Output) Send(e *log.Entry, to *database.Notify) bool {
|
||||
if to.Protocol != proto {
|
||||
return false
|
||||
}
|
||||
|
||||
n.ws.SendAll(&websocket.Message{
|
||||
out.ws.SendAll(&websocket.Message{
|
||||
Subject: to.Address(),
|
||||
Body: &log.Entry{
|
||||
Buffer: e.Buffer,
|
||||
|
@ -95,9 +93,9 @@ func (n *Notifier) Send(e *log.Entry, to *database.Notify) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (n *Notifier) Close() {
|
||||
func (out *Output) Close() {
|
||||
}
|
||||
|
||||
func init() {
|
||||
notify.AddNotifier(Init)
|
||||
output.Add("websocket", Init)
|
||||
}
|
|
@ -6,12 +6,12 @@ import (
|
|||
xmpp_client "dev.sum7.eu/genofire/yaja/client"
|
||||
xmpp "dev.sum7.eu/genofire/yaja/xmpp"
|
||||
"dev.sum7.eu/genofire/yaja/xmpp/base"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"dev.sum7.eu/genofire/logmania/bot"
|
||||
"dev.sum7.eu/genofire/logmania/database"
|
||||
"dev.sum7.eu/genofire/logmania/lib"
|
||||
"dev.sum7.eu/genofire/logmania/notify"
|
||||
"dev.sum7.eu/genofire/logmania/output"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -20,20 +20,31 @@ const (
|
|||
nickname = "logmania"
|
||||
)
|
||||
|
||||
var logger = log.WithField("notify", proto)
|
||||
var logger = log.WithField("output", proto)
|
||||
|
||||
type Notifier struct {
|
||||
notify.Notifier
|
||||
type Output struct {
|
||||
output.Output
|
||||
defaults []*database.Notify
|
||||
client *xmpp_client.Client
|
||||
channels map[string]bool
|
||||
formatter log.Formatter
|
||||
}
|
||||
|
||||
func Init(config *lib.NotifyConfig, db *database.DB, bot *bot.Bot) notify.Notifier {
|
||||
type OutputConfig struct {
|
||||
JID string `mapstructure:"jid"`
|
||||
Password string `mapstructure:"password"`
|
||||
Defaults map[string]bool `mapstructure:"default"`
|
||||
}
|
||||
|
||||
func Init(configInterface interface{}, db *database.DB, bot *bot.Bot) output.Output {
|
||||
var config OutputConfig
|
||||
if err := mapstructure.Decode(configInterface, &config); err != nil {
|
||||
logger.Warnf("not able to decode data: %s", err)
|
||||
return nil
|
||||
}
|
||||
channels := make(map[string]bool)
|
||||
|
||||
client, err := xmpp_client.NewClient(xmppbase.NewJID(config.XMPP.JID), config.XMPP.Password)
|
||||
client, err := xmpp_client.NewClient(xmppbase.NewJID(config.JID), config.Password)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
return nil
|
||||
|
@ -42,7 +53,7 @@ func Init(config *lib.NotifyConfig, db *database.DB, bot *bot.Bot) notify.Notifi
|
|||
for {
|
||||
if err := client.Start(); err != nil {
|
||||
log.Warn("close connection, try reconnect")
|
||||
client.Connect(config.XMPP.Password)
|
||||
client.Connect(config.Password)
|
||||
} else {
|
||||
log.Warn("closed connection")
|
||||
return
|
||||
|
@ -130,10 +141,10 @@ func Init(config *lib.NotifyConfig, db *database.DB, bot *bot.Bot) notify.Notifi
|
|||
}
|
||||
}
|
||||
|
||||
logger.WithField("jid", config.XMPP.JID).Info("startup")
|
||||
logger.WithField("jid", config.JID).Info("startup")
|
||||
|
||||
var defaults []*database.Notify
|
||||
for to, muc := range config.XMPP.Defaults {
|
||||
for to, muc := range config.Defaults {
|
||||
def := &database.Notify{
|
||||
Protocol: proto,
|
||||
To: to,
|
||||
|
@ -143,7 +154,7 @@ func Init(config *lib.NotifyConfig, db *database.DB, bot *bot.Bot) notify.Notifi
|
|||
}
|
||||
defaults = append(defaults, def)
|
||||
}
|
||||
return &Notifier{
|
||||
return &Output{
|
||||
channels: channels,
|
||||
defaults: defaults,
|
||||
client: client,
|
||||
|
@ -153,31 +164,31 @@ func Init(config *lib.NotifyConfig, db *database.DB, bot *bot.Bot) notify.Notifi
|
|||
}
|
||||
}
|
||||
|
||||
func (n *Notifier) Default() []*database.Notify {
|
||||
return n.defaults
|
||||
func (out *Output) Default() []*database.Notify {
|
||||
return out.defaults
|
||||
}
|
||||
|
||||
func (n *Notifier) Send(e *log.Entry, to *database.Notify) bool {
|
||||
textByte, err := n.formatter.Format(e)
|
||||
func (out *Output) Send(e *log.Entry, to *database.Notify) bool {
|
||||
textByte, err := out.formatter.Format(e)
|
||||
if err != nil {
|
||||
logger.Error("during format notify", err)
|
||||
return false
|
||||
}
|
||||
text := strings.TrimRight(to.RunReplace(string(textByte)), "\n")
|
||||
if to.Protocol == protoGroup {
|
||||
if _, ok := n.channels[to.To]; ok {
|
||||
if _, ok := out.channels[to.To]; ok {
|
||||
toJID := xmppbase.NewJID(to.To)
|
||||
toJID.Resource = nickname
|
||||
err := n.client.Send(&xmpp.PresenceClient{
|
||||
err := out.client.Send(&xmpp.PresenceClient{
|
||||
To: toJID,
|
||||
})
|
||||
if err != nil {
|
||||
logger.Error("xmpp could not join ", toJID.String(), " error:", err)
|
||||
} else {
|
||||
n.channels[to.To] = true
|
||||
out.channels[to.To] = true
|
||||
}
|
||||
}
|
||||
err := n.client.Send(&xmpp.MessageClient{
|
||||
err := out.client.Send(&xmpp.MessageClient{
|
||||
Type: xmpp.MessageTypeGroupchat,
|
||||
To: xmppbase.NewJID(to.To),
|
||||
Body: text,
|
||||
|
@ -188,7 +199,7 @@ func (n *Notifier) Send(e *log.Entry, to *database.Notify) bool {
|
|||
return true
|
||||
}
|
||||
if to.Protocol == proto {
|
||||
err := n.client.Send(&xmpp.MessageClient{
|
||||
err := out.client.Send(&xmpp.MessageClient{
|
||||
Type: xmpp.MessageTypeChat,
|
||||
To: xmppbase.NewJID(to.To),
|
||||
Body: text,
|
||||
|
@ -201,11 +212,11 @@ func (n *Notifier) Send(e *log.Entry, to *database.Notify) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (n *Notifier) Close() {
|
||||
for jid := range n.channels {
|
||||
func (out *Output) Close() {
|
||||
for jid := range out.channels {
|
||||
toJID := xmppbase.NewJID(jid)
|
||||
toJID.Resource = nickname
|
||||
err := n.client.Send(&xmpp.PresenceClient{
|
||||
err := out.client.Send(&xmpp.PresenceClient{
|
||||
To: toJID,
|
||||
Type: xmpp.PresenceTypeUnavailable,
|
||||
})
|
||||
|
@ -213,9 +224,9 @@ func (n *Notifier) Close() {
|
|||
logger.Error("xmpp could not leave ", toJID.String(), " error:", err)
|
||||
}
|
||||
}
|
||||
n.client.Close()
|
||||
out.client.Close()
|
||||
}
|
||||
|
||||
func init() {
|
||||
notify.AddNotifier(Init)
|
||||
output.Add(proto, Init)
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
package all
|
||||
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"dev.sum7.eu/genofire/logmania/lib"
|
||||
"dev.sum7.eu/genofire/logmania/receive"
|
||||
)
|
||||
|
||||
type Receiver struct {
|
||||
receive.Receiver
|
||||
list []receive.Receiver
|
||||
}
|
||||
|
||||
func Init(config *lib.ReceiveConfig, exportChannel chan *log.Entry) receive.Receiver {
|
||||
var list []receive.Receiver
|
||||
for _, init := range receive.Register {
|
||||
receiver := init(config, exportChannel)
|
||||
|
||||
if receiver == nil {
|
||||
continue
|
||||
}
|
||||
list = append(list, receiver)
|
||||
}
|
||||
return &Receiver{
|
||||
list: list,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Receiver) Listen() {
|
||||
for _, item := range r.list {
|
||||
go item.Listen()
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Receiver) Close() {
|
||||
for _, item := range r.list {
|
||||
item.Close()
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
package all
|
||||
|
||||
import (
|
||||
_ "dev.sum7.eu/genofire/logmania/receive/journald_json"
|
||||
_ "dev.sum7.eu/genofire/logmania/receive/logrus"
|
||||
_ "dev.sum7.eu/genofire/logmania/receive/syslog"
|
||||
)
|
|
@ -1,65 +0,0 @@
|
|||
package journald_json
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"dev.sum7.eu/genofire/logmania/lib"
|
||||
"dev.sum7.eu/genofire/logmania/receive"
|
||||
)
|
||||
|
||||
var logger = log.WithField("receive", "journald_json")
|
||||
|
||||
type Receiver struct {
|
||||
receive.Receiver
|
||||
exportChannel chan *log.Entry
|
||||
serverSocket *net.UDPConn
|
||||
}
|
||||
|
||||
func Init(config *lib.ReceiveConfig, exportChannel chan *log.Entry) receive.Receiver {
|
||||
addr, err := net.ResolveUDPAddr(config.JournaldJSON.Type, config.JournaldJSON.Address)
|
||||
ln, err := net.ListenUDP(config.JournaldJSON.Type, addr)
|
||||
|
||||
if err != nil {
|
||||
logger.Error("init ", err)
|
||||
return nil
|
||||
}
|
||||
recv := &Receiver{
|
||||
serverSocket: ln,
|
||||
exportChannel: exportChannel,
|
||||
}
|
||||
|
||||
logger.Info("init")
|
||||
|
||||
return recv
|
||||
}
|
||||
|
||||
const maxDataGramSize = 8192
|
||||
|
||||
func (rc *Receiver) Listen() {
|
||||
logger.Info("listen")
|
||||
for {
|
||||
buf := make([]byte, maxDataGramSize)
|
||||
n, src, err := rc.serverSocket.ReadFromUDP(buf)
|
||||
if err != nil {
|
||||
logger.Warn("failed to accept connection", err)
|
||||
continue
|
||||
}
|
||||
|
||||
raw := make([]byte, n)
|
||||
copy(raw, buf)
|
||||
entry := toLogEntry(raw, src.IP.String())
|
||||
if entry != nil {
|
||||
rc.exportChannel <- entry
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (rc *Receiver) Close() {
|
||||
rc.serverSocket.Close()
|
||||
}
|
||||
|
||||
func init() {
|
||||
receive.AddReceiver("journald_json", Init)
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
package receive
|
||||
|
||||
import (
|
||||
"dev.sum7.eu/genofire/logmania/lib"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var Register = make(map[string]ReceiverInit)
|
||||
|
||||
type Receiver interface {
|
||||
Listen()
|
||||
Close()
|
||||
}
|
||||
|
||||
type ReceiverInit func(*lib.ReceiveConfig, chan *log.Entry) Receiver
|
||||
|
||||
func AddReceiver(name string, n ReceiverInit) {
|
||||
Register[name] = n
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
package syslog
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"dev.sum7.eu/genofire/logmania/lib"
|
||||
"dev.sum7.eu/genofire/logmania/receive"
|
||||
)
|
||||
|
||||
var logger = log.WithField("receive", "syslog")
|
||||
|
||||
type Receiver struct {
|
||||
receive.Receiver
|
||||
exportChannel chan *log.Entry
|
||||
serverSocket *net.UDPConn
|
||||
}
|
||||
|
||||
func Init(config *lib.ReceiveConfig, exportChannel chan *log.Entry) receive.Receiver {
|
||||
addr, err := net.ResolveUDPAddr(config.Syslog.Type, config.Syslog.Address)
|
||||
ln, err := net.ListenUDP(config.Syslog.Type, addr)
|
||||
|
||||
if err != nil {
|
||||
logger.Error("init ", err)
|
||||
return nil
|
||||
}
|
||||
recv := &Receiver{
|
||||
serverSocket: ln,
|
||||
exportChannel: exportChannel,
|
||||
}
|
||||
|
||||
logger.Info("init")
|
||||
|
||||
return recv
|
||||
}
|
||||
|
||||
const maxDataGramSize = 8192
|
||||
|
||||
func (rc *Receiver) Listen() {
|
||||
logger.Info("listen")
|
||||
for {
|
||||
buf := make([]byte, maxDataGramSize)
|
||||
n, src, err := rc.serverSocket.ReadFromUDP(buf)
|
||||
if err != nil {
|
||||
logger.Warn("failed to accept connection", err)
|
||||
continue
|
||||
}
|
||||
|
||||
raw := make([]byte, n)
|
||||
copy(raw, buf)
|
||||
entry := toLogEntry(raw, src.IP.String())
|
||||
if entry != nil {
|
||||
rc.exportChannel <- entry
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (rc *Receiver) Close() {
|
||||
rc.serverSocket.Close()
|
||||
}
|
||||
|
||||
func init() {
|
||||
receive.AddReceiver("syslog", Init)
|
||||
}
|
Loading…
Reference in New Issue