Like Prometheus, but for logs.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
loki/pkg/dataobj/sections/stats/reader.go

89 lines
2.3 KiB

package stats
import (
"context"
"fmt"
"io"
)
// Reader reads columnar data from a stats [Section].
//
// Use [RowReader] for higher-level access to typed [Stat] rows.
type Reader struct {
sec *Section
readers map[string]ColumnReader
rowCount int
}
// NewReader creates a new Reader that reads from the provided [Section].
func NewReader(sec *Section) (*Reader, error) {
if sec == nil {
return nil, fmt.Errorf("section must not be nil")
}
return &Reader{
sec: sec,
readers: make(map[string]ColumnReader),
rowCount: sec.RowCount,
}, nil
}
// RowCount returns the total number of rows in the section.
func (r *Reader) RowCount() int { return r.rowCount }
// getOrOpenColumn lazily opens and caches a ColumnReader for the named column.
func (r *Reader) getOrOpenColumn(name string) (ColumnReader, error) {
if cr, ok := r.readers[name]; ok {
return cr, nil
}
cr, err := r.sec.OpenColumn(name)
if err != nil {
return nil, err
}
r.readers[name] = cr
return cr, nil
}
// readInt64Column reads up to count values from a named int64 column.
// Returns the values slice and the number of values read.
func (r *Reader) readInt64Column(ctx context.Context, name string, count int) ([]int64, error) {
cr, err := r.getOrOpenColumn(name)
if err != nil {
return nil, fmt.Errorf("column %q not found: %w", name, err)
}
arr, err := cr.Read(ctx, count)
if err != nil && err != io.EOF {
return nil, fmt.Errorf("reading column %q: %w", name, err)
}
if arr == nil {
return nil, io.EOF
}
return extractInt64Values(arr)
}
// readStringColumn reads up to count values from a named UTF8 column.
// Returns the string slice and the number of values read.
func (r *Reader) readStringColumn(ctx context.Context, name string, count int) ([]string, error) {
cr, err := r.getOrOpenColumn(name)
if err != nil {
return nil, fmt.Errorf("column %q not found: %w", name, err)
}
arr, err := cr.Read(ctx, count)
if err != nil && err != io.EOF {
return nil, fmt.Errorf("reading column %q: %w", name, err)
}
if arr == nil {
return nil, io.EOF
}
return extractStringValues(arr)
}
// Close closes the reader and releases any resources.
func (r *Reader) Close() error {
var firstErr error
for _, cr := range r.readers {
if err := cr.Close(); err != nil && firstErr == nil {
firstErr = err
}
}
return firstErr
}