|
|
|
@ -1,50 +1,17 @@
|
|
|
|
|
/* |
|
|
|
|
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 implement zabbix sender protocol for send metrics to zabbix.
|
|
|
|
|
package zabbix |
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
|
"encoding/binary" |
|
|
|
|
"encoding/json" |
|
|
|
|
"fmt" |
|
|
|
|
"fmt" |
|
|
|
|
"io/ioutil" |
|
|
|
|
"net" |
|
|
|
|
"os" |
|
|
|
|
"time" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
// Metric class
|
|
|
|
|
// Metric class.
|
|
|
|
|
type Metric struct { |
|
|
|
|
Host string `json:"host"` |
|
|
|
|
Key string `json:"key"` |
|
|
|
@ -52,7 +19,7 @@ type Metric struct {
|
|
|
|
|
Clock int64 `json:"clock"` |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Metric class constructor
|
|
|
|
|
// Metric class constructor.
|
|
|
|
|
func NewMetric(host, key, value string, clock ...int64) *Metric { |
|
|
|
|
m := new(Metric) |
|
|
|
|
m.Host = host |
|
|
|
@ -65,120 +32,122 @@ func NewMetric(host, key, value string, clock ...int64) *Metric {
|
|
|
|
|
return m |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Packet class
|
|
|
|
|
// Packet class.
|
|
|
|
|
type Packet struct { |
|
|
|
|
Request string `json:"request"` |
|
|
|
|
Data []*Metric `json:"data"` |
|
|
|
|
Clock int64 `json:"clock"` |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Packet class cunstructor
|
|
|
|
|
// Packet class cunstructor.
|
|
|
|
|
func NewPacket(data []*Metric, clock ...int64) *Packet { |
|
|
|
|
p := new(Packet) |
|
|
|
|
p.Request = `sender data` |
|
|
|
|
p.Data = data |
|
|
|
|
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 |
|
|
|
|
return p |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// DataLen. Packet class method, return 8 bytes with packet length in little endian order
|
|
|
|
|
// 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 |
|
|
|
|
JSONData, _ := json.Marshal(p) |
|
|
|
|
binary.LittleEndian.PutUint32(dataLen, uint32(len(JSONData))) |
|
|
|
|
return dataLen |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Sender class
|
|
|
|
|
// Sender class.
|
|
|
|
|
type Sender struct { |
|
|
|
|
Host string |
|
|
|
|
Port int |
|
|
|
|
Host string |
|
|
|
|
Port int |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Sender class constructor
|
|
|
|
|
// Sender class constructor.
|
|
|
|
|
func NewSender(host string, port int) *Sender { |
|
|
|
|
s := new(Sender) |
|
|
|
|
s.Host = host |
|
|
|
|
s.Port = port |
|
|
|
|
return s |
|
|
|
|
s := new(Sender) |
|
|
|
|
s.Host = host |
|
|
|
|
s.Port = port |
|
|
|
|
return s |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Method Sender class, return zabbix header
|
|
|
|
|
// Method Sender class, return zabbix header.
|
|
|
|
|
func (s Sender) getHeader() []byte { |
|
|
|
|
return []byte("ZBXD\x01") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Method Sender class, resolve uri by name:port
|
|
|
|
|
// 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) |
|
|
|
|
// format: hostname:port
|
|
|
|
|
addr := fmt.Sprintf("%s:%d", s.Host, s.Port) |
|
|
|
|
|
|
|
|
|
// Resolve hostname:port to ip:port
|
|
|
|
|
iaddr, err := net.ResolveTCPAddr("tcp", addr) |
|
|
|
|
// Resolve hostname:port to ip:port
|
|
|
|
|
iaddr, err := net.ResolveTCPAddr("tcp", addr) |
|
|
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
if err != nil { |
|
|
|
|
fmt.Printf("Connection failed: %s", err.Error()) |
|
|
|
|
os.Exit(1) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return iaddr |
|
|
|
|
return iaddr |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Method Sender class, make connection to uri
|
|
|
|
|
// 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) |
|
|
|
|
iaddr := s.getTCPAddr() |
|
|
|
|
conn, err := net.DialTCP("tcp", nil, iaddr) |
|
|
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
if err != nil { |
|
|
|
|
fmt.Printf("Connection failed: %s", err.Error()) |
|
|
|
|
os.Exit(1) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return conn |
|
|
|
|
return conn |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Method Sender class, read data from connection
|
|
|
|
|
// Method Sender class, read data from connection.
|
|
|
|
|
func (s Sender) read(conn *net.TCPConn) []byte { |
|
|
|
|
res := make([]byte, 1024) |
|
|
|
|
|
|
|
|
|
res, err := ioutil.ReadAll(conn) |
|
|
|
|
res, err := ioutil.ReadAll(conn) |
|
|
|
|
if err != nil { |
|
|
|
|
fmt.Printf("Error whule receiving the data: %s", err.Error()) |
|
|
|
|
os.Exit(1) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return res |
|
|
|
|
return res |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Method Sender class, send packet to zabbix
|
|
|
|
|
func (s Sender) Send(packet *Packet) { |
|
|
|
|
|
|
|
|
|
conn := s.connect() |
|
|
|
|
// Method Sender class, send packet to zabbix.
|
|
|
|
|
func (s Sender) Send(packet *Packet) []byte { |
|
|
|
|
conn := s.connect() |
|
|
|
|
defer conn.Close() |
|
|
|
|
|
|
|
|
|
dataPacket, _ := json.Marshal(packet) |
|
|
|
|
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)) |
|
|
|
|
// 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...) |
|
|
|
|
// Fill buffer
|
|
|
|
|
buffer := append(s.getHeader(), packet.DataLen()...) |
|
|
|
|
buffer = append(buffer, dataPacket...) |
|
|
|
|
|
|
|
|
|
// Sent packet to zabbix
|
|
|
|
|
_, err := conn.Write(buffer) |
|
|
|
|
// 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)) |
|
|
|
|
res := s.read(conn) |
|
|
|
|
/* |
|
|
|
|
fmt.Printf("RESPONSE: %s\n", string(res)) |
|
|
|
|
*/ |
|
|
|
|
return res |
|
|
|
|
} |
|
|
|
|