// // does num pings against conn, waits for any we know of to return. // will wait up to wait seconds for a response, and sends 1 ping at a minimum // of interval. // // returns a tuple of float64 with at maximum num values: rtt in ms. // func (pi *PingInfo) pingTimes(conn net.Conn, registry *metrics.Registry) { count := 0 ping := NewPing(conn, pi) go ping.pingReader() wait_for := time.After(time.Duration(pi.Wait) * time.Second) for i := 0; i < pi.Count; i++ { go ping.sendPing() time.Sleep(time.Duration(ping.PingInfo.Interval) * time.Second) } timeout := false for i := pi.Count; i != 0 && !timeout; { select { case <-wait_for: timeout = true break case result := <-ping.ResultChannel: i-- count++ metrics.GetOrRegisterHistogram( "ns", *registry, metrics.NewUniformSample(pi.Count), ).Update(result) default: time.Sleep(1 * time.Nanosecond) } } update := int64(math.Floor(float64(count) / float64(pi.Count) * 100)) metrics.GetOrRegisterHistogram( "success", *registry, metrics.NewUniformSample(pi.Count), ).Update(update) }
func (a *Addr) ping() { errors := int64(0) start := time.Now() conn, err := net.Dial("tcp", a.Address) if err != nil { errors = 100 } else { conn.Close() metrics.GetOrRegisterHistogram( "ns", *a.Registry, metrics.NewUniformSample(60), ).Update(time.Since(start).Nanoseconds()) } metrics.GetOrRegisterHistogram( "errors", *a.Registry, metrics.NewUniformSample(60), ).Update(errors) }
// initializeFieldTagPath traverses the given struct trying to initialize // metric values. The "metric" struct tag is used to determine the name of the // metrics for each struct field. If there is no "metric" struct tag, the // lowercased struct field name is used for the metric name. The name is // prefixed with tags from previous struct fields if any, separated by a dot. // For example: // // Messages struct { // Smtp struct { // Latency metrics.Timer `metric:"latency"` // } `metric:"smtp"` // Http struct { // Latency metrics.Timer `metric:"latency"` // } `metric:"http"` // } `metric:"messages"` // // yields timers with names "messages.smtp.latency" and "messages.http.latency" // respectively. // // If there is no metric tag for a field it is skipped and assumed it is used // for other purposes such as configuration. func (m *MetricTags) initializeFieldTagPath(fieldType reflect.Value, prefix string) { for i := 0; i < fieldType.NumField(); i++ { val := fieldType.Field(i) field := fieldType.Type().Field(i) tag := field.Tag.Get("metric") if tag == "" { // If tag isn't found, derive tag from the lower case name of // the field. tag = strings.ToLower(field.Name) } if prefix != "" { tag = prefix + m.separator + tag } if field.Type.Kind() == reflect.Struct { // Recursively traverse an embedded struct m.initializeFieldTagPath(val, tag) } else if field.Type.Kind() == reflect.Map && field.Type.Key().Kind() == reflect.String { // If this is a map[string]Something, then use the string key as bucket name and recursively generate the metrics below for _, k := range val.MapKeys() { m.initializeFieldTagPath(val.MapIndex(k).Elem(), tag+m.separator+k.String()) } } else { // Found a field, initialize switch field.Type.String() { case "metrics.Counter": c := metrics.NewCounter() metrics.Register(tag, c) val.Set(reflect.ValueOf(c)) case "metrics.Timer": t := metrics.NewTimer() metrics.Register(tag, t) val.Set(reflect.ValueOf(t)) case "metrics.Meter": m := metrics.NewMeter() metrics.Register(tag, m) val.Set(reflect.ValueOf(m)) case "metrics.Gauge": g := metrics.NewGauge() metrics.Register(tag, g) val.Set(reflect.ValueOf(g)) case "metrics.Histogram": s := metrics.NewUniformSample(1028) h := metrics.NewHistogram(s) metrics.Register(tag, h) val.Set(reflect.ValueOf(h)) } } } }
func (a *Addr) ping() { errors := int64(0) start := time.Now() res, err := http.Get(a.Address) if err != nil { errors = 100 } else { defer res.Body.Close() metrics.GetOrRegisterHistogram( "ns", *a.Registry, metrics.NewUniformSample(60), ).Update(time.Since(start).Nanoseconds()) } metrics.GetOrRegisterHistogram( "errors", *a.Registry, metrics.NewUniformSample(60), ).Update(errors) }
func TestHistograms(t *testing.T) { mock := &MockPutMetricsClient{} filter := &config.NoFilter{} cfg := &config.Config{ Client: mock, Filter: filter, } registry := metrics.NewRegistry() hist := metrics.GetOrRegisterHistogram(fmt.Sprintf("histo"), registry, metrics.NewUniformSample(1024)) hist.Update(1000) hist.Update(500) emitMetrics(registry, cfg) if mock.metricsPut < len(filter.Percentiles("")) { t.Fatal("No Metrics Put") } }