Repository: rs/zerolog
Pull request #190 (2019-10-13 03:02:29)

[journald] Writter should return written size when message was sent without error
The journald writer currently always returns zero. This causes an ErrShortWrite if used together with MultiWriter: https://github.com/golang/go/blob/master/src/io/multi.go#L64
- Fixes ErrShortWrite if used with io.MultiWriter

rs: Tests are failing. Can you please fix them so I can merge?
IljaN:  Not sure, need to debug, they pass locally.
rs: Try with `go test -tags binary_log`

Patch:
diff --git a/README.md b/README.md
index 718681a..bd28c29 100644
--- a/README.md
+++ b/README.md
@@ -31,7 +31,7 @@ Find out [who uses zerolog](https://github.com/rs/zerolog/wiki/Who-uses-zerolog)
 
 ## Installation
 
-```go
+```bash
 go get -u github.com/rs/zerolog/log
 ```
 
diff --git a/console.go b/console.go
index 75f6e45..54f7994 100644
--- a/console.go
+++ b/console.go
@@ -300,9 +300,13 @@ func consoleDefaultFormatTimestamp(timeFormat string, noColor bool) Formatter {
 				t = tt.String()
 			} else {
 				var sec, nsec int64 = i, 0
-				if TimeFieldFormat == TimeFormatUnixMs {
+				switch TimeFieldFormat {
+				case TimeFormatUnixMs:
 					nsec = int64(time.Duration(i) * time.Millisecond)
 					sec = 0
+				case TimeFormatUnixMicro:
+					nsec = int64(time.Duration(i) * time.Microsecond)
+					sec = 0
 				}
 				ts := time.Unix(sec, nsec).UTC()
 				t = ts.Format(timeFormat)
diff --git a/journald/journald.go b/journald/journald.go
index 058a68a..630ed7e 100644
--- a/journald/journald.go
+++ b/journald/journald.go
@@ -73,7 +73,9 @@ func (w journalWriter) Write(p []byte) (n int, err error) {
 		err = fmt.Errorf("cannot connect to journalD")
 		return
 	}
+
 	var event map[string]interface{}
+	origPLen := len(p)
 	p = cbor.DecodeIfBinaryToBytes(p)
 	d := json.NewDecoder(bytes.NewReader(p))
 	d.UseNumber()
@@ -114,5 +116,10 @@ func (w journalWriter) Write(p []byte) (n int, err error) {
 	}
 	args["JSON"] = string(p)
 	err = journal.Send(msg, jPrio, args)
+
+	if err == nil {
+		n = origPLen
+	}
+
 	return
 }
diff --git a/log.go b/log.go
index 0af296c..b1e7ac1 100644
--- a/log.go
+++ b/log.go
@@ -179,7 +179,7 @@ func ParseLevel(levelStr string) (Level, error) {
 
 // A Logger represents an active logging object that generates lines
 // of JSON output to an io.Writer. Each logging operation makes a single
-// call to the Writer's Write method. There is no guaranty on access
+// call to the Writer's Write method. There is no guarantee on access
 // serialization to the Writer. If your Writer is not thread safe,
 // you may consider a sync wrapper.
 type Logger struct {
@@ -195,7 +195,7 @@ type Logger struct {
 // one.
 //
 // Each logging operation makes a single call to the Writer's Write method. There is no
-// guaranty on access serialization to the Writer. If your Writer is not thread safe,
+// guarantee on access serialization to the Writer. If your Writer is not thread safe,
 // you may consider using sync wrapper.
 func New(w io.Writer) Logger {
 	if w == nil {


Test patch:
diff --git a/console_test.go b/console_test.go
index 4567e9e..751cdcd 100644
--- a/console_test.go
+++ b/console_test.go
@@ -165,6 +165,28 @@ func TestConsoleWriter(t *testing.T) {
 		}
 	})
 
+	t.Run("Unix timestamp us input format", func(t *testing.T) {
+		of := zerolog.TimeFieldFormat
+		defer func() {
+			zerolog.TimeFieldFormat = of
+		}()
+		zerolog.TimeFieldFormat = zerolog.TimeFormatUnixMicro
+
+		buf := &bytes.Buffer{}
+		w := zerolog.ConsoleWriter{Out: buf, TimeFormat: time.StampMicro, NoColor: true}
+
+		_, err := w.Write([]byte(`{"time": 1234567891, "level": "debug", "message": "Foobar", "foo": "bar"}`))
+		if err != nil {
+			t.Errorf("Unexpected error when writing output: %s", err)
+		}
+
+		expectedOutput := "Jan  1 00:20:34.567891 DBG Foobar foo=bar\n"
+		actualOutput := buf.String()
+		if actualOutput != expectedOutput {
+			t.Errorf("Unexpected output %q, want: %q", actualOutput, expectedOutput)
+		}
+	})
+
 	t.Run("No message field", func(t *testing.T) {
 		buf := &bytes.Buffer{}
 		w := zerolog.ConsoleWriter{Out: buf, NoColor: true}
diff --git a/journald/journald_test.go b/journald/journald_test.go
index 7ea40b5..d3624c1 100644
--- a/journald/journald_test.go
+++ b/journald/journald_test.go
@@ -2,7 +2,12 @@
 
 package journald_test
 
-import "github.com/rs/zerolog"
+import (
+	"bytes"
+	"github.com/rs/zerolog"
+	"io"
+	"testing"
+)
 import "github.com/rs/zerolog/journald"
 
 func ExampleNewJournalDWriter() {
@@ -42,3 +47,39 @@ Thu 2018-04-26 22:30:20.768136 PDT [s=3284d695bde946e4b5017c77a399237f;i=329f0;b
     _PID=27103
     _SOURCE_REALTIME_TIMESTAMP=1524807020768136
 */
+
+func TestWriteReturnsNoOfWrittenBytes(t *testing.T) {
+	input := []byte(`{"level":"info","time":1570912626,"message":"Starting..."}`)
+	wr := journald.NewJournalDWriter()
+	want := len(input)
+	got, err := wr.Write(input)
+
+	if err != nil {
+		t.Errorf("Unexpected error %v", err)
+	}
+
+	if want != got {
+		t.Errorf("Expected %d bytes to be written got %d", want, got)
+	}
+}
+
+func TestMultiWrite(t *testing.T) {
+	var (
+		w1 = new(bytes.Buffer)
+		w2 = new(bytes.Buffer)
+		w3 = journald.NewJournalDWriter()
+	)
+
+	zerolog.ErrorHandler = func(err error) {
+		if err == io.ErrShortWrite {
+			t.Errorf("Unexpected ShortWriteError")
+			t.FailNow()
+		}
+	}
+
+	log := zerolog.New(io.MultiWriter(w1, w2, w3)).With().Logger()
+
+	for i := 0; i < 10; i++ {
+		log.Info().Msg("Tick!")
+	}
+}