Skip to content

Commit 5887997

Browse files
authored
Introduce support for multiple logging providers. (#135)
1 parent 739b01a commit 5887997

20 files changed

Lines changed: 543 additions & 133 deletions

.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ jobs:
4242
runs-on: ubuntu-latest
4343
strategy:
4444
matrix:
45-
go-version: ["1.19", "1.20", "1.21", "1.22"]
45+
go-version: ["1.21", "1.22", "1.23"]
4646
steps:
4747
- uses: actions/checkout@v4
4848
- name: Setup Go ${{ matrix.go-version }}

v4/README.md

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<p align="center"><img src="https://user-images.githubusercontent.com/5921929/73911149-1dad9280-4866-11ea-8818-fed1cd49e8b1.png" width="360"></p>
22

33
# work
4+
45
> A compact library for tracking and committing atomic changes to your entities.
56
67
[![GoDoc][doc-img]][doc] [![Build Status][ci-img]][ci]
@@ -16,6 +17,7 @@
1617
### Construction
1718

1819
Starting with entities `Foo` and `Bar`,
20+
1921
```go
2022
// entities.
2123
f, b := Foo{}, Bar{}
@@ -32,62 +34,85 @@ unit, err := unit.New(opts...)
3234
```
3335

3436
### Adding
37+
3538
When creating new entities, use [`Add`][unit-doc]:
39+
3640
```go
3741
additions := []interface{}{ f, b }
3842
err := u.Add(additions...)
3943
```
4044

4145
### Updating
46+
4247
When modifying existing entities, use [`Alter`][unit-doc]:
48+
4349
```go
4450
updates := []interface{}{ f, b }
4551
err := u.Alter(updates...)
4652
```
4753

4854
### Removing
55+
4956
When removing existing entities, use [`Remove`][unit-doc]:
57+
5058
```go
5159
removals := []interface{}{ f, b }
5260
err := u.Remove(removals...)
5361
```
5462

55-
### Registering
63+
### Registering
64+
5665
When retrieving existing entities, track their intial state using
5766
[`Register`][unit-doc]:
67+
5868
```go
5969
fetched := []interface{}{ f, b }
6070
err := u.Register(fetched...)
6171
```
6272

6373
### Saving
74+
6475
When you are ready to commit your work unit, use [`Save`][unit-doc]:
76+
6577
```go
6678
ctx := context.Background()
6779
err := u.Save(ctx)
6880
```
6981

7082
### Logging
71-
We use [`zap`][zap] as our logging library of choice. To leverage the logs
72-
emitted from the work units, utilize the [`unit.Logger`][unit-logger-doc]
73-
option with an instance of [`*zap.Logger`][logger-doc] upon creation:
83+
84+
We support the following logging packages:
85+
86+
- [`zap`][zap]
87+
- `log`
88+
- `log/slog`
89+
- [`logrus`][logrus]
90+
91+
In addition, we also support custom loggers that implement the `unit.Logger`
92+
interface. For each approach, there is a corresponding option that can be
93+
specified during the creation of the work unit.
94+
95+
The following example demonstrates how to use the `zap` logger:
96+
7497
```go
7598
// create logger.
7699
l, _ := zap.NewDevelopment()
77100

78101
opts = []unit.Option{
79102
unit.DB(db),
80103
unit.DataMappers(m),
81-
unit.Logger(l), // 🎉
104+
unit.ZapLogger(l), // 🎉
82105
}
83106
u, err := unit.New(opts...)
84107
```
85108

86109
### Metrics
110+
87111
For emitting metrics, we use [`tally`][tally]. To utilize the metrics emitted
88112
from the work units, leverage the [`unit.Scope`][unit-scope-doc] option
89113
with a [`tally.Scope`][scope-doc] upon creation. Assuming we have a
90114
scope `s`, it would look like so:
115+
91116
```go
92117
opts = []unit.Option{
93118
unit.DB(db),
@@ -101,25 +126,27 @@ u, err := unit.New(opts...)
101126

102127
<p align="center"><img src="https://user-images.githubusercontent.com/5921929/106403546-191daa80-63e4-11eb-98b5-6b5d1989bacb.gif" width="960"></p>
103128

104-
| Name | Type | Description |
105-
| -------------------------------- | ------- | ------------------------------------------------------------ |
106-
| [_PREFIX._]unit.save.success | counter | The number of successful work unit saves. |
107-
| [_PREFIX._]unit.save | timer | The time duration when saving a work unit. |
108-
| [_PREFIX._]unit.rollback.success | counter | The number of successful work unit rollbacks. |
109-
| [_PREFIX._]unit.rollback.failure | counter | The number of unsuccessful work unit rollbacks. |
110-
| [_PREFIX._]unit.rollback | timer | The time duration when rolling back a work unit. |
111-
| [_PREFIX._]unit.retry.attempt | counter | The number of retry attempts. |
112-
| [_PREFIX._]unit.insert | counter | The number of successful inserts performed. |
113-
| [_PREFIX._]unit.update | counter | The number of successful updates performed. |
114-
| [_PREFIX._]unit.delete | counter | The number of successful deletes performed. |
115-
| [_PREFIX._]unit.cache.insert | counter | The number of registered entities inserted into the cache. |
116-
| [_PREFIX._]unit.cache.delete | counter | The number of registered entities removed from the cache. |
129+
| Name | Type | Description |
130+
| -------------------------------- | ------- | ---------------------------------------------------------- |
131+
| [_PREFIX._]unit.save.success | counter | The number of successful work unit saves. |
132+
| [_PREFIX._]unit.save | timer | The time duration when saving a work unit. |
133+
| [_PREFIX._]unit.rollback.success | counter | The number of successful work unit rollbacks. |
134+
| [_PREFIX._]unit.rollback.failure | counter | The number of unsuccessful work unit rollbacks. |
135+
| [_PREFIX._]unit.rollback | timer | The time duration when rolling back a work unit. |
136+
| [_PREFIX._]unit.retry.attempt | counter | The number of retry attempts. |
137+
| [_PREFIX._]unit.insert | counter | The number of successful inserts performed. |
138+
| [_PREFIX._]unit.update | counter | The number of successful updates performed. |
139+
| [_PREFIX._]unit.delete | counter | The number of successful deletes performed. |
140+
| [_PREFIX._]unit.cache.insert | counter | The number of registered entities inserted into the cache. |
141+
| [_PREFIX._]unit.cache.delete | counter | The number of registered entities removed from the cache. |
117142

118143
### Uniters
144+
119145
In most circumstances, an application has many aspects that result in the
120146
creation of a work unit. To tackle that challenge, we recommend using
121147
[`unit.Uniter`][uniter-doc] to create instances of [`unit.`][unit-doc],
122148
like so:
149+
123150
```go
124151
opts = []unit.Option{
125152
unit.DB(db),
@@ -164,6 +191,9 @@ supported data mapper operations follow this paradigm.
164191
[db-doc]: https://golang.org/pkg/database/sql/#DB
165192
[unit-doc]: https://godoc.org/github.com/freerware/work#Unit
166193
[zap]: https://github.com/uber-go/zap
194+
[log-doc]: https://pkg.go.dev/log
195+
[slog-doc]: https://pkg.go.dev/log/slog
196+
[logrus]: https://github.com/sirupsen/logrus
167197
[tally]: https://github.com/uber-go/tally
168198
[logger-doc]: https://godoc.org/go.uber.org/zap#Logger
169199
[scope-doc]: https://godoc.org/github.com/uber-go/tally#Scope

v4/best_effort_unit.go

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121

2222
"github.com/avast/retry-go/v4"
2323
"go.uber.org/multierr"
24-
"go.uber.org/zap"
2524
)
2625

2726
var (
@@ -43,11 +42,11 @@ type bestEffortUnit struct {
4342

4443
func (u *bestEffortUnit) rollbackInserts(ctx context.Context, mCtx UnitMapperContext) (err error) {
4544
//delete successfully inserted entities.
46-
u.logger.Debug("attempting to rollback inserted entities", zap.Int("count", u.successfulInsertCount))
45+
u.logger.Debug("attempting to rollback inserted entities", "count", u.successfulInsertCount)
4746
for typeName, i := range u.successfulInserts {
4847
if f, ok := u.deleteFunc(typeName); ok {
4948
if err = f(ctx, mCtx, i...); err != nil {
50-
u.logger.Error(err.Error(), zap.String("typeName", typeName.String()))
49+
u.logger.Error(err.Error(), "typeName", typeName.String())
5150
return
5251
}
5352
}
@@ -57,11 +56,11 @@ func (u *bestEffortUnit) rollbackInserts(ctx context.Context, mCtx UnitMapperCon
5756

5857
func (u *bestEffortUnit) rollbackUpdates(ctx context.Context, mCtx UnitMapperContext) (err error) {
5958
//reapply previously registered state for the entities.
60-
u.logger.Debug("attempting to rollback updated entities", zap.Int("count", u.successfulUpdateCount))
59+
u.logger.Debug("attempting to rollback updated entities", "count", u.successfulUpdateCount)
6160
for typeName, r := range u.registered {
6261
if f, ok := u.updateFunc(typeName); ok {
6362
if err = f(ctx, mCtx, r...); err != nil {
64-
u.logger.Error(err.Error(), zap.String("typeName", typeName.String()))
63+
u.logger.Error(err.Error(), "typeName", typeName.String())
6564
return
6665
}
6766
}
@@ -71,11 +70,11 @@ func (u *bestEffortUnit) rollbackUpdates(ctx context.Context, mCtx UnitMapperCon
7170

7271
func (u *bestEffortUnit) rollbackDeletes(ctx context.Context, mCtx UnitMapperContext) (err error) {
7372
//reinsert successfully deleted entities.
74-
u.logger.Debug("attempting to rollback deleted entities", zap.Int("count", u.successfulDeleteCount))
73+
u.logger.Debug("attempting to rollback deleted entities", "count", u.successfulDeleteCount)
7574
for typeName, d := range u.successfulDeletes {
7675
if f, ok := u.insertFunc(typeName); ok {
7776
if err = f(ctx, mCtx, d...); err != nil {
78-
u.logger.Error(err.Error(), zap.String("typeName", typeName.String()))
77+
u.logger.Error(err.Error(), "typeName", typeName.String())
7978
return
8079
}
8180
}
@@ -92,7 +91,7 @@ func (u *bestEffortUnit) rollback(ctx context.Context, mCtx UnitMapperContext) (
9291
stop()
9392
if r := recover(); r != nil {
9493
msg := "panic: unable to rollback work unit"
95-
u.logger.Error(msg, zap.String("panic", fmt.Sprintf("%v", r)))
94+
u.logger.Error(msg, "panic", fmt.Sprintf("%v", r))
9695
u.scope.Counter(rollbackFailure).Inc(1)
9796
panic(r)
9897
}
@@ -128,7 +127,7 @@ func (u *bestEffortUnit) applyInserts(ctx context.Context, mCtx UnitMapperContex
128127
u.executeActions(UnitActionTypeAfterRollback)
129128
}
130129
err = multierr.Combine(err, errRollback)
131-
u.logger.Error(err.Error(), zap.String("typeName", typeName.String()))
130+
u.logger.Error(err.Error(), "typeName", typeName.String())
132131
return
133132
}
134133
if _, ok := u.successfulInserts[typeName]; !ok {
@@ -152,7 +151,7 @@ func (u *bestEffortUnit) applyUpdates(ctx context.Context, mCtx UnitMapperContex
152151
u.executeActions(UnitActionTypeAfterRollback)
153152
}
154153
err = multierr.Combine(err, errRollback)
155-
u.logger.Error(err.Error(), zap.String("typeName", typeName.String()))
154+
u.logger.Error(err.Error(), "typeName", typeName.String())
156155
return
157156
}
158157
if _, ok := u.successfulUpdates[typeName]; !ok {
@@ -176,7 +175,7 @@ func (u *bestEffortUnit) applyDeletes(ctx context.Context, mCtx UnitMapperContex
176175
u.executeActions(UnitActionTypeAfterRollback)
177176
}
178177
err = multierr.Combine(err, errRollback)
179-
u.logger.Error(err.Error(), zap.String("typeName", typeName.String()))
178+
u.logger.Error(err.Error(), "typeName", typeName.String())
180179
return
181180
}
182181
if _, ok := u.successfulDeletes[typeName]; !ok {
@@ -244,8 +243,7 @@ func (u *bestEffortUnit) Save(ctx context.Context) (err error) {
244243
}
245244
err = multierr.Combine(
246245
fmt.Errorf("panic: unable to save work unit\n%v", r), err)
247-
u.logger.Error("panic: unable to save work unit",
248-
zap.String("panic", fmt.Sprintf("%v", r)))
246+
u.logger.Error("panic: unable to save work unit", "panic", fmt.Sprintf("%v", r))
249247
panic(r)
250248
}
251249
if err == nil {
@@ -261,11 +259,7 @@ func (u *bestEffortUnit) Save(ctx context.Context) (err error) {
261259
retry.OnRetry(func(attempt uint, err error) {
262260
u.resetSuccesses()
263261
u.resetSuccessCounts()
264-
u.logger.Warn(
265-
"attempted retry",
266-
zap.Int("attempt", int(attempt+1)),
267-
zap.Error(err),
268-
)
262+
u.logger.Warn("attempted retry", "attempt", int(attempt+1), "error", err.Error())
269263
u.scope.Counter(retryAttempt).Inc(1)
270264
})
271265
u.retryOptions = append(u.retryOptions, retry.Context(ctx), onRetry)

0 commit comments

Comments
 (0)