|
|
|
|
@ -1,16 +1,18 @@ |
|
|
|
|
package main |
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
|
"cmp" |
|
|
|
|
"context" |
|
|
|
|
"errors" |
|
|
|
|
"fmt" |
|
|
|
|
"io" |
|
|
|
|
"os" |
|
|
|
|
"slices" |
|
|
|
|
"strings" |
|
|
|
|
"time" |
|
|
|
|
|
|
|
|
|
"github.com/alecthomas/kingpin/v2" |
|
|
|
|
"github.com/fatih/color" |
|
|
|
|
"github.com/prometheus/prometheus/model/labels" |
|
|
|
|
|
|
|
|
|
"github.com/grafana/loki/v3/pkg/dataobj" |
|
|
|
|
"github.com/grafana/loki/v3/pkg/dataobj/sections/streams" |
|
|
|
|
@ -18,7 +20,8 @@ import ( |
|
|
|
|
|
|
|
|
|
// listStreamsCommand lists the streams in the data object.
|
|
|
|
|
type listStreamsCommand struct { |
|
|
|
|
files *[]string |
|
|
|
|
files *[]string |
|
|
|
|
tenant *string |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (cmd *listStreamsCommand) run(c *kingpin.ParseContext) error { |
|
|
|
|
@ -46,11 +49,18 @@ func (cmd *listStreamsCommand) listStreamsInFile(name string) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (cmd *listStreamsCommand) listStreams(ctx context.Context, dataObj *dataobj.Object) { |
|
|
|
|
type key struct { |
|
|
|
|
tenant string |
|
|
|
|
id int64 |
|
|
|
|
} |
|
|
|
|
var ( |
|
|
|
|
result = make(map[int64]streams.Stream) |
|
|
|
|
result = make(map[key]streams.Stream) |
|
|
|
|
tmp = make([]streams.Stream, 512) |
|
|
|
|
) |
|
|
|
|
for _, sec := range dataObj.Sections() { |
|
|
|
|
if *cmd.tenant != "" && sec.Tenant != *cmd.tenant { |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
if streams.CheckSection(sec) { |
|
|
|
|
streamsSec, err := streams.Open(ctx, sec) |
|
|
|
|
if err != nil { |
|
|
|
|
@ -66,22 +76,20 @@ func (cmd *listStreamsCommand) listStreams(ctx context.Context, dataObj *dataobj |
|
|
|
|
break |
|
|
|
|
} |
|
|
|
|
for _, s := range tmp[:n] { |
|
|
|
|
result[s.ID] = s |
|
|
|
|
result[key{tenant: sec.Tenant, id: s.ID}] = s |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
sorted := make([]int64, 0, len(result)) |
|
|
|
|
sorted := make([]key, 0, len(result)) |
|
|
|
|
for id := range result { |
|
|
|
|
sorted = append(sorted, id) |
|
|
|
|
} |
|
|
|
|
slices.Sort(sorted) |
|
|
|
|
slices.SortFunc(sorted, func(a, b key) int { return cmp.Or(strings.Compare(a.tenant, b.tenant), int(a.id-b.id)) }) |
|
|
|
|
bold := color.New(color.Bold) |
|
|
|
|
for _, id := range sorted { |
|
|
|
|
bold.Printf("id: %d, labels:\n", id) |
|
|
|
|
result[id].Labels.Range(func(l labels.Label) { |
|
|
|
|
fmt.Printf("\t%s=%s\n", l.Name, l.Value) |
|
|
|
|
}) |
|
|
|
|
for _, k := range sorted { |
|
|
|
|
s := result[k] |
|
|
|
|
bold.Printf("tenant: %s, id: %d, from: %s, to: %s, labels: %s\n", k.tenant, k.id, s.MinTimestamp.Format(time.DateTime), s.MaxTimestamp.Format(time.DateTime), s.Labels) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -89,4 +97,5 @@ func addListStreamsCommand(app *kingpin.Application) { |
|
|
|
|
cmd := &listStreamsCommand{} |
|
|
|
|
dump := app.Command("list-streams", "Lists all streams in the data object.").Action(cmd.run) |
|
|
|
|
cmd.files = dump.Arg("file", "The file to list.").ExistingFiles() |
|
|
|
|
cmd.tenant = dump.Flag("tenant", "Filter the list to a specific tenant").String() |
|
|
|
|
} |
|
|
|
|
|