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/engine/internal/executor/parse_logfmt.go

55 lines
1.6 KiB

package executor
import (
"github.com/apache/arrow-go/v18/arrow"
"github.com/apache/arrow-go/v18/arrow/array"
"github.com/apache/arrow-go/v18/arrow/memory"
"github.com/grafana/loki/v3/pkg/engine/internal/types"
"github.com/grafana/loki/v3/pkg/logql/log/logfmt"
)
func buildLogfmtColumns(input *array.String, requestedKeys []string, allocator memory.Allocator) ([]string, []arrow.Array) {
return buildColumns(input, requestedKeys, allocator, tokenizeLogfmt, types.LogfmtParserErrorType)
}
// tokenizeLogfmt parses logfmt input using the standard decoder
// Returns a map of key-value pairs with last-wins semantics for duplicates
// If requestedKeys is provided, the result will be filtered to only include those keys
func tokenizeLogfmt(input string, requestedKeys []string) (map[string]string, error) {
result := make(map[string]string)
var requestedKeyLookup map[string]struct{}
if len(requestedKeys) > 0 {
requestedKeyLookup = make(map[string]struct{}, len(requestedKeys))
for _, key := range requestedKeys {
requestedKeyLookup[key] = struct{}{}
}
}
decoder := logfmt.NewDecoder(unsafeBytes(input))
for !decoder.EOL() && decoder.ScanKeyval() {
key := unsafeString(decoder.Key())
if requestedKeyLookup != nil {
if _, wantKey := requestedKeyLookup[key]; !wantKey {
continue
}
}
val := decoder.Value()
if len(val) == 0 {
//TODO: retain empty values if --keep-empty is set
continue
}
// Last-wins semantics for duplicates
result[key] = unsafeString(decoder.Value())
}
// Check for parsing errors
if err := decoder.Err(); err != nil {
return result, err
}
return result, nil
}