示例#1
0
// NewContextErrorGeneric ...
func NewContextErrorGeneric(logger log.Logger, err error) *log.Context {
	if code := grpc.Code(err); code != codes.Unknown {
		return log.NewContext(logger).With(sklog.KeyMessage, grpc.ErrorDesc(err), "code", code.String())
	}

	return log.NewContext(logger).With(sklog.KeyMessage, grpc.ErrorDesc(err))
}
示例#2
0
文件: multi.go 项目: weaveworks/flux
func (m *MultitenantInstancer) Get(instanceID flux.InstanceID) (*Instance, error) {
	c, err := m.DB.GetConfig(instanceID)
	if err != nil {
		return nil, errors.Wrap(err, "getting instance config from DB")
	}

	// Platform interface for this instance
	platform, err := m.Connecter.Connect(instanceID)
	if err != nil {
		return nil, errors.Wrap(err, "connecting to platform")
	}

	// Logger specialised to this instance
	instanceLogger := log.NewContext(m.Logger).With("instanceID", instanceID)

	// Registry client with instance's config
	creds, err := registry.CredentialsFromConfig(c.Settings)
	if err != nil {
		return nil, errors.Wrap(err, "decoding registry credentials")
	}
	regClient := &registry.Client{
		Credentials: creds,
		Logger:      log.NewContext(instanceLogger).With("component", "registry"),
	}

	repo := gitRepoFromSettings(c.Settings)

	// Events for this instance
	eventRW := EventReadWriter{instanceID, m.History}
	var eventW history.EventWriter = eventRW
	if c.Settings.Slack.HookURL != "" {
		eventW = history.TeeWriter(eventRW, history.NewSlackEventWriter(
			http.DefaultClient,
			c.Settings.Slack.HookURL,
			c.Settings.Slack.Username,
			`Regrade`, // only catch the final message
		))
	}

	// Configuration for this instance
	config := configurer{instanceID, m.DB}

	return New(
		platform,
		regClient,
		config,
		repo,
		instanceLogger,
		m.Histogram,
		eventRW,
		eventW,
	), nil
}
示例#3
0
// Test that Context.Log has a consistent function stack depth when binding
// log.Valuers, regardless of how many times Context.With has been called or
// whether Context.Log is called via an interface typed variable or a concrete
// typed variable.
func TestContextStackDepth(t *testing.T) {
	t.Parallel()
	fn := fmt.Sprintf("%n", stack.Caller(0))

	var output []interface{}

	logger := log.Logger(log.LoggerFunc(func(keyvals ...interface{}) error {
		output = keyvals
		return nil
	}))

	stackValuer := log.Valuer(func() interface{} {
		for i, c := range stack.Trace() {
			if fmt.Sprintf("%n", c) == fn {
				return i
			}
		}
		t.Fatal("Test function not found in stack trace.")
		return nil
	})

	concrete := log.NewContext(logger).With("stack", stackValuer)
	var iface log.Logger = concrete

	// Call through interface to get baseline.
	iface.Log("k", "v")
	want := output[1].(int)

	for len(output) < 10 {
		concrete.Log("k", "v")
		if have := output[1]; have != want {
			t.Errorf("%d Withs: have %v, want %v", len(output)/2-1, have, want)
		}

		iface.Log("k", "v")
		if have := output[1]; have != want {
			t.Errorf("%d Withs: have %v, want %v", len(output)/2-1, have, want)
		}

		wrapped := log.NewContext(concrete)
		wrapped.Log("k", "v")
		if have := output[1]; have != want {
			t.Errorf("%d Withs: have %v, want %v", len(output)/2-1, have, want)
		}

		concrete = concrete.With("k", "v")
		iface = concrete
	}
}
func Register() {
	logger := klog.NewLogfmtLogger(os.Stderr)
	ctx := context.Background()

	fieldKeys := []string{"method", "error"}
	requestCount := kitprometheus.NewCounter(stdprometheus.CounterOpts{
		Namespace: "my_group",
		Subsystem: "string_service",
		Name:      "request_count",
		Help:      "Number of requests received.",
	}, fieldKeys)
	requestLatency := metrics.NewTimeHistogram(time.Microsecond, kitprometheus.NewSummary(stdprometheus.SummaryOpts{
		Namespace: "my_group",
		Subsystem: "string_service",
		Name:      "request_latency_microseconds",
		Help:      "Total duraction of the requests in microseconds.",
	}, fieldKeys))
	countResult := kitprometheus.NewSummary(stdprometheus.SummaryOpts{
		Namespace: "my_group",
		Subsystem: "string_service",
		Name:      "count_result",
		Help:      "The result of each count method.",
	}, []string{})

	var svc StringService
	svc = stringService{}
	svc = appLoggingMiddleware{logger, svc}
	svc = instrumentingMiddleware{requestCount, requestLatency, countResult, svc}

	uppercaseHandler := httptransport.Server{
		Context:            ctx,
		Endpoint:           loggingMiddleware(klog.NewContext(logger).With("method", "uppercase"))(makeUppercaseEndpoint(svc)),
		DecodeRequestFunc:  decodeUppercaseRequest,
		EncodeResponseFunc: encodeResponse,
	}

	countHandler := httptransport.Server{
		Context:            ctx,
		Endpoint:           loggingMiddleware(klog.NewContext(logger).With("method", "count"))(makeCountEndpoint(svc)),
		DecodeRequestFunc:  decodeCountRequest,
		EncodeResponseFunc: encodeResponse,
	}

	http.Handle("/uppercase", uppercaseHandler)
	http.Handle("/count", countHandler)
	http.Handle("/metrics", stdprometheus.Handler())
	log.Fatal(http.ListenAndServe(":8901", nil))
}
示例#5
0
文件: log_test.go 项目: ryancox/kit
func TestContextMissingValue(t *testing.T) {
	t.Parallel()
	var output []interface{}
	logger := log.Logger(log.LoggerFunc(func(keyvals ...interface{}) error {
		output = keyvals
		return nil
	}))

	lc := log.NewContext(logger)

	lc.Log("k")
	if want, have := 2, len(output); want != have {
		t.Errorf("want len(output) == %v, have %v", want, have)
	}
	if want, have := log.ErrMissingValue, output[1]; want != have {
		t.Errorf("want %#v, have %#v", want, have)
	}

	lc.With("k1").WithPrefix("k0").Log("k2")
	if want, have := 6, len(output); want != have {
		t.Errorf("want len(output) == %v, have %v", want, have)
	}
	for i := 1; i < 6; i += 2 {
		if want, have := log.ErrMissingValue, output[i]; want != have {
			t.Errorf("want output[%d] == %#v, have %#v", i, want, have)
		}
	}
}
示例#6
0
文件: main.go 项目: wolfeidau/sensord
func main() {

	// setup a logger
	logger = log.NewLogfmtLogger(os.Stderr)
	logger = log.NewContext(logger).With("svc", "sensor").With("caller", log.DefaultCaller)

	// setup rethinkdb session
	session := getSession()

	// build the context
	ctx := context.Background()

	// new service
	svc := NewSensorService(session)

	// wrap it in the logging middleware
	svc = loggingMiddleware(logger)(svc)

	// bind the service to HTTP with the context
	// with it's matching encoder/decoder
	recordHandler := httptransport.NewServer(
		ctx,
		makeRecordEndpoint(svc),
		decodeRecordRequest,
		encodeResponse,
	)

	// assign an endpoint route
	http.Handle("/sensor/record", recordHandler)

	// bind the listener
	logger.Log("msg", "HTTP", "addr", ":5000")
	logger.Log("err", http.ListenAndServe(":5000", nil))
}
示例#7
0
func NewHandler(s api.FluxService, r *mux.Router, logger log.Logger, h metrics.Histogram) http.Handler {
	for method, handlerFunc := range map[string]func(api.FluxService) http.Handler{
		"ListServices":   handleListServices,
		"ListImages":     handleListImages,
		"PostRelease":    handlePostRelease,
		"GetRelease":     handleGetRelease,
		"Automate":       handleAutomate,
		"Deautomate":     handleDeautomate,
		"Lock":           handleLock,
		"Unlock":         handleUnlock,
		"History":        handleHistory,
		"GetConfig":      handleGetConfig,
		"SetConfig":      handleSetConfig,
		"RegisterDaemon": handleRegister,
		"IsConnected":    handleIsConnected,
	} {
		var handler http.Handler
		handler = handlerFunc(s)
		handler = logging(handler, log.NewContext(logger).With("method", method))
		handler = observing(handler, h.With("method", method))

		r.Get(method).Handler(handler)
	}
	return r
}
示例#8
0
func main() {
	// `package log` domain
	var logger kitlog.Logger
	logger = kitlog.NewLogfmtLogger(os.Stderr)
	logger = kitlog.NewContext(logger).With("ts", kitlog.DefaultTimestampUTC)
	stdlog.SetOutput(kitlog.NewStdlibAdapter(logger)) // redirect stdlib logging to us
	stdlog.SetFlags(0)                                // flags are handled in our logger

	// read configuration from environment
	c, err := config.LoadConfiguration()
	if err != nil {
		logger.Log("fatal", err.Error())
		return
	}

	// Mechanical stuff
	rand.Seed(time.Now().UnixNano())
	root := context.Background()
	errc := make(chan error)

	go func() {
		errc <- interrupt()
	}()

	// Start bindings
	binding.StartApplicationSQSConsumer(logger, root, errc, c)
	binding.StartHealthCheckHTTPListener(logger, root, errc, c)

	logger.Log("fatal", <-errc)
}
示例#9
0
func Example_context() {
	logger := log.NewLogfmtLogger(os.Stdout)

	type Task struct {
		ID  int
		Cmd string
	}

	taskHelper := func(cmd string, logger log.Logger) {
		// execute(cmd)
		logger.Log("cmd", cmd, "dur", 42*time.Millisecond)
	}

	RunTask := func(task Task, logger log.Logger) {
		logger = log.NewContext(logger).With("taskID", task.ID)
		logger.Log("event", "starting task")

		taskHelper(task.Cmd, logger)

		logger.Log("event", "task complete")
	}

	RunTask(Task{ID: 1, Cmd: "echo Hello, world!"}, logger)

	// Output:
	// taskID=1 event="starting task"
	// taskID=1 cmd="echo Hello, world!" dur=42ms
	// taskID=1 event="task complete"
}
示例#10
0
// NewContextErrorGeneric creates context for given error.
// Performs error type check internally to choose strategy that fits the best.
func NewContextError(logger log.Logger, err error) *log.Context {
	if ctx, ok := err.(sklog.Contexter); ok {
		return log.NewContext(logger).With(ctx.Context())
	}

	switch e := err.(type) {
	case *json.MarshalerError:
		return NewContextJSONMarshalerError(logger, e)
	case *json.InvalidUnmarshalError:
		return NewContextJSONInvalidUnmarshalError(logger, e)
	case *json.UnmarshalFieldError:
		return NewContextJSONUnmarshalFieldError(logger, e)
	case *json.UnmarshalTypeError:
		return NewContextJSONUnmarshalTypeError(logger, e)
	case *json.UnsupportedTypeError:
		return NewContextJSONUnsupportedTypeError(logger, e)
	case *json.UnsupportedValueError:
		return NewContextJSONUnsupportedValueError(logger, e)
	case *json.InvalidUTF8Error:
		return NewContextJSONInvalidUTF8Error(logger, e)
	case *json.SyntaxError:
		return NewContextJSONSyntaxError(logger, e)
	default:
		return sklog.NewContextErrorGeneric(logger, e)
	}
}
示例#11
0
文件: registrar.go 项目: crezam/kit
// NewRegistrar returns a Consul Registrar acting on the provided catalog
// registration.
func NewRegistrar(client Client, r *stdconsul.AgentServiceRegistration, logger log.Logger) *Registrar {
	return &Registrar{
		client:       client,
		registration: r,
		logger:       log.NewContext(logger).With("service", r.Name, "tags", fmt.Sprint(r.Tags), "address", r.Address),
	}
}
示例#12
0
func main() {
	logger := log.NewLogfmtLogger(os.Stderr)
	logger = log.NewContext(logger).With("ts", log.DefaultTimestampUTC)

	err := godotenv.Load()
	if err != nil {
		logger.Log("level", "fatal", "err", err)
	}

	config := &Config{
		Addr: os.Getenv("ADDR"),
		DSN:  os.Getenv("DSN"),
	}

	db, err := gorm.Open("postgres", config.DSN)
	if err != nil {
		panic(err)
	}

	app := cli.NewApp()

	app.Commands = []cli.Command{{
		Name:   "serve",
		Action: serve(logger, config, db),
	}}

	if err := app.Run(os.Args); err != nil {
		logger.Log("level", "fatal", "err", err)
	}

}
示例#13
0
// NewEndpointCache produces a new EndpointCache, ready for use. Instance
// strings will be converted to endpoints via the provided factory function.
// The logger is used to log errors.
func NewEndpointCache(f Factory, logger log.Logger) *EndpointCache {
	return &EndpointCache{
		f:      f,
		m:      map[string]endpointCloser{},
		logger: log.NewContext(logger).With("component", "Endpoint Cache"),
	}
}
示例#14
0
文件: log_test.go 项目: ryancox/kit
func TestContext(t *testing.T) {
	t.Parallel()
	buf := &bytes.Buffer{}
	logger := log.NewLogfmtLogger(buf)

	kvs := []interface{}{"a", 123}
	lc := log.NewContext(logger).With(kvs...)
	kvs[1] = 0 // With should copy its key values

	lc = lc.With("b", "c") // With 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: %shave: %s", want, have)
	}

	buf.Reset()
	lc = lc.WithPrefix("p", "first")
	if err := lc.Log("msg", "message"); err != nil {
		t.Fatal(err)
	}
	if want, have := "p=first a=123 b=c msg=message\n", buf.String(); want != have {
		t.Errorf("\nwant: %shave: %s", want, have)
	}
}
示例#15
0
func main() {
	logger = log.NewLogfmtLogger(os.Stderr)
	logger = log.NewContext(logger).With("ts", log.DefaultTimestampUTC, "caller", log.DefaultCaller)
	logger.Log("msg", "Starting bikefinder")
	var err error

	db_url := os.Getenv("DATABASE_URL")
	DB, err = crud.Connect("mysql", db_url)

	if err != nil {
		logger.Log("msg", "Failed to connect to db at "+db_url, "error", err)
		panic(err)
	}

	err = DB.CreateTables(DockingStationStatus{})
	if err != nil {
		logger.Log("msg", "Failed to create db table", "error", err)
		panic(err)
	}

	http.HandleFunc("/schemes", getSchemes)
	http.HandleFunc("/stations", getStationsInside)
	http.HandleFunc("/bikes-near", getBikesNear)
	http.HandleFunc("/freedocks-near", getFreeDocksNear)
	http.HandleFunc("/map", getMap)
	http.HandleFunc("/ingest", ingest)
	http.Handle("/", http.FileServer(http.Dir("./static")))
	bind := fmt.Sprintf("%s:%s", os.Getenv("OPENSHIFT_GO_IP"), os.Getenv("OPENSHIFT_GO_PORT"))
	logger.Log("msg", "Attempting to listen on "+bind)
	err = http.ListenAndServe(bind, nil)
	if err != nil {
		logger.Log("msg", "Failed to listen", "error", err)
		panic(err)
	}
}
示例#16
0
func (s *Server) createConnection(conn *net.TCPConn) *connection {
	connID := atomic.AddUint64(&s.connCounter, 1)

	// child context with the connection id
	ctx := context.WithValue(s.Context, ConnID, connID)

	// logger with connection id as prefix
	logger := kitlog.NewContext(s.Logger).WithPrefix(ConnID, strconv.FormatUint(connID, 16))
	// child context with the new logger
	ctx = context.WithValue(ctx, LoggerKey, logger)

	// pipe to move bytes from connection to the protocol
	pr, pw := io.Pipe()
	gc := &connection{
		st:           &s.t,
		id:           connID,
		ctx:          ctx,
		logger:       logger,
		conn:         conn,
		readTimeout:  s.ReadTimeout,
		writeTimeout: s.WriteTimeout,
		pw:           pw,
		p:            s.ProtocolFactory(ctx, pr),
	}
	return gc
}
示例#17
0
// copied from log/benchmark_test.go
func benchmarkRunner(b *testing.B, logger log.Logger, f func(log.Logger)) {
	lc := log.NewContext(logger).With("common_key", "common_value")
	b.ReportAllocs()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		f(lc)
	}
}
示例#18
0
文件: main.go 项目: cnicolov/kit
func main() {
	var (
		listen = flag.String("listen", ":8080", "HTTP listen address")
		proxy  = flag.String("proxy", "", "Optional comma-separated list of URLs to proxy uppercase requests")
	)
	flag.Parse()

	var logger log.Logger
	logger = log.NewLogfmtLogger(os.Stderr)
	logger = log.NewContext(logger).With("listen", *listen).With("caller", log.DefaultCaller)

	ctx := context.Background()

	fieldKeys := []string{"method", "error"}
	requestCount := kitprometheus.NewCounter(stdprometheus.CounterOpts{
		Namespace: "my_group",
		Subsystem: "string_service",
		Name:      "request_count",
		Help:      "Number of requests received.",
	}, fieldKeys)
	requestLatency := metrics.NewTimeHistogram(time.Microsecond, kitprometheus.NewSummary(stdprometheus.SummaryOpts{
		Namespace: "my_group",
		Subsystem: "string_service",
		Name:      "request_latency_microseconds",
		Help:      "Total duration of requests in microseconds.",
	}, fieldKeys))
	countResult := kitprometheus.NewSummary(stdprometheus.SummaryOpts{
		Namespace: "my_group",
		Subsystem: "string_service",
		Name:      "count_result",
		Help:      "The result of each count method.",
	}, []string{})

	var svc StringService
	svc = stringService{}
	svc = proxyingMiddleware(*proxy, ctx, logger)(svc)
	svc = loggingMiddleware(logger)(svc)
	svc = instrumentingMiddleware(requestCount, requestLatency, countResult)(svc)

	uppercaseHandler := httptransport.NewServer(
		ctx,
		makeUppercaseEndpoint(svc),
		decodeUppercaseRequest,
		encodeResponse,
	)
	countHandler := httptransport.NewServer(
		ctx,
		makeCountEndpoint(svc),
		decodeCountRequest,
		encodeResponse,
	)

	http.Handle("/uppercase", uppercaseHandler)
	http.Handle("/count", countHandler)
	http.Handle("/metrics", stdprometheus.Handler())
	logger.Log("msg", "HTTP", "addr", *listen)
	logger.Log("err", http.ListenAndServe(*listen, nil))
}
示例#19
0
func TestNopLogger(t *testing.T) {
	logger := log.NewNopLogger()
	if err := logger.Log("abc", 123); err != nil {
		t.Error(err)
	}
	if err := log.NewContext(logger).With("def", "ghi").Log(); err != nil {
		t.Error(err)
	}
}
示例#20
0
func BenchmarkValueBindingTimestamp(b *testing.B) {
	logger := log.NewNopLogger()
	lc := log.NewContext(logger).With("ts", log.DefaultTimestamp)
	b.ReportAllocs()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		lc.Log("k", "v")
	}
}
示例#21
0
func BenchmarkValueBindingCaller(b *testing.B) {
	logger := discard
	lc := log.NewContext(logger).With("caller", log.DefaultCaller)
	b.ReportAllocs()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		lc.Log("k", "v")
	}
}
示例#22
0
文件: log_test.go 项目: ryancox/kit
func BenchmarkOneWith(b *testing.B) {
	logger := discard
	lc := log.NewContext(logger).With("k", "v")
	b.ReportAllocs()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		lc.Log("k", "v")
	}
}
示例#23
0
文件: main.go 项目: patterns/re
func main() {
	var (
		httpAddr = flag.String("http.addr", ":8080", "HTTP listen address")
		maildir  = flag.String("maildir", ".Maildir", "Maildir directory path")
	)
	flag.Parse()

	var logger log.Logger
	{
		logger = log.NewLogfmtLogger(os.Stderr)
		logger = log.NewContext(logger).With("ts", log.DefaultTimestampUTC)
		logger = log.NewContext(logger).With("caller", log.DefaultCaller)
	}

	var ctx context.Context
	{
		ctx = context.Background()
	}

	var s restsvc.Service
	{
		s = restsvc.NewInmemService(*maildir)
		s = restsvc.LoggingMiddleware(logger)(s)
	}

	var h http.Handler
	{
		h = restsvc.MakeHTTPHandler(ctx, s, log.NewContext(logger).With("component", "HTTP"))
	}

	errs := make(chan error)
	go func() {
		c := make(chan os.Signal)
		signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
		errs <- fmt.Errorf("%s", <-c)
	}()

	go func() {
		logger.Log("transport", "HTTP", "addr", *httpAddr)
		errs <- http.ListenAndServe(*httpAddr, handlers.CORS()(h))
	}()

	logger.Log("exit", <-errs)
}
示例#24
0
文件: slack.go 项目: botyard/botyard
func NewSlackGateway(cfg config.SlackGateway) *SlackGateway {
	client := slacker.NewAPIClient(cfg.Token, "")
	gw := &SlackGateway{
		id:     "slack",
		cfg:    cfg,
		client: client,
		logger: kitlog.NewContext(log.Logger).With("m", "Gateway-Slack"),
	}
	return gw
}
示例#25
0
文件: registrar.go 项目: crezam/kit
// NewRegistrar returns a etcd Registrar acting on the provided catalog
// registration.
func NewRegistrar(client Client, service Service, logger log.Logger) *Registrar {
	return &Registrar{
		client:  client,
		service: service,
		logger: log.NewContext(logger).With(
			"value", service.Value,
			"key", service.Key,
		),
	}
}
示例#26
0
文件: main.go 项目: qband/down
func main() {
	var (
		httpAddr = flag.String("http.addr", ":8080", "HTTP listen address")
	)
	flag.Parse()

	var logger log.Logger
	{
		logger = log.NewLogfmtLogger(os.Stderr)
		logger = log.NewContext(logger).With("ts", log.DefaultTimestampUTC)
		logger = log.NewContext(logger).With("caller", log.DefaultCaller)
	}

	var ctx context.Context
	{
		ctx = context.Background()
	}

	var s ProfileService
	{
		s = newInmemService()
		s = loggingMiddleware{s, log.NewContext(logger).With("component", "svc")}
	}

	var h http.Handler
	{
		h = makeHandler(ctx, s, log.NewContext(logger).With("component", "http"))
	}

	errs := make(chan error, 2)
	go func() {
		logger.Log("transport", "http", "address", *httpAddr, "msg", "listening")
		errs <- http.ListenAndServe(*httpAddr, h)
	}()
	go func() {
		c := make(chan os.Signal)
		signal.Notify(c, syscall.SIGINT)
		errs <- fmt.Errorf("%s", <-c)
	}()

	logger.Log("terminated", <-errs)
}
示例#27
0
文件: registrar.go 项目: crezam/kit
// NewRegistrar returns a ZooKeeper Registrar acting on the provided catalog
// registration.
func NewRegistrar(client Client, service Service, logger log.Logger) *Registrar {
	return &Registrar{
		client:  client,
		service: service,
		logger: log.NewContext(logger).With(
			"service", service.Name,
			"path", service.Path,
			"data", string(service.Data),
		),
	}
}
示例#28
0
// NewEndpointCache produces a new EndpointCache, ready for use. Instance
// strings will be converted to endpoints via the provided factory function.
// The logger is used to log errors.
func NewEndpointCache(f Factory, logger log.Logger) *EndpointCache {
	endpointCache := &EndpointCache{
		f:      f,
		m:      map[string]endpointCloser{},
		logger: log.NewContext(logger).With("component", "Endpoint Cache"),
	}

	endpointCache.cache.Store(make([]endpoint.Endpoint, 0))

	return endpointCache
}
示例#29
0
func NewDispatcher(ctx context.Context,
	msgChannel chan *message.Message, loader *Loader) *Dispatcher {
	d := &Dispatcher{
		ctx:        ctx,
		loader:     loader,
		msgChannel: msgChannel,
		logger:     kitlog.NewContext(log.Logger).With("m", "dispatcher"),
	}

	go d.dispatch()
	return d
}
示例#30
0
func BenchmarkTenWith(b *testing.B) {
	logger := log.NewNopLogger()
	lc := log.NewContext(logger).With("k", "v")
	for i := 1; i < 10; i++ {
		lc = lc.With("k", "v")
	}
	b.ReportAllocs()
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		lc.Log("k", "v")
	}
}