Skip to content

Commit

Permalink
send to mackerel
Browse files Browse the repository at this point in the history
  • Loading branch information
yseto committed Feb 20, 2023
1 parent af5619d commit 728ecc7
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 10 deletions.
6 changes: 6 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,15 @@ type Trap struct {
Format string `yaml:"format"`
}

type Mackerel struct {
ApiKey string `yaml:"x-api-key"`
HostID string `yaml:"host-id"`
}

type Config struct {
MIB *MIB `yaml:"mib"`
TrapServer *TrapServer `yaml:"snmp"`
Trap []*Trap `yaml:"trap"`
Debug bool `yaml:"debug"`
Mackerel *Mackerel `yaml:"mackerel"`
}
4 changes: 3 additions & 1 deletion config.yaml.sample
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,6 @@ trap:
format: '{{ addr }} {{ read "IF-MIB::ifDescr" }} is linkdown'
- ident: .1.3.6.1.6.3.1.1.5.4
format: '{{ addr }} {{ read "IF-MIB::ifDescr" }} is linkup'

mackerel:
x-api-key: ****
host-id: ****
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.19

require (
github.com/gosnmp/gosnmp v1.35.0
github.com/mackerelio/mackerel-client-go v0.24.0
github.com/sleepinggenius2/gosmi v0.4.4
gopkg.in/yaml.v3 v3.0.1
)
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gosnmp/gosnmp v1.35.0 h1:EuWWNPxTCdAUx2/NbQcSa3WdNxjzpy4Phv57b4MWpJM=
github.com/gosnmp/gosnmp v1.35.0/go.mod h1:2AvKZ3n9aEl5TJEo/fFmf/FGO4Nj4cVeEc5yuk88CYc=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/mackerelio/mackerel-client-go v0.24.0 h1:Y9FeTgrQlDdtLU7FtMM6hd5mL5T4TvGCVUY0LH+bceQ=
github.com/mackerelio/mackerel-client-go v0.24.0/go.mod h1:b4qVMQi+w4rxtKQIFycLWXNBtIi9d0r571RzYmg/aXo=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand Down
47 changes: 47 additions & 0 deletions mackerel.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package main

import (
"context"
"fmt"
"log"
"time"

mackerel "github.com/mackerelio/mackerel-client-go"
)

type mackerelCheck struct {
Addr string
Message string
}

func sendToMackerel(ctx context.Context, client *mackerel.Client, hostId string) {
if buffers.Len() == 0 {
return
}

e := buffers.Front()
// log.Infof("send current value: %#v", e.Value)
// log.Infof("buffers len: %d", buffers.Len())

v := e.Value.(mackerelCheck)

reports := []*mackerel.CheckReport{
{
Source: mackerel.NewCheckSourceHost(hostId),
Status: mackerel.CheckStatusWarning,
Name: fmt.Sprintf("snmptrap %s", v.Addr),
Message: v.Message,
OccurredAt: time.Now().Unix(),
},
}
err := client.PostCheckReports(&mackerel.CheckReports{Reports: reports})
if err != nil {
log.Println(err)
return
} else {
log.Printf("mackerel success: %q %q", v.Addr, v.Message)
}
mutex.Lock()
buffers.Remove(e)
mutex.Unlock()
}
68 changes: 59 additions & 9 deletions trap.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
package main

import (
"bytes"
"container/list"
"context"
"fmt"
"log"
"net"
"os"
"os/signal"
"strings"
"sync"
"text/template"
"time"

g "github.com/gosnmp/gosnmp"
mackerel "github.com/mackerelio/mackerel-client-go"
"github.com/sleepinggenius2/gosmi/types"
"gopkg.in/yaml.v3"
)
Expand All @@ -17,23 +24,27 @@ const SnmpTrapOIDPrefix = ".1.3.6.1.6.3.1.1.4.1"

var mibParser SMI
var c Config
var buffers = list.New()
var mutex = &sync.Mutex{}

func main() {
defer func() {
mibParser.Close()
}()

// TODO args.
f, err := os.ReadFile("config.yaml")

// load config.
err = yaml.Unmarshal(f, &c)
if err != nil {
log.Fatalf("error: %v", err)
}

ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
defer stop()

// init mib parser
mibParser.Modules = c.MIB.LoadModules
mibParser.Paths = c.MIB.Directory
mibParser.Init()
defer mibParser.Close()

// template tests.
funcmap := template.FuncMap{
Expand All @@ -53,17 +64,48 @@ func main() {
}
}

// trapListner
trapListner := g.NewTrapListener()
trapListner.OnNewTrap = trapHandler
trapListner.Params = g.Default
if c.Debug {
trapListner.Params.Logger = g.NewLogger(log.New(os.Stdout, "<GOSNMP DEBUG LOGGER>", 0))
}

err = trapListner.Listen(net.JoinHostPort(c.TrapServer.Address, c.TrapServer.Port))
if err != nil {
log.Fatalf("error in listen: %s", err)
}
client := mackerel.NewClient(c.Mackerel.ApiKey)

wg := sync.WaitGroup{}

t := time.NewTicker(500 * time.Millisecond)
defer t.Stop()

wg.Add(1)
go func() {
err = trapListner.Listen(net.JoinHostPort(c.TrapServer.Address, c.TrapServer.Port))
if err != nil {
log.Fatalf("error in listen: %s", err)
}
wg.Done()
}()

wg.Add(1)
go func() {
defer wg.Done()
for {
select {
case <-t.C:
sendToMackerel(ctx, client, c.Mackerel.HostID)

case <-ctx.Done():
trapListner.Close()
log.Println("trapListner is close.")
log.Println("cancellation from context:", ctx.Err())
return
}
}
}()
log.Println("initialized.")
wg.Wait()
}

func trapHandler(packet *g.SnmpPacket, addr *net.UDPAddr) {
Expand Down Expand Up @@ -144,7 +186,15 @@ func trapHandler(packet *g.SnmpPacket, addr *net.UDPAddr) {

var tpl = template.New("").Funcs(funcmap)

if err := template.Must(tpl.Parse(specificTrapFormat)).Execute(os.Stdout, pad); err != nil {
var wr bytes.Buffer
if err := template.Must(tpl.Parse(specificTrapFormat)).Execute(&wr, pad); err != nil {
log.Println(err)
}

mutex.Lock()
buffers.PushBack(mackerelCheck{
Addr: addr.IP.String(),
Message: wr.String(),
})
mutex.Unlock()
}

0 comments on commit 728ecc7

Please sign in to comment.