Compare commits

..

5 Commits

Author SHA1 Message Date
Alexey Dubkov
3c6a95ec4f Merge pull request #5 from tutti-ch/master
Error Handling
2017-01-17 20:09:03 -08:00
komkom
cbd8b1e36b a test added 2017-01-11 11:50:42 +01:00
komkom
0b1c5a07d0 error handling added 2017-01-11 11:50:26 +01:00
Alexey Dubkov
60d3deaeed Merge pull request #4 from blacked/refs#1-refactoring
Refactoring zabbix.go
2015-03-01 14:12:53 -08:00
Alexey Dubkov
2a239bf2dd Refactoring zabbix.go 2015-03-01 14:06:42 -08:00
2 changed files with 80 additions and 41 deletions

@ -7,7 +7,6 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net" "net"
"os"
"time" "time"
) )
@ -21,10 +20,7 @@ type Metric struct {
// Metric class constructor. // Metric class constructor.
func NewMetric(host, key, value string, clock ...int64) *Metric { func NewMetric(host, key, value string, clock ...int64) *Metric {
m := new(Metric) m := &Metric{Host: host, Key: key, Value: value}
m.Host = host
m.Key = key
m.Value = value
// use current time, if `clock` is not specified // use current time, if `clock` is not specified
if m.Clock = time.Now().Unix(); len(clock) > 0 { if m.Clock = time.Now().Unix(); len(clock) > 0 {
m.Clock = int64(clock[0]) m.Clock = int64(clock[0])
@ -41,9 +37,7 @@ type Packet struct {
// Packet class cunstructor. // Packet class cunstructor.
func NewPacket(data []*Metric, clock ...int64) *Packet { func NewPacket(data []*Metric, clock ...int64) *Packet {
p := new(Packet) p := &Packet{Request: `sender data`, Data: data}
p.Request = `sender data`
p.Data = data
// use current time, if `clock` is not specified // use current time, if `clock` is not specified
if p.Clock = time.Now().Unix(); len(clock) > 0 { if p.Clock = time.Now().Unix(); len(clock) > 0 {
p.Clock = int64(clock[0]) p.Clock = int64(clock[0])
@ -52,7 +46,7 @@ func NewPacket(data []*Metric, clock ...int64) *Packet {
} }
// 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 { func (p *Packet) DataLen() []byte {
dataLen := make([]byte, 8) dataLen := make([]byte, 8)
JSONData, _ := json.Marshal(p) JSONData, _ := json.Marshal(p)
binary.LittleEndian.PutUint32(dataLen, uint32(len(JSONData))) binary.LittleEndian.PutUint32(dataLen, uint32(len(JSONData)))
@ -67,67 +61,89 @@ type Sender struct {
// Sender class constructor. // Sender class constructor.
func NewSender(host string, port int) *Sender { func NewSender(host string, port int) *Sender {
s := new(Sender) s := &Sender{Host: host, Port: port}
s.Host = host
s.Port = port
return s return s
} }
// Method Sender class, return zabbix header. // Method Sender class, return zabbix header.
func (s Sender) getHeader() []byte { func (s *Sender) getHeader() []byte {
return []byte("ZBXD\x01") 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 { func (s *Sender) getTCPAddr() (iaddr *net.TCPAddr, err error) {
// format: hostname:port // format: hostname:port
addr := fmt.Sprintf("%s:%d", s.Host, s.Port) addr := fmt.Sprintf("%s:%d", s.Host, s.Port)
// Resolve hostname:port to ip:port // Resolve hostname:port to ip:port
iaddr, err := net.ResolveTCPAddr("tcp", addr) iaddr, err = net.ResolveTCPAddr("tcp", addr)
if err != nil { if err != nil {
fmt.Printf("Connection failed: %s", err.Error()) err = fmt.Errorf("Connection failed: %s", err.Error())
os.Exit(1) return
} }
return iaddr return
} }
// Method Sender class, make connection to uri. // Method Sender class, make connection to uri.
func (s Sender) connect() *net.TCPConn { func (s *Sender) connect() (conn *net.TCPConn, err error) {
// Open connection to zabbix host
iaddr := s.getTCPAddr()
conn, err := net.DialTCP("tcp", nil, iaddr)
if err != nil { type DialResp struct {
fmt.Printf("Connection failed: %s", err.Error()) Conn *net.TCPConn
os.Exit(1) Error error
} }
return conn // Open connection to zabbix host
iaddr, err := s.getTCPAddr()
if err != nil {
return
}
// dial tcp and handle timeouts
ch := make(chan DialResp)
go func() {
conn, err = net.DialTCP("tcp", nil, iaddr)
ch <- DialResp{Conn: conn, Error: err}
}()
select {
case <-time.After(5 * time.Second):
err = fmt.Errorf("Connection Timeout")
case resp := <-ch:
if resp.Error != nil {
err = resp.Error
break
}
conn = resp.Conn
}
return
} }
// Method Sender class, read data from connection. // Method Sender class, read data from connection.
func (s Sender) read(conn *net.TCPConn) []byte { func (s *Sender) read(conn *net.TCPConn) (res []byte, err error) {
res := make([]byte, 1024) res = make([]byte, 1024)
res, err := ioutil.ReadAll(conn) res, err = ioutil.ReadAll(conn)
if err != nil { if err != nil {
fmt.Printf("Error whule receiving the data: %s", err.Error()) err = fmt.Errorf("Error whule receiving the data: %s", err.Error())
os.Exit(1) return
} }
return res return
} }
// Method Sender class, send packet to zabbix. // Method Sender class, send packet to zabbix.
func (s Sender) Send(packet *Packet) []byte { func (s *Sender) Send(packet *Packet) (res []byte, err error) {
conn := s.connect() conn, err := s.connect()
if err != nil {
return
}
defer conn.Close() 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("HEADER: % x (%s)\n", s.getHeader(), s.getHeader())
fmt.Printf("DATALEN: % x, %d byte\n", packet.DataLen(), len(packet.DataLen())) fmt.Printf("DATALEN: % x, %d byte\n", packet.DataLen(), len(packet.DataLen()))
@ -139,15 +155,16 @@ func (s Sender) Send(packet *Packet) []byte {
buffer = append(buffer, dataPacket...) buffer = append(buffer, dataPacket...)
// Sent packet to zabbix // Sent packet to zabbix
_, err := conn.Write(buffer) _, err = conn.Write(buffer)
if err != nil { if err != nil {
fmt.Printf("Error while sending the data: %s", err.Error()) err = fmt.Errorf("Error while sending the data: %s", err.Error())
os.Exit(1) return
} }
res := s.read(conn) res, err = s.read(conn)
/* /*
fmt.Printf("RESPONSE: %s\n", string(res)) fmt.Printf("RESPONSE: %s\n", string(res))
*/ */
return res return
} }

22
zabbix_test.go Normal file

@ -0,0 +1,22 @@
package zabbix
import "testing"
const (
hostname = `somehost.com`
zabbixhost = `172.30.30.30`
zabbixport = 1234
)
func TestSend(t *testing.T) {
sender := NewSender(zabbixhost, zabbixport)
metrics := []*Metric{NewMetric(hostname, `key`, `value`)}
_, err := sender.Send(NewPacket(metrics))
if err == nil {
t.Error("sending should have failed")
}
t.Logf("error: %v", err.Error())
}