Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Logcli remote storage. #1814

Merged
merged 4 commits into from
Mar 30, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/logcli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ func newQuery(instant bool, cmd *kingpin.CmdClause) *query.Query {
cmd.Flag("exclude-label", "Exclude labels given the provided key during output.").StringsVar(&query.IgnoreLabelsKey)
cmd.Flag("include-label", "Include labels given the provided key during output.").StringsVar(&query.ShowLabelsKey)
cmd.Flag("labels-length", "Set a fixed padding to labels").Default("0").IntVar(&query.FixedLabelsLen)
cmd.Flag("local-config", "Execute the current query using a configured storage from a given Loki configuration file.").Default("").StringVar(&query.LocalConfig)
Copy link
Contributor

@sandeepsukhani sandeepsukhani Mar 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

local-config sounds a little confusing. Should we call it storage-config or store-config instead?
What do you think?


return query
}
Expand Down
2 changes: 2 additions & 0 deletions docs/getting-started/logcli.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ Flags:
--tls-skip-verify Server certificate TLS skip verify.
--cert="" Path to the client certificate.
--key="" Path to the client certificate key.
--org-id=ORG-ID org ID header to be substituted for auth

Commands:
help [<command>...]
Expand Down Expand Up @@ -115,6 +116,7 @@ Flags:
--from=FROM Start looking for logs at this absolute time (inclusive)
--to=TO Stop looking for logs at this absolute time (exclusive)
--forward Scan forwards through logs.
--local-config="" Execute the current query using a configured storage from a given Loki configuration file.
-t, --tail Tail the logs
--delay-for=0 Delay in tailing by number of seconds to accumulate logs for re-ordering
--no-labels Do not print any labels
Expand Down
96 changes: 87 additions & 9 deletions pkg/logcli/query/query.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package query

import (
"context"
"fmt"
"log"
"os"
Expand All @@ -12,13 +13,20 @@ import (
"github.com/fatih/color"
json "github.com/json-iterator/go"
"github.com/prometheus/prometheus/promql"
"github.com/weaveworks/common/user"

"github.com/grafana/loki/pkg/cfg"
"github.com/grafana/loki/pkg/iter"
"github.com/grafana/loki/pkg/logcli/client"
"github.com/grafana/loki/pkg/logcli/output"
"github.com/grafana/loki/pkg/loghttp"
"github.com/grafana/loki/pkg/logproto"
"github.com/grafana/loki/pkg/logql"
"github.com/grafana/loki/pkg/logql/marshal"
"github.com/grafana/loki/pkg/logql/stats"
"github.com/grafana/loki/pkg/loki"
"github.com/grafana/loki/pkg/storage"
"github.com/grafana/loki/pkg/util/validation"
)

type streamEntryPair struct {
Expand All @@ -39,10 +47,20 @@ type Query struct {
IgnoreLabelsKey []string
ShowLabelsKey []string
FixedLabelsLen int

LocalConfig string
}

// DoQuery executes the query and prints out the results
func (q *Query) DoQuery(c *client.Client, out output.LogOutput, statistics bool) {

if q.LocalConfig != "" {
if err := q.DoLocalQuery(out, statistics, c.OrgID); err != nil {
log.Fatalf("Query failed: %+v", err)
}
return
}

d := q.resultsDirection()

var resp *loghttp.QueryResponse
Expand All @@ -62,21 +80,81 @@ func (q *Query) DoQuery(c *client.Client, out output.LogOutput, statistics bool)
q.printStats(resp.Data.Statistics)
}

switch resp.Data.ResultType {
q.printResult(resp.Data.Result, out)

}

func (q *Query) printResult(value loghttp.ResultValue, out output.LogOutput) {
switch value.Type() {
case logql.ValueTypeStreams:
streams := resp.Data.Result.(loghttp.Streams)
q.printStream(streams, out)
q.printStream(value.(loghttp.Streams), out)
case promql.ValueTypeScalar:
q.printScalar(resp.Data.Result.(loghttp.Scalar))
q.printScalar(value.(loghttp.Scalar))
case promql.ValueTypeMatrix:
matrix := resp.Data.Result.(loghttp.Matrix)
q.printMatrix(matrix)
q.printMatrix(value.(loghttp.Matrix))
case promql.ValueTypeVector:
vector := resp.Data.Result.(loghttp.Vector)
q.printVector(vector)
q.printVector(value.(loghttp.Vector))
default:
log.Fatalf("Unable to print unsupported type: %v", resp.Data.ResultType)
log.Fatalf("Unable to print unsupported type: %v", value.Type())
}
}

// DoLocalQuery executes the query against the local store using a Loki configuration file.
func (q *Query) DoLocalQuery(out output.LogOutput, statistics bool, orgID string) error {

var conf loki.Config
if err := cfg.Defaults()(&conf); err != nil {
return err
}
if err := cfg.YAML(&q.LocalConfig)(&conf); err != nil {
return err
}

querier, err := localStore(conf)
if err != nil {
return err
}

eng := logql.NewEngine(conf.Querier.Engine, querier)
var query logql.Query
if q.isInstant() {
query = eng.NewInstantQuery(q.QueryString, q.Start, q.resultsDirection(), uint32(q.Limit))
} else {
query = eng.NewRangeQuery(q.QueryString, q.Start, q.End, q.Step, q.resultsDirection(), uint32(q.Limit))
}

// execute the query
ctx := user.InjectOrgID(context.Background(), orgID)
result, err := query.Exec(ctx)
if err != nil {
return err
}

if statistics {
q.printStats(result.Statistics)
}

value, err := marshal.NewResultValue(result.Data)
if err != nil {
return err
}

q.printResult(value, out)
return nil
}

func localStore(conf loki.Config) (logql.Querier, error) {
limits, err := validation.NewOverrides(conf.LimitsConfig, nil)
if err != nil {
return nil, err
}
s, err := storage.NewStore(conf.StorageConfig, conf.ChunkStoreConfig, conf.SchemaConfig, limits)
if err != nil {
return nil, err
}
return logql.QuerierFunc(func(ctx context.Context, params logql.SelectParams) (iter.EntryIterator, error) {
return s.LazyQuery(ctx, params)
}), nil
}

// SetInstant makes the Query an instant type
Expand Down