github.com/mackerelio/mackerel-agent-plugins@v0.89.3/mackerel-plugin-php-apc/lib/php-apc.go (about) 1 package mpphpapc 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 // metric value structure 18 var graphdef = map[string]mp.Graphs{ 19 "php-apc.purges": { 20 Label: "PHP APC Cache Purge Count", 21 Unit: "integer", 22 Metrics: []mp.Metrics{ 23 {Name: "cache_full_count", Label: "File Cache", Diff: true, Stacked: false}, 24 {Name: "user_cache_full_count", Label: "User Cache", Diff: true, Stacked: false}, 25 }, 26 }, 27 "php-apc.stats": { 28 Label: "PHP APC File Cache Statistics", 29 Unit: "integer", 30 Metrics: []mp.Metrics{ 31 {Name: "cache_hits", Label: "Hits", Diff: true, Stacked: false}, 32 {Name: "cache_misses", Label: "Misses", Diff: true, Stacked: false}, 33 }, 34 }, 35 "php-apc.cache_size": { 36 Label: "PHP APC Cache Size", 37 Unit: "bytes", 38 Metrics: []mp.Metrics{ 39 {Name: "cached_files_size", Label: "File Cache", Diff: false, Stacked: true}, 40 {Name: "user_cache_vars_size", Label: "User Cache", Diff: false, Stacked: true}, 41 {Name: "total_memory", Label: "Total", Diff: false, Stacked: false}, 42 }, 43 }, 44 "php-apc.user_stats": { 45 Label: "PHP APC User Cache Statistics", 46 Unit: "integer", 47 Metrics: []mp.Metrics{ 48 {Name: "user_cache_hits", Label: "Hits", Diff: true, Stacked: false}, 49 {Name: "user_cache_misses", Label: "Misses", Diff: true, Stacked: false}, 50 }, 51 }, 52 } 53 54 // PhpApcPlugin mackerel plugin for php-apc 55 type PhpApcPlugin struct { 56 Host string 57 Port uint16 58 Path string 59 Tempfile string 60 } 61 62 // GraphDefinition interface for mackerelplugin 63 func (c PhpApcPlugin) GraphDefinition() map[string]mp.Graphs { 64 return graphdef 65 } 66 67 // main function 68 func doMain(c *cli.Context) error { 69 70 var phpapc PhpApcPlugin 71 72 phpapc.Host = c.String("http_host") 73 phpapc.Port = uint16(c.Int("http_port")) 74 phpapc.Path = c.String("status_page") 75 76 helper := mp.NewMackerelPlugin(phpapc) 77 helper.Tempfile = c.String("tempfile") 78 79 helper.Run() 80 return nil 81 } 82 83 // FetchMetrics interface for mackerelplugin 84 func (c PhpApcPlugin) FetchMetrics() (map[string]float64, error) { 85 data, err := getPhpApcMetrics(c.Host, c.Port, c.Path) 86 if err != nil { 87 return nil, err 88 } 89 90 stat := make(map[string]float64) 91 errStat := parsePhpApcStatus(data, &stat) 92 if errStat != nil { 93 return nil, errStat 94 } 95 96 return stat, nil 97 } 98 99 // parsing metrics from server-status?auto 100 func parsePhpApcStatus(str string, p *map[string]float64) error { 101 for _, line := range strings.Split(str, "\n") { 102 record := strings.Split(line, ":") 103 if len(record) != 2 { 104 continue 105 } 106 var errParse error 107 (*p)[record[0]], errParse = strconv.ParseFloat(strings.Trim(record[1], " "), 64) 108 if errParse != nil { 109 return errParse 110 } 111 } 112 113 if len(*p) == 0 { 114 return errors.New("status data not found") 115 } 116 117 return nil 118 } 119 120 // Getting php-apc status from server-status module data. 121 func getPhpApcMetrics(host string, port uint16, path string) (string, error) { 122 uri := "http://" + host + ":" + strconv.FormatUint(uint64(port), 10) + path 123 req, err := http.NewRequest(http.MethodGet, uri, nil) 124 if err != nil { 125 return "", err 126 } 127 req.Header.Set("User-Agent", "mackerel-plugin-php-apc") 128 129 resp, err := http.DefaultClient.Do(req) 130 if err != nil { 131 return "", err 132 } 133 defer resp.Body.Close() 134 if resp.StatusCode != http.StatusOK { 135 return "", fmt.Errorf("HTTP status error: %d", resp.StatusCode) 136 } 137 body, err := io.ReadAll(resp.Body) 138 if err != nil { 139 return "", err 140 } 141 return string(body[:]), nil 142 } 143 144 // Do the plugin 145 func Do() { 146 app := cli.NewApp() 147 app.Name = "php-apc_metrics" 148 app.Usage = "Get metrics from php-apc." 149 app.Author = "Yuichiro Saito" 150 app.Email = "saito@heartbeats.jp" 151 app.Flags = flags 152 app.Action = doMain 153 154 err := app.Run(os.Args) 155 if err != nil { 156 log.Fatalln(err) 157 } 158 }