Add tomcat input plugin (#3112)
This commit is contained in:
parent
fd3a9bf46a
commit
a91457e001
|
@ -0,0 +1,73 @@
|
||||||
|
# Tomcat Input Plugin
|
||||||
|
|
||||||
|
The Tomcat plugin collects statistics available from the tomcat manager status page from the `http://<host>/manager/status/all?XML=true URL.`
|
||||||
|
(`XML=true` will return only xml data). See the [Tomcat documentation](https://tomcat.apache.org/tomcat-9.0-doc/manager-howto.html#Server_Status) for details of these statistics.
|
||||||
|
|
||||||
|
### Configuration:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
# A Telegraf plugin to collect tomcat metrics.
|
||||||
|
[[inputs.tomcat]]
|
||||||
|
# A Tomcat status URI to gather stats.
|
||||||
|
# Default is "http://127.0.0.1:8080/manager/status/all?XML=true".
|
||||||
|
url = "http://127.0.0.1:8080/manager/status/all?XML=true"
|
||||||
|
# Credentials for status URI.
|
||||||
|
# Default is tomcat/s3cret.
|
||||||
|
username = "tomcat"
|
||||||
|
password = "s3cret"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Measurements & Fields:
|
||||||
|
|
||||||
|
- tomcat\_jvm\_memory
|
||||||
|
- free
|
||||||
|
- total
|
||||||
|
- max
|
||||||
|
- tomcat\_jvm\_memorypool
|
||||||
|
- max\_threads
|
||||||
|
- current\_thread\_count
|
||||||
|
- current\_threads\_busy
|
||||||
|
- max\_time
|
||||||
|
- processing\_time
|
||||||
|
- request\_count
|
||||||
|
- error\_count
|
||||||
|
- bytes\_received
|
||||||
|
- bytes\_sent
|
||||||
|
- tomcat\_connector
|
||||||
|
- max\_threads
|
||||||
|
- current\_thread\_count
|
||||||
|
- current\_thread\_busy
|
||||||
|
- max\_time
|
||||||
|
- processing\_time
|
||||||
|
- request\_count
|
||||||
|
- error\_count
|
||||||
|
- bytes\_received
|
||||||
|
- bytes\_sent
|
||||||
|
|
||||||
|
### Tags:
|
||||||
|
|
||||||
|
- tomcat\_jvm\_memorypool has the following tags:
|
||||||
|
- name
|
||||||
|
- type
|
||||||
|
- tomcat\_connector
|
||||||
|
- name
|
||||||
|
|
||||||
|
### Sample Queries:
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
### Example Output:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./telegraf -config telegraf.conf -input-filter tomcat -test
|
||||||
|
* Plugin: tomcat, Collection 1
|
||||||
|
> tomcat_jvm_memory,host=N8-MBP free=20014352i,max=127729664i,total=41459712i 1474663361000000000
|
||||||
|
> tomcat_jvm_memorypool,host=N8-MBP,name=Eden\ Space,type=Heap\ memory committed=11534336i,init=2228224i,max=35258368i,used=1941200i 1474663361000000000
|
||||||
|
> tomcat_jvm_memorypool,host=N8-MBP,name=Survivor\ Space,type=Heap\ memory committed=1376256i,init=262144i,max=4390912i,used=1376248i 1474663361000000000
|
||||||
|
> tomcat_jvm_memorypool,host=N8-MBP,name=Tenured\ Gen,type=Heap\ memory committed=28549120i,init=5636096i,max=88080384i,used=18127912i 1474663361000000000
|
||||||
|
> tomcat_jvm_memorypool,host=N8-MBP,name=Code\ Cache,type=Non-heap\ memory committed=6946816i,init=2555904i,max=251658240i,used=6406528i 1474663361000000000
|
||||||
|
> tomcat_jvm_memorypool,host=N8-MBP,name=Compressed\ Class\ Space,type=Non-heap\ memory committed=1966080i,init=0i,max=1073741824i,used=1816120i 1474663361000000000
|
||||||
|
> tomcat_jvm_memorypool,host=N8-MBP,name=Metaspace,type=Non-heap\ memory committed=18219008i,init=0i,max=-1i,used=17559376i 1474663361000000000
|
||||||
|
> tomcat_connector,host=N8-MBP,name=ajp-bio-8009 bytes_received=0i,bytes_sent=0i,current_thread_count=0i,current_threads_busy=0i,error_count=0i,max_threads=200i,max_time=0i,processing_time=0i,request_count=0i 1474663361000000000
|
||||||
|
> tomcat_connector,host=N8-MBP,name=http-bio-8080 bytes_received=0i,bytes_sent=86435i,current_thread_count=10i,current_threads_busy=1i,error_count=2i,max_threads=200i,max_time=167i,processing_time=245i,request_count=15i 1474663361000000000
|
||||||
|
```
|
|
@ -0,0 +1,176 @@
|
||||||
|
package tomcat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/xml"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/plugins/inputs"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TomcatStatus struct {
|
||||||
|
TomcatJvm TomcatJvm `xml:"jvm"`
|
||||||
|
TomcatConnectors []TomcatConnector `xml:"connector"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TomcatJvm struct {
|
||||||
|
JvmMemory JvmMemoryStat `xml:"memory"`
|
||||||
|
JvmMemoryPools []JvmMemoryPoolStat `xml:"memorypool"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JvmMemoryStat struct {
|
||||||
|
Free int64 `xml:"free,attr"`
|
||||||
|
Total int64 `xml:"total,attr"`
|
||||||
|
Max int64 `xml:"max,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type JvmMemoryPoolStat struct {
|
||||||
|
Name string `xml:"name,attr"`
|
||||||
|
Type string `xml:"type,attr"`
|
||||||
|
UsageInit int64 `xml:"usageInit,attr"`
|
||||||
|
UsageCommitted int64 `xml:"usageCommitted,attr"`
|
||||||
|
UsageMax int64 `xml:"usageMax,attr"`
|
||||||
|
UsageUsed int64 `xml:"usageUsed,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TomcatConnector struct {
|
||||||
|
Name string `xml:"name,attr"`
|
||||||
|
ThreadInfo ThreadInfo `xml:"threadInfo"`
|
||||||
|
RequestInfo RequestInfo `xml:"requestInfo"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ThreadInfo struct {
|
||||||
|
MaxThreads int64 `xml:"maxThreads,attr"`
|
||||||
|
CurrentThreadCount int64 `xml:"currentThreadCount,attr"`
|
||||||
|
CurrentThreadsBusy int64 `xml:"currentThreadsBusy,attr"`
|
||||||
|
}
|
||||||
|
type RequestInfo struct {
|
||||||
|
MaxTime int `xml:"maxTime,attr"`
|
||||||
|
ProcessingTime int `xml:"processingTime,attr"`
|
||||||
|
RequestCount int `xml:"requestCount,attr"`
|
||||||
|
ErrorCount int `xml:"errorCount,attr"`
|
||||||
|
BytesReceived int64 `xml:"bytesReceived,attr"`
|
||||||
|
BytesSent int64 `xml:"bytesSent,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Tomcat struct {
|
||||||
|
URL string
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
}
|
||||||
|
|
||||||
|
var sampleconfig = `
|
||||||
|
## A Tomcat status URI to gather stats.
|
||||||
|
## Default is "http://127.0.0.1:8080/manager/status/all?XML=true".
|
||||||
|
url = "http://127.0.0.1:8080/manager/status/all?XML=true"
|
||||||
|
## Credentials for status URI.
|
||||||
|
## Default is tomcat/s3cret.
|
||||||
|
username = "tomcat"
|
||||||
|
password = "s3cret"
|
||||||
|
`
|
||||||
|
|
||||||
|
func (s *Tomcat) Description() string {
|
||||||
|
return "A Telegraf plugin to collect tomcat metrics."
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Tomcat) SampleConfig() string {
|
||||||
|
return sampleconfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Tomcat) Gather(acc telegraf.Accumulator) error {
|
||||||
|
|
||||||
|
if s.URL == "" {
|
||||||
|
s.URL = "http://127.0.0.1:8080/manager/status/all?XML=true"
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Username == "" {
|
||||||
|
s.Username = "tomcat"
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Password == "" {
|
||||||
|
s.Password = "s3cret"
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := url.Parse(s.URL)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Unable to parse address '%s': %s", s.URL, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("GET", s.URL, nil)
|
||||||
|
req.SetBasicAuth(s.Username, s.Password)
|
||||||
|
cli := &http.Client{}
|
||||||
|
resp, err := cli.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Unable to call URL '%s': %s", s.URL, err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
|
||||||
|
var status TomcatStatus
|
||||||
|
xml.Unmarshal(body, &status)
|
||||||
|
|
||||||
|
// add tomcat_jvm_memory measurements
|
||||||
|
tcm := map[string]interface{}{
|
||||||
|
"free": status.TomcatJvm.JvmMemory.Free,
|
||||||
|
"total": status.TomcatJvm.JvmMemory.Total,
|
||||||
|
"max": status.TomcatJvm.JvmMemory.Max,
|
||||||
|
}
|
||||||
|
acc.AddFields("tomcat_jvm_memory", tcm, nil)
|
||||||
|
|
||||||
|
// add tomcat_jvm_memorypool measurements
|
||||||
|
for _, mp := range status.TomcatJvm.JvmMemoryPools {
|
||||||
|
|
||||||
|
tcmpTags := map[string]string{
|
||||||
|
"name": mp.Name,
|
||||||
|
"type": mp.Type,
|
||||||
|
}
|
||||||
|
|
||||||
|
tcmpFields := map[string]interface{}{
|
||||||
|
"init": mp.UsageInit,
|
||||||
|
"committed": mp.UsageCommitted,
|
||||||
|
"max": mp.UsageMax,
|
||||||
|
"used": mp.UsageUsed,
|
||||||
|
}
|
||||||
|
|
||||||
|
acc.AddFields("tomcat_jvm_memorypool", tcmpFields, tcmpTags)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// add tomcat_connector measurements
|
||||||
|
for _, c := range status.TomcatConnectors {
|
||||||
|
|
||||||
|
name, err := strconv.Unquote(c.Name)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Unable to unquote name '%s': %s", c.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tccTags := map[string]string{
|
||||||
|
"name": name,
|
||||||
|
}
|
||||||
|
|
||||||
|
tccFields := map[string]interface{}{
|
||||||
|
"max_threads": c.ThreadInfo.MaxThreads,
|
||||||
|
"current_thread_count": c.ThreadInfo.CurrentThreadCount,
|
||||||
|
"current_threads_busy": c.ThreadInfo.CurrentThreadsBusy,
|
||||||
|
"max_time": c.RequestInfo.MaxTime,
|
||||||
|
"processing_time": c.RequestInfo.ProcessingTime,
|
||||||
|
"request_count": c.RequestInfo.RequestCount,
|
||||||
|
"error_count": c.RequestInfo.ErrorCount,
|
||||||
|
"bytes_received": c.RequestInfo.BytesReceived,
|
||||||
|
"bytes_sent": c.RequestInfo.BytesSent,
|
||||||
|
}
|
||||||
|
|
||||||
|
acc.AddFields("tomcat_connector", tccFields, tccTags)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
inputs.Add("tomcat", func() telegraf.Input { return &Tomcat{} })
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
package tomcat
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/influxdata/telegraf/testutil"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
var tomcatStatus = `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<?xml-stylesheet type="text/xsl" href="/manager/xform.xsl" ?>
|
||||||
|
<status>
|
||||||
|
<jvm>
|
||||||
|
<memory free='17909336' total='58195968' max='620756992'/>
|
||||||
|
<memorypool name='PS Eden Space' type='Heap memory' usageInit='8912896' usageCommitted='35651584' usageMax='230686720' usageUsed='25591384'/>
|
||||||
|
<memorypool name='PS Old Gen' type='Heap memory' usageInit='21495808' usageCommitted='21495808' usageMax='465567744' usageUsed='13663040'/>
|
||||||
|
<memorypool name='PS Survivor Space' type='Heap memory' usageInit='1048576' usageCommitted='1048576' usageMax='1048576' usageUsed='1032208'/>
|
||||||
|
<memorypool name='Code Cache' type='Non-heap memory' usageInit='2555904' usageCommitted='2555904' usageMax='50331648' usageUsed='1220096'/>
|
||||||
|
<memorypool name='PS Perm Gen' type='Non-heap memory' usageInit='22020096' usageCommitted='22020096' usageMax='174063616' usageUsed='17533952'/>
|
||||||
|
</jvm>
|
||||||
|
<connector name='"ajp-apr-8009"'>
|
||||||
|
<threadInfo maxThreads="200" currentThreadCount="0" currentThreadsBusy="0"/>
|
||||||
|
<requestInfo maxTime="0" processingTime="0" requestCount="0" errorCount="0" bytesReceived="0" bytesSent="0"/>
|
||||||
|
<workers>
|
||||||
|
</workers>
|
||||||
|
</connector>
|
||||||
|
<connector name='"http-apr-8080"'>
|
||||||
|
<threadInfo maxThreads="200" currentThreadCount="5" currentThreadsBusy="1"/>
|
||||||
|
<requestInfo maxTime="68" processingTime="88" requestCount="2" errorCount="1" bytesReceived="0" bytesSent="9286"/>
|
||||||
|
<workers>
|
||||||
|
<worker stage="S" requestProcessingTime="4" requestBytesSent="0" requestBytesReceived="0" remoteAddr="127.0.0.1" virtualHost="127.0.0.1" method="GET" currentUri="/manager/status/all" currentQueryString="XML=true" protocol="HTTP/1.1"/>
|
||||||
|
</workers>
|
||||||
|
</connector>
|
||||||
|
</status>`
|
||||||
|
|
||||||
|
func TestHTTPTomcat(t *testing.T) {
|
||||||
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
fmt.Fprintln(w, tomcatStatus)
|
||||||
|
}))
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
tc := Tomcat{
|
||||||
|
URL: ts.URL,
|
||||||
|
Username: "tomcat",
|
||||||
|
Password: "s3cret",
|
||||||
|
}
|
||||||
|
|
||||||
|
var acc testutil.Accumulator
|
||||||
|
err := tc.Gather(&acc)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// tomcat_jvm_memory
|
||||||
|
jvmMemoryFields := map[string]interface{}{
|
||||||
|
"free": int64(17909336),
|
||||||
|
"total": int64(58195968),
|
||||||
|
"max": int64(620756992),
|
||||||
|
}
|
||||||
|
acc.AssertContainsFields(t, "tomcat_jvm_memory", jvmMemoryFields)
|
||||||
|
|
||||||
|
// tomcat_jvm_memorypool
|
||||||
|
jvmMemoryPoolFields := map[string]interface{}{
|
||||||
|
"init": int64(22020096),
|
||||||
|
"committed": int64(22020096),
|
||||||
|
"max": int64(174063616),
|
||||||
|
"used": int64(17533952),
|
||||||
|
}
|
||||||
|
jvmMemoryPoolTags := map[string]string{
|
||||||
|
"name": "PS Perm Gen",
|
||||||
|
"type": "Non-heap memory",
|
||||||
|
}
|
||||||
|
acc.AssertContainsTaggedFields(t, "tomcat_jvm_memorypool", jvmMemoryPoolFields, jvmMemoryPoolTags)
|
||||||
|
|
||||||
|
// tomcat_connector
|
||||||
|
connectorFields := map[string]interface{}{
|
||||||
|
"max_threads": int64(200),
|
||||||
|
"current_thread_count": int64(5),
|
||||||
|
"current_threads_busy": int64(1),
|
||||||
|
"max_time": int(68),
|
||||||
|
"processing_time": int(88),
|
||||||
|
"request_count": int(2),
|
||||||
|
"error_count": int(1),
|
||||||
|
"bytes_received": int64(0),
|
||||||
|
"bytes_sent": int64(9286),
|
||||||
|
}
|
||||||
|
connectorTags := map[string]string{
|
||||||
|
"name": "http-apr-8080",
|
||||||
|
}
|
||||||
|
acc.AssertContainsTaggedFields(t, "tomcat_connector", connectorFields, connectorTags)
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue