1
0
Fork 0
telegraf/plugins/inputs/tomcat/tomcat.go

207 lines
4.9 KiB
Go
Raw Normal View History

//go:generate ../../../tools/readme_config_includer/generator
package tomcat
import (
_ "embed"
"encoding/xml"
"fmt"
"net/http"
"net/url"
"strconv"
"time"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/config"
"github.com/influxdata/telegraf/plugins/common/tls"
"github.com/influxdata/telegraf/plugins/inputs"
)
//go:embed sample.conf
var sampleConfig string
type Tomcat struct {
URL string `toml:"url"`
Username string `toml:"username"`
Password string `toml:"password"`
Timeout config.Duration `toml:"timeout"`
tls.ClientConfig
client *http.Client
request *http.Request
}
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"`
}
func (*Tomcat) SampleConfig() string {
return sampleConfig
}
func (s *Tomcat) Gather(acc telegraf.Accumulator) error {
if s.client == nil {
client, err := s.createHTTPClient()
if err != nil {
return err
}
s.client = client
}
if s.request == nil {
_, err := url.Parse(s.URL)
if err != nil {
return err
}
request, err := http.NewRequest("GET", s.URL, nil)
if err != nil {
return err
}
request.SetBasicAuth(s.Username, s.Password)
s.request = request
}
resp, err := s.client.Do(s.request)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("received HTTP status code %d from %q; expected 200",
resp.StatusCode, s.URL)
}
var status tomcatStatus
if err := xml.NewDecoder(resp.Body).Decode(&status); err != nil {
return err
}
tags := map[string]string{
"source": s.URL,
}
// 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, tags)
// add tomcat_jvm_memorypool measurements
for _, mp := range status.TomcatJvm.JvmMemoryPools {
tcmpTags := map[string]string{
"name": mp.Name,
"type": mp.Type,
"source": s.URL,
}
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 {
name = c.Name
}
tccTags := map[string]string{
"name": name,
"source": s.URL,
}
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 (s *Tomcat) createHTTPClient() (*http.Client, error) {
tlsConfig, err := s.ClientConfig.TLSConfig()
if err != nil {
return nil, err
}
client := &http.Client{
Transport: &http.Transport{
TLSClientConfig: tlsConfig,
},
Timeout: time.Duration(s.Timeout),
}
return client, nil
}
func init() {
inputs.Add("tomcat", func() telegraf.Input {
return &Tomcat{
URL: "http://127.0.0.1:8080/manager/status/all?XML=true",
Username: "tomcat",
Password: "s3cret",
Timeout: config.Duration(5 * time.Second),
}
})
}