Skip to content

feat!: v0.3.0 — Err / ErrAny return single inline zap.Field#3

Merged
maxence2997 merged 5 commits into
mainfrom
feat/v0.3.0-err-inline
May 6, 2026
Merged

feat!: v0.3.0 — Err / ErrAny return single inline zap.Field#3
maxence2997 merged 5 commits into
mainfrom
feat/v0.3.0-err-inline

Conversation

@maxence2997
Copy link
Copy Markdown
Owner

Summary

BREAKING CHANGE. Err(err) and ErrAny(v) now return a single zap.Field (inline) instead of []zap.Field. Output JSON is unchanged — same flat dotted ECS keys.

Why

Surfaced from streaming-observer dogfooding (O4 in the v0.2.0 dogfood report):

The []zap.Field return type forces callers to break inline log call style and fight with prealloc lint:

// v0.2.0 — awkward
fields := make([]zap.Field, 0, 5)
fields = append(fields, ecsf.ServiceName("auth"), ecsf.EventAction("login"))
fields = append(fields, ecsf.Err(err)...)
logger.Error("failed", fields...)
// v0.3.0 — inline
logger.Error("failed",
    ecsf.ServiceName("auth"),
    ecsf.EventAction("login"),
    ecsf.Err(err),
)

v0.x allows breaking changes, so the cleaner API wins over a parallel ErrField helper that would split the API surface.

How

  • Err(err) zap.Field returns zap.Inline(errMarshaler{err: err}) — a single Field whose MarshalLogObject writes error.message / error.type / error.stack_trace directly into the encoder.
  • ErrAny(v) zap.Field mirrors the structure with errAnyMarshaler (handles typed-nil, non-error fallback, then delegates to errMarshaler).
  • Both return zap.Skip() when input is nil — the field is no-op when added, so unconditional inline use is safe.
  • zap.Inline flattens the marshaler's keys at the current namespace, so output is identical to the v0.2.0 multi-field shape (no nesting, no dot/object difference).

Test plan

  • make check passes (fmt + lint + race-detector test)
  • All 14 error tests rewritten to assert against zapcore.NewMapObjectEncoder output (which zap.Inline flattens into via AddTo)
  • Tests cover: nil → Skip, plain error, samber/oops StackTracer, pkg/errors StackTracer, string/int/struct (ErrAny non-error), typed-nil error (no panic)
  • CI green

1.[]Field broke inline log call style -> return one Field
2.zap.Inline preserves flat dotted keys -> output unchanged
3.nil input would force conditional append -> return zap.Skip
Copilot AI review requested due to automatic review settings May 6, 2026 03:42
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a breaking API change in the zap/ subpackage: Err(err) and ErrAny(v) now return a single inline zapcore.Field (via zap.Inline) instead of []zapcore.Field, while keeping the emitted ECS error.* keys and flat JSON output shape the same.

Changes:

  • Refactor Err / ErrAny to return a single inline zapcore.Field backed by zapcore.ObjectMarshaler.
  • Rewrite error tests to assert emitted encoder output (via zapcore.NewMapObjectEncoder) rather than inspecting field slices.
  • Update example + docs + changelog to reflect the new inline-call style and zap.Skip() nil behavior.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
zap/error.go Switch Err/ErrAny to zap.Inline + marshalers, and return zap.Skip() on nil input.
zap/error_test.go Update tests to validate encoded output for inline fields and skip behavior.
example/main.go Update example usage to pass ecsf.Err(err) inline (no slice append/splat).
docs/related-projects.md Adjust guidance table to remove ... splat usage for Err/ErrAny.
docs/ecs-coverage.md Update coverage notes to reflect new return types and inline behavior.
CHANGELOG.md Document the breaking change and provide migration snippet.

Comment thread zap/error.go
Comment thread zap/error_test.go
1.Err(typedNil) panicked in errMarshaler.Error -> guard moved
2.Two marshalers checked typed-nil -> single check in errMarshaler
3.Tests hard-coded *errors.errorString -> derive via %T
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

zap/error.go:56

  • The Err doc comment says error.message is always err.Error(), but typed-nil errors intentionally emit error.message = "<nil>" without calling Error(). Consider adjusting the bullet list to reflect this exception so the docs match the actual behavior.
// Err returns a single inline zap.Field that emits ECS error.* fields:
//
//   - error.message: always (err.Error())
//   - error.type:    always (fmt.Sprintf("%T", err))
//   - error.stack_trace: if any error in the chain implements one of the

Comment thread zap/error.go
1.errors.As matched typed-nil tracer -> StackTrace panicked
2.Fix only safe up to first typed-nil -> document limitation
3.Wrapped typed-nil scenario lacked test -> add safeWrapper case
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Comment thread zap/error.go Outdated
1.v0.3.0 returns single inline Field -> wording contradicted code
2.Multi-field tag added no info -> describe behavior directly
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Comment thread CHANGELOG.md Outdated
Comment thread zap/error.go
1.Snippet used unqualified names -> add ecsf prefix
2.Mentioned no import context -> note the recommended alias
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.

@maxence2997 maxence2997 merged commit efc5ad5 into main May 6, 2026
5 checks passed
@maxence2997 maxence2997 deleted the feat/v0.3.0-err-inline branch May 6, 2026 08:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants