mirror of
https://github.com/tailscale/tailscale.git
synced 2025-04-16 03:31:39 +00:00
logtail: always send a json array
The code goes to some effort to send a single JSON object when there's only a single line and a JSON array when there are multiple lines. It makes the code more complex and more expensive; when we add a second line, we have to use a second buffer to duplicate the first one after adding a leading square brackets. The savings come to two bytes. Instead, always send an array. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
This commit is contained in:
parent
93284209bc
commit
278e7de9c9
@ -203,6 +203,7 @@ func (l *Logger) drainBlock() (shuttingDown bool) {
|
|||||||
// If no logs are available, drainPending blocks until logs are available.
|
// If no logs are available, drainPending blocks until logs are available.
|
||||||
func (l *Logger) drainPending() (res []byte) {
|
func (l *Logger) drainPending() (res []byte) {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
|
buf.WriteByte('[')
|
||||||
entries := 0
|
entries := 0
|
||||||
|
|
||||||
var batchDone bool
|
var batchDone bool
|
||||||
@ -242,28 +243,15 @@ func (l *Logger) drainPending() (res []byte) {
|
|||||||
b = l.encodeText(b, true)
|
b = l.encodeText(b, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
if entries > 0 {
|
||||||
case entries == 0:
|
|
||||||
buf.Write(b)
|
|
||||||
case entries == 1:
|
|
||||||
buf2 := new(bytes.Buffer)
|
|
||||||
buf2.WriteByte('[')
|
|
||||||
buf2.Write(buf.Bytes())
|
|
||||||
buf2.WriteByte(',')
|
|
||||||
buf2.Write(b)
|
|
||||||
buf.Reset()
|
|
||||||
buf.Write(buf2.Bytes())
|
|
||||||
default:
|
|
||||||
buf.WriteByte(',')
|
buf.WriteByte(',')
|
||||||
buf.Write(b)
|
|
||||||
}
|
}
|
||||||
|
buf.Write(b)
|
||||||
entries++
|
entries++
|
||||||
}
|
}
|
||||||
|
|
||||||
if entries > 1 {
|
buf.WriteByte(']')
|
||||||
buf.WriteByte(']')
|
if buf.Len() <= len("[]") {
|
||||||
}
|
|
||||||
if buf.Len() == 0 {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return buf.Bytes()
|
return buf.Bytes()
|
||||||
|
@ -117,12 +117,7 @@ func TestEncodeAndUploadMessages(t *testing.T) {
|
|||||||
io.WriteString(l, tt.log)
|
io.WriteString(l, tt.log)
|
||||||
body := <-ts.uploaded
|
body := <-ts.uploaded
|
||||||
|
|
||||||
data := make(map[string]interface{})
|
data := unmarshalOne(t, body)
|
||||||
err := json.Unmarshal(body, &data)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
got := data["text"]
|
got := data["text"]
|
||||||
if got != tt.want {
|
if got != tt.want {
|
||||||
t.Errorf("%s: got %q; want %q", tt.name, got.(string), tt.want)
|
t.Errorf("%s: got %q; want %q", tt.name, got.(string), tt.want)
|
||||||
@ -154,11 +149,7 @@ func TestEncodeSpecialCases(t *testing.T) {
|
|||||||
// JSON log message already contains a logtail field.
|
// JSON log message already contains a logtail field.
|
||||||
io.WriteString(l, `{"logtail": "LOGTAIL", "text": "text"}`)
|
io.WriteString(l, `{"logtail": "LOGTAIL", "text": "text"}`)
|
||||||
body := <-ts.uploaded
|
body := <-ts.uploaded
|
||||||
data := make(map[string]interface{})
|
data := unmarshalOne(t, body)
|
||||||
err := json.Unmarshal(body, &data)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
errorHasLogtail, ok := data["error_has_logtail"]
|
errorHasLogtail, ok := data["error_has_logtail"]
|
||||||
if ok {
|
if ok {
|
||||||
if errorHasLogtail != "LOGTAIL" {
|
if errorHasLogtail != "LOGTAIL" {
|
||||||
@ -186,11 +177,7 @@ func TestEncodeSpecialCases(t *testing.T) {
|
|||||||
l.skipClientTime = true
|
l.skipClientTime = true
|
||||||
io.WriteString(l, "text")
|
io.WriteString(l, "text")
|
||||||
body = <-ts.uploaded
|
body = <-ts.uploaded
|
||||||
data = make(map[string]interface{})
|
data = unmarshalOne(t, body)
|
||||||
err = json.Unmarshal(body, &data)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
_, ok = data["logtail"]
|
_, ok = data["logtail"]
|
||||||
if ok {
|
if ok {
|
||||||
t.Errorf("skipClientTime: unexpected logtail map present: %v", data)
|
t.Errorf("skipClientTime: unexpected logtail map present: %v", data)
|
||||||
@ -204,11 +191,7 @@ func TestEncodeSpecialCases(t *testing.T) {
|
|||||||
longStr := strings.Repeat("0", 512)
|
longStr := strings.Repeat("0", 512)
|
||||||
io.WriteString(l, longStr)
|
io.WriteString(l, longStr)
|
||||||
body = <-ts.uploaded
|
body = <-ts.uploaded
|
||||||
data = make(map[string]interface{})
|
data = unmarshalOne(t, body)
|
||||||
err = json.Unmarshal(body, &data)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
text, ok := data["text"]
|
text, ok := data["text"]
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("lowMem: no text %v", data)
|
t.Errorf("lowMem: no text %v", data)
|
||||||
@ -219,7 +202,7 @@ func TestEncodeSpecialCases(t *testing.T) {
|
|||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
err = l.Shutdown(context.Background())
|
err := l.Shutdown(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@ -326,3 +309,16 @@ func TestPublicIDUnmarshalText(t *testing.T) {
|
|||||||
t.Errorf("allocs = %v; want 0", n)
|
t.Errorf("allocs = %v; want 0", n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func unmarshalOne(t *testing.T, body []byte) map[string]interface{} {
|
||||||
|
t.Helper()
|
||||||
|
var entries []map[string]interface{}
|
||||||
|
err := json.Unmarshal(body, &entries)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if len(entries) != 1 {
|
||||||
|
t.Fatalf("expected one entry, got %d", len(entries))
|
||||||
|
}
|
||||||
|
return entries[0]
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user