mirror of https://github.com/grafana/loki
Updated stream json objects to be more parse friendly (#1010)
* Added custom marshaller for Entry Signed-off-by: Joe Elliott <number101010@gmail.com> * Added comment and test Signed-off-by: Joe Elliott <number101010@gmail.com> * Fixed spelling error * Added a custom marshaller to map entries => values * Added support for labels Signed-off-by: Joe Elliott <number101010@gmail.com> * Changed test to only check to the microsecond level Signed-off-by: Joe Elliott <number101010@gmail.com> * Extended Entry tests Signed-off-by: Joe Elliott <number101010@gmail.com> * Swapped to nanosecs encoded as strings * Cleaned up docs with new loki paths. Removed references to deprecated endpoints * Added support for /loki/api/v1/push Signed-off-by: Joe Elliott <number101010@gmail.com> * Removed obsolete comment Signed-off-by: Joe Elliott <number101010@gmail.com> * Updated docs for new push endpoint Signed-off-by: Joe Elliott <number101010@gmail.com> * Ran gofmt on test file Signed-off-by: Joe Elliott <number101010@gmail.com> * Set GOGC=20 on test to avoid out of memory issue in circle ci Signed-off-by: Joe Elliott <number101010@gmail.com>pull/1016/head
parent
47637852fb
commit
6185d54320
@ -0,0 +1,35 @@ |
|||||||
|
package logproto |
||||||
|
|
||||||
|
import ( |
||||||
|
"encoding/json" |
||||||
|
fmt "fmt" |
||||||
|
|
||||||
|
"github.com/prometheus/prometheus/promql" |
||||||
|
) |
||||||
|
|
||||||
|
// MarshalJSON converts an Entry object to be prom compatible for http queries
|
||||||
|
func (e *Entry) MarshalJSON() ([]byte, error) { |
||||||
|
l, err := json.Marshal(e.Line) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
return []byte(fmt.Sprintf("[\"%d\",%s]", e.Timestamp.UnixNano(), l)), nil |
||||||
|
} |
||||||
|
|
||||||
|
// MarshalJSON converts a Stream object to be prom compatible for http queries
|
||||||
|
func (s *Stream) MarshalJSON() ([]byte, error) { |
||||||
|
parsedLabels, err := promql.ParseMetric(s.Labels) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
l, err := json.Marshal(parsedLabels) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
e, err := json.Marshal(s.Entries) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
|
||||||
|
return []byte(fmt.Sprintf("{\"stream\":%s,\"values\":%s}", l, e)), nil |
||||||
|
} |
||||||
@ -0,0 +1,85 @@ |
|||||||
|
package logproto |
||||||
|
|
||||||
|
import ( |
||||||
|
"encoding/json" |
||||||
|
fmt "fmt" |
||||||
|
reflect "reflect" |
||||||
|
"testing" |
||||||
|
time "time" |
||||||
|
|
||||||
|
"github.com/prometheus/prometheus/promql" |
||||||
|
"github.com/stretchr/testify/require" |
||||||
|
) |
||||||
|
|
||||||
|
var ( |
||||||
|
entries = []Entry{ |
||||||
|
{ |
||||||
|
Timestamp: time.Now(), |
||||||
|
Line: "testline", |
||||||
|
}, |
||||||
|
{ |
||||||
|
Timestamp: time.Date(2019, 9, 10, 1, 1, 1, 1, time.UTC), |
||||||
|
Line: "{}\"'!@$%&*^(_)(", |
||||||
|
}, |
||||||
|
} |
||||||
|
streams = []Stream{ |
||||||
|
{ |
||||||
|
Labels: "{}", |
||||||
|
Entries: []Entry{}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
Labels: "{name=\"value\",name1=\"value1\"}", |
||||||
|
Entries: []Entry{}, |
||||||
|
}, |
||||||
|
} |
||||||
|
) |
||||||
|
|
||||||
|
func Test_EntryMarshalJSON(t *testing.T) { |
||||||
|
var array []interface{} |
||||||
|
|
||||||
|
for _, entry := range entries { |
||||||
|
|
||||||
|
bytes, err := entry.MarshalJSON() |
||||||
|
require.NoError(t, err) |
||||||
|
|
||||||
|
err = json.Unmarshal(bytes, &array) |
||||||
|
require.NoError(t, err) |
||||||
|
|
||||||
|
timestamp, ok := array[0].(string) |
||||||
|
require.True(t, ok) |
||||||
|
|
||||||
|
line, ok := array[1].(string) |
||||||
|
require.True(t, ok) |
||||||
|
|
||||||
|
require.Equal(t, fmt.Sprint(entry.Timestamp.UnixNano()), timestamp, "Timestamps not equal ", array[0]) |
||||||
|
require.Equal(t, entry.Line, line, "Lines are not equal ", array[1]) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func Test_StreamMarshalJSON(t *testing.T) { |
||||||
|
actual := struct { |
||||||
|
Labels map[string]string `json:"stream"` |
||||||
|
Entries []Entry `json:"values"` |
||||||
|
}{} |
||||||
|
|
||||||
|
for _, expected := range streams { |
||||||
|
|
||||||
|
bytes, err := expected.MarshalJSON() |
||||||
|
require.NoError(t, err) |
||||||
|
|
||||||
|
err = json.Unmarshal(bytes, &actual) |
||||||
|
require.NoError(t, err) |
||||||
|
|
||||||
|
// check labels
|
||||||
|
expectedLabels, err := promql.ParseMetric(expected.Labels) |
||||||
|
require.NoError(t, err) |
||||||
|
|
||||||
|
require.Equal(t, len(actual.Labels), len(expectedLabels)) |
||||||
|
for _, l := range expectedLabels { |
||||||
|
require.Equal(t, l.Value, actual.Labels[l.Name]) |
||||||
|
} |
||||||
|
|
||||||
|
// check entries
|
||||||
|
require.True(t, reflect.DeepEqual(actual.Entries, expected.Entries)) |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue