Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Input plugin for Teamspeak 3 servers #3315

Merged
merged 8 commits into from
Nov 1, 2017
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Godeps
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ github.com/kballard/go-shellquote d8ec1a69a250a17bb0e419c386eac1f3711dc142
github.com/matttproud/golang_protobuf_extensions c12348ce28de40eed0136aa2b644d0ee0650e56c
github.com/Microsoft/go-winio ce2922f643c8fd76b46cadc7f404a06282678b34
github.com/miekg/dns 99f84ae56e75126dd77e5de4fae2ea034a468ca1
github.com/multiplay/go-ts3 07477f49b8dfa3ada231afc7b7b17617d42afe8e
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add to docs/LICENSE_OF_DEPENDENCIES.md?

github.com/naoina/go-stringutil 6b638e95a32d0c1131db0e7fe83775cbea4a0d0b
github.com/nats-io/go-nats ea9585611a4ab58a205b9b125ebd74c389a6b898
github.com/nats-io/nats ea9585611a4ab58a205b9b125ebd74c389a6b898
Expand Down
1 change: 1 addition & 0 deletions docs/LICENSE_OF_DEPENDENCIES.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ following works:
- 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/testify [MIT](https://github.com/stretchr/testify/blob/master/LICENCE.txt)
- 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/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)
Expand Down
1 change: 1 addition & 0 deletions plugins/inputs/all/all.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ import (
_ "github.com/influxdata/telegraf/plugins/inputs/system"
_ "github.com/influxdata/telegraf/plugins/inputs/tail"
_ "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/trig"
_ "github.com/influxdata/telegraf/plugins/inputs/twemproxy"
Expand Down
45 changes: 45 additions & 0 deletions plugins/inputs/teamspeak/README.md
Original file line number Diff line number Diff line change
@@ -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)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to find a good link with more info, but the best I could find is this pdf linked from go-ts3, do you know of any better reference material (preferably html)? If not maybe we can link to the pdf, this will help if someone has additional questions about the meaning of the fields.

http://media.teamspeak.com/ts3_literature/TeamSpeak%203%20Server%20Query%20Manual.pdf

Copy link

@Thor77 Thor77 Nov 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the documentation directly from teamspeak for the query interface is quite bad.
There are txt files shipped with every server release containing plaintext documentation for each command (I wrote a small script generating a webpage from these here (src)).

### 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
```
100 changes: 100 additions & 0 deletions plugins/inputs/teamspeak/teamspeak.go
Original file line number Diff line number Diff line change
@@ -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
Virtual_servers []int

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.Virtual_servers {
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",
Virtual_servers: []int{1},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you change this variable to Go style: VirtualServers?

}
})
}
87 changes: 87 additions & 0 deletions plugins/inputs/teamspeak/teamspeak_test.go
Original file line number Diff line number Diff line change
@@ -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",
Virtual_servers: []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"))
}
}
}