github.com/mackerelio/mackerel-agent-plugins@v0.89.3/mackerel-plugin-varnish/lib/varnish.go (about) 1 package mpvarnish 2 3 import ( 4 "flag" 5 "fmt" 6 "os/exec" 7 "regexp" 8 "strconv" 9 "strings" 10 11 mp "github.com/mackerelio/go-mackerel-plugin-helper" 12 ) 13 14 var graphdef = map[string]mp.Graphs{ 15 "varnish.requests": { 16 Label: "Varnish Client Requests", 17 Unit: "integer", 18 Metrics: []mp.Metrics{ 19 {Name: "requests", Label: "Requests", Diff: true}, 20 {Name: "cache_hits", Label: "Hits", Diff: true}, 21 }, 22 }, 23 "varnish.backend": { 24 Label: "Varnish Backend", 25 Unit: "integer", 26 Metrics: []mp.Metrics{ 27 {Name: "backend_req", Label: "Requests", Diff: true}, 28 {Name: "backend_conn", Label: "Conn success", Diff: true}, 29 {Name: "backend_fail", Label: "Conn fail", Diff: true}, 30 {Name: "backend_reuse", Label: "Conn reuse", Diff: true}, 31 {Name: "backend_recycle", Label: "Conn recycle", Diff: true}, 32 }, 33 }, 34 "varnish.objects": { 35 Label: "Varnish Objects", 36 Unit: "integer", 37 Metrics: []mp.Metrics{ 38 {Name: "n_object", Label: "object", Diff: false}, 39 {Name: "n_objectcore", Label: "objectcore", Diff: false}, 40 {Name: "n_objecthead", Label: "objecthead", Diff: false}, 41 }, 42 }, 43 "varnish.objects_expire": { 44 Label: "Varnish Objects Expire", 45 Unit: "integer", 46 Metrics: []mp.Metrics{ 47 {Name: "n_expired", Label: "expire", Diff: true}, 48 }, 49 }, 50 "varnish.busy_requests": { 51 Label: "Varnish Busy Requests", 52 Unit: "integer", 53 Metrics: []mp.Metrics{ 54 {Name: "busy_sleep", Label: "sleep", Diff: true}, 55 {Name: "busy_wakeup", Label: "wakeup", Diff: true}, 56 }, 57 }, 58 "varnish.sma.g_alloc.#": { 59 Label: "Varnish SMA Allocations", 60 Unit: "integer", 61 Metrics: []mp.Metrics{ 62 {Name: "g_alloc", Label: "num", Diff: false}, 63 }, 64 }, 65 "varnish.sma.memory.#": { 66 Label: "Varnish SMA Memory", 67 Unit: "integer", 68 Metrics: []mp.Metrics{ 69 {Name: "allocated", Label: "Allocated", Diff: false}, 70 {Name: "available", Label: "Available", Diff: false}, 71 }, 72 }, 73 } 74 75 // VarnishPlugin mackerel plugin for varnish 76 type VarnishPlugin struct { 77 VarnishStatPath string 78 VarnishName string 79 Tempfile string 80 } 81 82 // FetchMetrics interface for mackerelplugin 83 func (m VarnishPlugin) FetchMetrics() (map[string]interface{}, error) { 84 var out []byte 85 var err error 86 87 if m.VarnishName == "" { 88 out, err = exec.Command(m.VarnishStatPath, "-1").CombinedOutput() 89 } else { 90 out, err = exec.Command(m.VarnishStatPath, "-1", "-n", m.VarnishName).CombinedOutput() 91 } 92 if err != nil { 93 return nil, fmt.Errorf("%s: %s", err, out) 94 } 95 96 lineexp := regexp.MustCompile(`^([^ ]+) +(\d+)`) 97 smaexp := regexp.MustCompile(`^SMA\.([^\.]+)\.(.+)$`) 98 99 stat := map[string]interface{}{ 100 "requests": float64(0), 101 } 102 103 var tmpv float64 104 for _, line := range strings.Split(string(out), "\n") { 105 match := lineexp.FindStringSubmatch(line) 106 if match == nil { 107 continue 108 } 109 110 tmpv, err = strconv.ParseFloat(match[2], 64) 111 if err != nil { 112 continue 113 } 114 115 switch match[1] { 116 case "cache_hit", "MAIN.cache_hit": 117 stat["cache_hits"] = tmpv 118 stat["requests"] = stat["requests"].(float64) + tmpv 119 case "cache_miss", "MAIN.cache_miss": 120 stat["requests"] = stat["requests"].(float64) + tmpv 121 case "cache_hitpass", "MAIN.cache_hitpass": 122 stat["requests"] = stat["requests"].(float64) + tmpv 123 case "MAIN.backend_req": 124 stat["backend_req"] = tmpv 125 case "MAIN.backend_conn": 126 stat["backend_conn"] = tmpv 127 case "MAIN.backend_fail": 128 stat["backend_fail"] = tmpv 129 case "MAIN.backend_reuse": 130 stat["backend_reuse"] = tmpv 131 case "MAIN.backend_recycle": 132 stat["backend_recycle"] = tmpv 133 case "MAIN.n_object": 134 stat["n_object"] = tmpv 135 case "MAIN.n_objectcore": 136 stat["n_objectcore"] = tmpv 137 case "MAIN.n_expired": 138 stat["n_expired"] = tmpv 139 case "MAIN.n_objecthead": 140 stat["n_objecthead"] = tmpv 141 case "MAIN.busy_sleep": 142 stat["busy_sleep"] = tmpv 143 case "MAIN.busy_wakeup": 144 stat["busy_wakeup"] = tmpv 145 default: 146 smamatch := smaexp.FindStringSubmatch(match[1]) 147 if smamatch == nil { 148 continue 149 } 150 switch smamatch[2] { 151 case "g_alloc": 152 stat["varnish.sma.g_alloc."+smamatch[1]+".g_alloc"] = tmpv 153 case "g_bytes": 154 stat["varnish.sma.memory."+smamatch[1]+".allocated"] = tmpv 155 case "g_space": 156 stat["varnish.sma.memory."+smamatch[1]+".available"] = tmpv 157 } 158 } 159 } 160 161 return stat, err 162 } 163 164 // GraphDefinition interface for mackerelplugin 165 func (m VarnishPlugin) GraphDefinition() map[string]mp.Graphs { 166 return graphdef 167 } 168 169 // Do the plugin 170 func Do() { 171 optVarnishStatPath := flag.String("varnishstat", "/usr/bin/varnishstat", "Path of varnishstat") 172 optVarnishName := flag.String("varnish-name", "", "Varnish name") 173 optTempfile := flag.String("tempfile", "", "Temp file name") 174 flag.Parse() 175 176 var varnish VarnishPlugin 177 varnish.VarnishStatPath = *optVarnishStatPath 178 varnish.VarnishName = *optVarnishName 179 helper := mp.NewMackerelPlugin(varnish) 180 181 if *optTempfile != "" { 182 helper.Tempfile = *optTempfile 183 } 184 185 helper.Run() 186 }