Skip to content

Commit 129dced

Browse files
AchoArnoldCopilot
andcommitted
refactor(api): use stacktrace formatting helpers
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: ebe8f80e-c697-4bb6-b456-e13081b5bd0f
1 parent af57e73 commit 129dced

90 files changed

Lines changed: 868 additions & 866 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

api/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ require (
1212
github.com/NdoleStudio/go-otelroundtripper v0.0.15
1313
github.com/NdoleStudio/lemonsqueezy-go v1.3.1
1414
github.com/NdoleStudio/plunk-go v0.0.2
15-
github.com/NdoleStudio/stacktrace v1.0.0
15+
github.com/NdoleStudio/stacktrace v1.1.0
1616
github.com/avast/retry-go/v5 v5.0.0
1717
github.com/axiomhq/axiom-go v0.32.0
1818
github.com/carlmjohnson/requests v0.25.1

api/go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ github.com/NdoleStudio/plunk-go v0.0.2 h1:afPW7MHK4Z3rsybpJBnmTmxKCLKF1M7sPI+BNG
6262
github.com/NdoleStudio/plunk-go v0.0.2/go.mod h1:pqG3zKhpn/A2bL1K+WsWzvfTpOeSkYgXhNk5H65uEc8=
6363
github.com/NdoleStudio/stacktrace v1.0.0 h1:YIDg0twM2BXRKIFjorX7v2dC0l8z4VEITurI+MNqvVQ=
6464
github.com/NdoleStudio/stacktrace v1.0.0/go.mod h1:WOBcbXShYu+v8JtjFEM+rRV9GJW50m+dwIvp4sLuVTg=
65+
github.com/NdoleStudio/stacktrace v1.1.0 h1:Ai0j//4tDo/So3nR8bZgS3pQ4NYmViHlarpIReiyb5k=
66+
github.com/NdoleStudio/stacktrace v1.1.0/go.mod h1:WOBcbXShYu+v8JtjFEM+rRV9GJW50m+dwIvp4sLuVTg=
6567
github.com/PuerkitoBio/goquery v1.12.0 h1:pAcL4g3WRXekcB9AU/y1mbKez2dbY2AajVhtkO8RIBo=
6668
github.com/PuerkitoBio/goquery v1.12.0/go.mod h1:802ej+gV2y7bbIhOIoPY5sT183ZW0YFofScC4q/hIpQ=
6769
github.com/andybalholm/brotli v1.2.1 h1:R+f5xP285VArJDRgowrfb9DqL18yVK0gKAW/F+eTWro=

api/pkg/cache/memory_cache.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func (cache *memoryCache) Get(ctx context.Context, key string) (value string, er
3030

3131
response, ok := cache.store.Get(key)
3232
if !ok {
33-
return "", stacktrace.NewError("no item found in cache with key [%s]", key)
33+
return "", stacktrace.NewErrorf("no item found in cache with key [%s]", key)
3434
}
3535

3636
return response.(string), nil

api/pkg/cache/redis_cache.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ func (cache *redisCache) Get(ctx context.Context, key string) (value string, err
3131

3232
response, err := cache.client.Get(ctx, key).Result()
3333
if errors.Is(err, redis.Nil) {
34-
return "", stacktrace.Propagate(err, "no item found in redis with key [%s]", key)
34+
return "", stacktrace.Propagatef(err, "no item found in redis with key [%s]", key)
3535
}
3636
if err != nil {
37-
return "", stacktrace.Propagate(err, "cannot get item in redis with key [%s]", key)
37+
return "", stacktrace.Propagatef(err, "cannot get item in redis with key [%s]", key)
3838
}
3939
return response, nil
4040
}
@@ -46,7 +46,7 @@ func (cache *redisCache) Set(ctx context.Context, key string, value string, ttl
4646

4747
err := cache.client.Set(ctx, key, value, ttl).Err()
4848
if err != nil {
49-
return cache.tracer.WrapErrorSpan(span, stacktrace.Propagate(err, "cannot set item in redis"))
49+
return cache.tracer.WrapErrorSpan(span, stacktrace.Propagatef(err, "cannot set item in redis"))
5050
}
5151
return nil
5252
}

api/pkg/di/container.go

Lines changed: 37 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ func (container *Container) DedicatedDB() (db *gorm.DB) {
268268
}
269269

270270
if err = db.Use(tracing.NewPlugin()); err != nil {
271-
container.logger.Fatal(stacktrace.Propagate(err, "cannot use GORM tracing plugin"))
271+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot use GORM tracing plugin"))
272272
}
273273

274274
container.dedicatedDB = db
@@ -279,11 +279,11 @@ func (container *Container) DedicatedDB() (db *gorm.DB) {
279279

280280
container.logger.Debug(fmt.Sprintf("Running migrations for dedicated [%T]", db))
281281
if err = db.AutoMigrate(&entities.Heartbeat{}); err != nil {
282-
container.logger.Fatal(stacktrace.Propagate(err, "cannot migrate %T", &entities.Heartbeat{}))
282+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot migrate %T", &entities.Heartbeat{}))
283283
}
284284

285285
if err = db.AutoMigrate(&entities.HeartbeatMonitor{}); err != nil {
286-
container.logger.Fatal(stacktrace.Propagate(err, "cannot migrate %T", &entities.HeartbeatMonitor{}))
286+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot migrate %T", &entities.HeartbeatMonitor{}))
287287
}
288288

289289
return container.dedicatedDB
@@ -326,7 +326,7 @@ func (container *Container) DBWithoutMigration() (db *gorm.DB) {
326326
container.db = db
327327

328328
if err = db.Use(tracing.NewPlugin()); err != nil {
329-
container.logger.Fatal(stacktrace.Propagate(err, "cannot use GORM tracing plugin"))
329+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot use GORM tracing plugin"))
330330
}
331331
return container.db
332332
}
@@ -351,7 +351,7 @@ func (container *Container) DB() (db *gorm.DB) {
351351
container.db = db
352352

353353
if err = db.Use(tracing.NewPlugin()); err != nil {
354-
container.logger.Fatal(stacktrace.Propagate(err, "cannot use GORM tracing plugin"))
354+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot use GORM tracing plugin"))
355355
}
356356

357357
if os.Getenv("DATABASE_MIGRATION_SKIP") != "" {
@@ -371,47 +371,47 @@ ALTER TABLE discords ADD CONSTRAINT IF NOT EXISTS uni_discords_server_id CHECK (
371371
}
372372

373373
if err = db.AutoMigrate(&entities.Message{}); err != nil {
374-
container.logger.Fatal(stacktrace.Propagate(err, "cannot migrate %T", &entities.Message{}))
374+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot migrate %T", &entities.Message{}))
375375
}
376376

377377
if err = db.AutoMigrate(&entities.MessageThread{}); err != nil {
378-
container.logger.Fatal(stacktrace.Propagate(err, "cannot migrate %T", &entities.MessageThread{}))
378+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot migrate %T", &entities.MessageThread{}))
379379
}
380380

381381
if err = db.AutoMigrate(&entities.User{}); err != nil {
382-
container.logger.Fatal(stacktrace.Propagate(err, "cannot migrate %T", &entities.User{}))
382+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot migrate %T", &entities.User{}))
383383
}
384384

385385
if err = db.AutoMigrate(&entities.MessageSendSchedule{}); err != nil {
386-
container.logger.Fatal(stacktrace.Propagate(err, "cannot migrate %T", &entities.MessageSendSchedule{}))
386+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot migrate %T", &entities.MessageSendSchedule{}))
387387
}
388388

389389
if err = db.AutoMigrate(&entities.Phone{}); err != nil {
390-
container.logger.Fatal(stacktrace.Propagate(err, "cannot migrate %T", &entities.Phone{}))
390+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot migrate %T", &entities.Phone{}))
391391
}
392392

393393
if err = db.AutoMigrate(&entities.PhoneNotification{}); err != nil {
394-
container.logger.Fatal(stacktrace.Propagate(err, "cannot migrate %T", &entities.PhoneNotification{}))
394+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot migrate %T", &entities.PhoneNotification{}))
395395
}
396396

397397
if err = db.AutoMigrate(&entities.BillingUsage{}); err != nil {
398-
container.logger.Fatal(stacktrace.Propagate(err, "cannot migrate %T", &entities.BillingUsage{}))
398+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot migrate %T", &entities.BillingUsage{}))
399399
}
400400

401401
if err = db.AutoMigrate(&entities.Webhook{}); err != nil {
402-
container.logger.Fatal(stacktrace.Propagate(err, "cannot migrate %T", &entities.Webhook{}))
402+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot migrate %T", &entities.Webhook{}))
403403
}
404404

405405
if err = db.AutoMigrate(&entities.Discord{}); err != nil {
406-
container.logger.Fatal(stacktrace.Propagate(err, "cannot migrate %T", &entities.Discord{}))
406+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot migrate %T", &entities.Discord{}))
407407
}
408408

409409
if err = db.AutoMigrate(&entities.Integration3CX{}); err != nil {
410-
container.logger.Fatal(stacktrace.Propagate(err, "cannot migrate %T", &entities.Integration3CX{}))
410+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot migrate %T", &entities.Integration3CX{}))
411411
}
412412

413413
if err = db.AutoMigrate(&entities.PhoneAPIKey{}); err != nil {
414-
container.logger.Fatal(stacktrace.Propagate(err, "cannot migrate %T", &entities.PhoneAPIKey{}))
414+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot migrate %T", &entities.PhoneAPIKey{}))
415415
}
416416

417417
return container.db
@@ -423,7 +423,7 @@ func (container *Container) FirebaseApp() (app *firebase.App) {
423423

424424
app, err := firebase.NewApp(context.Background(), nil, option.WithCredentialsJSON(container.FirebaseCredentials()))
425425
if err != nil {
426-
container.logger.Fatal(stacktrace.Propagate(err, "cannot initialize firebase application"))
426+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot initialize firebase application"))
427427
}
428428
return app
429429
}
@@ -444,7 +444,7 @@ func (container *Container) Cache() cache.Cache {
444444
container.logger.Debug("creating cache.Cache")
445445
opt, err := redis.ParseURL(os.Getenv("REDIS_URL"))
446446
if err != nil {
447-
container.logger.Fatal(stacktrace.Propagate(err, "cannot parse redis url [%s]", os.Getenv("REDIS_URL")))
447+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot parse redis url [%s]", os.Getenv("REDIS_URL")))
448448
}
449449
if strings.HasPrefix(os.Getenv("REDIS_URL"), "rediss://") {
450450
opt.TLSConfig = &tls.Config{
@@ -456,12 +456,12 @@ func (container *Container) Cache() cache.Cache {
456456

457457
// Enable tracing instrumentation.
458458
if err = redisotel.InstrumentTracing(redisClient); err != nil {
459-
container.logger.Error(stacktrace.Propagate(err, "cannot instrument redis tracing"))
459+
container.logger.Error(stacktrace.Propagatef(err, "cannot instrument redis tracing"))
460460
}
461461

462462
// Enable metrics instrumentation.
463463
if err = redisotel.InstrumentMetrics(redisClient); err != nil {
464-
container.logger.Fatal(stacktrace.Propagate(err, "cannot instrument redis metrics"))
464+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot instrument redis metrics"))
465465
}
466466

467467
return cache.NewRedisCache(container.Tracer(), redisClient)
@@ -472,7 +472,7 @@ func (container *Container) FirebaseAuthClient() (client *auth.Client) {
472472
container.logger.Debug(fmt.Sprintf("creating %T", client))
473473
authClient, err := container.FirebaseApp().Auth(context.Background())
474474
if err != nil {
475-
container.logger.Fatal(stacktrace.Propagate(err, "cannot initialize firebase auth client"))
475+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot initialize firebase auth client"))
476476
}
477477
return authClient
478478
}
@@ -483,7 +483,7 @@ func (container *Container) CloudTasksClient() (client *cloudtasks.Client) {
483483

484484
client, err := cloudtasks.NewClient(context.Background(), option.WithCredentialsJSON(container.FirebaseCredentials()))
485485
if err != nil {
486-
container.logger.Fatal(stacktrace.Propagate(err, "cannot initialize cloud tasks client"))
486+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot initialize cloud tasks client"))
487487
}
488488

489489
return client
@@ -551,7 +551,7 @@ func (container *Container) FCMClient() services.FCMClient {
551551
container.logger.Debug("creating FirebaseFCMClient")
552552
messagingClient, err := container.FirebaseApp().Messaging(context.Background())
553553
if err != nil {
554-
container.logger.Fatal(stacktrace.Propagate(err, "cannot initialize firebase messaging client"))
554+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot initialize firebase messaging client"))
555555
}
556556
return services.NewFirebaseFCMClient(messagingClient)
557557
}
@@ -745,7 +745,7 @@ func (container *Container) Float64Histogram(name, unit, description string) ote
745745
)
746746
histogram, err := meter.Float64Histogram(name, otelMetric.WithUnit(unit), otelMetric.WithDescription(description))
747747
if err != nil {
748-
container.logger.Fatal(stacktrace.Propagate(err, "cannot create float64 histogram"))
748+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot create float64 histogram"))
749749
}
750750
return histogram
751751
}
@@ -1525,7 +1525,7 @@ func (container *Container) RegisterWebsocketListeners() {
15251525
container.logger.Debug(fmt.Sprintf("registering listeners for %T", listeners.WebsocketListener{}))
15261526

15271527
if os.Getenv("PUSHER_SECRET") == "" {
1528-
container.logger.Warn(stacktrace.NewError("skipping websocket listeners because the PUSHER_SECRET env variable is not set"))
1528+
container.logger.Warn(stacktrace.NewErrorf("skipping websocket listeners because the PUSHER_SECRET env variable is not set"))
15291529
return
15301530
}
15311531

@@ -1579,7 +1579,7 @@ func (container *Container) AttachmentRepository() repositories.AttachmentReposi
15791579
container.logger.Debug("creating GoogleCloudStorageAttachmentRepository")
15801580
client, err := storage.NewClient(context.Background(), option.WithAuthCredentialsJSON(option.ServiceAccount, container.FirebaseCredentials()))
15811581
if err != nil {
1582-
container.logger.Fatal(stacktrace.Propagate(err, "cannot create GCS client"))
1582+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot create GCS client"))
15831583
}
15841584
container.attachmentRepository = repositories.NewGoogleCloudStorageAttachmentRepository(
15851585
container.Logger(),
@@ -1767,7 +1767,7 @@ func (container *Container) PhoneRistrettoCache() *ristretto.Cache[string, *enti
17671767
BufferItems: 64,
17681768
})
17691769
if err != nil {
1770-
container.logger.Fatal(stacktrace.Propagate(err, "cannot create phone ristretto cache"))
1770+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot create phone ristretto cache"))
17711771
}
17721772
container.phoneRistrettoCache = ristrettoCache
17731773
return container.phoneRistrettoCache
@@ -1785,7 +1785,7 @@ func (container *Container) UserRistrettoCache() *ristretto.Cache[string, entiti
17851785
BufferItems: 64,
17861786
})
17871787
if err != nil {
1788-
container.logger.Fatal(stacktrace.Propagate(err, "cannot create user ristretto cache"))
1788+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot create user ristretto cache"))
17891789
}
17901790
container.userRistrettoCache = ristrettoCache
17911791
return ristrettoCache
@@ -1801,7 +1801,7 @@ func (container *Container) initializeGoogleTraceProvider(version string, namesp
18011801

18021802
traceExporter, err := cloudtrace.New(cloudtrace.WithProjectID(os.Getenv("GCP_PROJECT_ID")))
18031803
if err != nil {
1804-
container.logger.Fatal(stacktrace.Propagate(err, "cannot create cloud trace traceExporter"))
1804+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot create cloud trace traceExporter"))
18051805
}
18061806

18071807
tp := trace.NewTracerProvider(
@@ -1813,7 +1813,7 @@ func (container *Container) initializeGoogleTraceProvider(version string, namesp
18131813

18141814
metricExporter, err := mexporter.New(mexporter.WithProjectID(os.Getenv("GCP_PROJECT_ID")))
18151815
if err != nil {
1816-
container.logger.Fatal(stacktrace.Propagate(err, "cannot create cloud metric traceExporter"))
1816+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot create cloud metric traceExporter"))
18171817
}
18181818

18191819
meterProvider := metric.NewMeterProvider(
@@ -1824,10 +1824,10 @@ func (container *Container) initializeGoogleTraceProvider(version string, namesp
18241824

18251825
return func() {
18261826
if err = metricExporter.Shutdown(context.Background()); err != nil {
1827-
container.logger.Error(stacktrace.Propagate(err, "cannot shutdown cloud metric metric exporter"))
1827+
container.logger.Error(stacktrace.Propagatef(err, "cannot shutdown cloud metric metric exporter"))
18281828
}
18291829
if err = traceExporter.Shutdown(context.Background()); err != nil {
1830-
container.logger.Error(stacktrace.Propagate(err, "cannot shutdown cloud trace trace exporter"))
1830+
container.logger.Error(stacktrace.Propagatef(err, "cannot shutdown cloud trace trace exporter"))
18311831
}
18321832
}
18331833
}
@@ -1846,7 +1846,7 @@ func (container *Container) initializeAxiomTraceProvider(version string, namespa
18461846
otlptracehttp.WithHeaders(traceHeaders),
18471847
)
18481848
if err != nil {
1849-
container.logger.Fatal(stacktrace.Propagate(err, "cannot create axiom OTLP trace exporter"))
1849+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot create axiom OTLP trace exporter"))
18501850
}
18511851

18521852
tp := trace.NewTracerProvider(
@@ -1872,7 +1872,7 @@ func (container *Container) initializeAxiomTraceProvider(version string, namespa
18721872
otlpmetrichttp.WithHeaders(metricHeaders),
18731873
)
18741874
if err != nil {
1875-
container.logger.Fatal(stacktrace.Propagate(err, "cannot create axiom OTLP metric exporter"))
1875+
container.logger.Fatal(stacktrace.Propagatef(err, "cannot create axiom OTLP metric exporter"))
18761876
}
18771877

18781878
meterProvider := metric.NewMeterProvider(
@@ -1883,10 +1883,10 @@ func (container *Container) initializeAxiomTraceProvider(version string, namespa
18831883

18841884
return func() {
18851885
if err := tp.Shutdown(context.Background()); err != nil {
1886-
container.logger.Error(stacktrace.Propagate(err, "cannot shutdown axiom trace provider"))
1886+
container.logger.Error(stacktrace.Propagatef(err, "cannot shutdown axiom trace provider"))
18871887
}
18881888
if err := meterProvider.Shutdown(context.Background()); err != nil {
1889-
container.logger.Error(stacktrace.Propagate(err, "cannot shutdown axiom meter provider"))
1889+
container.logger.Error(stacktrace.Propagatef(err, "cannot shutdown axiom meter provider"))
18901890
}
18911891
}
18921892
}
@@ -1937,7 +1937,7 @@ func axiomLogger(skipFrameCount int) *zerodriver.Logger {
19371937
axiomzerolog.SetDataset(os.Getenv("AXIOM_DATASET_EVENTS")),
19381938
)
19391939
if err != nil {
1940-
log.Fatal(stacktrace.Propagate(err, "cannot create axiom zerolog writer"))
1940+
log.Fatal(stacktrace.Propagatef(err, "cannot create axiom zerolog writer"))
19411941
}
19421942

19431943
zl := zerolog.New(axiomWriter).With().Timestamp().CallerWithSkipFrameCount(skipFrameCount).Logger()

api/pkg/emails/hermes_notification_email_factory.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,12 @@ func (factory *hermesNotificationEmailFactory) DiscordSendFailed(user *entities.
6262

6363
html, err := factory.generator.GenerateHTML(email)
6464
if err != nil {
65-
return nil, stacktrace.Propagate(err, "cannot generate html email")
65+
return nil, stacktrace.Propagatef(err, "cannot generate html email")
6666
}
6767

6868
text, err := factory.generator.GeneratePlainText(email)
6969
if err != nil {
70-
return nil, stacktrace.Propagate(err, "cannot generate text email")
70+
return nil, stacktrace.Propagatef(err, "cannot generate text email")
7171
}
7272

7373
return &Email{
@@ -120,7 +120,7 @@ func (factory *hermesNotificationEmailFactory) WebhookSendFailed(user *entities.
120120

121121
html, err := factory.generator.GenerateHTML(email)
122122
if err != nil {
123-
return nil, stacktrace.Propagate(err, "cannot generate html email")
123+
return nil, stacktrace.Propagatef(err, "cannot generate html email")
124124
}
125125

126126
eventPayloadEntryIndex := len(email.Body.Dictionary) - 1
@@ -129,7 +129,7 @@ func (factory *hermesNotificationEmailFactory) WebhookSendFailed(user *entities.
129129
return factory.generator.GeneratePlainText(email)
130130
}, formattedPayload)
131131
if err != nil {
132-
return nil, stacktrace.Propagate(err, "cannot generate text email")
132+
return nil, stacktrace.Propagatef(err, "cannot generate text email")
133133
}
134134

135135
return &Email{
@@ -198,12 +198,12 @@ func (factory *hermesNotificationEmailFactory) MessageExpired(user *entities.Use
198198

199199
html, err := factory.generator.GenerateHTML(email)
200200
if err != nil {
201-
return nil, stacktrace.Propagate(err, "cannot generate html email")
201+
return nil, stacktrace.Propagatef(err, "cannot generate html email")
202202
}
203203

204204
text, err := factory.generator.GeneratePlainText(email)
205205
if err != nil {
206-
return nil, stacktrace.Propagate(err, "cannot generate text email")
206+
return nil, stacktrace.Propagatef(err, "cannot generate text email")
207207
}
208208

209209
return &Email{
@@ -249,12 +249,12 @@ func (factory *hermesNotificationEmailFactory) MessageFailed(user *entities.User
249249

250250
html, err := factory.generator.GenerateHTML(email)
251251
if err != nil {
252-
return nil, stacktrace.Propagate(err, "cannot generate html email")
252+
return nil, stacktrace.Propagatef(err, "cannot generate html email")
253253
}
254254

255255
text, err := factory.generator.GeneratePlainText(email)
256256
if err != nil {
257-
return nil, stacktrace.Propagate(err, "cannot generate text email")
257+
return nil, stacktrace.Propagatef(err, "cannot generate text email")
258258
}
259259

260260
return &Email{

0 commit comments

Comments
 (0)