Add Teamspeak 3 input plugin (#3315)

This commit is contained in:
Patric Kanngießer 2017-11-01 21:28:00 +01:00 committed by Daniel Nelson
parent 5f215c22fe
commit 76ed70340b
6 changed files with 237 additions and 0 deletions

2
Godeps
View File

@ -40,6 +40,8 @@ github.com/kballard/go-shellquote d8ec1a69a250a17bb0e419c386eac1f3711dc142
github.com/matttproud/golang_protobuf_extensions c12348ce28de40eed0136aa2b644d0ee0650e56c github.com/matttproud/golang_protobuf_extensions c12348ce28de40eed0136aa2b644d0ee0650e56c
github.com/Microsoft/go-winio ce2922f643c8fd76b46cadc7f404a06282678b34 github.com/Microsoft/go-winio ce2922f643c8fd76b46cadc7f404a06282678b34
github.com/miekg/dns 99f84ae56e75126dd77e5de4fae2ea034a468ca1 github.com/miekg/dns 99f84ae56e75126dd77e5de4fae2ea034a468ca1
github.com/mitchellh/mapstructure d0303fe809921458f417bcf828397a65db30a7e4
github.com/multiplay/go-ts3 07477f49b8dfa3ada231afc7b7b17617d42afe8e
github.com/naoina/go-stringutil 6b638e95a32d0c1131db0e7fe83775cbea4a0d0b github.com/naoina/go-stringutil 6b638e95a32d0c1131db0e7fe83775cbea4a0d0b
github.com/nats-io/go-nats ea9585611a4ab58a205b9b125ebd74c389a6b898 github.com/nats-io/go-nats ea9585611a4ab58a205b9b125ebd74c389a6b898
github.com/nats-io/nats ea9585611a4ab58a205b9b125ebd74c389a6b898 github.com/nats-io/nats ea9585611a4ab58a205b9b125ebd74c389a6b898

View File

@ -82,6 +82,8 @@ following works:
- github.com/streadway/amqp [BSD](https://github.com/streadway/amqp/blob/master/LICENSE) - github.com/streadway/amqp [BSD](https://github.com/streadway/amqp/blob/master/LICENSE)
- github.com/stretchr/objx [MIT](https://github.com/stretchr/objx/blob/master/LICENSE.md) - github.com/stretchr/objx [MIT](https://github.com/stretchr/objx/blob/master/LICENSE.md)
- github.com/stretchr/testify [MIT](https://github.com/stretchr/testify/blob/master/LICENCE.txt) - github.com/stretchr/testify [MIT](https://github.com/stretchr/testify/blob/master/LICENCE.txt)
- github.com/mitchellh/mapstructure [MIT](https://github.com/mitchellh/mapstructure/blob/master/LICENSE)
- github.com/multiplay/go-ts3 [BSD](https://github.com/multiplay/go-ts3/blob/master/LICENSE)
- github.com/vjeantet/grok [APACHE](https://github.com/vjeantet/grok/blob/master/LICENSE) - github.com/vjeantet/grok [APACHE](https://github.com/vjeantet/grok/blob/master/LICENSE)
- github.com/wvanbergen/kafka [MIT](https://github.com/wvanbergen/kafka/blob/master/LICENSE) - github.com/wvanbergen/kafka [MIT](https://github.com/wvanbergen/kafka/blob/master/LICENSE)
- github.com/wvanbergen/kazoo-go [MIT](https://github.com/wvanbergen/kazoo-go/blob/master/MIT-LICENSE) - github.com/wvanbergen/kazoo-go [MIT](https://github.com/wvanbergen/kazoo-go/blob/master/MIT-LICENSE)

View File

@ -86,6 +86,7 @@ import (
_ "github.com/influxdata/telegraf/plugins/inputs/system" _ "github.com/influxdata/telegraf/plugins/inputs/system"
_ "github.com/influxdata/telegraf/plugins/inputs/tail" _ "github.com/influxdata/telegraf/plugins/inputs/tail"
_ "github.com/influxdata/telegraf/plugins/inputs/tcp_listener" _ "github.com/influxdata/telegraf/plugins/inputs/tcp_listener"
_ "github.com/influxdata/telegraf/plugins/inputs/teamspeak"
_ "github.com/influxdata/telegraf/plugins/inputs/tomcat" _ "github.com/influxdata/telegraf/plugins/inputs/tomcat"
_ "github.com/influxdata/telegraf/plugins/inputs/trig" _ "github.com/influxdata/telegraf/plugins/inputs/trig"
_ "github.com/influxdata/telegraf/plugins/inputs/twemproxy" _ "github.com/influxdata/telegraf/plugins/inputs/twemproxy"

View File

@ -0,0 +1,45 @@
# Teamspeak 3 Input Plugin
This plugin uses the Teamspeak 3 ServerQuery interface of the Teamspeak server to collect statistics of one or more
virtual servers. If you are querying an external Teamspeak server, make sure to add the host which is running Telegraf
to query_ip_whitelist.txt in the Teamspeak Server directory. For information about how to configure the server take a look
the [Teamspeak 3 ServerQuery Manual](http://media.teamspeak.com/ts3_literature/TeamSpeak%203%20Server%20Query%20Manual.pdf)
### Configuration:
```
# Reads metrics from a Teamspeak 3 Server via ServerQuery
[[inputs.teamspeak]]
## Server address for Teamspeak 3 ServerQuery
# server = "127.0.0.1:10011"
## Username for ServerQuery
username = "serverqueryuser"
## Password for ServerQuery
password = "secret"
## Array of virtual servers
# virtual_servers = [1]
```
### Measurements:
- teamspeak
- uptime
- clients_online
- total_ping
- total_packet_loss
- packets_sent_total
- packets_received_total
- bytes_sent_total
- bytes_received_total
### Tags:
- The following tags are used:
- virtual_server
- name
### Example output:
```
teamspeak,virtual_server=1,name=LeopoldsServer,host=vm01 bytes_received_total=29638202639i,uptime=13567846i,total_ping=26.89,total_packet_loss=0,packets_sent_total=415821252i,packets_received_total=237069900i,bytes_sent_total=55309568252i,clients_online=11i 1507406561000000000
```

View File

@ -0,0 +1,100 @@
package teamspeak
import (
"github.com/multiplay/go-ts3"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/inputs"
"strconv"
)
type Teamspeak struct {
Server string
Username string
Password string
VirtualServers []int `toml:"virtual_servers"`
client *ts3.Client
connected bool
}
func (ts *Teamspeak) Description() string {
return "Reads metrics from a Teamspeak 3 Server via ServerQuery"
}
const sampleConfig = `
## Server address for Teamspeak 3 ServerQuery
# server = "127.0.0.1:10011"
## Username for ServerQuery
username = "serverqueryuser"
## Password for ServerQuery
password = "secret"
## Array of virtual servers
# virtual_servers = [1]
`
func (ts *Teamspeak) SampleConfig() string {
return sampleConfig
}
func (ts *Teamspeak) Gather(acc telegraf.Accumulator) error {
var err error
if !ts.connected {
ts.client, err = ts3.NewClient(ts.Server)
if err != nil {
return err
}
err = ts.client.Login(ts.Username, ts.Password)
if err != nil {
return err
}
ts.connected = true
}
for _, vserver := range ts.VirtualServers {
ts.client.Use(vserver)
sm, err := ts.client.Server.Info()
if err != nil {
ts.connected = false
return err
}
sc, err := ts.client.Server.ServerConnectionInfo()
if err != nil {
ts.connected = false
return err
}
tags := map[string]string{
"virtual_server": strconv.Itoa(sm.ID),
"name": sm.Name,
}
fields := map[string]interface{}{
"uptime": sm.Uptime,
"clients_online": sm.ClientsOnline,
"total_ping": sm.TotalPing,
"total_packet_loss": sm.TotalPacketLossTotal,
"packets_sent_total": sc.PacketsSentTotal,
"packets_received_total": sc.PacketsReceivedTotal,
"bytes_sent_total": sc.BytesSentTotal,
"bytes_received_total": sc.BytesReceivedTotal,
}
acc.AddFields("teamspeak", fields, tags)
}
return nil
}
func init() {
inputs.Add("teamspeak", func() telegraf.Input {
return &Teamspeak{
Server: "127.0.0.1:10011",
VirtualServers: []int{1},
}
})
}

View File

@ -0,0 +1,87 @@
package teamspeak
import (
"bufio"
"net"
"strings"
"testing"
"github.com/influxdata/telegraf/testutil"
)
const welcome = `Welcome to the TeamSpeak 3 ServerQuery interface, type "help" for a list of commands and "help <command>" for information on a specific command.`
const ok = `error id=0 msg=ok`
const errorMsg = `error id=256 msg=command\snot\sfound`
var cmd = map[string]string{
"login": "",
"use": "",
"serverinfo": `virtualserver_unique_identifier=a1vn9PLF8CMIU virtualserver_name=Testserver virtualserver_welcomemessage=Test virtualserver_platform=Linux virtualserver_version=3.0.13.8\s[Build:\s1500452811] virtualserver_maxclients=32 virtualserver_password virtualserver_clientsonline=2 virtualserver_channelsonline=1 virtualserver_created=1507400243 virtualserver_uptime=148 virtualserver_codec_encryption_mode=0 virtualserver_hostmessage virtualserver_hostmessage_mode=0 virtualserver_filebase=files\/virtualserver_1 virtualserver_default_server_group=8 virtualserver_default_channel_group=8 virtualserver_flag_password=0 virtualserver_default_channel_admin_group=5 virtualserver_max_download_total_bandwidth=18446744073709551615 virtualserver_max_upload_total_bandwidth=18446744073709551615 virtualserver_hostbanner_url virtualserver_hostbanner_gfx_url virtualserver_hostbanner_gfx_interval=0 virtualserver_complain_autoban_count=5 virtualserver_complain_autoban_time=1200 virtualserver_complain_remove_time=3600 virtualserver_min_clients_in_channel_before_forced_silence=100 virtualserver_priority_speaker_dimm_modificator=-18.0000 virtualserver_id=1 virtualserver_antiflood_points_tick_reduce=5 virtualserver_antiflood_points_needed_command_block=150 virtualserver_antiflood_points_needed_ip_block=250 virtualserver_client_connections=1 virtualserver_query_client_connections=1 virtualserver_hostbutton_tooltip virtualserver_hostbutton_url virtualserver_hostbutton_gfx_url virtualserver_queryclientsonline=1 virtualserver_download_quota=18446744073709551615 virtualserver_upload_quota=18446744073709551615 virtualserver_month_bytes_downloaded=0 virtualserver_month_bytes_uploaded=0 virtualserver_total_bytes_downloaded=0 virtualserver_total_bytes_uploaded=0 virtualserver_port=9987 virtualserver_autostart=1 virtualserver_machine_id virtualserver_needed_identity_security_level=8 virtualserver_log_client=0 virtualserver_log_query=0 virtualserver_log_channel=0 virtualserver_log_permissions=1 virtualserver_log_server=0 virtualserver_log_filetransfer=0 virtualserver_min_client_version=1445512488 virtualserver_name_phonetic virtualserver_icon_id=0 virtualserver_reserved_slots=0 virtualserver_total_packetloss_speech=0.0000 virtualserver_total_packetloss_keepalive=0.0000 virtualserver_total_packetloss_control=0.0000 virtualserver_total_packetloss_total=0.0000 virtualserver_total_ping=1.0000 virtualserver_ip=0.0.0.0,\s:: virtualserver_weblist_enabled=1 virtualserver_ask_for_privilegekey=0 virtualserver_hostbanner_mode=0 virtualserver_channel_temp_delete_delay_default=0 virtualserver_min_android_version=1407159763 virtualserver_min_ios_version=1407159763 virtualserver_status=online connection_filetransfer_bandwidth_sent=0 connection_filetransfer_bandwidth_received=0 connection_filetransfer_bytes_sent_total=0 connection_filetransfer_bytes_received_total=0 connection_packets_sent_speech=0 connection_bytes_sent_speech=0 connection_packets_received_speech=0 connection_bytes_received_speech=0 connection_packets_sent_keepalive=261 connection_bytes_sent_keepalive=10701 connection_packets_received_keepalive=261 connection_bytes_received_keepalive=10961 connection_packets_sent_control=54 connection_bytes_sent_control=15143 connection_packets_received_control=55 connection_bytes_received_control=4239 connection_packets_sent_total=315 connection_bytes_sent_total=25844 connection_packets_received_total=316 connection_bytes_received_total=15200 connection_bandwidth_sent_last_second_total=81 connection_bandwidth_sent_last_minute_total=141 connection_bandwidth_received_last_second_total=83 connection_bandwidth_received_last_minute_total=98`,
"serverrequestconnectioninfo": `connection_filetransfer_bandwidth_sent=0 connection_filetransfer_bandwidth_received=0 connection_filetransfer_bytes_sent_total=0 connection_filetransfer_bytes_received_total=0 connection_packets_sent_total=369 connection_bytes_sent_total=28058 connection_packets_received_total=370 connection_bytes_received_total=17468 connection_bandwidth_sent_last_second_total=81 connection_bandwidth_sent_last_minute_total=109 connection_bandwidth_received_last_second_total=83 connection_bandwidth_received_last_minute_total=94 connection_connected_time=174 connection_packetloss_total=0.0000 connection_ping=1.0000`,
}
func TestGather(t *testing.T) {
l, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatal("Initializing test server failed")
}
defer l.Close()
go handleRequest(l, t)
var acc testutil.Accumulator
testConfig := Teamspeak{
Server: l.Addr().String(),
Username: "serveradmin",
Password: "test",
VirtualServers: []int{1},
}
err = testConfig.Gather(&acc)
if err != nil {
t.Fatalf("Gather returned error. Error: %s\n", err)
}
fields := map[string]interface{}{
"uptime": int(148),
"clients_online": int(2),
"total_ping": float32(1.0000),
"total_packet_loss": float64(0.0000),
"packets_sent_total": uint64(369),
"packets_received_total": uint64(370),
"bytes_sent_total": uint64(28058),
"bytes_received_total": uint64(17468),
}
acc.AssertContainsFields(t, "teamspeak", fields)
}
func handleRequest(l net.Listener, t *testing.T) {
c, err := l.Accept()
if err != nil {
t.Fatal("Error accepting test connection")
}
c.Write([]byte("TS3\n\r" + welcome + "\n\r"))
for {
msg, _, err := bufio.NewReader(c).ReadLine()
if err != nil {
return
}
r, exists := cmd[strings.Split(string(msg), " ")[0]]
if exists {
switch r {
case "":
c.Write([]byte(ok + "\n\r"))
case "quit":
c.Write([]byte(ok + "\n\r"))
c.Close()
return
default:
c.Write([]byte(r + "\n\r" + ok + "\n\r"))
}
} else {
c.Write([]byte(errorMsg + "\n\r"))
}
}
}