github.com/mackerelio/mackerel-agent-plugins@v0.89.3/mackerel-plugin-php-opcache/lib/php-opcache.go (about) 1 package mpphpopcache 2 3 import ( 4 "errors" 5 "fmt" 6 "io" 7 "log" 8 "net/http" 9 "os" 10 "strconv" 11 "strings" 12 13 mp "github.com/mackerelio/go-mackerel-plugin" 14 "github.com/urfave/cli" 15 ) 16 17 var graphdef = map[string]mp.Graphs{ 18 "php-opcache.memory_size": { 19 Label: "PHP OPCache Memory Size", 20 Unit: "integer", 21 Metrics: []mp.Metrics{ 22 {Name: "used_memory", Label: "Used Memory", Diff: false, Stacked: false}, 23 {Name: "free_memory", Label: "Free Memory", Diff: false, Stacked: false}, 24 {Name: "wasted_memory", Label: "Wasted Memory", Diff: false, Stacked: false}, 25 }, 26 }, 27 "php-opcache.memory": { 28 Label: "PHP OPCache Memory Statistics", 29 Unit: "integer", 30 Metrics: []mp.Metrics{ 31 {Name: "opcache_hit_rate", Label: "OPCache hit rate", Diff: false, Stacked: false}, 32 {Name: "current_wasted_percentage", Label: "Used Memory", Diff: false, Stacked: false}, 33 }, 34 }, 35 36 "php-opcache.cache_size": { 37 Label: "PHP OPCache Cache Size", 38 Unit: "integer", 39 Metrics: []mp.Metrics{ 40 {Name: "num_cached_scripts", Label: "Cached Script", Diff: false, Stacked: false}, 41 {Name: "num_cached_keys", Label: "Num Cached Key", Diff: false, Stacked: false}, 42 {Name: "max_cached_keys", Label: "Max Cached Key", Diff: false, Stacked: false}, 43 }, 44 }, 45 "php-opcache.stats": { 46 Label: "PHP OPCache Cache Statistics", 47 Unit: "integer", 48 Metrics: []mp.Metrics{ 49 {Name: "hits", Label: "Hits", Diff: true, Stacked: false}, 50 {Name: "misses", Label: "Misses", Diff: true, Stacked: false}, 51 {Name: "blacklist_misses", Label: "Blacklist Misses", Diff: true, Stacked: false}, 52 }, 53 }, 54 } 55 56 // PhpOpcachePlugin mackerel plugin for php-opcache 57 type PhpOpcachePlugin struct { 58 Host string 59 Port uint16 60 Path string 61 Tempfile string 62 } 63 64 // GraphDefinition interface for mackerelplugin 65 func (c PhpOpcachePlugin) GraphDefinition() map[string]mp.Graphs { 66 return graphdef 67 } 68 69 // FetchMetrics interface for mackerelplugin 70 func (c PhpOpcachePlugin) FetchMetrics() (map[string]float64, error) { 71 data, err := getPhpOpcacheMetrics(c.Host, c.Port, c.Path) 72 if err != nil { 73 return nil, err 74 } 75 76 stat := make(map[string]float64) 77 errStat := parsePhpOpcacheStatus(data, &stat) 78 if errStat != nil { 79 return nil, errStat 80 } 81 82 return stat, nil 83 } 84 85 func parsePhpOpcacheStatus(str string, p *map[string]float64) error { 86 for _, line := range strings.Split(str, "\n") { 87 record := strings.Split(line, ":") 88 if len(record) != 2 { 89 continue 90 } 91 var errParse error 92 (*p)[record[0]], errParse = strconv.ParseFloat(strings.Trim(record[1], " "), 64) 93 if errParse != nil { 94 return errParse 95 } 96 } 97 98 if len(*p) == 0 { 99 return errors.New("status data not found") 100 } 101 102 return nil 103 } 104 105 func getPhpOpcacheMetrics(host string, port uint16, path string) (string, error) { 106 uri := "http://" + host + ":" + strconv.FormatUint(uint64(port), 10) + path 107 req, err := http.NewRequest(http.MethodGet, uri, nil) 108 if err != nil { 109 return "", err 110 } 111 req.Header.Set("User-Agent", "mackerel-plugin-php-opcache") 112 113 resp, err := http.DefaultClient.Do(req) 114 if err != nil { 115 return "", err 116 } 117 defer resp.Body.Close() 118 if resp.StatusCode != http.StatusOK { 119 return "", fmt.Errorf("HTTP status error: %d", resp.StatusCode) 120 } 121 body, err := io.ReadAll(resp.Body) 122 if err != nil { 123 return "", err 124 } 125 return string(body[:]), nil 126 } 127 128 func doMain(c *cli.Context) error { 129 var phpopcache PhpOpcachePlugin 130 131 phpopcache.Host = c.String("http_host") 132 phpopcache.Port = uint16(c.Int("http_port")) 133 phpopcache.Path = c.String("status_page") 134 135 helper := mp.NewMackerelPlugin(phpopcache) 136 helper.Tempfile = c.String("tempfile") 137 138 helper.Run() 139 return nil 140 } 141 142 // Do the plugin 143 func Do() { 144 app := cli.NewApp() 145 app.Name = "php-opcache_metrics" 146 app.Usage = "Get metrics from php-opcache." 147 app.Author = "Yuichiro Mukai" 148 app.Email = "y.iky917@gmail.com" 149 app.Flags = flags 150 app.Action = doMain 151 152 err := app.Run(os.Args) 153 if err != nil { 154 log.Fatalln(err) 155 } 156 }