From 5f7e2ed0566dd12bd99b0e491e39832ef6894b51 Mon Sep 17 00:00:00 2001 From: dev-mull Date: Tue, 12 Oct 2021 23:32:25 -0500 Subject: [PATCH] added logger --- README.md | 12 ++++++++++-- example-config.yml | 2 +- go.mod | 6 +++++- go.sum | 41 ++++++++++++++++++++++++++++++++++++++ main.go | 44 ++++++++++++++++++++++++++--------------- pb/trap.pb.go | 44 +++++++++++++++++++++++++---------------- trap.go | 49 ++++++++++++++++++++++++++++++++-------------- trap.proto | 3 ++- 8 files changed, 148 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index bedf5dd..cff8b15 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ # crap A high performance snmp trap to nats proxy. +Receives snmp traps, encodes them as json or protobuf and publishes them to a nats subject. -Receives snmp traps, encodes them as json and publishes them to a nats subject. +This tool is intended to be a building block for other systems. Not a full blown alerting engine with a trap receiver. It only starts here.. continue by enabling jetstream, adding streams and writing consumers. @@ -9,8 +10,15 @@ This system should be able to scale from a single embedded instance on a raspber Messages can be reliably delivered once they have been received by ```crap``` +## Status +This is mostly stable, but reporting issues will help a lot. +## Deployments +- Local. By running local the machine can basically send its traps over nats. This removes complexity with configuration management, h/a and load balancing +- Cloud/Datacenter with single node or multiple node +- Edge/Branch: If message reliability is of concern you may want to deploy an instance to edge/branch locations. This will let messages get buffered on the LAN and reliably sent upstream. + ## Features -- Encode snmp traps (v1,v2 & v3) into JSON +- Encode snmp traps (v1,v2 & v3) into Protocol Buffers or JSON - Internal stats sent to nats diff --git a/example-config.yml b/example-config.yml index 3ebab80..fcfd3d5 100644 --- a/example-config.yml +++ b/example-config.yml @@ -1,5 +1,5 @@ port: 162 -encoding: json + #encoding: json stats: subject: stats.test interval: 10s diff --git a/go.mod b/go.mod index 9caa9a9..43bfa5e 100644 --- a/go.mod +++ b/go.mod @@ -6,9 +6,10 @@ require ( github.com/deejross/go-snmplib v0.0.0-20190126151901-0ff3fc321a43 github.com/golang/protobuf v1.5.2 // indirect github.com/nats-io/nats-server/v2 v2.6.1 // indirect - github.com/nats-io/nats.go v1.12.3 + github.com/nats-io/nats.go v1.13.0 github.com/sirupsen/logrus v1.8.1 github.com/soniah/gosnmp v1.26.0 + go.uber.org/zap v1.19.1 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect golang.org/x/sys v0.0.0-20211006225509-1a26e0398eed // indirect google.golang.org/protobuf v1.27.1 @@ -18,4 +19,7 @@ require ( require ( github.com/nats-io/nkeys v0.3.0 // indirect github.com/nats-io/nuid v1.0.1 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.7.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/go.sum b/go.sum index 599761f..df6cd64 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,4 @@ +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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= @@ -20,6 +21,9 @@ github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/klauspost/compress v1.13.4 h1:0zhec2I8zGnjWcKyLl6i3gPqKANCCn5e9xmviEEeX6s= github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/minio/highwayhash v1.0.1 h1:dZ6IIu8Z14VlC0VpfKofAhCy74wu/Qb5gcn52yWoz/0= github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/nats-io/jwt v1.2.2 h1:w3GMTO969dFg+UOKTmmyuu7IGdusK+7Ytlt//OYH/uU= @@ -30,11 +34,14 @@ github.com/nats-io/nats-server/v2 v2.6.1 h1:cJy+ia7/4EaJL+ZYDmIy2rD1mDWTfckhtPBU github.com/nats-io/nats-server/v2 v2.6.1/go.mod h1:Az91TbZiV7K4a6k/4v6YYdOKEoxCXj+iqhHVf/MlrKo= github.com/nats-io/nats.go v1.12.3 h1:te0GLbRsjtejEkZKKiuk46tbfIn6FfCSv3WWSo1+51E= github.com/nats-io/nats.go v1.12.3/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w= +github.com/nats-io/nats.go v1.13.0 h1:LvYqRB5epIzZWQp6lmeltOOZNLqCvm4b+qfvzZO03HE= +github.com/nats-io/nats.go v1.13.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w= github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8= github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= @@ -43,21 +50,43 @@ github.com/soniah/gosnmp v1.26.0 h1:WkqN0GVuiaYE/ZG2BC62W8TdDvgve1FrYlafxYffCP8= github.com/soniah/gosnmp v1.26.0/go.mod h1:hF/8DZgfcJ/2KObJTGoG1KKjitz0a/kC9rE0RFhdPkY= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= +go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= +go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI= +go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211006225509-1a26e0398eed h1:E159xujlywdAeN3FqsTBPzRKGUq/pDHolXbuttkC36E= golang.org/x/sys v0.0.0-20211006225509-1a26e0398eed/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -67,8 +96,14 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -81,6 +116,12 @@ google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+Rur google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index a0f1000..221f21d 100644 --- a/main.go +++ b/main.go @@ -3,14 +3,15 @@ package main import ( "flag" "os" + "sync/atomic" "github.com/nats-io/nats.go" - log "github.com/sirupsen/logrus" - "gopkg.in/yaml.v2" + "go.uber.org/zap" + "gopkg.in/yaml.v3" ) var configPath, logLevel string -var received, drops int64 +var natsErrs, received, drops int64 func init() { flag.StringVar(&configPath, "config", "./config.yml", "path to config file") @@ -19,9 +20,13 @@ func init() { func main() { flag.Parse() + //logger, _ := zap.NewProduction() + logger, _ := zap.NewDevelopment() + defer logger.Sync() + cfg, err := getConfig(configPath) if err != nil { - log.Fatal(err) + logger.Fatal(err.Error()) } nargs := []nats.Option{} @@ -31,36 +36,43 @@ func main() { if cfg.Nats.RootCa != "" { nargs = append(nargs, nats.RootCAs(cfg.Nats.RootCa)) } + nargs = append(nargs, nats.ErrorHandler(func(conn *nats.Conn, sub *nats.Subscription, err error) { + atomic.AddInt64(&natsErrs, 1) + })) + nargs = append(nargs, nats.DisconnectErrHandler(func(conn *nats.Conn, err error) { + logger.Info("nats disconnect", + zap.String("error", err.Error()), + ) + atomic.AddInt64(&natsErrs, 1) + })) + nargs = append(nargs, nats.ReconnectHandler(func(conn *nats.Conn) { + logger.Info("nats reconnect") + })) nc, err := nats.Connect(cfg.Nats.Url, nargs...) if err != nil { - log.Fatal(err) + logger.Fatal(err.Error()) } - tp, th, err := NewTrapServer(cfg, nc, cfg.Nats.Subject) + tp, th, err := NewTrapServer(cfg, nc, logger) if err != nil { - log.Fatal(err) + logger.Fatal(err.Error()) } if cfg.Stats.Subject != "" { go th.StartStats(cfg) } - log.Infof("Listening for traps on port %v\n", cfg.Port) + logger.Info("Listening for traps", zap.Int("port", cfg.Port)) tp.ListenAndServe(th) } func getConfig(configPath string) (*Config, error) { - // Create config structure config := &Config{} - // Open config file - file, err := os.Open(configPath) + b, err := os.ReadFile(configPath) if err != nil { return nil, err } - defer file.Close() - // Init new YAML decode - d := yaml.NewDecoder(file) - // Start YAML decoding from file - if err := d.Decode(&config); err != nil { + + if err := yaml.Unmarshal(b, config); err != nil { return nil, err } return config, nil diff --git a/pb/trap.pb.go b/pb/trap.pb.go index 1e5216e..4e6b79d 100644 --- a/pb/trap.pb.go +++ b/pb/trap.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v3.17.3 +// protoc v3.18.1 // source: trap.proto package pb @@ -130,10 +130,11 @@ type Stat struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Time *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=time,proto3" json:"time,omitempty"` - Hostname string `protobuf:"bytes,2,opt,name=hostname,proto3" json:"hostname,omitempty"` - Drops int64 `protobuf:"varint,3,opt,name=drops,proto3" json:"drops,omitempty"` - Count int64 `protobuf:"varint,4,opt,name=count,proto3" json:"count,omitempty"` + Time *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=time,proto3" json:"time,omitempty"` + Hostname string `protobuf:"bytes,2,opt,name=hostname,proto3" json:"hostname,omitempty"` + Drops int64 `protobuf:"varint,3,opt,name=drops,proto3" json:"drops,omitempty"` + Received int64 `protobuf:"varint,4,opt,name=received,proto3" json:"received,omitempty"` + NatsErrors int64 `protobuf:"varint,5,opt,name=nats_errors,json=natsErrors,proto3" json:"nats_errors,omitempty"` } func (x *Stat) Reset() { @@ -189,9 +190,16 @@ func (x *Stat) GetDrops() int64 { return 0 } -func (x *Stat) GetCount() int64 { +func (x *Stat) GetReceived() int64 { if x != nil { - return x.Count + return x.Received + } + return 0 +} + +func (x *Stat) GetNatsErrors() int64 { + if x != nil { + return x.NatsErrors } return 0 } @@ -220,16 +228,18 @@ var file_trap_proto_rawDesc = []byte{ 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x74, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x72, 0x61, 0x70, 0x5f, 0x6f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x74, 0x72, 0x61, 0x70, 0x4f, 0x69, 0x64, 0x22, 0x7e, 0x0a, 0x04, 0x53, 0x74, 0x61, 0x74, - 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, - 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, - 0x64, 0x72, 0x6f, 0x70, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x64, 0x72, 0x6f, - 0x70, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x07, 0x74, 0x72, 0x61, 0x70, 0x4f, 0x69, 0x64, 0x22, 0xa5, 0x01, 0x0a, 0x04, 0x53, 0x74, 0x61, + 0x74, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x74, 0x69, 0x6d, + 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, + 0x05, 0x64, 0x72, 0x6f, 0x70, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x64, 0x72, + 0x6f, 0x70, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x12, + 0x1f, 0x0a, 0x0b, 0x6e, 0x61, 0x74, 0x73, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x6e, 0x61, 0x74, 0x73, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, + 0x42, 0x06, 0x5a, 0x04, 0x2e, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/trap.go b/trap.go index 3071f10..bc5b63f 100644 --- a/trap.go +++ b/trap.go @@ -11,13 +11,15 @@ import ( "github.com/deejross/go-snmplib" "github.com/dev-mull/crap/pb" "github.com/nats-io/nats.go" + "go.uber.org/zap" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/timestamppb" ) -func NewTrapServer(cfg *Config, nc *nats.Conn, subject string) (*snmplib.TrapServer, *Handler, error) { +func NewTrapServer(cfg *Config, nc *nats.Conn, logger *zap.Logger) (*snmplib.TrapServer, + *Handler, error) { server, err := snmplib.NewTrapServer(cfg.Address, cfg.Port) if err != nil { return nil, nil, err @@ -33,20 +35,22 @@ func NewTrapServer(cfg *Config, nc *nats.Conn, subject string) (*snmplib.TrapSer server.Users = append(server.Users, user) } - h, err := NewHandler(nc, cfg) + h, err := NewHandler(nc, cfg, logger) return &server, h, err } type Handler struct { - c *nats.Conn - js nats.JetStreamContext - cfg *Config + c *nats.Conn + js nats.JetStreamContext + cfg *Config + logger *zap.Logger } -func NewHandler(nc *nats.Conn, cfg *Config) (*Handler, error) { +func NewHandler(nc *nats.Conn, cfg *Config, logger *zap.Logger) (*Handler, error) { h := &Handler{ - c: nc, - cfg: cfg, + c: nc, + cfg: cfg, + logger: logger, } if cfg.Nats.Jetstream { var err error @@ -83,6 +87,7 @@ func (h *Handler) OnTrap(addr net.Addr, trap snmplib.Trap) { } nvb, err := structpb.NewStruct(vb) if err != nil { + h.logger.Error("failed to map varbinds", zap.String("error", err.Error())) atomic.AddInt64(&drops, 1) return } @@ -111,7 +116,13 @@ func (h *Handler) OnTrap(addr net.Addr, trap snmplib.Trap) { strings.ReplaceAll(trap.Community, ".", "_") + "." + strings.ReplaceAll(tt.TrapOid, ".", "-") - h.Publish(sub, tt) + if err := h.Publish(sub, tt); err != nil { + h.logger.Error("failed publish", + zap.String("error", err.Error()), + zap.String("sub", sub), + ) + atomic.AddInt64(&drops, 1) + } }(addr, trap) } @@ -131,6 +142,10 @@ func (h *Handler) Publish(subject string, m proto.Message) error { } func (h *Handler) OnError(addr net.Addr, err error) { + h.logger.Error("failed to handle trap", + zap.String("error", err.Error()), + zap.String("addr", addr.String()), + ) atomic.AddInt64(&drops, 1) } @@ -141,14 +156,18 @@ func (h *Handler) StartStats(cfg *Config) { for { select { case <-t.C: - count := atomic.LoadInt64(&received) - dropCount := atomic.LoadInt64(&drops) s := &pb.Stat{ - Time: timestamppb.Now(), - Hostname: hostname, - Drops: dropCount, - Count: count, + Time: timestamppb.Now(), + Hostname: hostname, + Drops: atomic.LoadInt64(&drops), + Received: atomic.LoadInt64(&received), + NatsErrors: atomic.LoadInt64(&natsErrs), } + h.logger.Info("stats", + zap.Int64("drops", s.Drops), + zap.Int64("received", s.Received), + zap.Int64("nats-errors", s.NatsErrors), + ) h.Publish(cfg.Stats.Subject, s) } diff --git a/trap.proto b/trap.proto index c553f3b..59e0e96 100644 --- a/trap.proto +++ b/trap.proto @@ -20,5 +20,6 @@ message Stat { google.protobuf.Timestamp time = 1; string hostname = 2; int64 drops = 3; - int64 count = 4; + int64 received = 4; + int64 nats_errors = 5; }