/* Create a http.HandlerFunc that is tied to r Registry such that requests against it generate a representation of the housed metrics. */ func (registry *Registry) YieldExporter() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var instrumentable metrics.InstrumentableCall = func() { requestCount.Increment() url := r.URL if strings.HasSuffix(url.Path, jsonSuffix) { w.WriteHeader(http.StatusOK) w.Header().Set(contentType, jsonContentType) composite := make(map[string]interface{}, len(registry.NameToMetric)) for name, metric := range registry.NameToMetric { composite[name] = metric.Marshallable() } data, _ := json.Marshal(composite) w.Write(data) } else { w.WriteHeader(http.StatusNotFound) } } metrics.InstrumentCall(instrumentable, requestLatencyAccumulator) } }
func (t *target) Scrape(earliest time.Time, results chan Result) (err error) { result := Result{} defer func() { futureState := t.state switch err { case nil: futureState = ALIVE default: futureState = UNREACHABLE } t.scheduler.Reschedule(earliest, futureState) result.Err = err results <- result }() done := make(chan bool) request := func() { ti := time.Now() resp, err := http.Get(t.Address()) if err != nil { return } defer resp.Body.Close() raw, err := ioutil.ReadAll(resp.Body) if err != nil { return } intermediate := make(map[string]interface{}) err = json.Unmarshal(raw, &intermediate) if err != nil { return } baseLabels := model.LabelSet{"instance": model.LabelValue(t.Address())} for baseK, baseV := range t.BaseLabels { baseLabels[baseK] = baseV } for name, v := range intermediate { asMap, ok := v.(map[string]interface{}) if !ok { continue } switch asMap["type"] { case "counter": m := model.Metric{} m["name"] = model.LabelValue(name) asFloat, ok := asMap["value"].(float64) if !ok { continue } s := model.Sample{ Metric: m, Value: model.SampleValue(asFloat), Timestamp: ti, } for baseK, baseV := range baseLabels { m[baseK] = baseV } result.Samples = append(result.Samples, s) case "histogram": values, ok := asMap["value"].(map[string]interface{}) if !ok { continue } for p, pValue := range values { asString, ok := pValue.(string) if !ok { continue } float, err := strconv.ParseFloat(asString, 64) if err != nil { continue } m := model.Metric{} m["name"] = model.LabelValue(name) m["percentile"] = model.LabelValue(p) s := model.Sample{ Metric: m, Value: model.SampleValue(float), Timestamp: ti, } for baseK, baseV := range baseLabels { m[baseK] = baseV } result.Samples = append(result.Samples, s) } } } done <- true } accumulator := func(d time.Duration) { ms := float64(d) / float64(time.Millisecond) labels := map[string]string{address: t.Address(), outcome: success} if err != nil { labels[outcome] = failure } targetOperationLatencies.Add(labels, ms) targetOperations.Increment(labels) } go metrics.InstrumentCall(request, accumulator) select { case <-done: break case <-time.After(t.Deadline): err = fmt.Errorf("Target %s exceeded %s deadline.", t, t.Deadline) } return }