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  }