github.com/mackerelio/mackerel-agent-plugins@v0.89.3/mackerel-plugin-gostats/lib/mackerel-plugin-gostats.go (about) 1 package mpgostats 2 3 import ( 4 "encoding/json" 5 "flag" 6 "fmt" 7 "io" 8 "net/http" 9 10 stats_api "github.com/fukata/golang-stats-api-handler" 11 mp "github.com/mackerelio/go-mackerel-plugin" 12 "golang.org/x/text/cases" 13 "golang.org/x/text/language" 14 ) 15 16 // GostatsPlugin mackerel plugin for go server 17 type GostatsPlugin struct { 18 URI string 19 Prefix string 20 } 21 22 /* 23 { 24 "time": 1449124022112358000, 25 "go_version": "go1.5.1", 26 "go_os": "darwin", 27 "go_arch": "amd64", 28 "cpu_num": 4, 29 "goroutine_num": 6, 30 "gomaxprocs": 4, 31 "cgo_call_num": 5, 32 "memory_alloc": 213360, 33 "memory_total_alloc": 213360, 34 "memory_sys": 3377400, 35 "memory_lookups": 15, 36 "memory_mallocs": 1137, 37 "memory_frees": 0, 38 "memory_stack": 393216, 39 "heap_alloc": 213360, 40 "heap_sys": 655360, 41 "heap_idle": 65536, 42 "heap_inuse": 589824, 43 "heap_released": 0, 44 "heap_objects": 1137, 45 "gc_next": 4194304, 46 "gc_last": 0, 47 "gc_num": 0, 48 "gc_per_second": 0, 49 "gc_pause_per_second": 0, 50 "gc_pause": [] 51 } 52 */ 53 54 // GraphDefinition interface for mackerelplugin 55 func (m GostatsPlugin) GraphDefinition() map[string]mp.Graphs { 56 labelPrefix := cases.Title(language.Und, cases.NoLower).String(m.Prefix) 57 return map[string]mp.Graphs{ 58 (m.Prefix + ".runtime"): { 59 Label: (labelPrefix + " Runtime"), 60 Unit: "integer", 61 Metrics: []mp.Metrics{ 62 {Name: "goroutine_num", Label: "Goroutine Num"}, 63 {Name: "cgo_call_num", Label: "CGO Call Num", Diff: true}, 64 }, 65 }, 66 (m.Prefix + ".memory"): { 67 Label: (labelPrefix + " Memory"), 68 Unit: "bytes", 69 Metrics: []mp.Metrics{ 70 {Name: "memory_alloc", Label: "Alloc"}, 71 {Name: "memory_sys", Label: "Sys"}, 72 {Name: "memory_stack", Label: "Stack In Use"}, 73 }, 74 }, 75 (m.Prefix + ".operation"): { 76 Label: (labelPrefix + " Operation"), 77 Unit: "integer", 78 Metrics: []mp.Metrics{ 79 {Name: "memory_lookups", Label: "Pointer Lookups", Diff: true}, 80 {Name: "memory_mallocs", Label: "Mallocs", Diff: true}, 81 {Name: "memory_frees", Label: "Frees", Diff: true}, 82 }, 83 }, 84 (m.Prefix + ".heap"): { 85 Label: (labelPrefix + " Heap"), 86 Unit: "bytes", 87 Metrics: []mp.Metrics{ 88 {Name: "heap_sys", Label: "Sys"}, 89 {Name: "heap_idle", Label: "Idle"}, 90 {Name: "heap_inuse", Label: "In Use"}, 91 {Name: "heap_released", Label: "Released", Diff: true}, 92 }, 93 }, 94 (m.Prefix + ".gc"): { 95 Label: (labelPrefix + " GC"), 96 Unit: "float", 97 Metrics: []mp.Metrics{ 98 {Name: "gc_num", Label: "GC Num", Diff: true}, 99 {Name: "gc_per_second", Label: "GC Per Second"}, 100 {Name: "gc_pause_per_second", Label: "GC Pause Per Second"}, 101 }, 102 }, 103 } 104 } 105 106 // FetchMetrics interface for mackerelplugin 107 func (m GostatsPlugin) FetchMetrics() (map[string]float64, error) { 108 req, err := http.NewRequest(http.MethodGet, m.URI, nil) 109 if err != nil { 110 return nil, err 111 } 112 req.Header.Set("User-Agent", "mackerel-plugin-gostats") 113 114 resp, err := http.DefaultClient.Do(req) 115 if err != nil { 116 return nil, err 117 } 118 defer resp.Body.Close() 119 120 return m.parseStats(resp.Body) 121 } 122 123 func (m GostatsPlugin) parseStats(body io.Reader) (map[string]float64, error) { 124 stat := make(map[string]float64) 125 decoder := json.NewDecoder(body) 126 127 s := stats_api.Stats{} 128 err := decoder.Decode(&s) 129 if err != nil { 130 return nil, err 131 } 132 stat["goroutine_num"] = float64(s.GoroutineNum) 133 stat["cgo_call_num"] = float64(s.CgoCallNum) 134 stat["memory_sys"] = float64(s.MemorySys) 135 stat["memory_alloc"] = float64(s.MemoryAlloc) 136 stat["memory_stack"] = float64(s.StackInUse) 137 stat["memory_lookups"] = float64(s.MemoryLookups) 138 stat["memory_frees"] = float64(s.MemoryFrees) 139 stat["memory_mallocs"] = float64(s.MemoryMallocs) 140 stat["heap_sys"] = float64(s.HeapSys) 141 stat["heap_idle"] = float64(s.HeapIdle) 142 stat["heap_inuse"] = float64(s.HeapInuse) 143 stat["heap_released"] = float64(s.HeapReleased) 144 stat["gc_num"] = float64(s.GcNum) 145 stat["gc_per_second"] = float64(s.GcPerSecond) 146 stat["gc_pause_per_second"] = float64(s.GcPausePerSecond) 147 148 return stat, nil 149 } 150 151 // Do the plugin 152 func Do() { 153 optURI := flag.String("uri", "", "URI") 154 optScheme := flag.String("scheme", "http", "Scheme") 155 optHost := flag.String("host", "localhost", "Hostname") 156 optPort := flag.String("port", "8080", "Port") 157 optPath := flag.String("path", "/api/stats", "Path") 158 optPrefix := flag.String("metric-key-prefix", "gostats", "Metric key prefix") 159 optTempfile := flag.String("tempfile", "", "Temp file name") 160 flag.Parse() 161 162 gosrv := GostatsPlugin{ 163 Prefix: *optPrefix, 164 } 165 if *optURI != "" { 166 gosrv.URI = *optURI 167 } else { 168 gosrv.URI = fmt.Sprintf("%s://%s:%s%s", *optScheme, *optHost, *optPort, *optPath) 169 } 170 171 helper := mp.NewMackerelPlugin(gosrv) 172 helper.Tempfile = *optTempfile 173 174 helper.Run() 175 }