From e9ec862cb47b5fb7ca7d78e1f837f2c091446253 Mon Sep 17 00:00:00 2001 From: Maxime Wojtczak Date: Sun, 5 Nov 2023 08:43:12 +0100 Subject: [PATCH] fix(traps): send trap to all destinations on failure (#169) --- configuration/configuration.go | 1 + httpserver/http_server.go | 32 +++-- httpserver/http_server_test.go | 230 +++++++++++++++------------------ snmp_notifier.go | 11 +- telemetry/telemetry.go | 21 +-- trapsender/trap_sender.go | 125 +++++++++++------- trapsender/trap_sender_test.go | 7 +- 7 files changed, 222 insertions(+), 205 deletions(-) diff --git a/configuration/configuration.go b/configuration/configuration.go index a85aa9c..f94588b 100644 --- a/configuration/configuration.go +++ b/configuration/configuration.go @@ -7,6 +7,7 @@ import ( "text/template" "github.com/go-kit/log" + "github.com/prometheus/common/promlog" promlogflag "github.com/prometheus/common/promlog/flag" diff --git a/httpserver/http_server.go b/httpserver/http_server.go index 6b8e6ce..c09dfc8 100644 --- a/httpserver/http_server.go +++ b/httpserver/http_server.go @@ -20,6 +20,7 @@ import ( "net/http" "strconv" + "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/prometheus/exporter-toolkit/web" @@ -31,7 +32,6 @@ import ( "github.com/prometheus/client_golang/prometheus/promhttp" - "github.com/go-kit/log" "github.com/prometheus/common/version" ) @@ -40,7 +40,8 @@ type HTTPServer struct { configuration Configuration alertParser alertparser.AlertParser trapSender trapsender.TrapSender - logger log.Logger + logger *log.Logger + server *http.Server } // Configuration describes the configuration for serving HTTP requests @@ -49,12 +50,12 @@ type Configuration struct { } // New creates an HTTPServer instance -func New(configuration Configuration, alertParser alertparser.AlertParser, trapSender trapsender.TrapSender, logger log.Logger) *HTTPServer { - return &HTTPServer{configuration, alertParser, trapSender, logger} +func New(configuration Configuration, alertParser alertparser.AlertParser, trapSender trapsender.TrapSender, logger *log.Logger) *HTTPServer { + return &HTTPServer{configuration, alertParser, trapSender, logger, nil} } // Configure creates and configures the HTTP server -func (httpServer HTTPServer) Configure() *http.Server { +func (httpServer HTTPServer) Start() error { mux := http.NewServeMux() server := &http.Server{ Handler: mux, @@ -75,7 +76,7 @@ func (httpServer HTTPServer) Configure() *http.Server { }) mux.HandleFunc("/alerts", func(w http.ResponseWriter, req *http.Request) { - level.Debug(httpServer.logger).Log("msg", "Handling /alerts webhook request") + level.Debug(*httpServer.logger).Log("msg", "Handling /alerts webhook request") defer req.Body.Close() @@ -104,7 +105,22 @@ func (httpServer HTTPServer) Configure() *http.Server { mux.Handle("/metrics", promhttp.Handler()) mux.HandleFunc("/health", healthHandler) - return server + if err := web.ListenAndServe(server, &httpServer.configuration.ToolKitConfiguration, *httpServer.logger); err != nil { + level.Error(*httpServer.logger).Log("err", err) + return err + } + + httpServer.server = server + + return nil +} + +func (httpServer HTTPServer) Stop() error { + if httpServer.server != nil { + level.Error(*httpServer.logger).Log("msg", "stopping server") + return httpServer.server.Close() + } + return nil } func healthHandler(w http.ResponseWriter, r *http.Request) { @@ -128,6 +144,6 @@ func (httpServer HTTPServer) errorHandler(w http.ResponseWriter, status int, err json := string(bytes[:]) fmt.Fprint(w, json) - level.Error(httpServer.logger).Log("status", status, "statustext", http.StatusText(status), "err", err, "data", data) + level.Error(*httpServer.logger).Log("status", status, "statustext", http.StatusText(status), "err", err, "data", data) telemetry.RequestTotal.WithLabelValues(strconv.FormatInt(int64(status), 10)).Inc() } diff --git a/httpserver/http_server_test.go b/httpserver/http_server_test.go index c6e6288..c79426c 100644 --- a/httpserver/http_server_test.go +++ b/httpserver/http_server_test.go @@ -19,11 +19,13 @@ import ( "fmt" "io/ioutil" "log" + "math/rand" "net/http" "strings" "testing" "time" + "github.com/k-sone/snmpgo" "github.com/maxwo/snmp_notifier/alertparser" "github.com/maxwo/snmp_notifier/trapsender" @@ -43,15 +45,9 @@ Description: {{ $value.Annotations.description }} {{ end -}}` type Test struct { - DescriptionTemplate string - DefaultOID string - OIDLabel string - DefaultSeverity string - Severities []string - SeverityLabel string AlertsFileName string TrapsFileName string - SNMPConnectionPort int + SNMPDestinationPort int URI string Verb string ExpectStatus int @@ -59,12 +55,6 @@ type Test struct { var tests = []Test{ { - dummyDescriptionTemplate, - "1", - "oid", - "critical", - strings.Split("critical,warning,info", ","), - "severity", "test_mixed_alerts.json", "test_mixed_traps.json", 1164, @@ -73,12 +63,6 @@ var tests = []Test{ 200, }, { - dummyDescriptionTemplate, - "1", - "oid", - "critical", - strings.Split("critical,warning,info", ","), - "severity", "test_unprocessable_alerts.json", "test_no_trap.json", 1164, @@ -87,40 +71,22 @@ var tests = []Test{ 422, }, { - dummyDescriptionTemplate, - "1", - "oid", - "critical", - strings.Split("critical,warning,info", ","), - "severity", - "test_wrong_oid_alerts.json", + "test_mixed_alerts.json", "test_no_trap.json", - 1164, + 1166, "/alerts", "POST", - 400, + 502, }, { - dummyDescriptionTemplate, - "1", - "oid", - "critical", - strings.Split("critical,warning,info", ","), - "severity", - "test_mixed_alerts.json", + "test_wrong_oid_alerts.json", "test_no_trap.json", - 1166, + 1164, "/alerts", "POST", - 502, + 400, }, { - dummyDescriptionTemplate, - "1", - "oid", - "critical", - strings.Split("critical,warning,info", ","), - "severity", "test_mixed_alerts.json", "test_no_trap.json", 1164, @@ -129,12 +95,6 @@ var tests = []Test{ 200, }, { - dummyDescriptionTemplate, - "1", - "oid", - "critical", - strings.Split("critical,warning,info", ","), - "severity", "test_mixed_alerts.json", "test_no_trap.json", 1164, @@ -145,81 +105,96 @@ var tests = []Test{ } func TestPostAlerts(t *testing.T) { - server, channel, err := testutils.LaunchTrapReceiver("127.0.0.1:1164") + + server, trapChannel, err := testutils.LaunchTrapReceiver("127.0.0.1:1164") if err != nil { - t.Fatal("Error while opening server:", err) + t.Fatal("msg", "Error while starting SNMP server:", "err", err) } defer server.Close() for _, test := range tests { - httpserver := launchHTTPServer(t, test) + launchSingleTest(t, test, trapChannel) + } +} - t.Log("Testing with file", test.AlertsFileName) - alertsByteData, err := ioutil.ReadFile(test.AlertsFileName) - if err != nil { - t.Fatal("Error while reading alert file:", err) - } - alertsReader := bytes.NewReader(alertsByteData) +func launchSingleTest(t *testing.T, test Test, trapChannel chan *snmpgo.TrapRequest) { - url := fmt.Sprintf("http://127.0.0.1:9465%s", test.URI) - req, err := http.NewRequest(test.Verb, url, alertsReader) - if err != nil { - t.Fatal("Error while building request:", err) - } - req.Header.Set("Content-Type", "application/json") + httpserver, notifierPort := launchHTTPServer(t, test) - client := &http.Client{} - resp, err := client.Do(req) - if err != nil { - t.Fatal("Error while sending request:", err) - } - defer resp.Body.Close() + defer httpserver.Stop() - httpserver.Close() + t.Log("Testing with file", test.AlertsFileName) + alertsByteData, err := ioutil.ReadFile(test.AlertsFileName) + if err != nil { + t.Fatal("Error while reading alert file:", err) + } + alertsReader := bytes.NewReader(alertsByteData) - t.Log("response Status:", resp.Status) - t.Log("response Headers:", resp.Header) - body, _ := ioutil.ReadAll(resp.Body) - t.Log("response Body:", string(body)) + url := fmt.Sprintf("http://127.0.0.1:%d%s", notifierPort, test.URI) + req, err := http.NewRequest(test.Verb, url, alertsReader) + if err != nil { + t.Fatal("Error while building request:", err) + } + req.Header.Set("Content-Type", "application/json") - if resp.StatusCode != test.ExpectStatus { - t.Error(test.ExpectStatus, "status expected, but got:", resp.StatusCode) - } else { - receivedTraps := testutils.ReadTraps(channel) + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + t.Fatal("Error while sending request:", err) + } + defer resp.Body.Close() - log.Print("Traps received:", receivedTraps) + t.Log("response Status:", resp.Status) + t.Log("response Headers:", resp.Header) + body, _ := ioutil.ReadAll(resp.Body) + t.Log("response Body:", string(body)) - expectedTrapsByteData, err := ioutil.ReadFile(test.TrapsFileName) - if err != nil { - t.Fatal("Error while reading traps file:", err) - } - expectedTrapsReader := bytes.NewReader(expectedTrapsByteData) - expectedTrapsData := []map[string]string{} - err = json.NewDecoder(expectedTrapsReader).Decode(&expectedTrapsData) - if err != nil { - t.Fatal("Error while parsing traps file:", err) - } + if resp.StatusCode != test.ExpectStatus { + t.Fatal(test.ExpectStatus, "status expected, but got:", resp.StatusCode) + } else { + receivedTraps := testutils.ReadTraps(trapChannel) - if len(receivedTraps) != len(expectedTrapsData) { - t.Error(len(expectedTrapsData), "traps expected, but received", receivedTraps) - } + log.Print("Traps received:", receivedTraps) - for _, expectedTrap := range expectedTrapsData { - if !testutils.FindTrap(receivedTraps, expectedTrap) { - t.Fatal("Expected trap not found:", expectedTrap) - } + expectedTrapsByteData, err := ioutil.ReadFile(test.TrapsFileName) + if err != nil { + t.Fatal("Error while reading traps file:", err) + } + expectedTrapsReader := bytes.NewReader(expectedTrapsByteData) + expectedTrapsData := []map[string]string{} + err = json.NewDecoder(expectedTrapsReader).Decode(&expectedTrapsData) + if err != nil { + t.Fatal("Error while parsing traps file:", err) + } + + if len(receivedTraps) != len(expectedTrapsData) { + t.Fatal(len(expectedTrapsData), "traps expected, but received", receivedTraps) + } + + for _, expectedTrap := range expectedTrapsData { + if !testutils.FindTrap(receivedTraps, expectedTrap) { + t.Fatal("Expected trap not found:", expectedTrap) } } } } -func launchHTTPServer(t *testing.T, test Test) *http.Server { - snmpDestination := fmt.Sprintf("127.0.0.1:%d", test.SNMPConnectionPort) +func launchHTTPServer(t *testing.T, test Test) (*HTTPServer, int) { + notfierRandomPort := 10000 + rand.Intn(1000) + + snmpDestination := fmt.Sprintf("127.0.0.1:%d", test.SNMPDestinationPort) + notifierAddress := fmt.Sprintf(":%d", notfierRandomPort) - alertParserConfiguration := alertparser.Configuration{test.DefaultOID, test.OIDLabel, test.DefaultSeverity, test.Severities, test.SeverityLabel} + alertParserConfiguration := alertparser.Configuration{ + DefaultOID: "1", + OIDLabel: "oid", + DefaultSeverity: "critical", + Severities: strings.Split("critical,warning,info", ","), + SeverityLabel: "severity", + } alertParser := alertparser.New(alertParserConfiguration) - descriptionTemplate, err := template.New("description").Parse(test.DescriptionTemplate) + descriptionTemplate, err := template.New("description").Parse(dummyDescriptionTemplate) if err != nil { t.Fatal("Error while building template") } @@ -228,41 +203,44 @@ func launchHTTPServer(t *testing.T, test Test) *http.Server { var emptyString = "" trapSenderConfiguration := trapsender.Configuration{ - []string{snmpDestination}, - 1, - "V2c", - 5 * time.Second, - "public", - false, - "", - "", - "", - false, - "", - "", - "", - "", - "", - *descriptionTemplate, - make(map[string]template.Template), + SNMPDestination: []string{snmpDestination}, + SNMPRetries: 1, + SNMPVersion: "V2c", + SNMPTimeout: 5 * time.Second, + SNMPCommunity: "public", + SNMPAuthenticationEnabled: false, + SNMPAuthenticationProtocol: "", + SNMPAuthenticationUsername: "", + SNMPAuthenticationPassword: "", + SNMPPrivateEnabled: false, + SNMPPrivateProtocol: "", + SNMPPrivatePassword: "", + SNMPSecurityEngineID: "", + SNMPContextEngineID: "", + SNMPContextName: "", + DescriptionTemplate: *descriptionTemplate, + ExtraFieldTemplates: make(map[string]template.Template), } - trapSender := trapsender.New(trapSenderConfiguration) + + promlogConfig := promlog.Config{} + logger := promlog.New(&promlogConfig) + + trapSender := trapsender.New(trapSenderConfiguration, &logger) httpServerConfiguration := Configuration{ web.FlagConfig{ - WebListenAddresses: &[]string{":9465"}, + WebListenAddresses: &[]string{notifierAddress}, WebSystemdSocket: &falseValue, WebConfigFile: &emptyString, }, } - - promlogConfig := promlog.Config{} - logger := promlog.New(&promlogConfig) - httpServer := New(httpServerConfiguration, alertParser, trapSender, logger).Configure() + httpServer := New(httpServerConfiguration, alertParser, trapSender, &logger) go func() { - web.ListenAndServe(httpServer, &httpServerConfiguration.ToolKitConfiguration, logger) + if err := httpServer.Start(); err != nil { + t.Error("err", err) + } }() time.Sleep(200 * time.Millisecond) - return httpServer + return httpServer, notfierRandomPort } diff --git a/snmp_notifier.go b/snmp_notifier.go index 85d2d09..0d5d744 100755 --- a/snmp_notifier.go +++ b/snmp_notifier.go @@ -18,7 +18,6 @@ import ( "os" "github.com/go-kit/log/level" - "github.com/prometheus/exporter-toolkit/web" "github.com/maxwo/snmp_notifier/alertparser" "github.com/maxwo/snmp_notifier/configuration" @@ -38,14 +37,16 @@ func main() { os.Exit(1) } - trapSender := trapsender.New(configuration.TrapSenderConfiguration) + level.Debug(logger).Log("configuration", configuration) + + trapSender := trapsender.New(configuration.TrapSenderConfiguration, &logger) alertParser := alertparser.New(configuration.AlertParserConfiguration) - httpServer := httpserver.New(configuration.HTTPServerConfiguration, alertParser, trapSender, logger) + httpServer := httpserver.New(configuration.HTTPServerConfiguration, alertParser, trapSender, &logger) telemetry.Init() - if err := web.ListenAndServe(httpServer.Configure(), &configuration.HTTPServerConfiguration.ToolKitConfiguration, logger); err != nil { - level.Error(logger).Log("err", err) + if err := httpServer.Start(); err != nil { + level.Error(logger).Log("msg", "error while launching the SNMP notifier", "err", err) os.Exit(1) } } diff --git a/telemetry/telemetry.go b/telemetry/telemetry.go index 93f5876..87cccd0 100644 --- a/telemetry/telemetry.go +++ b/telemetry/telemetry.go @@ -20,31 +20,22 @@ var ( RequestTotal = prometheus.NewCounterVec( prometheus.CounterOpts{ Name: "snmp_notifier_requests_total", - Help: "Requests processed, by status code.", + Help: "Total number of HTTP requests by status code.", }, []string{"code"}, ) // SNMPSentTotal counts the number of SNMP traps sent. - SNMPSentTotal = prometheus.NewCounterVec( + SNMPTrapTotal = prometheus.NewCounterVec( prometheus.CounterOpts{ - Name: "snmp_notifier_trap_sent_total", - Help: "Traps sent, by SNMP destination.", + Name: "snmp_notifier_traps_total", + Help: "Total number of trap by SNMP destination and outcome.", }, - []string{}, - ) - // SNMPErrorTotal counts the number of SNMP traps in error. - SNMPErrorTotal = prometheus.NewCounterVec( - prometheus.CounterOpts{ - Name: "snmp_notifier_trap_error_total", - Help: "Traps send errors, by SNMP destination.", - }, - []string{}, + []string{"destination", "outcome"}, ) ) // Init starts Prometheus metric counters collection func Init() { prometheus.Register(RequestTotal) - prometheus.Register(SNMPSentTotal) - prometheus.Register(SNMPErrorTotal) + prometheus.Register(SNMPTrapTotal) } diff --git a/trapsender/trap_sender.go b/trapsender/trap_sender.go index 249f6a5..7974116 100644 --- a/trapsender/trap_sender.go +++ b/trapsender/trap_sender.go @@ -14,6 +14,7 @@ package trapsender import ( + "errors" "strings" "time" @@ -23,13 +24,18 @@ import ( "text/template" + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/k-sone/snmpgo" "github.com/shirou/gopsutil/host" ) // TrapSender sends traps according to given alerts type TrapSender struct { - configuration Configuration + logger *log.Logger + configuration Configuration + snmpConnectionArguments []snmpgo.SNMPArguments } // Configuration describes the configuration for sending traps @@ -57,37 +63,71 @@ type Configuration struct { } // New creates a new TrapSender -func New(configuration Configuration) TrapSender { - return TrapSender{configuration} +func New(configuration Configuration, logger *log.Logger) TrapSender { + snmpConnectionArguments := generationConnectionArguments(configuration) + return TrapSender{logger, configuration, snmpConnectionArguments} } // SendAlertTraps sends a bucket of alerts to the given SNMP connection func (trapSender TrapSender) SendAlertTraps(alertBucket types.AlertBucket) error { traps, err := trapSender.generateTraps(alertBucket) if err != nil { + for _, connection := range trapSender.snmpConnectionArguments { + telemetry.SNMPTrapTotal.WithLabelValues(connection.Address, "failure").Add(float64(len(traps))) + } + return err + } + + hasError := false + + for _, connection := range trapSender.snmpConnectionArguments { + if trapSender.sendTraps(connection, traps) != nil { + hasError = true + } + } + + if hasError { + return errors.New("error while sending one or more traps") + } + return nil +} + +func (trapSender TrapSender) sendTraps(connectionArguments snmpgo.SNMPArguments, traps []snmpgo.VarBinds) error { + distinationForMetrics := connectionArguments.Address + + snmp, err := snmpgo.NewSNMP(connectionArguments) + if err != nil { + level.Error(*trapSender.logger).Log("msg", "error while creating SNMP connection", "err", err) + telemetry.SNMPTrapTotal.WithLabelValues(distinationForMetrics, "failure").Add(float64(len(traps))) return err } - connections, err := trapSender.connect() + + err = snmp.Open() if err != nil { + level.Error(*trapSender.logger).Log("msg", "error while opening SNMP connection", "err", err) + telemetry.SNMPTrapTotal.WithLabelValues(distinationForMetrics, "failure").Add(float64(len(traps))) return err } + defer func() { - for _, connection := range connections { - connection.Close() - } + snmp.Close() }() - for _, connection := range connections { - for _, trap := range traps { - err = connection.V2Trap(trap) - if err != nil { - telemetry.SNMPErrorTotal.WithLabelValues().Inc() - return err - } - telemetry.SNMPSentTotal.WithLabelValues().Inc() + hasError := false + + for _, trap := range traps { + err = snmp.V2Trap(trap) + if err != nil { + telemetry.SNMPTrapTotal.WithLabelValues(distinationForMetrics, "failure").Inc() + level.Error(*trapSender.logger).Log("msg", "error while generating trap", "destination", distinationForMetrics, "err", err) + hasError = true } + telemetry.SNMPTrapTotal.WithLabelValues(distinationForMetrics, "success").Inc() } + if hasError == true { + return errors.New("error while sending one or more traps") + } return nil } @@ -146,64 +186,49 @@ func addTrapSubObject(varBinds snmpgo.VarBinds, alertOid string, subOid string, return append(varBinds, snmpgo.NewVarBind(oid, snmpgo.NewOctetString([]byte(strings.TrimSpace(value))))) } -func (trapSender TrapSender) connect() ([]*snmpgo.SNMP, error) { +func generationConnectionArguments(configuration Configuration) []snmpgo.SNMPArguments { snmpArguments := []snmpgo.SNMPArguments{} - for _, destination := range trapSender.configuration.SNMPDestination { + for _, destination := range configuration.SNMPDestination { snmpArgument := snmpgo.SNMPArguments{ Address: destination, - Retries: trapSender.configuration.SNMPRetries, - Timeout: trapSender.configuration.SNMPTimeout, + Retries: configuration.SNMPRetries, + Timeout: configuration.SNMPTimeout, } - if trapSender.configuration.SNMPVersion == "V2c" { + if configuration.SNMPVersion == "V2c" { snmpArgument.Version = snmpgo.V2c - snmpArgument.Community = trapSender.configuration.SNMPCommunity + snmpArgument.Community = configuration.SNMPCommunity } - if trapSender.configuration.SNMPVersion == "V3" { + if configuration.SNMPVersion == "V3" { snmpArgument.Version = snmpgo.V3 - snmpArgument.UserName = trapSender.configuration.SNMPAuthenticationUsername + snmpArgument.UserName = configuration.SNMPAuthenticationUsername - if trapSender.configuration.SNMPAuthenticationEnabled && trapSender.configuration.SNMPPrivateEnabled { + if configuration.SNMPAuthenticationEnabled && configuration.SNMPPrivateEnabled { snmpArgument.SecurityLevel = snmpgo.AuthPriv - } else if trapSender.configuration.SNMPAuthenticationEnabled { + } else if configuration.SNMPAuthenticationEnabled { snmpArgument.SecurityLevel = snmpgo.AuthNoPriv } else { snmpArgument.SecurityLevel = snmpgo.NoAuthNoPriv } - if trapSender.configuration.SNMPPrivateEnabled { - snmpArgument.PrivProtocol = snmpgo.PrivProtocol(trapSender.configuration.SNMPPrivateProtocol) - snmpArgument.PrivPassword = trapSender.configuration.SNMPPrivatePassword + if configuration.SNMPPrivateEnabled { + snmpArgument.PrivProtocol = snmpgo.PrivProtocol(configuration.SNMPPrivateProtocol) + snmpArgument.PrivPassword = configuration.SNMPPrivatePassword } - if trapSender.configuration.SNMPAuthenticationEnabled { - snmpArgument.AuthProtocol = snmpgo.AuthProtocol(trapSender.configuration.SNMPAuthenticationProtocol) - snmpArgument.AuthPassword = trapSender.configuration.SNMPAuthenticationPassword + if configuration.SNMPAuthenticationEnabled { + snmpArgument.AuthProtocol = snmpgo.AuthProtocol(configuration.SNMPAuthenticationProtocol) + snmpArgument.AuthPassword = configuration.SNMPAuthenticationPassword } - snmpArgument.SecurityEngineId = trapSender.configuration.SNMPSecurityEngineID - snmpArgument.ContextEngineId = trapSender.configuration.SNMPContextEngineID - snmpArgument.ContextName = trapSender.configuration.SNMPContextName + snmpArgument.SecurityEngineId = configuration.SNMPSecurityEngineID + snmpArgument.ContextEngineId = configuration.SNMPContextEngineID + snmpArgument.ContextName = configuration.SNMPContextName } snmpArguments = append(snmpArguments, snmpArgument) } - snmps := []*snmpgo.SNMP{} - for _, snmpArgument := range snmpArguments { - snmp, err := snmpgo.NewSNMP(snmpArgument) - if err != nil { - return nil, err - } - - err = snmp.Open() - if err != nil { - return nil, err - } - - snmps = append(snmps, snmp) - } - - return snmps, nil + return snmpArguments } diff --git a/trapsender/trap_sender_test.go b/trapsender/trap_sender_test.go index 385498d..7935242 100644 --- a/trapsender/trap_sender_test.go +++ b/trapsender/trap_sender_test.go @@ -17,6 +17,7 @@ import ( "bytes" "encoding/json" "io/ioutil" + "os" "testing" "time" @@ -24,6 +25,8 @@ import ( "github.com/maxwo/snmp_notifier/types" + loggergokit "github.com/go-kit/log" + testutils "github.com/maxwo/snmp_notifier/test" ) @@ -131,6 +134,8 @@ func TestSend(t *testing.T) { } defer server.Close() + logger := loggergokit.NewLogfmtLogger(loggergokit.NewSyncWriter(os.Stderr)) + for index, test := range tests { t.Log("Launching test ", index) bucketByteData, err := ioutil.ReadFile(test.BucketFileName) @@ -144,7 +149,7 @@ func TestSend(t *testing.T) { t.Fatal("Error while parsing bucket file:", err) } - trapSender := New(*test.Configuration) + trapSender := New(*test.Configuration, &logger) err = trapSender.SendAlertTraps(bucketData) if test.ExpectError && err == nil {