Add zabbix.go
This commit is contained in:
parent
20c5dd26d5
commit
5827377550
184
zabbix.go
Normal file
184
zabbix.go
Normal file
@ -0,0 +1,184 @@
|
||||
/*
|
||||
Zabbix sender protocol defenition:
|
||||
|
||||
HEADER: ZBXD\x01, 5 byte
|
||||
DATALEN: 8 byte, little-endian
|
||||
DATA: JSON data
|
||||
|
||||
Request packet to zabbix host:
|
||||
<HEADER><DATALEN>{
|
||||
"request": "sender data",
|
||||
"data": [
|
||||
{
|
||||
"host": "Host name 1",
|
||||
"key": "item_key",
|
||||
"value": "33",
|
||||
"clock": 1381482894
|
||||
},
|
||||
{
|
||||
"host": "Host name 2",
|
||||
"key": "item_key",
|
||||
"value": "55",
|
||||
"clock": 1381482894
|
||||
}
|
||||
],
|
||||
"clock": 1381482905
|
||||
}
|
||||
|
||||
Response packet:
|
||||
<HEADER><DATALEN>{
|
||||
"response":"success",
|
||||
"info":"Processed 2 Failed 0 Total 2 Seconds spent 0.002070"
|
||||
}
|
||||
*/
|
||||
|
||||
package zabbix
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Metric class
|
||||
type Metric struct {
|
||||
Host string `json:"host"`
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
Clock int64 `json:"clock"`
|
||||
}
|
||||
|
||||
// Metric class constructor
|
||||
func NewMetric(host, key, value string, clock ...int64) *Metric {
|
||||
m := new(Metric)
|
||||
m.Host = host
|
||||
m.Key = key
|
||||
m.Value = value
|
||||
// use current time, if `clock` is not specified
|
||||
if m.Clock = time.Now().Unix(); len(clock) > 0 {
|
||||
m.Clock = int64(clock[0])
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// Packet class
|
||||
type Packet struct {
|
||||
Request string `json:"request"`
|
||||
Data []*Metric `json:"data"`
|
||||
Clock int64 `json:"clock"`
|
||||
}
|
||||
|
||||
// Packet class cunstructor
|
||||
func NewPacket(data []*Metric, clock ...int64) *Packet {
|
||||
p := new(Packet)
|
||||
p.Request = `sender data`
|
||||
p.Data = data
|
||||
// use current time, if `clock` is not specified
|
||||
if p.Clock = time.Now().Unix(); len(clock) > 0 {
|
||||
p.Clock = int64(clock[0])
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// DataLen. Packet class method, return 8 bytes with packet length in little endian order
|
||||
func (p Packet) DataLen() []byte {
|
||||
dataLen := make([]byte, 8)
|
||||
jsonData, _ := json.Marshal(p)
|
||||
binary.LittleEndian.PutUint32(dataLen, uint32(len(jsonData)))
|
||||
return dataLen
|
||||
}
|
||||
|
||||
// Sender class
|
||||
type Sender struct {
|
||||
Host string
|
||||
Port int
|
||||
}
|
||||
|
||||
// Sender class constructor
|
||||
func NewSender(host string, port int) *Sender {
|
||||
s := new(Sender)
|
||||
s.Host = host
|
||||
s.Port = port
|
||||
return s
|
||||
}
|
||||
|
||||
// Method Sender class, return zabbix header
|
||||
func (s Sender) getHeader() []byte {
|
||||
return []byte("ZBXD\x01")
|
||||
}
|
||||
|
||||
// Method Sender class, resolve uri by name:port
|
||||
func (s Sender) getTCPAddr() *net.TCPAddr {
|
||||
// format: hostname:port
|
||||
addr := fmt.Sprintf("%s:%d", s.Host, s.Port)
|
||||
|
||||
// Resolve hostname:port to ip:port
|
||||
iaddr, err := net.ResolveTCPAddr("tcp", addr)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("Connection failed: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return iaddr
|
||||
}
|
||||
|
||||
// Method Sender class, make connection to uri
|
||||
func (s Sender) connect() *net.TCPConn {
|
||||
iaddr := s.getTCPAddr()
|
||||
|
||||
// Open connection to zabbix host
|
||||
conn, err := net.DialTCP("tcp", nil, iaddr)
|
||||
|
||||
if err != nil {
|
||||
fmt.Printf("Connection failed: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return conn
|
||||
}
|
||||
|
||||
// Method Sender class, read data from connection
|
||||
func (s Sender) read(conn *net.TCPConn) []byte {
|
||||
res := make([]byte, 1024)
|
||||
|
||||
res, err := ioutil.ReadAll(conn)
|
||||
if err != nil {
|
||||
fmt.Printf("Error whule receiving the data: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// Method Sender class, send packet to zabbix
|
||||
func (s Sender) Send(packet *Packet) {
|
||||
|
||||
conn := s.connect()
|
||||
defer conn.Close()
|
||||
|
||||
dataPacket, _ := json.Marshal(packet)
|
||||
|
||||
// Make zabbix header
|
||||
fmt.Printf("HEADER: % x (%s)\n", s.getHeader(), s.getHeader())
|
||||
fmt.Printf("DATALEN: % x, %d byte\n", packet.DataLen(), len(packet.DataLen()))
|
||||
fmt.Printf("BODY: %s\n", string(dataPacket))
|
||||
|
||||
// Fill buffer
|
||||
buffer := append(s.getHeader(), packet.DataLen()...)
|
||||
buffer = append(buffer, dataPacket...)
|
||||
|
||||
// Sent packet to zabbix
|
||||
_, err := conn.Write(buffer)
|
||||
if err != nil {
|
||||
fmt.Printf("Error while sending the data: %s", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
res := s.read(conn)
|
||||
fmt.Printf("RESPONSE: %s\n", string(res))
|
||||
}
|
Loading…
Reference in New Issue
Block a user