diff --git a/config/config.go b/config/config.go index 0b2a2df4..d6fb297a 100644 --- a/config/config.go +++ b/config/config.go @@ -1012,6 +1012,10 @@ func (c *Config) setupGraphiteMetrics() bool { metrics.InitQueryMetrics(c.ClickHouse.TaggedTable, &c.Metrics) } + if c.ClickHouse.TagsCountTable != "" { + metrics.InitQueryMetrics(c.ClickHouse.TagsCountTable, &c.Metrics) + } + return metrics.Graphite != nil } diff --git a/find/find.go b/find/find.go index 6e874acf..253f530f 100644 --- a/find/find.go +++ b/find/find.go @@ -28,8 +28,8 @@ func NewCached(config *config.Config, body []byte) *Find { } } -func New(config *config.Config, ctx context.Context, query string, stat *finder.FinderStat) (*Find, error) { - res, err := finder.Find(config, ctx, query, 0, 0, stat) +func New(config *config.Config, ctx context.Context, query string) (*Find, error) { + res, err := finder.Find(config, ctx, query, 0, 0) if err != nil { return nil, err } diff --git a/find/handler.go b/find/handler.go index 5738d316..b19d5596 100644 --- a/find/handler.go +++ b/find/handler.go @@ -11,7 +11,6 @@ import ( "github.com/go-graphite/carbonapi/pkg/parser" v3pb "github.com/go-graphite/protocol/carbonapi_v3_pb" "github.com/lomik/graphite-clickhouse/config" - "github.com/lomik/graphite-clickhouse/finder" "github.com/lomik/graphite-clickhouse/helper/clickhouse" "github.com/lomik/graphite-clickhouse/helper/utils" "github.com/lomik/graphite-clickhouse/logs" @@ -41,7 +40,7 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { var ( metricsCount int64 - stat finder.FinderStat + stat metrics.FinderStat queueFail bool queueDuration time.Duration findCache bool @@ -195,7 +194,7 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { }() } - f, err := New(h.config, r.Context(), query, &stat) + f, err := New(h.config, r.Context(), query) if entered { // release early as possible diff --git a/finder/base.go b/finder/base.go index 3e4d35ac..46d89143 100644 --- a/finder/base.go +++ b/finder/base.go @@ -9,6 +9,7 @@ import ( "github.com/lomik/graphite-clickhouse/config" "github.com/lomik/graphite-clickhouse/helper/clickhouse" + "github.com/lomik/graphite-clickhouse/metrics" "github.com/lomik/graphite-clickhouse/pkg/scope" "github.com/lomik/graphite-clickhouse/pkg/where" ) @@ -20,6 +21,7 @@ type BaseFinder struct { table string // graphite_tree table opts clickhouse.Options // timeout, connectTimeout body []byte // clickhouse response body + stats []metrics.FinderStat } func NewBase(url string, table string, opts clickhouse.Options) Finder { @@ -27,6 +29,7 @@ func NewBase(url string, table string, opts clickhouse.Options) Finder { url: url, table: table, opts: opts, + stats: make([]metrics.FinderStat, 0), } } @@ -40,8 +43,12 @@ func (b *BaseFinder) where(query string) *where.Where { return w } -func (b *BaseFinder) Execute(ctx context.Context, config *config.Config, query string, from int64, until int64, stat *FinderStat) (err error) { +func (b *BaseFinder) Execute(ctx context.Context, config *config.Config, query string, from int64, until int64) (err error) { w := b.where(query) + + b.stats = append(b.stats, metrics.FinderStat{}) + stat := &b.stats[len(b.stats)-1] + b.body, stat.ChReadRows, stat.ChReadBytes, err = clickhouse.Query( scope.WithTable(ctx, b.table), b.url, @@ -101,3 +108,7 @@ func (b *BaseFinder) Abs(v []byte) []byte { func (b *BaseFinder) Bytes() ([]byte, error) { return b.body, nil } + +func (b *BaseFinder) Stats() []metrics.FinderStat { + return b.stats +} diff --git a/finder/blacklist.go b/finder/blacklist.go index 43d04034..747775e2 100644 --- a/finder/blacklist.go +++ b/finder/blacklist.go @@ -5,6 +5,7 @@ import ( "regexp" "github.com/lomik/graphite-clickhouse/config" + "github.com/lomik/graphite-clickhouse/metrics" ) type BlacklistFinder struct { @@ -20,7 +21,7 @@ func WrapBlacklist(f Finder, blacklist []*regexp.Regexp) *BlacklistFinder { } } -func (p *BlacklistFinder) Execute(ctx context.Context, config *config.Config, query string, from int64, until int64, stat *FinderStat) (err error) { +func (p *BlacklistFinder) Execute(ctx context.Context, config *config.Config, query string, from int64, until int64) (err error) { for i := 0; i < len(p.blacklist); i++ { if p.blacklist[i].MatchString(query) { p.matched = true @@ -28,7 +29,7 @@ func (p *BlacklistFinder) Execute(ctx context.Context, config *config.Config, qu } } - return p.wrapped.Execute(ctx, config, query, from, until, stat) + return p.wrapped.Execute(ctx, config, query, from, until) } func (p *BlacklistFinder) List() [][]byte { @@ -55,3 +56,7 @@ func (p *BlacklistFinder) Abs(v []byte) []byte { func (p *BlacklistFinder) Bytes() ([]byte, error) { return nil, ErrNotImplemented } + +func (p *BlacklistFinder) Stats() []metrics.FinderStat { + return p.wrapped.Stats() +} diff --git a/finder/date.go b/finder/date.go index 9993be5f..5ce4b9b6 100644 --- a/finder/date.go +++ b/finder/date.go @@ -7,6 +7,7 @@ import ( "github.com/lomik/graphite-clickhouse/config" "github.com/lomik/graphite-clickhouse/helper/clickhouse" + "github.com/lomik/graphite-clickhouse/metrics" "github.com/lomik/graphite-clickhouse/pkg/scope" "github.com/lomik/graphite-clickhouse/pkg/where" ) @@ -30,7 +31,7 @@ func NewDateFinder(url string, table string, tableVersion int, opts clickhouse.O return &DateFinder{b, tableVersion} } -func (b *DateFinder) Execute(ctx context.Context, config *config.Config, query string, from int64, until int64, stat *FinderStat) (err error) { +func (b *DateFinder) Execute(ctx context.Context, config *config.Config, query string, from int64, until int64) (err error) { w := b.where(query) dateWhere := where.New() @@ -40,6 +41,9 @@ func (b *DateFinder) Execute(ctx context.Context, config *config.Config, query s time.Unix(until, 0).Format("2006-01-02"), ) + b.stats = append(b.stats, metrics.FinderStat{}) + stat := &b.stats[len(b.stats)-1] + if b.tableVersion == 2 { b.body, stat.ChReadRows, stat.ChReadBytes, err = clickhouse.Query( scope.WithTable(ctx, b.table), diff --git a/finder/date_reverse.go b/finder/date_reverse.go index a15ffefe..0f54e392 100644 --- a/finder/date_reverse.go +++ b/finder/date_reverse.go @@ -7,6 +7,7 @@ import ( "github.com/lomik/graphite-clickhouse/config" "github.com/lomik/graphite-clickhouse/helper/clickhouse" "github.com/lomik/graphite-clickhouse/helper/date" + "github.com/lomik/graphite-clickhouse/metrics" "github.com/lomik/graphite-clickhouse/pkg/scope" "github.com/lomik/graphite-clickhouse/pkg/where" ) @@ -39,8 +40,12 @@ func (f *DateFinderV3) whereFilter(query string, from int64, until int64) (*wher return w, dateWhere } -func (f *DateFinderV3) Execute(ctx context.Context, config *config.Config, query string, from int64, until int64, stat *FinderStat) (err error) { +func (f *DateFinderV3) Execute(ctx context.Context, config *config.Config, query string, from int64, until int64) (err error) { w, dateWhere := f.whereFilter(query, from, until) + + f.stats = append(f.stats, metrics.FinderStat{}) + stat := &f.stats[len(f.stats)-1] + f.body, stat.ChReadRows, stat.ChReadBytes, err = clickhouse.Query( scope.WithTable(ctx, f.table), f.url, diff --git a/finder/finder.go b/finder/finder.go index fb0d4b9a..348316c0 100644 --- a/finder/finder.go +++ b/finder/finder.go @@ -5,6 +5,7 @@ import ( "strings" "github.com/lomik/graphite-clickhouse/helper/clickhouse" + "github.com/lomik/graphite-clickhouse/metrics" "github.com/lomik/graphite-clickhouse/config" ) @@ -14,18 +15,11 @@ type Result interface { Series() [][]byte Abs([]byte) []byte Bytes() ([]byte, error) + Stats() []metrics.FinderStat } - -type FinderStat struct { - ReadBytes int64 - ChReadRows int64 - ChReadBytes int64 - Table string -} - type Finder interface { Result - Execute(ctx context.Context, config *config.Config, query string, from int64, until int64, stat *FinderStat) error + Execute(ctx context.Context, config *config.Config, query string, from int64, until int64) error } func newPlainFinder(ctx context.Context, config *config.Config, query string, from int64, until int64, useCache bool) Finder { @@ -108,15 +102,12 @@ func newPlainFinder(ctx context.Context, config *config.Config, query string, fr return f } -func Find(config *config.Config, ctx context.Context, query string, from int64, until int64, stat *FinderStat) (Result, error) { +func Find(config *config.Config, ctx context.Context, query string, from int64, until int64) (Result, error) { fnd := newPlainFinder(ctx, config, query, from, until, config.Common.FindCache != nil) - err := fnd.Execute(ctx, config, query, from, until, stat) - if err != nil { - return nil, err - } + err := fnd.Execute(ctx, config, query, from, until) - return fnd.(Result), nil + return fnd.(Result), err } // Leaf strips last dot and detect IsLeaf @@ -128,7 +119,7 @@ func Leaf(value []byte) ([]byte, bool) { return value, true } -func FindTagged(ctx context.Context, config *config.Config, terms []TaggedTerm, from int64, until int64, stat *FinderStat) (Result, error) { +func FindTagged(ctx context.Context, config *config.Config, terms []TaggedTerm, from int64, until int64) (Result, error) { opts := clickhouse.Options{ Timeout: config.ClickHouse.IndexTimeout, ConnectTimeout: config.ClickHouse.ConnectTimeout, @@ -141,7 +132,7 @@ func FindTagged(ctx context.Context, config *config.Config, terms []TaggedTerm, if plain != nil { plain.wrappedPlain = newPlainFinder(ctx, config, plain.Target(), from, until, useCache) - err := plain.Execute(ctx, config, plain.Target(), from, until, stat) + err := plain.Execute(ctx, config, plain.Target(), from, until) if err != nil { return nil, err } @@ -161,7 +152,7 @@ func FindTagged(ctx context.Context, config *config.Config, terms []TaggedTerm, config.ClickHouse.TaggedCosts, ) - err := fnd.ExecutePrepared(ctx, terms, from, until, stat) + err := fnd.ExecutePrepared(ctx, terms, from, until) if err != nil { return nil, err } diff --git a/finder/index.go b/finder/index.go index 949c0155..bb47174b 100644 --- a/finder/index.go +++ b/finder/index.go @@ -11,6 +11,7 @@ import ( "github.com/lomik/graphite-clickhouse/helper/clickhouse" "github.com/lomik/graphite-clickhouse/helper/date" "github.com/lomik/graphite-clickhouse/helper/errs" + "github.com/lomik/graphite-clickhouse/metrics" "github.com/lomik/graphite-clickhouse/pkg/scope" "github.com/lomik/graphite-clickhouse/pkg/where" ) @@ -37,6 +38,7 @@ type IndexFinder struct { reverse uint8 // calculated in IndexFinder.useReverse only once body []byte // clickhouse response body rows [][]byte + stats []metrics.FinderStat useCache bool // rotate body if needed (for store in cache) useDaily bool } @@ -59,6 +61,7 @@ func NewIndex(url string, table string, dailyEnabled bool, reverse string, rever dailyEnabled: dailyEnabled, confReverse: config.IndexReverse[reverse], confReverses: reverses, + stats: make([]metrics.FinderStat, 0), useCache: useCache, } } @@ -193,7 +196,7 @@ func validatePlainQuery(query string, wildcardMinDistance int) error { return nil } -func (idx *IndexFinder) Execute(ctx context.Context, config *config.Config, query string, from int64, until int64, stat *FinderStat) (err error) { +func (idx *IndexFinder) Execute(ctx context.Context, config *config.Config, query string, from int64, until int64) (err error) { err = validatePlainQuery(query, config.ClickHouse.WildcardMinDistance) if err != nil { return err @@ -201,6 +204,9 @@ func (idx *IndexFinder) Execute(ctx context.Context, config *config.Config, quer w := idx.whereFilter(query, from, until) + idx.stats = append(idx.stats, metrics.FinderStat{}) + stat := &idx.stats[len(idx.stats)-1] + idx.body, stat.ChReadRows, stat.ChReadBytes, err = clickhouse.Query( scope.WithTable(ctx, idx.table), idx.url, @@ -292,3 +298,7 @@ func (idx *IndexFinder) Series() [][]byte { func (idx *IndexFinder) Bytes() ([]byte, error) { return idx.body, nil } + +func (idx *IndexFinder) Stats() []metrics.FinderStat { + return idx.stats +} diff --git a/finder/mock.go b/finder/mock.go index 4a0cc06a..79f51204 100644 --- a/finder/mock.go +++ b/finder/mock.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/lomik/graphite-clickhouse/config" + "github.com/lomik/graphite-clickhouse/metrics" ) // MockFinder is used for testing purposes @@ -29,7 +30,7 @@ func NewMockTagged(result [][]byte) *MockFinder { } // Execute assigns given query to the query field -func (m *MockFinder) Execute(ctx context.Context, config *config.Config, query string, from int64, until int64, stat *FinderStat) (err error) { +func (m *MockFinder) Execute(ctx context.Context, config *config.Config, query string, from int64, until int64) (err error) { m.query = query return } @@ -58,3 +59,7 @@ func (m *MockFinder) Strings() []string { body, _ := m.fnd.Bytes() return strings.Split(string(body), "\n") } + +func (m *MockFinder) Stats() []metrics.FinderStat { + return m.fnd.Stats() +} diff --git a/finder/plain_from_tagged.go b/finder/plain_from_tagged.go index e0a13992..6d01c775 100644 --- a/finder/plain_from_tagged.go +++ b/finder/plain_from_tagged.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/lomik/graphite-clickhouse/config" + "github.com/lomik/graphite-clickhouse/metrics" ) // Special finder for query plain graphite from prometheus @@ -67,8 +68,8 @@ func (f *plainFromTaggedFinder) Target() string { return f.target } -func (f *plainFromTaggedFinder) Execute(ctx context.Context, config *config.Config, query string, from int64, until int64, stat *FinderStat) error { - return f.wrappedPlain.Execute(ctx, config, query, from, until, stat) +func (f *plainFromTaggedFinder) Execute(ctx context.Context, config *config.Config, query string, from int64, until int64) error { + return f.wrappedPlain.Execute(ctx, config, query, from, until) } // For Render @@ -129,3 +130,7 @@ func (f *plainFromTaggedFinder) List() [][]byte { func (f *plainFromTaggedFinder) Bytes() ([]byte, error) { return nil, ErrNotImplemented } + +func (f *plainFromTaggedFinder) Stats() []metrics.FinderStat { + return f.wrappedPlain.Stats() +} diff --git a/finder/prefix.go b/finder/prefix.go index 327a61a5..8e053eab 100644 --- a/finder/prefix.go +++ b/finder/prefix.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/lomik/graphite-clickhouse/config" + "github.com/lomik/graphite-clickhouse/metrics" "github.com/lomik/graphite-clickhouse/pkg/where" ) @@ -42,7 +43,7 @@ func WrapPrefix(f Finder, prefix string) *PrefixFinder { } } -func (p *PrefixFinder) Execute(ctx context.Context, config *config.Config, query string, from int64, until int64, stat *FinderStat) error { +func (p *PrefixFinder) Execute(ctx context.Context, config *config.Config, query string, from int64, until int64) error { qs := strings.Split(query, ".") // check regexp @@ -76,7 +77,7 @@ func (p *PrefixFinder) Execute(ctx context.Context, config *config.Config, query p.matched = PrefixMatched - return p.wrapped.Execute(ctx, config, strings.Join(qs[len(ps):], "."), from, until, stat) + return p.wrapped.Execute(ctx, config, strings.Join(qs[len(ps):], "."), from, until) } func (p *PrefixFinder) List() [][]byte { @@ -118,3 +119,7 @@ func (p *PrefixFinder) Abs(value []byte) []byte { func (p *PrefixFinder) Bytes() ([]byte, error) { return nil, ErrNotImplemented } + +func (p *PrefixFinder) Stats() []metrics.FinderStat { + return p.wrapped.Stats() +} diff --git a/finder/prefix_test.go b/finder/prefix_test.go index 87e87f8b..775fa107 100644 --- a/finder/prefix_test.go +++ b/finder/prefix_test.go @@ -36,10 +36,8 @@ func TestPrefixFinderExecute(t *testing.T) { f := WrapPrefix(m, test.prefix) - var stat FinderStat - config := config.New() - err := f.Execute(context.Background(), config, test.query, 0, 0, &stat) + err := f.Execute(context.Background(), config, test.query, 0, 0) if test.expectedError { assert.Error(err, testName) @@ -88,10 +86,8 @@ func TestPrefixFinderList(t *testing.T) { m := NewMockFinder(mockData) f := WrapPrefix(m, prefix) - var stat FinderStat - config := config.New() - f.Execute(context.Background(), config, test.query, 0, 0, &stat) + f.Execute(context.Background(), config, test.query, 0, 0) list := make([]string, 0) for _, r := range f.List() { diff --git a/finder/reverse.go b/finder/reverse.go index dcdbaa07..27289899 100644 --- a/finder/reverse.go +++ b/finder/reverse.go @@ -7,6 +7,7 @@ import ( "github.com/lomik/graphite-clickhouse/config" "github.com/lomik/graphite-clickhouse/helper/clickhouse" + "github.com/lomik/graphite-clickhouse/metrics" "github.com/lomik/graphite-clickhouse/pkg/where" ) @@ -50,19 +51,19 @@ func WrapReverse(f Finder, url string, table string, opts clickhouse.Options) *R } } -func (r *ReverseFinder) Execute(ctx context.Context, config *config.Config, query string, from int64, until int64, stat *FinderStat) (err error) { +func (r *ReverseFinder) Execute(ctx context.Context, config *config.Config, query string, from int64, until int64) (err error) { p := strings.LastIndexByte(query, '.') if p < 0 || p >= len(query)-1 { - return r.wrapped.Execute(ctx, config, query, from, until, stat) + return r.wrapped.Execute(ctx, config, query, from, until) } if where.HasWildcard(query[p+1:]) { - return r.wrapped.Execute(ctx, config, query, from, until, stat) + return r.wrapped.Execute(ctx, config, query, from, until) } r.isUsed = true - return r.baseFinder.Execute(ctx, config, ReverseString(query), from, until, stat) + return r.baseFinder.Execute(ctx, config, ReverseString(query), from, until) } func (r *ReverseFinder) List() [][]byte { @@ -98,3 +99,7 @@ func (r *ReverseFinder) Abs(v []byte) []byte { func (f *ReverseFinder) Bytes() ([]byte, error) { return f.wrapped.Bytes() } + +func (f *ReverseFinder) Stats() []metrics.FinderStat { + return f.wrapped.Stats() +} diff --git a/finder/split.go b/finder/split.go index 41ef9467..c1a7baa7 100644 --- a/finder/split.go +++ b/finder/split.go @@ -9,6 +9,7 @@ import ( "github.com/lomik/graphite-clickhouse/config" "github.com/lomik/graphite-clickhouse/helper/clickhouse" "github.com/lomik/graphite-clickhouse/helper/errs" + "github.com/lomik/graphite-clickhouse/metrics" "github.com/lomik/graphite-clickhouse/pkg/scope" "github.com/lomik/graphite-clickhouse/pkg/where" ) @@ -31,6 +32,7 @@ type SplitIndexFinder struct { wrapped Finder body []byte rows [][]byte + stats []metrics.FinderStat // useWrapped indicated if we should use wrapped Finder. useWrapped bool useReverse bool @@ -74,7 +76,6 @@ func (splitFinder *SplitIndexFinder) Execute( query string, from int64, until int64, - stat *FinderStat, ) error { if where.HasUnmatchedBrackets(query) { return errs.NewErrorWithCode("query has unmatched brackets", http.StatusBadRequest) @@ -85,7 +86,7 @@ func (splitFinder *SplitIndexFinder) Execute( idx := strings.IndexAny(query, "{}") if idx == -1 { splitFinder.useWrapped = true - return splitFinder.wrapped.Execute(ctx, config, query, from, until, stat) + return splitFinder.wrapped.Execute(ctx, config, query, from, until) } splitQueries, err := splitQuery(query, config.ClickHouse.MaxNodeToSplitIndex) @@ -95,7 +96,7 @@ func (splitFinder *SplitIndexFinder) Execute( if len(splitQueries) <= 1 { splitFinder.useWrapped = true - return splitFinder.wrapped.Execute(ctx, config, query, from, until, stat) + return splitFinder.wrapped.Execute(ctx, config, query, from, until) } w, err := splitFinder.whereFilter(splitQueries, from, until) @@ -103,6 +104,9 @@ func (splitFinder *SplitIndexFinder) Execute( return err } + splitFinder.stats = append(splitFinder.stats, metrics.FinderStat{}) + stat := &splitFinder.stats[len(splitFinder.stats)-1] + splitFinder.body, stat.ChReadRows, stat.ChReadBytes, err = clickhouse.Query( scope.WithTable(ctx, splitFinder.table), splitFinder.url, @@ -324,3 +328,11 @@ func (splitFinder *SplitIndexFinder) Bytes() ([]byte, error) { return splitFinder.body, nil } + +func (splitFinder *SplitIndexFinder) Stats() []metrics.FinderStat { + if splitFinder.useWrapped { + return splitFinder.wrapped.Stats() + } + + return splitFinder.stats +} diff --git a/finder/tag.go b/finder/tag.go index c8b709c9..d7b6158b 100644 --- a/finder/tag.go +++ b/finder/tag.go @@ -8,6 +8,7 @@ import ( "github.com/lomik/graphite-clickhouse/config" "github.com/lomik/graphite-clickhouse/helper/clickhouse" + "github.com/lomik/graphite-clickhouse/metrics" "github.com/lomik/graphite-clickhouse/pkg/scope" "github.com/lomik/graphite-clickhouse/pkg/where" ) @@ -66,10 +67,12 @@ type TagFinder struct { url string // clickhouse dsn table string // graphite_tag table opts clickhouse.Options // clickhouse timeout, connectTimeout, etc + stats []metrics.FinderStat state TagState tagQuery []TagQ seriesQuery string tagPrefix []byte + useWrapped bool body []byte // clickhouse response } @@ -77,11 +80,12 @@ var EmptyList [][]byte = [][]byte{} func WrapTag(f Finder, url string, table string, opts clickhouse.Options) *TagFinder { return &TagFinder{ - wrapped: f, - url: url, - table: table, - opts: opts, - tagQuery: make([]TagQ, 0), + wrapped: f, + url: url, + table: table, + opts: opts, + tagQuery: make([]TagQ, 0), + useWrapped: true, } } @@ -207,22 +211,24 @@ func (t *TagFinder) MakeSQL(query string) (string, error) { return t.seriesSQL() } -func (t *TagFinder) Execute(ctx context.Context, config *config.Config, query string, from int64, until int64, stat *FinderStat) (err error) { +func (t *TagFinder) Execute(ctx context.Context, config *config.Config, query string, from int64, until int64) (err error) { t.state = TagSkip if query == "" { - return t.wrapped.Execute(ctx, config, query, from, until, stat) + return t.wrapped.Execute(ctx, config, query, from, until) } if query == "*" { t.state = TagRoot - return t.wrapped.Execute(ctx, config, query, from, until, stat) + return t.wrapped.Execute(ctx, config, query, from, until) } if !strings.HasPrefix(query, "_tag.") && query != "_tag" { - return t.wrapped.Execute(ctx, config, query, from, until, stat) + return t.wrapped.Execute(ctx, config, query, from, until) } + t.useWrapped = false + var sql string sql, err = t.MakeSQL(query) @@ -230,6 +236,9 @@ func (t *TagFinder) Execute(ctx context.Context, config *config.Config, query st return } + t.stats = append(t.stats, metrics.FinderStat{}) + stat := &t.stats[len(t.stats)-1] + t.body, stat.ChReadRows, stat.ChReadBytes, err = clickhouse.Query(scope.WithTable(ctx, t.table), t.url, sql, t.opts, nil) stat.Table = t.table stat.ReadBytes = int64(len(t.body)) @@ -337,3 +346,11 @@ func (t *TagFinder) Abs(v []byte) []byte { func (t *TagFinder) Bytes() ([]byte, error) { return nil, ErrNotImplemented } + +func (t *TagFinder) Stats() []metrics.FinderStat { + if t.useWrapped { + return t.wrapped.Stats() + } + + return t.stats +} diff --git a/finder/tag_test.go b/finder/tag_test.go index 4f876452..dff90d5d 100644 --- a/finder/tag_test.go +++ b/finder/tag_test.go @@ -105,10 +105,8 @@ func _TestTags(t *testing.T) { m := NewMockFinder(mockData) f := WrapTag(m, srv.URL, "graphite_tag", clickhouse.Options{Timeout: time.Second, ConnectTimeout: time.Second}) - var stat FinderStat - config := config.New() - f.Execute(context.Background(), config, test.query, 0, 0, &stat) + f.Execute(context.Background(), config, test.query, 0, 0) list := make([]string, 0) for _, r := range f.List() { diff --git a/finder/tagged.go b/finder/tagged.go index 8147e06f..b3069210 100644 --- a/finder/tagged.go +++ b/finder/tagged.go @@ -13,6 +13,7 @@ import ( "github.com/lomik/graphite-clickhouse/helper/clickhouse" "github.com/lomik/graphite-clickhouse/helper/date" "github.com/lomik/graphite-clickhouse/helper/errs" + "github.com/lomik/graphite-clickhouse/metrics" "github.com/lomik/graphite-clickhouse/pkg/scope" "github.com/lomik/graphite-clickhouse/pkg/where" @@ -86,8 +87,8 @@ type TaggedFinder struct { useCarbonBehavior bool dontMatchMissingTags bool metricMightExists bool // if false, skip all subsequent queries because we determined that result will be empty anyway - - body []byte // clickhouse response + stats []metrics.FinderStat + body []byte // clickhouse response } func NewTagged(url string, table, tag1CountTable string, dailyEnabled, useCarbonBehavior, dontMatchMissingTags, absKeepEncoded bool, opts clickhouse.Options, taggedCosts map[string]*config.Costs) *TaggedFinder { @@ -102,6 +103,7 @@ func NewTagged(url string, table, tag1CountTable string, dailyEnabled, useCarbon useCarbonBehavior: useCarbonBehavior, dontMatchMissingTags: dontMatchMissingTags, metricMightExists: true, + stats: make([]metrics.FinderStat, 0), } } @@ -457,13 +459,13 @@ func NewCachedTags(body []byte) *TaggedFinder { } } -func (t *TaggedFinder) Execute(ctx context.Context, config *config.Config, query string, from int64, until int64, stat *FinderStat) error { - terms, err := t.PrepareTaggedTerms(ctx, config, query, from, until, stat) +func (t *TaggedFinder) Execute(ctx context.Context, config *config.Config, query string, from int64, until int64) error { + terms, err := t.PrepareTaggedTerms(ctx, config, query, from, until) if err != nil { return err } - return t.ExecutePrepared(ctx, terms, from, until, stat) + return t.ExecutePrepared(ctx, terms, from, until) } func (t *TaggedFinder) whereFilter(terms []TaggedTerm, from int64, until int64) (*where.Where, *where.Where, error) { @@ -488,11 +490,15 @@ func (t *TaggedFinder) whereFilter(terms []TaggedTerm, from int64, until int64) return w, pw, nil } -func (t *TaggedFinder) ExecutePrepared(ctx context.Context, terms []TaggedTerm, from int64, until int64, stat *FinderStat) error { +func (t *TaggedFinder) ExecutePrepared(ctx context.Context, terms []TaggedTerm, from int64, until int64) error { w, pw, err := t.whereFilter(terms, from, until) if err != nil { return err } + + t.stats = append(t.stats, metrics.FinderStat{}) + stat := &t.stats[len(t.stats)-1] + // TODO: consider consistent query generator sql := fmt.Sprintf("SELECT Path FROM %s %s %s GROUP BY Path FORMAT TabSeparatedRaw", t.table, pw.PreWhereSQL(), w.SQL()) t.body, stat.ChReadRows, stat.ChReadBytes, err = clickhouse.Query(scope.WithTable(ctx, t.table), t.url, sql, t.opts, nil) @@ -590,14 +596,18 @@ func (t *TaggedFinder) Bytes() ([]byte, error) { return nil, ErrNotImplemented } -func (t *TaggedFinder) PrepareTaggedTerms(ctx context.Context, cfg *config.Config, query string, from int64, until int64, stat *FinderStat) (terms []TaggedTerm, err error) { +func (t *TaggedFinder) Stats() []metrics.FinderStat { + return t.stats +} + +func (t *TaggedFinder) PrepareTaggedTerms(ctx context.Context, cfg *config.Config, query string, from int64, until int64) (terms []TaggedTerm, err error) { terms, err = ParseSeriesByTag(query, cfg) if err != nil { return nil, err } if t.tag1CountTable != "" { - err = t.SetCostsFromCountTable(ctx, terms, from, until, stat) + err = t.SetCostsFromCountTable(ctx, terms, from, until) if err != nil { return nil, err } @@ -649,7 +659,7 @@ func SortTaggedTermsByCost(terms []TaggedTerm) { }) } -func (t *TaggedFinder) SetCostsFromCountTable(ctx context.Context, terms []TaggedTerm, from int64, until int64, stat *FinderStat) error { +func (t *TaggedFinder) SetCostsFromCountTable(ctx context.Context, terms []TaggedTerm, from int64, until int64) error { w := where.New() eqTermCount := 0 @@ -687,7 +697,11 @@ func (t *TaggedFinder) SetCostsFromCountTable(ctx context.Context, terms []Tagge var err error - t.body, _, _, err = clickhouse.Query(scope.WithTable(ctx, t.tag1CountTable), t.url, sql, t.opts, nil) + t.stats = append(t.stats, metrics.FinderStat{}) + stat := &t.stats[len(t.stats)-1] + stat.Table = t.tag1CountTable + + t.body, stat.ChReadRows, stat.ChReadBytes, err = clickhouse.Query(scope.WithTable(ctx, t.tag1CountTable), t.url, sql, t.opts, nil) if err != nil { return err } diff --git a/finder/tagged_test.go b/finder/tagged_test.go index 964aaefd..8b8d2bb2 100644 --- a/finder/tagged_test.go +++ b/finder/tagged_test.go @@ -659,9 +659,7 @@ func TestParseSeriesByTagWithCostsFromCountTable(t *testing.T) { cfg.ClickHouse.TaggedCosts, ) - stat := &FinderStat{} - - terms, err := taggedFinder.PrepareTaggedTerms(context.Background(), cfg, query, from, until, stat) + terms, err := taggedFinder.PrepareTaggedTerms(context.Background(), cfg, query, from, until) if expectedErr != nil { assert.Equal(expectedErr, err, testName+", err") return @@ -1005,9 +1003,7 @@ func TestTaggedFinder_whereFilter(t *testing.T) { tt.taggedCosts, ) - stat := &FinderStat{} - - terms, err := f.PrepareTaggedTerms(context.Background(), config, tt.query, tt.from, tt.until, stat) + terms, err := f.PrepareTaggedTerms(context.Background(), config, tt.query, tt.from, tt.until) if err != nil { t.Fatal(err) } diff --git a/metrics/query_metrics.go b/metrics/query_metrics.go index b2b9a1f7..372e25e4 100644 --- a/metrics/query_metrics.go +++ b/metrics/query_metrics.go @@ -18,6 +18,13 @@ type QueryMetrics struct { RangeMetrics []QueryMetric } +type FinderStat struct { + ReadBytes int64 + ChReadRows int64 + ChReadBytes int64 + Table string +} + var ( QMetrics map[string]*QueryMetrics = make(map[string]*QueryMetrics) AutocompleteQMetric *QueryMetrics @@ -112,8 +119,10 @@ func SendQueryReadChecked(r *QueryMetrics, from, until, durationMs, read_rows, r } } -func SendQueryReadByTable(table string, from, until, durationMs, read_rows, read_bytes, ch_read_rows, ch_read_bytes int64, err bool) { - if r, ok := QMetrics[table]; ok { - SendQueryRead(r, from, until, durationMs, read_rows, read_bytes, ch_read_rows, ch_read_bytes, err) +func SendQueryReadByTable(from, until, durationMs, read_rows int64, stats []FinderStat, err bool) { + for _, stat := range stats { + if r, ok := QMetrics[stat.Table]; ok { + SendQueryRead(r, from, until, durationMs, read_rows, stat.ReadBytes, stat.ChReadRows, stat.ChReadBytes, err) + } } } diff --git a/prometheus/querier_select.go b/prometheus/querier_select.go index 176277aa..2c7a7c8c 100644 --- a/prometheus/querier_select.go +++ b/prometheus/querier_select.go @@ -26,7 +26,6 @@ func (q *Querier) lookup(ctx context.Context, from, until int64, qlimiter limite } var ( - stat finder.FinderStat limitCtx context.Context cancel context.CancelFunc ) @@ -49,7 +48,7 @@ func (q *Querier) lookup(ctx context.Context, from, until int64, qlimiter limite defer qlimiter.Leave(limitCtx, "render") } // TODO: implement use stat for Prometheus queries - fndResult, err := finder.FindTagged(ctx, q.config, terms, from, until, &stat) + fndResult, err := finder.FindTagged(ctx, q.config, terms, from, until) if err != nil { return nil, err diff --git a/render/handler.go b/render/handler.go index 8c4b1362..a2d99b70 100644 --- a/render/handler.go +++ b/render/handler.go @@ -201,15 +201,12 @@ func (h *Handler) finder(fetchRequests data.MultiTarget, ctx context.Context, lo var err error - // Search in small index table first - var stat finder.FinderStat - fStart := time.Now() - fndResult, err = finder.Find(h.config, ctx, target, tf.From, tf.Until, &stat) + fndResult, err = finder.Find(h.config, ctx, target, tf.From, tf.Until) d := time.Since(fStart).Milliseconds() if err != nil { - metrics.SendQueryReadByTable(stat.Table, tf.From, tf.Until, d, 0, 0, stat.ChReadRows, stat.ChReadBytes, true) + metrics.SendQueryReadByTable(tf.From, tf.Until, d, 0, fndResult.Stats(), true) logger.Error("find", zap.Error(err)) lock.Lock() errors = append(errors, err) @@ -237,7 +234,7 @@ func (h *Handler) finder(fetchRequests data.MultiTarget, ctx context.Context, lo lock.Unlock() *metricsLen += rows - metrics.SendQueryReadByTable(stat.Table, tf.From, tf.Until, d, int64(rows), stat.ReadBytes, stat.ChReadRows, stat.ChReadBytes, false) + metrics.SendQueryReadByTable(tf.From, tf.Until, d, int64(rows), fndResult.Stats(), false) }(tf, expr, targets, i) } }