func TestMultiLogger_Log(t *testing.T) { b1 := bytes.NewBuffer(nil) b2 := bytes.NewBuffer(nil) l1 := log.NewJSONLogger(b1) l2 := log.NewJSONLogger(b2) l := sklog.NewMultiLogger(l1, l2) sklog.Debug(l, "debug message") sklog.Info(l, "info message") sklog.Error(l, errors.New("sklog_test: example error message")) assert.Equal(t, b1.String(), b2.String()) b1.Reset() b2.Reset() l1 = &faultyLogger{} l2 = log.NewJSONLogger(b2) l = sklog.NewMultiLogger(l1, l2) sklog.Debug(l, "debug message") sklog.Info(l, "info message") sklog.Error(l, errors.New("sklog_test: example error message")) assert.Contains(t, b2.String(), "debug message") assert.Contains(t, b2.String(), "msg") assert.Contains(t, b2.String(), "info message") assert.Contains(t, b2.String(), "info") assert.Contains(t, b2.String(), "debug") assert.Contains(t, b2.String(), "sklog_test: example error message") }
func TestGRPCLogger_Print(t *testing.T) { b := bytes.NewBuffer(nil) l := log.NewJSONLogger(b) g := sklog.NewGRPCLogger(l) success := map[string][]interface{}{ "message": { "message", }, "message1, message2": { "message1", "message2", }, "1, [109 101 115 115 97 103 101 50]": { 1, []byte("message2"), }, "true, [message1 message2]": { true, []string{"message1", "message2"}, }, } for expected, args := range success { g.Print(args...) assert.Contains(t, b.String(), sklog.LevelDebug) assert.Contains(t, b.String(), sklog.KeyLevel) assert.Contains(t, b.String(), expected) b.Reset() } }
func TestGRPCLogger_Printf(t *testing.T) { b := bytes.NewBuffer(nil) l := log.NewJSONLogger(b) g := sklog.NewGRPCLogger(l) success := []struct { expected string format string args []interface{} }{ { expected: "message", format: "message", }, { expected: "message1, message2", format: "%s, %s", args: []interface{}{ "message1", "message2", }, }, } for _, data := range success { g.Printf(data.format, data.args...) assert.Contains(t, b.String(), sklog.LevelDebug) assert.Contains(t, b.String(), sklog.KeyLevel) assert.Contains(t, b.String(), data.expected) b.Reset() } }
func TestJSONLoggerStringValue(t *testing.T) { t.Parallel() tests := []struct { v interface{} expected string }{ { v: aller{}, expected: `{"v":"json"}`, }, { v: textstringer{}, expected: `{"v":"text"}`, }, { v: stringer("string"), expected: `{"v":"string"}`, }, } for _, test := range tests { buf := &bytes.Buffer{} logger := log.NewJSONLogger(buf) if err := logger.Log("v", test.v); err != nil { t.Fatal(err) } if want, have := test.expected+"\n", buf.String(); want != have { t.Errorf("\nwant %#v\nhave %#v", want, have) } } }
func testLevel(t *testing.T, scenarios ...func(*testing.T, *bytes.Buffer, log.Logger)) { b := bytes.NewBuffer(nil) l := log.NewJSONLogger(b) for _, scenario := range scenarios { scenario(t, b, l) b.Reset() } }
func TestJSONLogger(t *testing.T) { buf := &bytes.Buffer{} logger := log.NewJSONLogger(buf) if err := logger.Log("err", errors.New("err"), "m", map[string]int{"0": 0}, "a", []int{1, 2, 3}); err != nil { t.Fatal(err) } if want, have := `{"a":[1,2,3],"err":"err","m":{"0":0}}`+"\n", buf.String(); want != have { t.Errorf("want %#v, have %#v", want, have) } }
func TestJSONLoggerMissingValue(t *testing.T) { t.Parallel() buf := &bytes.Buffer{} logger := log.NewJSONLogger(buf) if err := logger.Log("k"); err != nil { t.Fatal(err) } if want, have := `{"k":"(MISSING)"}`+"\n", buf.String(); want != have { t.Errorf("\nwant %#v\nhave %#v", want, have) } }
func TestJSONLoggerNilStringerKey(t *testing.T) { t.Parallel() buf := &bytes.Buffer{} logger := log.NewJSONLogger(buf) if err := logger.Log((*stringer)(nil), "v"); err != nil { t.Fatal(err) } if want, have := `{"NULL":"v"}`+"\n", buf.String(); want != have { t.Errorf("\nwant %#v\nhave %#v", want, have) } }
func TestJSONLoggerNilErrorValue(t *testing.T) { t.Parallel() buf := &bytes.Buffer{} logger := log.NewJSONLogger(buf) if err := logger.Log("err", (*stringError)(nil)); err != nil { t.Fatal(err) } if want, have := `{"err":null}`+"\n", buf.String(); want != have { t.Errorf("\nwant %#v\nhave %#v", want, have) } }
func TestModifiedLevels(t *testing.T) { buf := bytes.Buffer{} logger := levels.New( log.NewJSONLogger(&buf), levels.Key("l"), levels.DebugValue("dbg"), ) logger.With("easter_island", "176°").Debug("msg", "moai") if want, have := `{"easter_island":"176°","l":"dbg","msg":"moai"}`+"\n", buf.String(); want != have { t.Errorf("want %#v, have %#v", want, have) } }
func TestJSONLoggerCaller(t *testing.T) { t.Parallel() buf := &bytes.Buffer{} logger := log.NewJSONLogger(buf) logger = log.NewContext(logger).With("caller", log.DefaultCaller) if err := logger.Log(); err != nil { t.Fatal(err) } if want, have := `{"caller":"json_logger_test.go:18"}`+"\n", buf.String(); want != have { t.Errorf("\nwant %#v\nhave %#v", want, have) } }
func TestContextWithPrefix(t *testing.T) { buf := &bytes.Buffer{} kvs := []interface{}{"a", 123} logger := log.NewJSONLogger(buf) lc := log.NewContext(logger).With(kvs...) kvs[1] = 0 // WithPrefix should copy its key values lc = lc.With("b", "c") // WithPrefix should stack if err := lc.Log("msg", "message"); err != nil { t.Fatal(err) } if want, have := `{"a":123,"b":"c","msg":"message"}`+"\n", buf.String(); want != have { t.Errorf("\nwant: %s\nhave: %s", want, have) } }
func TestAllowNoLevel(t *testing.T) { var buf bytes.Buffer logger := level.New(log.NewJSONLogger(&buf), level.Config{ SquelchNoLevel: false, ErrNoLevel: errors.New("I should never be returned!"), }) if want, have := error(nil), logger.Log("foo", "bar"); want != have { t.Errorf("want %v, have %v", want, have) } if want, have := `{"foo":"bar"}`, strings.TrimSpace(buf.String()); want != have { t.Errorf("want %q, have %q", want, have) } }
func TestErrNoLevel(t *testing.T) { myError := errors.New("no level specified") var buf bytes.Buffer logger := level.New(log.NewJSONLogger(&buf), level.Config{ SquelchNoLevel: true, ErrNoLevel: myError, }) if want, have := myError, logger.Log("foo", "bar"); want != have { t.Errorf("want %v, have %v", want, have) } if want, have := ``, strings.TrimSpace(buf.String()); want != have { t.Errorf("want %q, have %q", want, have) } }
func main() { logger := log.NewJSONLogger(os.Stdout) listen := os.Getenv("VANITY_LISTEN") if listen == "" { listen = ":8080" } listenMgmt := os.Getenv("VANITY_LISTEN_MGMT") if listenMgmt == "" { listenMgmt = ":8081" } config, err := loadConfiguration(logger, "conf/vanity.yaml") if err != nil { logger.Log("level", "error", "msg", "Could not load config", "err", err) os.Exit(1) } srv := server.New(server.Config{ Log: logger, Hosts: config.Hosts, }) go handleSigs() go func() { http.Handle("/metrics", prometheus.Handler()) http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) { http.Error(w, "OK", http.StatusOK) }) http.HandleFunc("/", http.NotFound) if err := http.ListenAndServe(listenMgmt, nil); err != nil { logger.Log("level", "error", "msg", "Failed to listen on management port", "err", err) } }() s := &http.Server{ Addr: listen, Handler: prometheus.InstrumentHandler("vanity", srv), } if err := s.ListenAndServe(); err != nil { logger.Log("level", "error", "msg", "Failed to listen", "err", err) os.Exit(1) } }
func main() { backgroundContext := context.Background() logger := log.NewJSONLogger(os.Stderr) var service PingPongService service = pingPongService{} service = LoggingMiddleware{logger, service} pongHandler := httpTransport.NewServer( backgroundContext, MakePingEndpoint(service), DecodePingRequest, EncodeResponse, ) http.Handle("/ping", pongHandler) logger.Log("msg", "HTTP", "addr", ":10002") logger.Log("err", http.ListenAndServe(":10002", nil)) }
func TestSwapLogger(t *testing.T) { t.Parallel() var logger log.SwapLogger // Zero value does not panic or error. err := logger.Log("k", "v") if got, want := err, error(nil); got != want { t.Errorf("got %v, want %v", got, want) } buf := &bytes.Buffer{} json := log.NewJSONLogger(buf) logger.Swap(json) if err := logger.Log("k", "v"); err != nil { t.Error(err) } if got, want := buf.String(), `{"k":"v"}`+"\n"; got != want { t.Errorf("got %v, want %v", got, want) } buf.Reset() prefix := log.NewLogfmtLogger(buf) logger.Swap(prefix) if err := logger.Log("k", "v"); err != nil { t.Error(err) } if got, want := buf.String(), "k=v\n"; got != want { t.Errorf("got %v, want %v", got, want) } buf.Reset() logger.Swap(nil) if err := logger.Log("k", "v"); err != nil { t.Error(err) } if got, want := buf.String(), ""; got != want { t.Errorf("got %v, want %v", got, want) } }
func TestNewContextErrorGeneric(t *testing.T) { sklog.SetContextErrorFunc(ctxpq.NewContextErrorGeneric) b := bytes.NewBuffer(nil) l := log.NewJSONLogger(b) for _, e := range pqErrors { sklog.Error(l, e) assertPqError(t, b, e) b.Reset() } for _, e := range genericErrors { sklog.Error(l, e) assertGenericError(t, b, e) b.Reset() } }
func init() { flag.StringVar(&port, "port", ":9494", "port to listen on") flag.StringVar(&version, "version", "", "output build date and commit data") flag.StringVar(&ramlFile, "ramlFile", "api.raml", "RAML file to parse") if err := godotenv.Load(); err != nil { log.Fatal("Error loading .env file") } serviceName = os.Getenv("SERVICE_NAME") serviceRegistration = os.Getenv("SERVICE_REGISTRATION") if serviceName == "" { serviceName = filepath.Base(os.Args[0]) } // Integrate go-kit logger. logger = kitlog.NewJSONLogger(os.Stdout) stdlog.SetOutput(kitlog.NewStdlibAdapter(logger)) }
func TestNewContextGeneric(t *testing.T) { b := bytes.NewBuffer(nil) l := log.NewJSONLogger(b) sklog.SetContextErrorFunc(ctxjson.NewContextError) for name, data := range successTestData { err := ctxstd.NewContextErrorGeneric(l, data.error).Log("key", "value") if assert.NoError(t, err) { got := b.String() for _, key := range data.keys { assert.Contains(t, got, key, name+" does not contain key: "+key) } for _, value := range data.values { assert.Contains(t, got, value, name+" does not contain value: "+value) } } b.Reset() } }
func TestVariousLevels(t *testing.T) { for _, testcase := range []struct { allowed []string want string }{ { level.AllowAll(), strings.Join([]string{ `{"level":"debug","this is":"debug log"}`, `{"level":"info","this is":"info log"}`, `{"level":"warn","this is":"warn log"}`, `{"level":"error","this is":"error log"}`, }, "\n"), }, { level.AllowDebugAndAbove(), strings.Join([]string{ `{"level":"debug","this is":"debug log"}`, `{"level":"info","this is":"info log"}`, `{"level":"warn","this is":"warn log"}`, `{"level":"error","this is":"error log"}`, }, "\n"), }, { level.AllowInfoAndAbove(), strings.Join([]string{ `{"level":"info","this is":"info log"}`, `{"level":"warn","this is":"warn log"}`, `{"level":"error","this is":"error log"}`, }, "\n"), }, { level.AllowWarnAndAbove(), strings.Join([]string{ `{"level":"warn","this is":"warn log"}`, `{"level":"error","this is":"error log"}`, }, "\n"), }, { level.AllowErrorOnly(), strings.Join([]string{ `{"level":"error","this is":"error log"}`, }, "\n"), }, { level.AllowNone(), ``, }, } { var buf bytes.Buffer logger := level.New(log.NewJSONLogger(&buf), level.Config{Allowed: testcase.allowed}) level.Debug(logger).Log("this is", "debug log") level.Info(logger).Log("this is", "info log") level.Warn(logger).Log("this is", "warn log") level.Error(logger).Log("this is", "error log") if want, have := testcase.want, strings.TrimSpace(buf.String()); want != have { t.Errorf("given Allowed=%v: want\n%s\nhave\n%s", testcase.allowed, want, have) } } }
func JSONLoggerTo(writer io.Writer) *CoreLogger { return NewCoreLogger(levels.New(kitlog.NewJSONLogger(writer))) }
// SetLogger allows user to output log data to a writer. func SetLogger(w io.Writer) { logger = kitlog.NewJSONLogger(w) stdlog.SetOutput(kitlog.NewStdlibAdapter(logger)) }
func init() { logger = kitlog.NewJSONLogger(os.Stdout) stdlog.SetOutput(kitlog.NewStdlibAdapter(logger)) }
func newLog(w io.Writer) *Log { return &Log{ctx: log.NewContext(log.NewJSONLogger(w))} }
func main() { logger := log.NewLogfmtLogger(os.Stderr) if os.Getenv("ENVIRONMENT") == "prod" || os.Getenv("ENVIRONMENT") == "stage" { logger = log.NewJSONLogger(os.Stdout) } logger = log.NewContext(logger).With( "ts", log.DefaultTimestampUTC, "caller", log.DefaultCaller, "name", Name, "version", Version, "build_time", BuildTime, "commit", Commit, ) logger.Log("level", "info", "msg", "Starting") cfg, err := New() if err != nil { logger.Log("level", "error", "msg", "Failed to parse config", "err", err) os.Exit(1) } runs := prometheus.NewCounterVec( prometheus.CounterOpts{ Name: "elasticsearch_index_maint_runs_total", Help: "Number of elasticsearch index maintenance runs", }, []string{"status"}, ) runs = prometheus.MustRegisterOrGet(runs).(*prometheus.CounterVec) deleted = prometheus.NewCounter( prometheus.CounterOpts{ Name: "elasticsearch_indices_deleted_total", Help: "Size of elasticsearch indices deleted", }, ) deleted = prometheus.MustRegisterOrGet(deleted).(prometheus.Counter) duration := prometheus.NewSummaryVec( prometheus.SummaryOpts{ Name: "elasticsearch_index_maint_duration", Help: "Duration of elasticsearch index maintenance runs", }, []string{"operation"}, ) duration = prometheus.MustRegisterOrGet(duration).(*prometheus.SummaryVec) go listen(logger) time.Sleep(time.Duration(rand.Int31n(30)) * time.Second) client, err := elastic.NewClient( elastic.SetURL(cfg.URL()), elastic.SetMaxRetries(10), ) if err != nil { logger.Log("level", "error", "msg", "Failed to create new ES client", "err", err) os.Exit(1) } interval := time.Hour * time.Duration(cfg.Interval) for { t0 := time.Now() err := remove(client, cfg, logger) if err != nil { runs.WithLabelValues("failed").Inc() logger.Log("level", "error", "msg", "Failed to delete indices", "err", err) continue } runs.WithLabelValues("ok").Inc() d0 := float64(time.Since(t0)) / float64(time.Microsecond) duration.WithLabelValues("delete").Observe(d0) if interval < time.Second { break } logger.Log("level", "info", "msg", "Waiting until next run", "interval", interval.String()) time.Sleep(interval) } client.Stop() os.Exit(0) }
func TestJSONLoggerConcurrency(t *testing.T) { testConcurrency(t, log.NewJSONLogger(ioutil.Discard)) }
func TestJSONLoggerConcurrency(t *testing.T) { t.Parallel() testConcurrency(t, log.NewJSONLogger(ioutil.Discard), 10000) }
func BenchmarkJSONLoggerContextual(b *testing.B) { benchmarkRunner(b, log.NewJSONLogger(ioutil.Discard), withMessage) }
func BenchmarkJSONLoggerSimple(b *testing.B) { benchmarkRunner(b, log.NewJSONLogger(ioutil.Discard), baseMessage) }