mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00:00
app/vlogscli: preserve the original order of fields in the displayed responses
This commit is contained in:
parent
4d9ad9654f
commit
596e4de248
2 changed files with 91 additions and 7 deletions
|
@ -46,15 +46,11 @@ func (jp *jsonPrettifier) closePipesWithError(err error) {
|
|||
|
||||
func (jp *jsonPrettifier) prettifyJSONLines() error {
|
||||
for jp.d.More() {
|
||||
var v any
|
||||
if err := jp.d.Decode(&v); err != nil {
|
||||
kvs, err := readNextJSONObject(jp.d)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
line, err := json.MarshalIndent(v, "", " ")
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("BUG: cannot marshal %v to JSON: %w", v, err))
|
||||
}
|
||||
if _, err := fmt.Fprintf(jp.pw, "%s\n", line); err != nil {
|
||||
if err := writeJSONObject(jp.pw, kvs); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -71,3 +67,89 @@ func (jp *jsonPrettifier) Close() error {
|
|||
func (jp *jsonPrettifier) Read(p []byte) (int, error) {
|
||||
return jp.pr.Read(p)
|
||||
}
|
||||
|
||||
func readNextJSONObject(d *json.Decoder) ([]kv, error) {
|
||||
t, err := d.Token()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot read '{': %w", err)
|
||||
}
|
||||
delim, ok := t.(json.Delim)
|
||||
if !ok || delim.String() != "{" {
|
||||
return nil, fmt.Errorf("unexpected token read; got %q; want '{'", delim)
|
||||
}
|
||||
|
||||
var kvs []kv
|
||||
for {
|
||||
// Read object key
|
||||
t, err := d.Token()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot read JSON object key or closing brace: %w", err)
|
||||
}
|
||||
delim, ok := t.(json.Delim)
|
||||
if ok {
|
||||
if delim.String() == "}" {
|
||||
return kvs, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected delimiter read; got %q; want '}'", delim)
|
||||
}
|
||||
key, ok := t.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected token read for object key: %v; want string or '}'", t)
|
||||
}
|
||||
|
||||
// read object value
|
||||
t, err = d.Token()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot read JSON object value: %w", err)
|
||||
}
|
||||
value, ok := t.(string)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected token read for oject value: %v; want string", t)
|
||||
}
|
||||
|
||||
kvs = append(kvs, kv{
|
||||
key: key,
|
||||
value: value,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func writeJSONObject(w io.Writer, kvs []kv) error {
|
||||
if len(kvs) == 0 {
|
||||
fmt.Fprintf(w, "{}\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "{\n")
|
||||
if err := writeJSONObjectKeyValue(w, kvs[0]); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, kv := range kvs[1:] {
|
||||
fmt.Fprintf(w, ",\n")
|
||||
if err := writeJSONObjectKeyValue(w, kv); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(w, "\n}\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
func writeJSONObjectKeyValue(w io.Writer, kv kv) error {
|
||||
key := getJSONString(kv.key)
|
||||
value := getJSONString(kv.value)
|
||||
_, err := fmt.Fprintf(w, " %s: %s", key, value)
|
||||
return err
|
||||
}
|
||||
|
||||
func getJSONString(s string) string {
|
||||
data, err := json.Marshal(s)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("unexpected error when marshaling string to JSON: %w", err))
|
||||
}
|
||||
return string(data)
|
||||
}
|
||||
|
||||
type kv struct {
|
||||
key string
|
||||
value string
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ according to [these docs](https://docs.victoriametrics.com/victorialogs/quicksta
|
|||
* FEATURE: [vlogscli](https://docs.victoriametrics.com/victorialogs/querying/vlogscli/): preserve `less` output after the exit from scrolling mode. This should help re-using previous query results in subsequent queries.
|
||||
* FEATURE: add [`len` pipe](https://docs.victoriametrics.com/victorialogs/logsql/#len-pipe) for calculating the length for the given [log field](https://docs.victoriametrics.com/victorialogs/keyconcepts/#data-model) value in bytes.
|
||||
|
||||
* BUGFIX: [vlogscli](https://docs.victoriametrics.com/victorialogs/querying/vlogscli/): preserve the original order of fields in the displayed query responses. Previously fields were sorted by name.
|
||||
|
||||
## [v0.33.0](https://github.com/VictoriaMetrics/VictoriaMetrics/releases/tag/v0.33.0-victorialogs)
|
||||
|
||||
Released at 2024-10-01
|
||||
|
|
Loading…
Reference in a new issue