Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add strict fields into log #876

Closed
kotyara85 opened this issue Nov 14, 2020 · 3 comments · Fixed by #912
Closed

Add strict fields into log #876

kotyara85 opened this issue Nov 14, 2020 · 3 comments · Fixed by #912

Comments

@kotyara85
Copy link

Hey there,
Let's say if I have a struct

type logFormat struct {
	Level        string    `json:"level,omitempty"`
	ClientIP     string    `json:"client_ip,omitempty"`
	Method       string    `json:"method,omitempty"`
	Path         string    `json:"path,omitempty"`
}

if there a way add it to zap logger in flat without sub field?

I was able easy to do this:

{"level":"info","ts":1605346064.461162,"caller":"logger/logger.go:109","msg":"","log":{"level":"WARNING","client_ip":"::1","method":"GET","path":"/api"}}

with sugar.Infow("", zap.Reflect("log", log))

but would be nice to construct something like this instead without using individual zap fields

{"level":"info","ts":1605346064.461162,"caller":"logger/logger.go:109","msg:"","client_ip":"::1","method":"GET","path":"/api"}

Thanks

@prashantv
Copy link
Collaborator

This isn't possible for reflected objects (as the encoder interface takes the object to reflect and decides how to encode it, not zap, and the encoder wraps the fields in an object), but it is possible if:

  • We add a new InlineObject feature in zap, which I have a simple PoC for.
  • The struct implements zap.ObjectMarshaler.

Here's a small example showing it in action:

type request struct {
	URL string
	IP  string
}

func (r request) MarshalLogObject(enc zapcore.ObjectEncoder) error {
	enc.AddString("url", r.URL)
	enc.AddString("ip", r.IP)
	return nil
}

func ExampleObject() {
	logger := zap.NewExample()
	defer logger.Sync()

	req := &request{"/test", "127.0.0.1"}
	logger.Info("new request, in nested object", zap.Object("req", req))
	logger.Info("new request, inline", zap.InlineObject(req))
	// Output:
	// {"level":"info","msg":"new request, in nested object","req":{"url":"/test","ip":"127.0.0.1"}}
	// {"level":"info","msg":"new request, inline","url":"/test","ip":"127.0.0.1"}
}

If this seems useful, I can add tests and make a PR out of it.

cc @abhinav Does this seem generally useful?

@dharmjit
Copy link

dharmjit commented Dec 8, 2020

This can be useful if applications need to have strict custom logging schema.

prashantv added a commit that referenced this issue Feb 5, 2021
Fixes #876

Currently, a `zap.Field` can only represent a single key-value. Add
`zap.InlineObject` so to allow adding multiple fields to the current
namespace from a type implementing `zap.ObjectMarshaler`.

This also solves a more general problem: a single `zap.Field` can now
be used to add multiple key/value pairs.
prashantv added a commit that referenced this issue Mar 2, 2021
Fixes #876

Currently, a `zap.Field` can only represent a single key-value. Add
`zap.InlineObject` so to allow adding multiple fields to the current
namespace from a type implementing `zap.ObjectMarshaler`.

This also solves a more general problem: a single `zap.Field` can now
be used to add multiple key/value pairs.
prashantv added a commit that referenced this issue Mar 23, 2021
Fixes #876

Currently, a `zap.Field` can only represent a single key-value. Add
`zap.Inline` to allow adding multiple fields to the current
namespace from a type implementing `zap.ObjectMarshaler`.

This also solves a more general problem: a single `zap.Field` can now
be used to add multiple key/value pairs.
@prashantv
Copy link
Collaborator

This is now possible using zap.Inline, please see #912 for the implementation along with examples + tests.

abhinav pushed a commit that referenced this issue May 25, 2021
Fixes #876

Currently, a `zap.Field` can only represent a single key-value. Add
`zap.Inline` to allow adding multiple fields to the current
namespace from a type implementing `zap.ObjectMarshaler`.

This also solves a more general problem: a single `zap.Field` can now
be used to add multiple key/value pairs.
cgxxv pushed a commit to cgxxv/zap that referenced this issue Mar 25, 2022
Fixes uber-go#876

Currently, a `zap.Field` can only represent a single key-value. Add
`zap.Inline` to allow adding multiple fields to the current
namespace from a type implementing `zap.ObjectMarshaler`.

This also solves a more general problem: a single `zap.Field` can now
be used to add multiple key/value pairs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

3 participants