You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Logging package to add context logger for workers and stores output to metadata (#844)
After adding support for job output, it got me thinking that it might
not be _that_ bad if we put in a way for users to be able to store
limited job-specific logging to job records. Like with output, this
would go in TOAST, and although it could be bad if too much data
accumulated, it shouldn't generally effect performance.
Here, prototype what that would look like. It's implemented as a
middleware in a separate `riverlog` package, which must be installed to
a client or worker to become active. Once it is, logging looks like:
func (w *LoggingWorker) Work(ctx context.Context, job *river.Job[LoggingArgs]) error {
riverlog.Logger(ctx).InfoContext(ctx, "Logged from worker")
return nil
}
The middleware takes a function that returns a slog handler, which has
the purpose of letting the user select between JSON, text, or something
else, and lets them select options like logging level.
I've left in enough flexibility that we should be able to extend the
interface only slightly to implement a system that sends logs to S3
instead of metadata, but metadata is a good default.
I figure that if we go down this route we can add special handling for
it to River UI to make logs easily accessible for installations even
without a full logging platform.
I also ended up adding support to `Client` and `rivertest.Worker` for
`rivershared.BaseService` in hooks and middleware so that if a hook or
middleware has a base service embedded, it gets its archetype
initialized just like other services in the client. This gives us an
easy way to inherit a client's log instead of a separate one having to
be injected which is _very_ convenient. This shouldn't be used outside
of River core packages, but it should be okay if we make use it.
Also added convenience helpers to make middleware like we already had
for hooks:
* `JobInsertMiddlewareFunc`
* `WorkerMiddlewareFunc `
I put these in because they're great for creating a hook or middleware
that's scoped to a single test case and which is a struct that can embed
something like `baseservice.BaseService`.
Copy file name to clipboardExpand all lines: CHANGELOG.md
+5Lines changed: 5 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
8
8
## [Unreleased]
9
9
10
+
### Added
11
+
12
+
- Added `river/riverlog` containing middleware that injects a context logger to workers that collates log output and persists it with job metadata. This is paired with a River UI enhancement that shows logs in the UI. [PR #844](https://github.com/riverqueue/river/pull/844).
13
+
- Added `JobInsertMiddlewareFunc` and `WorkerMiddlewareFunc` to easily implement middleware with a function instead of a struct. [PR #844](https://github.com/riverqueue/river/pull/844).
14
+
10
15
### Changed
11
16
12
17
- Client no longer returns an error if stopped before startup could complete (previously, it returned the unexported `ErrShutdown`). [PR #841](https://github.com/riverqueue/river/pull/841).
0 commit comments