github.com/mackerelio/mackerel-agent-plugins@v0.89.3/mackerel-plugin-jmx-jolokia/lib/jmx-jolokia.go (about) 1 package mpjmxjolokia 2 3 import ( 4 "encoding/json" 5 "flag" 6 "fmt" 7 "net/http" 8 9 mp "github.com/mackerelio/go-mackerel-plugin-helper" 10 "github.com/mackerelio/golib/logging" 11 ) 12 13 var logger = logging.GetLogger("metrics.plugin.jmx-jolokia") 14 15 // JmxJolokiaPlugin mackerel plugin for Jolokia 16 type JmxJolokiaPlugin struct { 17 Target string 18 Tempfile string 19 } 20 21 // JmxJolokiaResponse response for Jolokia 22 type JmxJolokiaResponse struct { 23 Status uint32 24 Timestamp uint32 25 Request map[string]interface{} 26 Value map[string]interface{} 27 Error string 28 } 29 30 var graphdef = map[string]mp.Graphs{ 31 "jmx.jolokia.memory.heap_memory_usage": { 32 Label: "Jmx HeapMemoryUsage", 33 Unit: "bytes", 34 Metrics: []mp.Metrics{ 35 {Name: "HeapMemoryInit", Label: "init", Diff: false, Type: "uint64"}, 36 {Name: "HeapMemoryCommitted", Label: "committed", Diff: false, Type: "uint64"}, 37 {Name: "HeapMemoryMax", Label: "max", Diff: false, Type: "uint64"}, 38 {Name: "HeapMemoryUsed", Label: "used", Diff: false, Type: "uint64"}, 39 }, 40 }, 41 "jmx.jolokia.memory.non_heap_memory_usage": { 42 Label: "Jmx NonHeapMemoryUsage", 43 Unit: "bytes", 44 Metrics: []mp.Metrics{ 45 {Name: "NonHeapMemoryInit", Label: "init", Diff: false, Type: "uint64"}, 46 {Name: "NonHeapMemoryCommitted", Label: "committed", Diff: false, Type: "uint64"}, 47 {Name: "NonHeapMemoryMax", Label: "max", Diff: false, Type: "uint64"}, 48 {Name: "NonHeapMemoryUsed", Label: "used", Diff: false, Type: "uint64"}, 49 }, 50 }, 51 "jmx.jolokia.class_load": { 52 Label: "Jmx ClassLoading", 53 Unit: "integer", 54 Metrics: []mp.Metrics{ 55 {Name: "LoadedClassCount", Label: "loaded", Diff: false, Type: "uint64"}, 56 {Name: "UnloadedClassCount", Label: "unloaded", Diff: false, Type: "uint64"}, 57 {Name: "TotalLoadedClassCount", Label: "total", Diff: false, Type: "uint64"}, 58 }, 59 }, 60 "jmx.jolokia.thread": { 61 Label: "Jmx Threading", 62 Unit: "integer", 63 Metrics: []mp.Metrics{ 64 {Name: "ThreadCount", Label: "thread", Diff: false, Type: "uint64"}, 65 {Name: "DaemonThreadCount", Label: "daemon", Diff: false, Type: "uint64"}, 66 {Name: "PeakThreadCount", Label: "peak", Diff: false, Type: "uint64"}, 67 }, 68 }, 69 "jmx.jolokia.ops.cpu_load": { 70 Label: "Jmx CpuLoad", 71 Unit: "percentage", 72 Metrics: []mp.Metrics{ 73 {Name: "ProcessCpuLoad", Label: "process", Diff: false, Type: "float64", Scale: 100}, 74 {Name: "SystemCpuLoad", Label: "system", Diff: false, Type: "float64", Scale: 100}, 75 }, 76 }, 77 } 78 79 // FetchMetrics interface for mackerelplugin 80 func (j JmxJolokiaPlugin) FetchMetrics() (map[string]interface{}, error) { 81 stat := make(map[string]interface{}) 82 if err := j.fetchMemory(stat); err != nil { 83 logger.Warningf(err.Error()) 84 } 85 86 if err := j.fetchClassLoad(stat); err != nil { 87 logger.Warningf(err.Error()) 88 } 89 90 if err := j.fetchThread(stat); err != nil { 91 logger.Warningf(err.Error()) 92 } 93 94 if err := j.fetchOperatingSystem(stat); err != nil { 95 logger.Warningf(err.Error()) 96 } 97 98 return stat, nil 99 } 100 101 func (j JmxJolokiaPlugin) fetchMemory(stat map[string]interface{}) error { 102 resp, err := j.executeGetRequest("java.lang:type=Memory") 103 if err != nil { 104 return err 105 } 106 heap := resp.Value["HeapMemoryUsage"].(map[string]interface{}) 107 stat["HeapMemoryInit"] = heap["init"] 108 stat["HeapMemoryCommitted"] = heap["committed"] 109 stat["HeapMemoryMax"] = heap["max"] 110 stat["HeapMemoryUsed"] = heap["used"] 111 112 nonHeap := resp.Value["NonHeapMemoryUsage"].(map[string]interface{}) 113 stat["NonHeapMemoryInit"] = nonHeap["init"] 114 stat["NonHeapMemoryCommitted"] = nonHeap["committed"] 115 stat["NonHeapMemoryMax"] = nonHeap["max"] 116 stat["NonHeapMemoryUsed"] = nonHeap["used"] 117 118 return nil 119 } 120 121 func (j JmxJolokiaPlugin) fetchClassLoad(stat map[string]interface{}) error { 122 resp, err := j.executeGetRequest("java.lang:type=ClassLoading") 123 if err != nil { 124 return err 125 } 126 stat["LoadedClassCount"] = resp.Value["LoadedClassCount"] 127 stat["UnloadedClassCount"] = resp.Value["UnloadedClassCount"] 128 stat["TotalLoadedClassCount"] = resp.Value["TotalLoadedClassCount"] 129 130 return nil 131 } 132 133 func (j JmxJolokiaPlugin) fetchThread(stat map[string]interface{}) error { 134 resp, err := j.executeGetRequest("java.lang:type=Threading") 135 if err != nil { 136 return err 137 } 138 stat["ThreadCount"] = resp.Value["ThreadCount"] 139 stat["DaemonThreadCount"] = resp.Value["DaemonThreadCount"] 140 stat["PeakThreadCount"] = resp.Value["PeakThreadCount"] 141 142 return nil 143 } 144 145 func (j JmxJolokiaPlugin) fetchOperatingSystem(stat map[string]interface{}) error { 146 resp, err := j.executeGetRequest("java.lang:type=OperatingSystem") 147 if err != nil { 148 return err 149 } 150 stat["ProcessCpuLoad"] = resp.Value["ProcessCpuLoad"] 151 stat["SystemCpuLoad"] = resp.Value["SystemCpuLoad"] 152 153 return nil 154 } 155 156 func (j JmxJolokiaPlugin) executeGetRequest(mbean string) (*JmxJolokiaResponse, error) { 157 req, err := http.NewRequest(http.MethodGet, j.Target+mbean, nil) 158 if err != nil { 159 return nil, err 160 } 161 req.Header.Set("User-Agent", "mackerel-plugin-jmx-jolokia") 162 163 resp, err := http.DefaultClient.Do(req) 164 if err != nil { 165 return nil, err 166 } 167 defer resp.Body.Close() 168 var respJ JmxJolokiaResponse 169 dec := json.NewDecoder(resp.Body) 170 if err := dec.Decode(&respJ); err != nil { 171 return nil, err 172 } 173 return &respJ, nil 174 } 175 176 // GraphDefinition interface for mackerelplugin 177 func (j JmxJolokiaPlugin) GraphDefinition() map[string]mp.Graphs { 178 return graphdef 179 } 180 181 // Do the plugin 182 func Do() { 183 optHost := flag.String("host", "localhost", "Hostname") 184 optPort := flag.String("port", "8778", "Port") 185 optTempfile := flag.String("tempfile", "", "Temp file name") 186 flag.Parse() 187 188 var jmxJolokia JmxJolokiaPlugin 189 jmxJolokia.Target = fmt.Sprintf("http://%s:%s/jolokia/read/", *optHost, *optPort) 190 191 helper := mp.NewMackerelPlugin(jmxJolokia) 192 if *optTempfile != "" { 193 helper.Tempfile = *optTempfile 194 } else { 195 helper.SetTempfileByBasename(fmt.Sprintf("mackerel-plugin-jmx-jolokia-%s-%s", *optHost, *optPort)) 196 } 197 helper.Run() 198 }