2015-10-22 21:50:19 +00:00
package riemann
import (
"fmt"
2016-10-11 11:28:20 +00:00
"log"
2015-10-22 21:50:19 +00:00
"os"
2016-02-03 22:06:41 +00:00
"sort"
"strings"
2015-10-22 21:50:19 +00:00
"github.com/amir/raidman"
2016-01-27 21:21:36 +00:00
"github.com/influxdata/telegraf"
2016-01-27 23:15:14 +00:00
"github.com/influxdata/telegraf/plugins/outputs"
2015-10-22 21:50:19 +00:00
)
2016-10-11 11:28:20 +00:00
const deprecationMsg = "I! WARNING: this Riemann output plugin will be deprecated in a future release, see https://github.com/influxdata/telegraf/issues/1878 for more details & discussion."
2015-10-22 21:50:19 +00:00
type Riemann struct {
URL string
Transport string
2016-02-03 22:06:41 +00:00
Separator string
2015-10-22 21:50:19 +00:00
2015-11-18 21:32:29 +00:00
client * raidman . Client
2015-10-22 21:50:19 +00:00
}
var sampleConfig = `
2016-02-18 21:26:51 +00:00
# # URL of server
2015-10-22 21:50:19 +00:00
url = "localhost:5555"
2016-02-18 21:26:51 +00:00
# # transport protocol to use either tcp or udp
2015-10-22 21:50:19 +00:00
transport = "tcp"
2016-02-18 21:26:51 +00:00
# # separator to use between input name and field name in Riemann service name
2016-02-03 22:06:41 +00:00
separator = " "
2015-10-22 21:50:19 +00:00
`
func ( r * Riemann ) Connect ( ) error {
2016-10-11 11:28:20 +00:00
log . Printf ( deprecationMsg )
2015-10-22 21:50:19 +00:00
c , err := raidman . Dial ( r . Transport , r . URL )
if err != nil {
2016-04-12 17:20:27 +00:00
r . client = nil
2015-10-22 21:50:19 +00:00
return err
}
2015-11-18 21:32:29 +00:00
r . client = c
2015-10-22 21:50:19 +00:00
return nil
}
func ( r * Riemann ) Close ( ) error {
2016-04-12 17:20:27 +00:00
if r . client == nil {
return nil
}
2015-10-22 21:50:19 +00:00
r . client . Close ( )
2016-04-12 17:20:27 +00:00
r . client = nil
2015-10-22 21:50:19 +00:00
return nil
}
func ( r * Riemann ) SampleConfig ( ) string {
return sampleConfig
}
func ( r * Riemann ) Description ( ) string {
return "Configuration for the Riemann server to send metrics to"
}
2016-01-27 23:15:14 +00:00
func ( r * Riemann ) Write ( metrics [ ] telegraf . Metric ) error {
2016-10-11 11:28:20 +00:00
log . Printf ( deprecationMsg )
2016-01-27 23:15:14 +00:00
if len ( metrics ) == 0 {
2015-10-22 21:50:19 +00:00
return nil
}
2016-04-12 17:20:27 +00:00
if r . client == nil {
err := r . Connect ( )
if err != nil {
return fmt . Errorf ( "FAILED to (re)connect to Riemann. Error: %s\n" , err )
}
}
2015-10-22 21:50:19 +00:00
var events [ ] * raidman . Event
2016-01-27 23:15:14 +00:00
for _ , p := range metrics {
2016-02-03 22:06:41 +00:00
evs := buildEvents ( p , r . Separator )
2015-12-19 21:55:44 +00:00
for _ , ev := range evs {
events = append ( events , ev )
}
2015-10-22 21:50:19 +00:00
}
var senderr = r . client . SendMulti ( events )
if senderr != nil {
2016-04-12 17:20:27 +00:00
r . Close ( ) // always retuns nil
2016-04-18 22:08:18 +00:00
return fmt . Errorf ( "FAILED to send riemann message (will try to reconnect). Error: %s\n" ,
senderr )
2015-10-22 21:50:19 +00:00
}
return nil
}
2016-02-03 22:06:41 +00:00
func buildEvents ( p telegraf . Metric , s string ) [ ] * raidman . Event {
2015-12-19 21:55:44 +00:00
events := [ ] * raidman . Event { }
for fieldName , value := range p . Fields ( ) {
host , ok := p . Tags ( ) [ "host" ]
if ! ok {
hostname , err := os . Hostname ( )
if err != nil {
host = "unknown"
} else {
host = hostname
}
2015-10-22 21:50:19 +00:00
}
2015-12-19 21:55:44 +00:00
event := & raidman . Event {
Host : host ,
2016-02-03 22:06:41 +00:00
Service : serviceName ( s , p . Name ( ) , p . Tags ( ) , fieldName ) ,
2015-12-19 21:55:44 +00:00
}
2016-02-03 22:06:41 +00:00
switch value . ( type ) {
case string :
event . State = value . ( string )
default :
event . Metric = value
}
2015-12-19 21:55:44 +00:00
events = append ( events , event )
2015-10-22 21:50:19 +00:00
}
2015-12-19 21:55:44 +00:00
return events
2015-10-22 21:50:19 +00:00
}
2016-02-03 22:06:41 +00:00
func serviceName ( s string , n string , t map [ string ] string , f string ) string {
serviceStrings := [ ] string { }
serviceStrings = append ( serviceStrings , n )
// we'll skip the 'host' tag
tagStrings := [ ] string { }
tagNames := [ ] string { }
for tagName := range t {
tagNames = append ( tagNames , tagName )
}
sort . Strings ( tagNames )
for _ , tagName := range tagNames {
if tagName != "host" {
tagStrings = append ( tagStrings , t [ tagName ] )
}
}
var tagString string = strings . Join ( tagStrings , s )
if tagString != "" {
serviceStrings = append ( serviceStrings , tagString )
}
serviceStrings = append ( serviceStrings , f )
return strings . Join ( serviceStrings , s )
}
2015-10-22 21:50:19 +00:00
func init ( ) {
2016-01-27 21:21:36 +00:00
outputs . Add ( "riemann" , func ( ) telegraf . Output {
2015-10-22 21:50:19 +00:00
return & Riemann { }
} )
}