diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index 04f4706ad..c49bdcd5c 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -22,6 +22,10 @@
"Comment": "v0.8.6-7-g9c060de",
"Rev": "9c060de643590dae45da9d7c26276463bfc46fa0"
},
+ {
+ "ImportPath": "github.com/amir/raidman",
+ "Rev": "6a8e089bbe32e6b907feae5ba688841974b3c339"
+ },
{
"ImportPath": "github.com/armon/go-metrics",
"Rev": "b2d95e5291cdbc26997d1301a5e467ecbb240e25"
@@ -164,7 +168,47 @@
"Rev": "5bb5cfc093ad18a28148c578f8632cfdb4d802e4"
},
{
- "ImportPath": "github.com/shirou/gopsutil",
+ "ImportPath": "github.com/shirou/gopsutil/common",
+ "Comment": "1.0.0-173-g1e9aabb",
+ "Rev": "1e9aabb3c8132314662698c9d1c0aef68d9da617"
+ },
+ {
+ "ImportPath": "github.com/shirou/gopsutil/cpu",
+ "Comment": "1.0.0-173-g1e9aabb",
+ "Rev": "1e9aabb3c8132314662698c9d1c0aef68d9da617"
+ },
+ {
+ "ImportPath": "github.com/shirou/gopsutil/disk",
+ "Comment": "1.0.0-173-g1e9aabb",
+ "Rev": "1e9aabb3c8132314662698c9d1c0aef68d9da617"
+ },
+ {
+ "ImportPath": "github.com/shirou/gopsutil/docker",
+ "Comment": "1.0.0-173-g1e9aabb",
+ "Rev": "1e9aabb3c8132314662698c9d1c0aef68d9da617"
+ },
+ {
+ "ImportPath": "github.com/shirou/gopsutil/host",
+ "Comment": "1.0.0-173-g1e9aabb",
+ "Rev": "1e9aabb3c8132314662698c9d1c0aef68d9da617"
+ },
+ {
+ "ImportPath": "github.com/shirou/gopsutil/load",
+ "Comment": "1.0.0-173-g1e9aabb",
+ "Rev": "1e9aabb3c8132314662698c9d1c0aef68d9da617"
+ },
+ {
+ "ImportPath": "github.com/shirou/gopsutil/mem",
+ "Comment": "1.0.0-173-g1e9aabb",
+ "Rev": "1e9aabb3c8132314662698c9d1c0aef68d9da617"
+ },
+ {
+ "ImportPath": "github.com/shirou/gopsutil/net",
+ "Comment": "1.0.0-173-g1e9aabb",
+ "Rev": "1e9aabb3c8132314662698c9d1c0aef68d9da617"
+ },
+ {
+ "ImportPath": "github.com/shirou/gopsutil/process",
"Comment": "1.0.0-173-g1e9aabb",
"Rev": "1e9aabb3c8132314662698c9d1c0aef68d9da617"
},
diff --git a/Godeps/_workspace/src/github.com/amir/raidman/README.md b/Godeps/_workspace/src/github.com/amir/raidman/README.md
new file mode 100644
index 000000000..5dbe8684e
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/amir/raidman/README.md
@@ -0,0 +1,73 @@
+Raidman
+=======
+
+Go Riemann client
+
+```go
+package main
+
+import (
+ "github.com/amir/raidman"
+)
+
+func main() {
+ c, err := raidman.Dial("tcp", "localhost:5555")
+ if err != nil {
+ panic(err)
+ }
+
+ var event = &raidman.Event{
+ State: "success",
+ Host: "raidman",
+ Service: "raidman-sample",
+ Metric: 100,
+ Ttl: 10,
+ }
+
+ // send one event
+ err = c.Send(event)
+ if err != nil {
+ panic(err)
+ }
+
+ // send multiple events at once
+ err = c.SendMulti([]*raidman.Event{
+ &raidman.Event{
+ State: "success",
+ Host: "raidman",
+ Service: "raidman-sample",
+ Metric: 100,
+ Ttl: 10,
+ },
+ &raidman.Event{
+ State: "failure",
+ Host: "raidman",
+ Service: "raidman-sample",
+ Metric: 100,
+ Ttl: 10,
+ },
+ &raidman.Event{
+ State: "success",
+ Host: "raidman",
+ Service: "raidman-sample",
+ Metric: 100,
+ Ttl: 10,
+ },
+ })
+ if err != nil {
+ panic(err)
+ }
+
+ events, err := c.Query("host = \"raidman\"")
+ if err != nil {
+ panic(err)
+ }
+
+ if len(events) < 1 {
+ panic("Submitted event not found")
+ }
+
+ c.Close()
+}
+
+```
diff --git a/Godeps/_workspace/src/github.com/amir/raidman/UNLICENSE b/Godeps/_workspace/src/github.com/amir/raidman/UNLICENSE
new file mode 100644
index 000000000..68a49daad
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/amir/raidman/UNLICENSE
@@ -0,0 +1,24 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to
diff --git a/Godeps/_workspace/src/github.com/amir/raidman/proto/Makefile b/Godeps/_workspace/src/github.com/amir/raidman/proto/Makefile
new file mode 100644
index 000000000..5349cc839
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/amir/raidman/proto/Makefile
@@ -0,0 +1,6 @@
+proto.pb.go: proto.proto
+ mkdir -p _pb
+ protoc --go_out=_pb $<
+ cat _pb/$@\
+ |gofmt >$@
+ rm -rf _pb
diff --git a/Godeps/_workspace/src/github.com/amir/raidman/proto/proto.pb.go b/Godeps/_workspace/src/github.com/amir/raidman/proto/proto.pb.go
new file mode 100644
index 000000000..42eea684d
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/amir/raidman/proto/proto.pb.go
@@ -0,0 +1,273 @@
+// Code generated by protoc-gen-go.
+// source: proto.proto
+// DO NOT EDIT!
+
+package proto
+
+import proto1 "github.com/golang/protobuf/proto"
+import json "encoding/json"
+import math "math"
+
+// Reference proto, json, and math imports to suppress error if they are not otherwise used.
+var _ = proto1.Marshal
+var _ = &json.SyntaxError{}
+var _ = math.Inf
+
+type State struct {
+ Time *int64 `protobuf:"varint,1,opt,name=time" json:"time,omitempty"`
+ State *string `protobuf:"bytes,2,opt,name=state" json:"state,omitempty"`
+ Service *string `protobuf:"bytes,3,opt,name=service" json:"service,omitempty"`
+ Host *string `protobuf:"bytes,4,opt,name=host" json:"host,omitempty"`
+ Description *string `protobuf:"bytes,5,opt,name=description" json:"description,omitempty"`
+ Once *bool `protobuf:"varint,6,opt,name=once" json:"once,omitempty"`
+ Tags []string `protobuf:"bytes,7,rep,name=tags" json:"tags,omitempty"`
+ Ttl *float32 `protobuf:"fixed32,8,opt,name=ttl" json:"ttl,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (this *State) Reset() { *this = State{} }
+func (this *State) String() string { return proto1.CompactTextString(this) }
+func (*State) ProtoMessage() {}
+
+func (this *State) GetTime() int64 {
+ if this != nil && this.Time != nil {
+ return *this.Time
+ }
+ return 0
+}
+
+func (this *State) GetState() string {
+ if this != nil && this.State != nil {
+ return *this.State
+ }
+ return ""
+}
+
+func (this *State) GetService() string {
+ if this != nil && this.Service != nil {
+ return *this.Service
+ }
+ return ""
+}
+
+func (this *State) GetHost() string {
+ if this != nil && this.Host != nil {
+ return *this.Host
+ }
+ return ""
+}
+
+func (this *State) GetDescription() string {
+ if this != nil && this.Description != nil {
+ return *this.Description
+ }
+ return ""
+}
+
+func (this *State) GetOnce() bool {
+ if this != nil && this.Once != nil {
+ return *this.Once
+ }
+ return false
+}
+
+func (this *State) GetTags() []string {
+ if this != nil {
+ return this.Tags
+ }
+ return nil
+}
+
+func (this *State) GetTtl() float32 {
+ if this != nil && this.Ttl != nil {
+ return *this.Ttl
+ }
+ return 0
+}
+
+type Event struct {
+ Time *int64 `protobuf:"varint,1,opt,name=time" json:"time,omitempty"`
+ State *string `protobuf:"bytes,2,opt,name=state" json:"state,omitempty"`
+ Service *string `protobuf:"bytes,3,opt,name=service" json:"service,omitempty"`
+ Host *string `protobuf:"bytes,4,opt,name=host" json:"host,omitempty"`
+ Description *string `protobuf:"bytes,5,opt,name=description" json:"description,omitempty"`
+ Tags []string `protobuf:"bytes,7,rep,name=tags" json:"tags,omitempty"`
+ Ttl *float32 `protobuf:"fixed32,8,opt,name=ttl" json:"ttl,omitempty"`
+ Attributes []*Attribute `protobuf:"bytes,9,rep,name=attributes" json:"attributes,omitempty"`
+ MetricSint64 *int64 `protobuf:"zigzag64,13,opt,name=metric_sint64" json:"metric_sint64,omitempty"`
+ MetricD *float64 `protobuf:"fixed64,14,opt,name=metric_d" json:"metric_d,omitempty"`
+ MetricF *float32 `protobuf:"fixed32,15,opt,name=metric_f" json:"metric_f,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (this *Event) Reset() { *this = Event{} }
+func (this *Event) String() string { return proto1.CompactTextString(this) }
+func (*Event) ProtoMessage() {}
+
+func (this *Event) GetTime() int64 {
+ if this != nil && this.Time != nil {
+ return *this.Time
+ }
+ return 0
+}
+
+func (this *Event) GetState() string {
+ if this != nil && this.State != nil {
+ return *this.State
+ }
+ return ""
+}
+
+func (this *Event) GetService() string {
+ if this != nil && this.Service != nil {
+ return *this.Service
+ }
+ return ""
+}
+
+func (this *Event) GetHost() string {
+ if this != nil && this.Host != nil {
+ return *this.Host
+ }
+ return ""
+}
+
+func (this *Event) GetDescription() string {
+ if this != nil && this.Description != nil {
+ return *this.Description
+ }
+ return ""
+}
+
+func (this *Event) GetTags() []string {
+ if this != nil {
+ return this.Tags
+ }
+ return nil
+}
+
+func (this *Event) GetTtl() float32 {
+ if this != nil && this.Ttl != nil {
+ return *this.Ttl
+ }
+ return 0
+}
+
+func (this *Event) GetAttributes() []*Attribute {
+ if this != nil {
+ return this.Attributes
+ }
+ return nil
+}
+
+func (this *Event) GetMetricSint64() int64 {
+ if this != nil && this.MetricSint64 != nil {
+ return *this.MetricSint64
+ }
+ return 0
+}
+
+func (this *Event) GetMetricD() float64 {
+ if this != nil && this.MetricD != nil {
+ return *this.MetricD
+ }
+ return 0
+}
+
+func (this *Event) GetMetricF() float32 {
+ if this != nil && this.MetricF != nil {
+ return *this.MetricF
+ }
+ return 0
+}
+
+type Query struct {
+ String_ *string `protobuf:"bytes,1,opt,name=string" json:"string,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (this *Query) Reset() { *this = Query{} }
+func (this *Query) String() string { return proto1.CompactTextString(this) }
+func (*Query) ProtoMessage() {}
+
+func (this *Query) GetString_() string {
+ if this != nil && this.String_ != nil {
+ return *this.String_
+ }
+ return ""
+}
+
+type Msg struct {
+ Ok *bool `protobuf:"varint,2,opt,name=ok" json:"ok,omitempty"`
+ Error *string `protobuf:"bytes,3,opt,name=error" json:"error,omitempty"`
+ States []*State `protobuf:"bytes,4,rep,name=states" json:"states,omitempty"`
+ Query *Query `protobuf:"bytes,5,opt,name=query" json:"query,omitempty"`
+ Events []*Event `protobuf:"bytes,6,rep,name=events" json:"events,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (this *Msg) Reset() { *this = Msg{} }
+func (this *Msg) String() string { return proto1.CompactTextString(this) }
+func (*Msg) ProtoMessage() {}
+
+func (this *Msg) GetOk() bool {
+ if this != nil && this.Ok != nil {
+ return *this.Ok
+ }
+ return false
+}
+
+func (this *Msg) GetError() string {
+ if this != nil && this.Error != nil {
+ return *this.Error
+ }
+ return ""
+}
+
+func (this *Msg) GetStates() []*State {
+ if this != nil {
+ return this.States
+ }
+ return nil
+}
+
+func (this *Msg) GetQuery() *Query {
+ if this != nil {
+ return this.Query
+ }
+ return nil
+}
+
+func (this *Msg) GetEvents() []*Event {
+ if this != nil {
+ return this.Events
+ }
+ return nil
+}
+
+type Attribute struct {
+ Key *string `protobuf:"bytes,1,req,name=key" json:"key,omitempty"`
+ Value *string `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
+ XXX_unrecognized []byte `json:"-"`
+}
+
+func (this *Attribute) Reset() { *this = Attribute{} }
+func (this *Attribute) String() string { return proto1.CompactTextString(this) }
+func (*Attribute) ProtoMessage() {}
+
+func (this *Attribute) GetKey() string {
+ if this != nil && this.Key != nil {
+ return *this.Key
+ }
+ return ""
+}
+
+func (this *Attribute) GetValue() string {
+ if this != nil && this.Value != nil {
+ return *this.Value
+ }
+ return ""
+}
+
+func init() {
+}
diff --git a/Godeps/_workspace/src/github.com/amir/raidman/proto/proto.proto b/Godeps/_workspace/src/github.com/amir/raidman/proto/proto.proto
new file mode 100644
index 000000000..3e946a3a0
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/amir/raidman/proto/proto.proto
@@ -0,0 +1,45 @@
+option java_package = "com.aphyr.riemann";
+option java_outer_classname = "Proto";
+
+message State {
+ optional int64 time = 1;
+ optional string state = 2;
+ optional string service = 3;
+ optional string host = 4;
+ optional string description = 5;
+ optional bool once = 6;
+ repeated string tags = 7;
+ optional float ttl = 8;
+}
+
+message Event {
+ optional int64 time = 1;
+ optional string state = 2;
+ optional string service = 3;
+ optional string host = 4;
+ optional string description = 5;
+ repeated string tags = 7;
+ optional float ttl = 8;
+ repeated Attribute attributes = 9;
+
+ optional sint64 metric_sint64 = 13;
+ optional double metric_d = 14;
+ optional float metric_f = 15;
+}
+
+message Query {
+ optional string string = 1;
+}
+
+message Msg {
+ optional bool ok = 2;
+ optional string error = 3;
+ repeated State states = 4;
+ optional Query query = 5;
+ repeated Event events = 6;
+}
+
+message Attribute {
+ required string key = 1;
+ optional string value = 2;
+}
diff --git a/Godeps/_workspace/src/github.com/amir/raidman/raidman.go b/Godeps/_workspace/src/github.com/amir/raidman/raidman.go
new file mode 100644
index 000000000..87c82777c
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/amir/raidman/raidman.go
@@ -0,0 +1,313 @@
+// Go Riemann client
+package raidman
+
+import (
+ "bytes"
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "io"
+ "net"
+ "os"
+ "reflect"
+ "sync"
+ "time"
+
+ "github.com/amir/raidman/proto"
+ pb "github.com/golang/protobuf/proto"
+)
+
+type network interface {
+ Send(message *proto.Msg, conn net.Conn) (*proto.Msg, error)
+}
+
+type tcp struct{}
+
+type udp struct{}
+
+// Client represents a connection to a Riemann server
+type Client struct {
+ sync.Mutex
+ net network
+ connection net.Conn
+ timeout time.Duration
+}
+
+// An Event represents a single Riemann event
+type Event struct {
+ Ttl float32
+ Time int64
+ Tags []string
+ Host string // Defaults to os.Hostname()
+ State string
+ Service string
+ Metric interface{} // Could be Int, Float32, Float64
+ Description string
+ Attributes map[string]string
+}
+
+// Dial establishes a connection to a Riemann server at addr, on the network
+// netwrk, with a timeout of timeout
+//
+// Known networks are "tcp", "tcp4", "tcp6", "udp", "udp4", and "udp6".
+func DialWithTimeout(netwrk, addr string, timeout time.Duration) (c *Client, err error) {
+ c = new(Client)
+
+ var cnet network
+ switch netwrk {
+ case "tcp", "tcp4", "tcp6":
+ cnet = new(tcp)
+ case "udp", "udp4", "udp6":
+ cnet = new(udp)
+ default:
+ return nil, fmt.Errorf("dial %q: unsupported network %q", netwrk, netwrk)
+ }
+
+ c.net = cnet
+ c.timeout = timeout
+ c.connection, err = net.Dial(netwrk, addr)
+ if err != nil {
+ return nil, err
+ }
+
+ return c, nil
+}
+
+// Dial establishes a connection to a Riemann server at addr, on the network
+// netwrk.
+//
+// Known networks are "tcp", "tcp4", "tcp6", "udp", "udp4", and "udp6".
+func Dial(netwrk, addr string) (c *Client, err error) {
+ return DialWithTimeout(netwrk, addr, 0)
+}
+
+func (network *tcp) Send(message *proto.Msg, conn net.Conn) (*proto.Msg, error) {
+ msg := &proto.Msg{}
+ data, err := pb.Marshal(message)
+ if err != nil {
+ return msg, err
+ }
+ b := new(bytes.Buffer)
+ if err = binary.Write(b, binary.BigEndian, uint32(len(data))); err != nil {
+ return msg, err
+ }
+ if _, err = conn.Write(b.Bytes()); err != nil {
+ return msg, err
+ }
+ if _, err = conn.Write(data); err != nil {
+ return msg, err
+ }
+ var header uint32
+ if err = binary.Read(conn, binary.BigEndian, &header); err != nil {
+ return msg, err
+ }
+ response := make([]byte, header)
+ if err = readFully(conn, response); err != nil {
+ return msg, err
+ }
+ if err = pb.Unmarshal(response, msg); err != nil {
+ return msg, err
+ }
+ if msg.GetOk() != true {
+ return msg, errors.New(msg.GetError())
+ }
+ return msg, nil
+}
+
+func readFully(r io.Reader, p []byte) error {
+ for len(p) > 0 {
+ n, err := r.Read(p)
+ p = p[n:]
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (network *udp) Send(message *proto.Msg, conn net.Conn) (*proto.Msg, error) {
+ data, err := pb.Marshal(message)
+ if err != nil {
+ return nil, err
+ }
+ if _, err = conn.Write(data); err != nil {
+ return nil, err
+ }
+
+ return nil, nil
+}
+
+func isZero(v reflect.Value) bool {
+ switch v.Kind() {
+ case reflect.Map:
+ return v.IsNil()
+ case reflect.Slice:
+ zero := true
+ for i := 0; i < v.Len(); i++ {
+ zero = zero && isZero(v.Index(i))
+ }
+ return zero
+ }
+ zero := reflect.Zero(v.Type())
+ return v.Interface() == zero.Interface()
+}
+
+func eventToPbEvent(event *Event) (*proto.Event, error) {
+ var e proto.Event
+
+ if event.Host == "" {
+ event.Host, _ = os.Hostname()
+ }
+ t := reflect.ValueOf(&e).Elem()
+ s := reflect.ValueOf(event).Elem()
+ typeOfEvent := s.Type()
+ for i := 0; i < s.NumField(); i++ {
+ f := s.Field(i)
+ value := reflect.ValueOf(f.Interface())
+ if !isZero(f) {
+ name := typeOfEvent.Field(i).Name
+ switch name {
+ case "State", "Service", "Host", "Description":
+ tmp := reflect.ValueOf(pb.String(value.String()))
+ t.FieldByName(name).Set(tmp)
+ case "Ttl":
+ tmp := reflect.ValueOf(pb.Float32(float32(value.Float())))
+ t.FieldByName(name).Set(tmp)
+ case "Time":
+ tmp := reflect.ValueOf(pb.Int64(value.Int()))
+ t.FieldByName(name).Set(tmp)
+ case "Tags":
+ tmp := reflect.ValueOf(value.Interface().([]string))
+ t.FieldByName(name).Set(tmp)
+ case "Metric":
+ switch reflect.TypeOf(f.Interface()).Kind() {
+ case reflect.Int:
+ tmp := reflect.ValueOf(pb.Int64(int64(value.Int())))
+ t.FieldByName("MetricSint64").Set(tmp)
+ case reflect.Int64:
+ tmp := reflect.ValueOf(pb.Int64(int64(value.Int())))
+ t.FieldByName("MetricSint64").Set(tmp)
+ case reflect.Float32:
+ tmp := reflect.ValueOf(pb.Float32(float32(value.Float())))
+ t.FieldByName("MetricF").Set(tmp)
+ case reflect.Float64:
+ tmp := reflect.ValueOf(pb.Float64(value.Float()))
+ t.FieldByName("MetricD").Set(tmp)
+ default:
+ return nil, fmt.Errorf("Metric of invalid type (type %v)",
+ reflect.TypeOf(f.Interface()).Kind())
+ }
+ case "Attributes":
+ var attrs []*proto.Attribute
+ for k, v := range value.Interface().(map[string]string) {
+ // Copy k,v so we can take
+ // pointers to the new
+ // temporaries
+ k_, v_ := k, v
+ attrs = append(attrs, &proto.Attribute{
+ Key: &k_,
+ Value: &v_,
+ })
+ }
+ t.FieldByName(name).Set(reflect.ValueOf(attrs))
+ }
+ }
+ }
+
+ return &e, nil
+}
+
+func pbEventsToEvents(pbEvents []*proto.Event) []Event {
+ var events []Event
+
+ for _, event := range pbEvents {
+ e := Event{
+ State: event.GetState(),
+ Service: event.GetService(),
+ Host: event.GetHost(),
+ Description: event.GetDescription(),
+ Ttl: event.GetTtl(),
+ Time: event.GetTime(),
+ Tags: event.GetTags(),
+ }
+ if event.MetricF != nil {
+ e.Metric = event.GetMetricF()
+ } else if event.MetricD != nil {
+ e.Metric = event.GetMetricD()
+ } else {
+ e.Metric = event.GetMetricSint64()
+ }
+ if event.Attributes != nil {
+ e.Attributes = make(map[string]string, len(event.GetAttributes()))
+ for _, attr := range event.GetAttributes() {
+ e.Attributes[attr.GetKey()] = attr.GetValue()
+ }
+ }
+
+ events = append(events, e)
+ }
+
+ return events
+}
+
+// Send sends an event to Riemann
+func (c *Client) Send(event *Event) error {
+ return c.SendMulti([]*Event{event})
+}
+
+// SendMulti sends multiple events to Riemann
+func (c *Client) SendMulti(events []*Event) error {
+ message := &proto.Msg{}
+
+ for _, event := range events {
+ e, err := eventToPbEvent(event)
+ if err != nil {
+ return err
+ }
+
+ message.Events = append(message.Events, e)
+ }
+
+ c.Lock()
+ defer c.Unlock()
+
+ if c.timeout > 0 {
+ err := c.connection.SetDeadline(time.Now().Add(c.timeout))
+ if err != nil {
+ return err
+ }
+ }
+
+ _, err := c.net.Send(message, c.connection)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// Query returns a list of events matched by query
+func (c *Client) Query(q string) ([]Event, error) {
+ switch c.net.(type) {
+ case *udp:
+ return nil, errors.New("Querying over UDP is not supported")
+ }
+ query := &proto.Query{}
+ query.String_ = pb.String(q)
+ message := &proto.Msg{}
+ message.Query = query
+ c.Lock()
+ defer c.Unlock()
+ response, err := c.net.Send(message, c.connection)
+ if err != nil {
+ return nil, err
+ }
+ return pbEventsToEvents(response.GetEvents()), nil
+}
+
+// Close closes the connection to Riemann
+func (c *Client) Close() {
+ c.Lock()
+ c.connection.Close()
+ c.Unlock()
+}
diff --git a/Godeps/_workspace/src/github.com/amir/raidman/raidman_test.go b/Godeps/_workspace/src/github.com/amir/raidman/raidman_test.go
new file mode 100644
index 000000000..8a824ee3c
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/amir/raidman/raidman_test.go
@@ -0,0 +1,268 @@
+package raidman
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestTCP(t *testing.T) {
+ c, err := Dial("tcp", "localhost:5555")
+ if err != nil {
+ t.Fatal(err.Error())
+ }
+ var event = &Event{
+ State: "success",
+ Host: "raidman",
+ Service: "tcp",
+ Metric: 42,
+ Ttl: 1,
+ Tags: []string{"tcp", "test", "raidman"},
+ Attributes: map[string]string{"type": "test"},
+ }
+
+ err = c.Send(event)
+ if err != nil {
+ t.Error(err.Error())
+ }
+
+ events, err := c.Query("tagged \"test\"")
+ if err != nil {
+ t.Error(err.Error())
+ }
+
+ if len(events) < 1 {
+ t.Error("Submitted event not found")
+ }
+
+ testAttributeExists := false
+ for _, event := range events {
+ if val, ok := event.Attributes["type"]; ok && val == "test" {
+ testAttributeExists = true
+ }
+ }
+
+ if !testAttributeExists {
+ t.Error("Attribute \"type\" is missing")
+ }
+
+ c.Close()
+}
+
+func TestMultiTCP(t *testing.T) {
+ c, err := Dial("tcp", "localhost:5555")
+ if err != nil {
+ t.Fatal(err.Error())
+ }
+
+ err = c.SendMulti([]*Event{
+ &Event{
+ State: "success",
+ Host: "raidman",
+ Service: "tcp-multi-1",
+ Metric: 42,
+ Ttl: 1,
+ Tags: []string{"tcp", "test", "raidman", "multi"},
+ Attributes: map[string]string{"type": "test"},
+ },
+ &Event{
+ State: "success",
+ Host: "raidman",
+ Service: "tcp-multi-2",
+ Metric: 42,
+ Ttl: 1,
+ Tags: []string{"tcp", "test", "raidman", "multi"},
+ Attributes: map[string]string{"type": "test"},
+ },
+ })
+ if err != nil {
+ t.Error(err.Error())
+ }
+
+ events, err := c.Query("tagged \"test\" and tagged \"multi\"")
+ if err != nil {
+ t.Error(err.Error())
+ }
+
+ if len(events) != 2 {
+ t.Error("Submitted event not found")
+ }
+
+ c.Close()
+}
+
+func TestMetricIsInt64(t *testing.T) {
+ c, err := Dial("tcp", "localhost:5555")
+ if err != nil {
+ t.Fatal(err.Error())
+ }
+
+ var int64metric int64 = 9223372036854775807
+
+ var event = &Event{
+ State: "success",
+ Host: "raidman",
+ Service: "tcp",
+ Metric: int64metric,
+ Ttl: 1,
+ Tags: []string{"tcp", "test", "raidman"},
+ Attributes: map[string]string{"type": "test"},
+ }
+
+ err = c.Send(event)
+ if err != nil {
+ t.Error(err.Error())
+ }
+}
+
+func TestUDP(t *testing.T) {
+ c, err := Dial("udp", "localhost:5555")
+ if err != nil {
+ t.Fatal(err.Error())
+ }
+ var event = &Event{
+ State: "warning",
+ Host: "raidman",
+ Service: "udp",
+ Metric: 3.4,
+ Ttl: 10.7,
+ }
+
+ err = c.Send(event)
+ if err != nil {
+ t.Error(err.Error())
+ }
+ c.Close()
+}
+
+func TestTCPWithoutHost(t *testing.T) {
+ c, err := Dial("tcp", "localhost:5555")
+ if err != nil {
+ t.Fatal(err.Error())
+ }
+ defer c.Close()
+
+ var event = &Event{
+ State: "success",
+ Service: "tcp-host-not-set",
+ Ttl: 5,
+ }
+
+ err = c.Send(event)
+ if err != nil {
+ t.Error(err.Error())
+ }
+
+ events, err := c.Query("service = \"tcp-host-not-set\"")
+ if err != nil {
+ t.Error(err.Error())
+ }
+
+ if len(events) < 1 {
+ t.Error("Submitted event not found")
+ }
+
+ for _, e := range events {
+ if e.Host == "" {
+ t.Error("Default host name is not set")
+ }
+ }
+}
+
+func TestIsZero(t *testing.T) {
+ event := &Event{
+ Time: 1,
+ }
+ elem := reflect.ValueOf(event).Elem()
+ eventType := elem.Type()
+ for i := 0; i < elem.NumField(); i++ {
+ field := elem.Field(i)
+ name := eventType.Field(i).Name
+ if name == "Time" {
+ if isZero(field) {
+ t.Error("Time should not be zero")
+ }
+ } else {
+ if !isZero(field) {
+ t.Errorf("%s should be zero", name)
+ }
+ }
+ }
+}
+
+func BenchmarkTCP(b *testing.B) {
+ c, err := Dial("tcp", "localhost:5555")
+
+ var event = &Event{
+ State: "good",
+ Host: "raidman",
+ Service: "benchmark",
+ }
+
+ if err == nil {
+ for i := 0; i < b.N; i++ {
+ c.Send(event)
+ }
+ }
+ c.Close()
+}
+
+func BenchmarkUDP(b *testing.B) {
+ c, err := Dial("udp", "localhost:5555")
+
+ var event = &Event{
+ State: "good",
+ Host: "raidman",
+ Service: "benchmark",
+ }
+
+ if err == nil {
+ for i := 0; i < b.N; i++ {
+ c.Send(event)
+ }
+ }
+ c.Close()
+}
+
+func BenchmarkConcurrentTCP(b *testing.B) {
+ c, err := Dial("tcp", "localhost:5555")
+
+ var event = &Event{
+ Host: "raidman",
+ Service: "tcp_concurrent",
+ Tags: []string{"concurrent", "tcp", "benchmark"},
+ }
+
+ ch := make(chan int, b.N)
+ for i := 0; i < b.N; i++ {
+ go func(metric int) {
+ event.Metric = metric
+ err = c.Send(event)
+ ch <- i
+ }(i)
+ }
+ <-ch
+
+ c.Close()
+}
+
+func BenchmarkConcurrentUDP(b *testing.B) {
+ c, err := Dial("udp", "localhost:5555")
+
+ var event = &Event{
+ Host: "raidman",
+ Service: "udp_concurrent",
+ Tags: []string{"concurrent", "udp", "benchmark"},
+ }
+
+ ch := make(chan int, b.N)
+ for i := 0; i < b.N; i++ {
+ go func(metric int) {
+ event.Metric = metric
+ err = c.Send(event)
+ ch <- i
+ }(i)
+ }
+ <-ch
+
+ c.Close()
+}
diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/.gitignore b/Godeps/_workspace/src/github.com/shirou/gopsutil/.gitignore
deleted file mode 100644
index 194eab896..000000000
--- a/Godeps/_workspace/src/github.com/shirou/gopsutil/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-*~
-#*
-_obj
-*.tmp
\ No newline at end of file
diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/LICENSE b/Godeps/_workspace/src/github.com/shirou/gopsutil/LICENSE
deleted file mode 100644
index 602b2c098..000000000
--- a/Godeps/_workspace/src/github.com/shirou/gopsutil/LICENSE
+++ /dev/null
@@ -1,27 +0,0 @@
-gopsutil is distributed under BSD license reproduced below.
-
-Copyright (c) 2014, WAKAYAMA Shirou
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- * Neither the name of the gopsutil authors nor the names of its contributors
- may be used to endorse or promote products derived from this software without
- specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/README.rst b/Godeps/_workspace/src/github.com/shirou/gopsutil/README.rst
deleted file mode 100644
index a858ff09e..000000000
--- a/Godeps/_workspace/src/github.com/shirou/gopsutil/README.rst
+++ /dev/null
@@ -1,270 +0,0 @@
-gopsutil: psutil for golang
-==============================
-
-.. image:: https://drone.io/github.com/shirou/gopsutil/status.png
- :target: https://drone.io/github.com/shirou/gopsutil
-
-.. image:: https://coveralls.io/repos/shirou/gopsutil/badge.png?branch=master
- :target: https://coveralls.io/r/shirou/gopsutil?branch=master
-
-
-This is a port of psutil (http://pythonhosted.org/psutil/). The challenge is porting all
-psutil functions on some architectures...
-
-.. highlights:: Package Structure Changed!
-
- Package (a.k.a. directory) structure has been changed!! see `issue 24 `_
-
-.. highlights:: golang 1.4 will become REQUIRED!
-
- Since syscall package becomes frozen, we should use golang/x/sys of golang 1.4 as soon as possible.
-
-
-Available Architectures
-------------------------------------
-
-- FreeBSD i386/amd64
-- Linux i386/amd64/arm(raspberry pi)
-- Windows/amd64
-- Darwin/amd64
-
-All works are implemented without cgo by porting c struct to golang struct.
-
-
-Usage
----------
-
-.. code:: go
-
- import (
- "fmt"
-
- "github.com/shirou/gopsutil/mem"
- )
-
- func main() {
- v, _ := mem.VirtualMemory()
-
- // almost every return value is a struct
- fmt.Printf("Total: %v, Free:%v, UsedPercent:%f%%\n", v.Total, v.Free, v.UsedPercent)
-
- // convert to JSON. String() is also implemented
- fmt.Println(v)
- }
-
-The output is below.
-
-::
-
- Total: 3179569152, Free:284233728, UsedPercent:84.508194%
- {"total":3179569152,"available":492572672,"used":2895335424,"usedPercent":84.50819439828305, (snip)}
-
-You can set an alternative location to /proc by setting the HOST_PROC environment variable.
-
-Documentation
-------------------------
-
-see http://godoc.org/github.com/shirou/gopsutil
-
-
-More Info
---------------------
-
-Several methods have been added which are not present in psutil, but will provide useful information.
-
-- host/HostInfo() (linux)
-
- - Hostname
- - Uptime
- - Procs
- - OS (ex: "linux")
- - Platform (ex: "ubuntu", "arch")
- - PlatformFamily (ex: "debian")
- - PlatformVersion (ex: "Ubuntu 13.10")
- - VirtualizationSystem (ex: "LXC")
- - VirtualizationRole (ex: "guest"/"host")
-
-- cpu/CPUInfo() (linux, freebsd)
-
- - CPU (ex: 0, 1, ...)
- - VendorID (ex: "GenuineIntel")
- - Family
- - Model
- - Stepping
- - PhysicalID
- - CoreID
- - Cores (ex: 2)
- - ModelName (ex: "Intel(R) Core(TM) i7-2640M CPU @ 2.80GHz")
- - Mhz
- - CacheSize
- - Flags (ex: "fpu vme de pse tsc msr pae mce cx8 ...")
-
-- load/LoadAvg() (linux, freebsd)
-
- - Load1
- - Load5
- - Load15
-
-- docker/GetDockerIDList() (linux only)
-
- - container id list ([]string)
-
-- docker/CgroupCPU() (linux only)
-
- - user
- - system
-
-- docker/CgroupMem() (linux only)
-
- - various status
-
-Some codes are ported from Ohai. many thanks.
-
-
-Current Status
-------------------
-
-- x: work
-- b: almost work but something broken
-
-================= ====== ======= ====== =======
-name Linux FreeBSD MacOSX Windows
-cpu_times x x x x
-cpu_count x x x x
-cpu_percent x x x x
-cpu_times_percent x x x x
-virtual_memory x x x x
-swap_memory x x x
-disk_partitions x x x x
-disk_io_counters x x
-disk_usage x x x x
-net_io_counters x x b x
-boot_time x x x x
-users x x x x
-pids x x x x
-pid_exists x x x x
-net_connections x x
-net_if_addrs
-net_if_stats
-================= ====== ======= ====== =======
-
-Process class
-^^^^^^^^^^^^^^^
-
-================ ===== ======= ====== =======
-name Linux FreeBSD MacOSX Windows
-pid x x x x
-ppid x x x x
-name x x x x
-cmdline x x x
-create_time x
-status x x x
-cwd x
-exe x x x
-uids x x x
-gids x x x
-terminal x x x
-io_counters x
-nice x x x
-num_fds x
-num_ctx_switches x
-num_threads x x x x
-cpu_times x
-memory_info x x x
-memory_info_ex x
-memory_maps x
-open_files x
-send_signal x x x
-suspend x x x
-resume x x x
-terminate x x x
-kill x x x
-username x
-ionice
-rlimit
-num_handlres
-threads
-cpu_percent x x
-cpu_affinity
-memory_percent
-parent x x
-children
-connections x x
-is_running
-================ ===== ======= ====== =======
-
-Original Metrics
-^^^^^^^^^^^^^^^^^^^
-================== ===== ======= ====== =======
-item Linux FreeBSD MacOSX Windows
-**HostInfo**
-hostname x x x x
- uptime x x x
- proces x x
- os x x x x
- platform x x x
- platformfamiliy x x x
- virtualization x
-**CPU**
- VendorID x x x x
- Family x x x x
- Model x x x x
- Stepping x x x x
- PhysicalID x
- CoreID x
- Cores x x
- ModelName x x x x
-**LoadAvg**
- Load1 x x x
- Load5 x x x
- Load15 x x x
-**GetDockerID**
- container id x no no no
-**CgroupsCPU**
- user x no no no
- system x no no no
-**CgroupsMem**
- various x no no no
-================== ===== ======= ====== =======
-
-- future work
-
- - process_iter
- - wait_procs
- - Process class
-
- - as_dict
- - wait
-
-
-License
-------------
-
-New BSD License (same as psutil)
-
-
-Related Works
------------------------
-
-I have been influenced by the following great works:
-
-- psutil: http://pythonhosted.org/psutil/
-- dstat: https://github.com/dagwieers/dstat
-- gosigar: https://github.com/cloudfoundry/gosigar/
-- goprocinfo: https://github.com/c9s/goprocinfo
-- go-ps: https://github.com/mitchellh/go-ps
-- ohai: https://github.com/opscode/ohai/
-- bosun: https://github.com/bosun-monitor/bosun/tree/master/cmd/scollector/collectors
-- mackerel: https://github.com/mackerelio/mackerel-agent/tree/master/metrics
-
-How to Contribute
----------------------------
-
-1. Fork it
-2. Create your feature branch (git checkout -b my-new-feature)
-3. Commit your changes (git commit -am 'Add some feature')
-4. Push to the branch (git push origin my-new-feature)
-5. Create new Pull Request
-
-My English is terrible, so documentation or correcting comments are also
-welcome.
diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/coverall.sh b/Godeps/_workspace/src/github.com/shirou/gopsutil/coverall.sh
deleted file mode 100644
index 35aa298ba..000000000
--- a/Godeps/_workspace/src/github.com/shirou/gopsutil/coverall.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#/bin/sh
-
-# see http://www.songmu.jp/riji/entry/2015-01-15-goveralls-multi-package.html
-
-set -e
-# cleanup
-cleanup() {
- if [ $tmpprof != "" ] && [ -f $tmpprof ]; then
- rm -f $tmpprof
- fi
- exit
-}
-trap cleanup INT QUIT TERM EXIT
-
-# メインの処理
-prof=${1:-".profile.cov"}
-echo "mode: count" > $prof
-gopath1=$(echo $GOPATH | cut -d: -f1)
-for pkg in $(go list ./...); do
- tmpprof=$gopath1/src/$pkg/profile.tmp
- go test -covermode=count -coverprofile=$tmpprof $pkg
- if [ -f $tmpprof ]; then
- cat $tmpprof | tail -n +2 >> $prof
- rm $tmpprof
- fi
-done
diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/doc.go b/Godeps/_workspace/src/github.com/shirou/gopsutil/doc.go
deleted file mode 100644
index 6a65fe268..000000000
--- a/Godeps/_workspace/src/github.com/shirou/gopsutil/doc.go
+++ /dev/null
@@ -1 +0,0 @@
-package gopsutil
diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/mktypes.sh b/Godeps/_workspace/src/github.com/shirou/gopsutil/mktypes.sh
deleted file mode 100644
index 7bf2e2412..000000000
--- a/Godeps/_workspace/src/github.com/shirou/gopsutil/mktypes.sh
+++ /dev/null
@@ -1,37 +0,0 @@
-
-DIRS="cpu disk docker host load mem net process"
-
-GOOS=`uname | tr '[:upper:]' '[:lower:]'`
-ARCH=`uname -m`
-
-case $ARCH in
- amd64)
- GOARCH="amd64"
- ;;
- x86_64)
- GOARCH="amd64"
- ;;
- i386)
- GOARCH="386"
- ;;
- i686)
- GOARCH="386"
- ;;
- arm)
- GOARCH="arm"
- ;;
- *)
- echo "unknown arch: $ARCH"
- exit 1
-esac
-
-for DIR in $DIRS
-do
- if [ -e ${DIR}/types_${GOOS}.go ]; then
- echo "// +build $GOOS" > ${DIR}/${DIR}_${GOOS}_${GOARCH}.go
- echo "// +build $GOARCH" >> ${DIR}/${DIR}_${GOOS}_${GOARCH}.go
- go tool cgo -godefs ${DIR}/types_${GOOS}.go >> ${DIR}/${DIR}_${GOOS}_${GOARCH}.go
- fi
-done
-
-
diff --git a/Godeps/_workspace/src/github.com/shirou/gopsutil/windows_memo.rst b/Godeps/_workspace/src/github.com/shirou/gopsutil/windows_memo.rst
deleted file mode 100644
index 38abed819..000000000
--- a/Godeps/_workspace/src/github.com/shirou/gopsutil/windows_memo.rst
+++ /dev/null
@@ -1,36 +0,0 @@
-Windows memo
-=====================
-
-Size
-----------
-
-DWORD
- 32-bit unsigned integer
-DWORDLONG
- 64-bit unsigned integer
-DWORD_PTR
- unsigned long type for pointer precision
-DWORD32
- 32-bit unsigned integer
-DWORD64
- 64-bit unsigned integer
-HALF_PTR
- _WIN64 = int, else short
-INT
- 32-bit signed integer
-INT_PTR
- _WIN64 = __int64 else int
-LONG
- 32-bit signed integer
-LONGLONG
- 64-bit signed integer
-LONG_PTR
- _WIN64 = __int64 else long
-SHORT
- 16-bit integer
-SIZE_T
- maximum number of bytes to which a pointer can point. typedef ULONG_PTR SIZE_T;
-SSIZE_T
- signed version of SIZE_T. typedef LONG_PTR SSIZE_T;
-WORD
- 16-bit unsigned integer
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 49e571ef8..58b5b1560 100644
--- a/Makefile
+++ b/Makefile
@@ -57,6 +57,7 @@ endif
docker run --name aerospike -p "3000:3000" -d aerospike
docker run --name nsq -p "4150:4150" -d nsqio/nsq /nsqd
docker run --name mqtt -p "1883:1883" -d ncarlier/mqtt
+ docker run --name riemann -p "5555:5555" -d blalor/riemann
# Run docker containers necessary for CircleCI unit tests
docker-run-circle:
@@ -69,11 +70,12 @@ docker-run-circle:
docker run --name aerospike -p "3000:3000" -d aerospike
docker run --name nsq -p "4150:4150" -d nsqio/nsq /nsqd
docker run --name mqtt -p "1883:1883" -d ncarlier/mqtt
+ docker run --name riemann -p "5555:5555" -d blalor/riemann
# Kill all docker containers, ignore errors
docker-kill:
- -docker kill nsq aerospike redis opentsdb rabbitmq postgres memcached mysql kafka mqtt
- -docker rm nsq aerospike redis opentsdb rabbitmq postgres memcached mysql kafka mqtt
+ -docker kill nsq aerospike redis opentsdb rabbitmq postgres memcached mysql kafka mqtt riemann
+ -docker rm nsq aerospike redis opentsdb rabbitmq postgres memcached mysql kafka mqtt riemann
# Run full unit tests using docker containers (includes setup and teardown)
test: docker-kill prepare docker-run