// Export populates a expvar.Map with the state of all // of the features. func Export(m *expvar.Map) { fMu.RLock() defer fMu.RUnlock() for f, v := range features { m.Set(f.String(), boolVar(v)) } }
func determineProperties(sizes []int) *expvar.Map { var sum int props := new(expvar.Map).Init() for _, n := range sizes { sum += n } // Determine properties sort.Ints(sizes) if len(sizes) > 0 { summary := map[string]int{ "min": sizes[0], "max": sizes[len(sizes)-1], "length": len(sizes), "sum": sum, "95e": sizes[int(float64(len(sizes))*0.95)], } mean := float64(sum) / float64(summary["length"]) // Pack them into an expvar Map for k, v := range summary { n := new(expvar.Int) n.Set(int64(v)) props.Set(k, n) } avge := new(expvar.Float) avge.Set(mean) props.Set("avg", avge) } return props }
func newListener(nl net.Listener, ns *expvar.Map) *listener { statNS := new(expvar.Map).Init() ns.Set("handshake", statNS) lis := &listener{ Listener: nl, handshakeStats: newHandshakeStats(statNS), } return lis }
func resetVarMap(varMap *expvar.Map) { // There is no easy way to delete/clear expvar.Map. As such there is a slight // race here. *sigh* keys := []string{} varMap.Do(func(kv expvar.KeyValue) { keys = append(keys, kv.Key) }) for _, key := range keys { varMap.Set(key, new(expvar.Int)) } }
func init() { pacStatementSplit = regexp.MustCompile(`\s*;\s*`) pacItemSplit = regexp.MustCompile(`\s+`) pacCallFindProxyForURLResultCount = new(expvar.Map).Init() pacCallFindProxyForURLParamHostCount = new(expvar.Map).Init() callFindProxyForURLMap := new(expvar.Map).Init() callFindProxyForURLMap.Set("resultCount", pacCallFindProxyForURLResultCount) callFindProxyForURLMap.Set("urlHostCount", pacCallFindProxyForURLParamHostCount) pacExpvarMap := expvar.NewMap("pac") pacExpvarMap.Set("callFindProxyForURL", callFindProxyForURLMap) }
func init() { // NOTE(stevvooe): Setup registry metrics structure to report to expvar. // Ideally, we do more metrics through logging but we need some nice // realtime metrics for queue state for now. registry := expvar.Get("registry") if registry == nil { registry = expvar.NewMap("registry") } var notifications expvar.Map notifications.Init() notifications.Set("endpoints", expvar.Func(func() interface{} { endpoints.mu.Lock() defer endpoints.mu.Unlock() var names []interface{} for _, v := range endpoints.registered { var epjson struct { Name string `json:"name"` URL string `json:"url"` EndpointConfig Metrics EndpointMetrics } epjson.Name = v.Name() epjson.URL = v.URL() epjson.EndpointConfig = v.EndpointConfig v.ReadMetrics(&epjson.Metrics) names = append(names, epjson) } return names })) registry.(*expvar.Map).Set("notifications", ¬ifications) }
func newOriginAllower(blockedDomains []string, hostname string, gclog logClient, ns *expvar.Map) *originAllower { mu := &sync.RWMutex{} topKAllDomains := topk.New(100) topKOfflistDomains := topk.New(100) lifetime := new(expvar.Map).Init() ns.Set("lifetime", lifetime) lifetime.Set("top_all_domains", expvar.Func(func() interface{} { mu.RLock() defer mu.RUnlock() return topKAllDomains.Keys() })) lifetime.Set("top_offlist_domains", expvar.Func(func() interface{} { mu.RLock() defer mu.RUnlock() return topKOfflistDomains.Keys() })) oa := &originAllower{ m: make(map[string]struct{}), ns: ns, hostname: hostname, gclog: gclog, mu: mu, topKAllDomains: topKAllDomains, topKOfflistDomains: topKOfflistDomains, } for _, d := range blockedDomains { oa.m[d] = struct{}{} } return oa }
// calculateTargetSummaryStats builds per-tier, per-target, metric-to-host summary stats func calculateTargetSummaryStats(tiers *[]Tier) { for _, tier := range *tiers { totalSizes := []int{} tierStats := new(expvar.Map).Init() // Determine summary stats per target for target, hosts := range tier.Mappings { sizes := []int{} for _, metrics := range hosts { sizes = append(sizes, len(metrics)) totalSizes = append(totalSizes, len(metrics)) } if len(sizes) == 0 { continue } // Build summary props := determineProperties(sizes) tierStats.Set(target, props) } props := determineProperties(totalSizes) tierStats.Set("total", props) distCounts.Set(tier.Name, tierStats) } }
func NewStatusStats(outer *expvar.Map) *statusStats { m := new(expvar.Map).Init() outer.Set("statuses", m) status1xx := &expvar.Int{} status2xx := &expvar.Int{} status3xx := &expvar.Int{} status4xx := &expvar.Int{} status5xx := &expvar.Int{} m.Set("1xx", status1xx) m.Set("2xx", status2xx) m.Set("3xx", status3xx) m.Set("4xx", status4xx) m.Set("5xx", status5xx) return &statusStats{ status1xx, status2xx, status3xx, status4xx, status5xx, } }
// TODO: maybe we should use Func() and just keep a stats structure. // But that would require locking and nngh nngh. func setupExpvars() { var m expvar.Map m.Init() m.Set("notls", expvar.Func(notls.Stats)) m.Set("yakkers", expvar.Func(yakkers.Stats)) stats.Set("sizes", &m) stats.Set("dnsbl_hits", expvar.Func(dblcounts.Stats)) stats.Set("sbl_hits", expvar.Func(sblcounts.Stats)) // BUG: must remember to do this for all counters so they have // an initial value. var evts expvar.Map evts.Init() evts.Set("connections", &events.connections) evts.Set("tls_errors", &events.tlserrs) evts.Set("yakkers", &events.yakkers) evts.Set("notls_conns", &events.notlscnt) evts.Set("rules_errors", &events.ruleserr) evts.Set("yakker_adds", &events.yakads) evts.Set("rsetdrops", &events.rsetdrops) evts.Set("abandons", &events.abandons) evts.Set("refuseds", &events.refuseds) stats.Set("events", &evts) var mailevts expvar.Map var goodevts expvar.Map var cmds expvar.Map mailevts.Init() goodevts.Init() cmds.Init() // Maybe these should track refused commands? Not sure. cmds.Set("ehlo", &events.ehlo) cmds.Set("mailfrom", &events.mailfrom) cmds.Set("rcptto", &events.rcptto) cmds.Set("data", &events.data) mailevts.Set("commands", &cmds) // These are counts of *accepted* commands. // TODO: maybe revise how things are counted? Dunno. goodevts.Set("ehlo", &events.ehloAccept) goodevts.Set("mailfrom", &events.mailfromAccept) goodevts.Set("rcptto", &events.rcpttoAccept) goodevts.Set("data", &events.dataAccept) goodevts.Set("messages", &events.messages) mailevts.Set("accepted", &goodevts) mailevts.Set("ehlo_tlson", &events.tlson) mailevts.Set("quits", &events.quits) mailevts.Set("aborts", &events.aborts) mailevts.Set("rsets", &events.rsets) stats.Set("smtpcounts", &mailevts) // constants stats.Add("pid", int64(os.Getpid())) var stime expvar.String stime.Set(time.Now().String()) stats.Set("startTime", &stime) var conntime expvar.String times.Init() // We're going to have connections, so we set this now. times.Set("connection", &conntime) stats.Set("last", ×) }
func ExampleExpvarCollector() { expvarCollector := prometheus.NewExpvarCollector(map[string]*prometheus.Desc{ "memstats": prometheus.NewDesc( "expvar_memstats", "All numeric memstats as one metric family. Not a good role-model, actually... ;-)", []string{"type"}, nil, ), "lone-int": prometheus.NewDesc( "expvar_lone_int", "Just an expvar int as an example.", nil, nil, ), "http-request-map": prometheus.NewDesc( "expvar_http_request_total", "How many http requests processed, partitioned by status code and http method.", []string{"code", "method"}, nil, ), }) prometheus.MustRegister(expvarCollector) // The Prometheus part is done here. But to show that this example is // doing anything, we have to manually export something via expvar. In // real-life use-cases, some library would already have exported via // expvar what we want to re-export as Prometheus metrics. expvar.NewInt("lone-int").Set(42) expvarMap := expvar.NewMap("http-request-map") var ( expvarMap1, expvarMap2 expvar.Map expvarInt11, expvarInt12, expvarInt21, expvarInt22 expvar.Int ) expvarMap1.Init() expvarMap2.Init() expvarInt11.Set(3) expvarInt12.Set(13) expvarInt21.Set(11) expvarInt22.Set(212) expvarMap1.Set("POST", &expvarInt11) expvarMap1.Set("GET", &expvarInt12) expvarMap2.Set("POST", &expvarInt21) expvarMap2.Set("GET", &expvarInt22) expvarMap.Set("404", &expvarMap1) expvarMap.Set("200", &expvarMap2) // Results in the following expvar map: // "http-request-count": {"200": {"POST": 11, "GET": 212}, "404": {"POST": 3, "GET": 13}} // Let's see what the scrape would yield, but exclude the memstats metrics. metricStrings := []string{} metric := dto.Metric{} metricChan := make(chan prometheus.Metric) go func() { expvarCollector.Collect(metricChan) close(metricChan) }() for m := range metricChan { if strings.Index(m.Desc().String(), "expvar_memstats") == -1 { metric.Reset() m.Write(&metric) metricStrings = append(metricStrings, metric.String()) } } sort.Strings(metricStrings) for _, s := range metricStrings { fmt.Println(strings.TrimRight(s, " ")) } // Output: // label:<name:"code" value:"200" > label:<name:"method" value:"GET" > untyped:<value:212 > // label:<name:"code" value:"200" > label:<name:"method" value:"POST" > untyped:<value:11 > // label:<name:"code" value:"404" > label:<name:"method" value:"GET" > untyped:<value:13 > // label:<name:"code" value:"404" > label:<name:"method" value:"POST" > untyped:<value:3 > // untyped:<value:42 > }
func newHandshakeStats(ns *expvar.Map) *handshakeStats { s := &handshakeStats{ Successes: &expvar.Int{}, Errs: &expvar.Int{}, ReadTimeouts: &expvar.Int{}, WriteTimeouts: &expvar.Int{}, UnknownTimeouts: &expvar.Int{}, EOFs: &expvar.Int{}, } ns.Set("successes", s.Successes) ns.Set("errors", s.Errs) ns.Set("read_timeouts", s.ReadTimeouts) ns.Set("write_timeouts", s.WriteTimeouts) ns.Set("unknown_timeouts", s.UnknownTimeouts) ns.Set("eofs", s.EOFs) return s }