func (w *whispers) FetchOrCreate(metric string) *carbonmem.Whisper { m := w.Fetch(metric) if m == nil { prefix := findNodePrefix(w.prefix, metric) var ok bool w.Lock() m, ok = w.metrics[prefix] if !ok { m = carbonmem.NewWhisper(int32(w.epoch0), w.epochSize, w.windowSize, carbonmem.TrigramCutoff(100000)) w.metrics[prefix] = m } w.Unlock() } return m }
func TestTopKFind(t *testing.T) { metrics := carbonmem.NewWhisper(120, 60, 600) for _, m := range []struct { epoch int32 metric string count uint64 }{ {120, "foo.bar", 10}, {120, "foo.baz", 50}, {120 + 1*60, "foo.bar", 11}, {120 + 1*60, "foo.baz", 40}, {120 + 2*60, "foo.bar", 12}, {120 + 3*60, "foo.bar", 13}, {120 + 3*60, "foo.qux", 13}, {120 + 4*60, "foo.bar", 14}, } { metrics.Set(m.epoch, m.metric, m.count) } Whispers.metrics = map[string]*carbonmem.Whisper{"foo": metrics} for _, tt := range []struct { query string want pb.GlobResponse }{ { "foo.*", pb.GlobResponse{ Name: proto.String("foo.*"), Matches: []*pb.GlobMatch{ &pb.GlobMatch{Path: proto.String("foo.bar"), IsLeaf: proto.Bool(true)}, &pb.GlobMatch{Path: proto.String("foo.baz"), IsLeaf: proto.Bool(true)}, &pb.GlobMatch{Path: proto.String("foo.qux"), IsLeaf: proto.Bool(true)}, }, }, }, { "foo.*.TopK.3m", pb.GlobResponse{ Name: proto.String("foo.*.TopK.3m"), Matches: []*pb.GlobMatch{ &pb.GlobMatch{Path: proto.String("foo.bar.TopK.3m"), IsLeaf: proto.Bool(true)}, &pb.GlobMatch{Path: proto.String("foo.qux.TopK.3m"), IsLeaf: proto.Bool(true)}, }, }, }, { "foo.*.TopK.5m", pb.GlobResponse{ Name: proto.String("foo.*.TopK.5m"), Matches: []*pb.GlobMatch{ &pb.GlobMatch{Path: proto.String("foo.baz.TopK.5m"), IsLeaf: proto.Bool(true)}, &pb.GlobMatch{Path: proto.String("foo.bar.TopK.5m"), IsLeaf: proto.Bool(true)}, &pb.GlobMatch{Path: proto.String("foo.qux.TopK.5m"), IsLeaf: proto.Bool(true)}, }, }, }, } { req, _ := http.NewRequest("GET", fmt.Sprintf("/metrics/find/?query=%s&format=json", tt.query), nil) w := httptest.NewRecorder() findHandler(w, req) var response pb.GlobResponse json.Unmarshal(w.Body.Bytes(), &response) if !reflect.DeepEqual(response, tt.want) { t.Errorf("Find(%s)=%#v, want %#v", tt.query, spew.Sdump(response), spew.Sdump(tt.want)) } } }
func TestTopKRender(t *testing.T) { metrics := carbonmem.NewWhisper(100, 10, 60) for _, m := range []struct { epoch int32 metric string count uint64 }{ {120, "foo.bar", 10}, {120, "foo.baz", 50}, {121, "foo.bar", 11}, {121, "foo.baz", 40}, {122, "foo.bar", 12}, {123, "foo.bar", 13}, {123, "foo.qux", 13}, {124, "foo.bar", 14}, } { metrics.Set(m.epoch, m.metric, m.count) } Whispers.metrics = map[string]*carbonmem.Whisper{"foo": metrics} for _, tt := range []struct { target string from int32 until int32 want pb.MultiFetchResponse }{ { "foo.bar", 120, 124, pb.MultiFetchResponse{ Metrics: []*pb.FetchResponse{ &pb.FetchResponse{ Name: proto.String("foo.bar"), StartTime: proto.Int32(120), StopTime: proto.Int32(124), StepTime: proto.Int32(1), Values: []float64{10, 11, 12, 13, 14}, IsAbsent: []bool{false, false, false, false, false}, }, }, }, }, { "foo.bar.TopK.3s", 120, 124, pb.MultiFetchResponse{ Metrics: []*pb.FetchResponse{ &pb.FetchResponse{ Name: proto.String("foo.bar.TopK.3s"), StartTime: proto.Int32(120), StopTime: proto.Int32(124), StepTime: proto.Int32(1), Values: []float64{10, 11, 12, 13, 14}, IsAbsent: []bool{false, false, false, false, false}, }, }, }, }, } { req, _ := http.NewRequest("GET", fmt.Sprintf("/render/?target=%s&from=%d&until=%d&format=json", tt.target, tt.from, tt.until), nil) w := httptest.NewRecorder() renderHandler(w, req) var response pb.MultiFetchResponse json.Unmarshal(w.Body.Bytes(), &response) if !reflect.DeepEqual(response, tt.want) { t.Errorf("Render(%s,%d,%d)=%#v, want %#v", tt.target, tt.from, tt.until, spew.Sdump(response), spew.Sdump(tt.want)) } } }