Skip to content

Commit bdd5a5a

Browse files
committed
chore(webapp,run-engine): downgrade boundary log noise to warn
Several boundary log sites and customer-input validation paths were unconditionally logging at error level for failures the system already handles gracefully (disconnect, retry-skip, return early). This batch downgrades them to warn or counts them as metrics — visibility is preserved in stdout / OTel metrics without surfacing them as alerts. - apiBuilder.server.ts: logBoundaryError helper — warn for AbortError and ServiceValidationError at loader/action boundary catches - handleSocketIo.server.ts: warn for "Worker authentication failed" (system disconnects on auth failure; refs TRI-8863) - waitpointSystem.ts: skip throw and warn when run was canceled while suspended (benign cancel-vs-resume race, no checkpoint to resume from) - runAttemptSystem.ts: warn for failed parse/validate of customer's flushedMetadata (system already returns gracefully) - batch-queue/index.ts: warn for non-retryable batch item failures via result.skipRetries (queue size limit exceeded, etc.) - queryPerformanceMonitor.server.ts: slow queries are observability, not errors — warn - timeoutDeployment.server.ts: deployment-state mismatch is a benign timeout-vs-completion race — warn - platform.v3.server.ts: platform_client.failures_total OTel counter with {function, kind} labels replaces logger.error from BillingClient call sites; helper recordPlatformFailure(fn, kind) - waitpointCompletionPacket.server.ts: log inner uploadError before throwing the wrapper ServiceValidationError so the underlying error context isn't lost
1 parent c69e939 commit bdd5a5a

11 files changed

Lines changed: 181 additions & 114 deletions

File tree

apps/webapp/app/runEngine/concerns/waitpointCompletionPacket.server.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { type IOPacket, packetRequiresOffloading, tryCatch } from "@trigger.dev/
22
import type { AuthenticatedEnvironment } from "~/services/apiAuth.server";
33
import { env } from "~/env.server";
44
import { uploadPacketToObjectStore } from "~/v3/objectStore.server";
5+
import { logger } from "~/services/logger.server";
56
import { ServiceValidationError } from "~/v3/services/common.server";
67

78
function packetExtensionForDataType(dataType: string): string {
@@ -53,6 +54,11 @@ export async function processWaitpointCompletionPacket(
5354
);
5455

5556
if (uploadError) {
57+
logger.error("Failed to upload large waitpoint to object store", {
58+
error: uploadError,
59+
filename,
60+
environmentId: environment.id,
61+
});
5662
throw new ServiceValidationError("Failed to upload large waitpoint to object store", 500);
5763
}
5864

apps/webapp/app/services/platform.v3.server.ts

Lines changed: 50 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { newProjectPath, organizationBillingPath } from "~/utils/pathBuilder";
3131
import { singleton } from "~/utils/singleton";
3232
import { RedisCacheStore } from "./unkey/redisCacheStore.server";
3333
import { $replica } from "~/db.server";
34+
import { metrics } from "@opentelemetry/api";
3435

3536
function initializeClient() {
3637
if (isCloud() && process.env.BILLING_API_URL && process.env.BILLING_API_KEY) {
@@ -43,6 +44,22 @@ function initializeClient() {
4344
}
4445

4546
const client = singleton("billingClient", initializeClient);
47+
// Failures from @trigger.dev/platform billing client calls. Logged at warn
48+
// (so they stay in stdout) and counted as a metric — Sentry was the wrong
49+
// tool for this signal because every task invocation hits these paths.
50+
const platformClientMeter = metrics.getMeter("trigger.dev/platform-client");
51+
const platformClientFailuresCounter = platformClientMeter.createCounter(
52+
"platform_client.failures_total",
53+
{
54+
description:
55+
"Failures returned or thrown by @trigger.dev/platform billing client calls",
56+
}
57+
);
58+
59+
function recordPlatformFailure(fn: string, kind: "caught" | "no_success") {
60+
platformClientFailuresCounter.add(1, { function: fn, kind });
61+
}
62+
4663

4764
function initializePlatformCache() {
4865
const ctx = new DefaultStatefulContext();
@@ -206,7 +223,7 @@ export async function getCurrentPlan(orgId: string) {
206223
firstDayOfNextMonth.setUTCHours(0, 0, 0, 0);
207224

208225
if (!result.success) {
209-
logger.error("Error getting current plan - no success", { orgId, error: result.error });
226+
recordPlatformFailure("getCurrentPlan", "no_success");
210227
return undefined;
211228
}
212229

@@ -222,7 +239,7 @@ export async function getCurrentPlan(orgId: string) {
222239

223240
return { ...result, usage };
224241
} catch (e) {
225-
logger.error("Error getting current plan - caught error", { orgId, error: e });
242+
recordPlatformFailure("getCurrentPlan", "caught");
226243
return undefined;
227244
}
228245
}
@@ -233,13 +250,13 @@ export async function getLimits(orgId: string) {
233250
try {
234251
const result = await client.currentPlan(orgId);
235252
if (!result.success) {
236-
logger.error("Error getting limits - no success", { orgId, error: result.error });
253+
recordPlatformFailure("getLimits", "no_success");
237254
return undefined;
238255
}
239256

240257
return result.v3Subscription?.plan?.limits;
241258
} catch (e) {
242-
logger.error("Error getting limits - caught error", { orgId, error: e });
259+
recordPlatformFailure("getLimits", "caught");
243260
return undefined;
244261
}
245262
}
@@ -315,7 +332,7 @@ export async function customerPortalUrl(orgId: string, orgSlug: string) {
315332
returnUrl: `${env.APP_ORIGIN}${organizationBillingPath({ slug: orgSlug })}`,
316333
});
317334
} catch (e) {
318-
logger.error("Error getting customer portal Url", { orgId, error: e });
335+
recordPlatformFailure("customerPortalUrl", "caught");
319336
return undefined;
320337
}
321338
}
@@ -326,12 +343,12 @@ export async function getPlans() {
326343
try {
327344
const result = await client.plans();
328345
if (!result.success) {
329-
logger.error("Error getting plans - no success", { error: result.error });
346+
recordPlatformFailure("getPlans", "no_success");
330347
return undefined;
331348
}
332349
return result;
333350
} catch (e) {
334-
logger.error("Error getting plans - caught error", { error: e });
351+
recordPlatformFailure("getPlans", "caught");
335352
return undefined;
336353
}
337354
}
@@ -408,12 +425,12 @@ export async function setConcurrencyAddOn(organizationId: string, amount: number
408425
try {
409426
const result = await client.setAddOn(organizationId, { type: "concurrency", amount });
410427
if (!result.success) {
411-
logger.error("Error setting concurrency add on - no success", { error: result.error });
428+
recordPlatformFailure("setConcurrencyAddOn", "no_success");
412429
return undefined;
413430
}
414431
return result;
415432
} catch (e) {
416-
logger.error("Error setting concurrency add on - caught error", { error: e });
433+
recordPlatformFailure("setConcurrencyAddOn", "caught");
417434
return undefined;
418435
}
419436
}
@@ -424,12 +441,12 @@ export async function setSeatsAddOn(organizationId: string, amount: number) {
424441
try {
425442
const result = await client.setAddOn(organizationId, { type: "seats", amount });
426443
if (!result.success) {
427-
logger.error("Error setting seats add on - no success", { error: result.error });
444+
recordPlatformFailure("setSeatsAddOn", "no_success");
428445
return undefined;
429446
}
430447
return result;
431448
} catch (e) {
432-
logger.error("Error setting seats add on - caught error", { error: e });
449+
recordPlatformFailure("setSeatsAddOn", "caught");
433450
return undefined;
434451
}
435452
}
@@ -440,12 +457,12 @@ export async function setBranchesAddOn(organizationId: string, amount: number) {
440457
try {
441458
const result = await client.setAddOn(organizationId, { type: "branches", amount });
442459
if (!result.success) {
443-
logger.error("Error setting branches add on - no success", { error: result.error });
460+
recordPlatformFailure("setBranchesAddOn", "no_success");
444461
return undefined;
445462
}
446463
return result;
447464
} catch (e) {
448-
logger.error("Error setting branches add on - caught error", { error: e });
465+
recordPlatformFailure("setBranchesAddOn", "caught");
449466
return undefined;
450467
}
451468
}
@@ -456,12 +473,12 @@ export async function getUsage(organizationId: string, { from, to }: { from: Dat
456473
try {
457474
const result = await client.usage(organizationId, { from, to });
458475
if (!result.success) {
459-
logger.error("Error getting usage - no success", { error: result.error });
476+
recordPlatformFailure("getUsage", "no_success");
460477
return undefined;
461478
}
462479
return result;
463480
} catch (e) {
464-
logger.error("Error getting usage - caught error", { error: e });
481+
recordPlatformFailure("getUsage", "caught");
465482
return undefined;
466483
}
467484
}
@@ -490,12 +507,12 @@ export async function getUsageSeries(organizationId: string, params: UsageSeries
490507
try {
491508
const result = await client.usageSeries(organizationId, params);
492509
if (!result.success) {
493-
logger.error("Error getting usage series - no success", { error: result.error });
510+
recordPlatformFailure("getUsageSeries", "no_success");
494511
return undefined;
495512
}
496513
return result;
497514
} catch (e) {
498-
logger.error("Error getting usage series - caught error", { error: e });
515+
recordPlatformFailure("getUsageSeries", "caught");
499516
return undefined;
500517
}
501518
}
@@ -514,12 +531,12 @@ export async function reportInvocationUsage(
514531
additionalData,
515532
});
516533
if (!result.success) {
517-
logger.error("Error reporting invocation - no success", { error: result.error });
534+
recordPlatformFailure("reportInvocationUsage", "no_success");
518535
return undefined;
519536
}
520537
return result;
521538
} catch (e) {
522-
logger.error("Error reporting invocation - caught error", { error: e });
539+
recordPlatformFailure("reportInvocationUsage", "caught");
523540
return undefined;
524541
}
525542
}
@@ -550,12 +567,12 @@ export async function getEntitlement(
550567
try {
551568
const response = await client.getEntitlement(organizationId);
552569
if (!response.success) {
553-
logger.error("Error getting entitlement - no success", { error: response.error });
570+
recordPlatformFailure("getEntitlement", "no_success");
554571
return undefined;
555572
}
556573
return response;
557574
} catch (e) {
558-
logger.error("Error getting entitlement - caught error", { error: e });
575+
recordPlatformFailure("getEntitlement", "caught");
559576
return undefined;
560577
}
561578
});
@@ -602,7 +619,7 @@ export async function getBillingAlerts(
602619
if (!client) return undefined;
603620
const result = await client.getBillingAlerts(organizationId);
604621
if (!result.success) {
605-
logger.error("Error getting billing alert", { error: result.error, organizationId });
622+
recordPlatformFailure("getBillingAlert", "no_success");
606623
throw new Error("Error getting billing alert");
607624
}
608625
return result;
@@ -615,7 +632,7 @@ export async function setBillingAlert(
615632
if (!client) return undefined;
616633
const result = await client.updateBillingAlerts(organizationId, alert);
617634
if (!result.success) {
618-
logger.error("Error setting billing alert", { error: result.error, organizationId });
635+
recordPlatformFailure("setBillingAlert", "no_success");
619636
throw new Error("Error setting billing alert");
620637
}
621638
return result;
@@ -628,11 +645,7 @@ export async function generateRegistryCredentials(
628645
if (!client) return undefined;
629646
const result = await client.generateRegistryCredentials(projectId, region);
630647
if (!result.success) {
631-
logger.error("Error generating registry credentials", {
632-
error: result.error,
633-
projectId,
634-
region,
635-
});
648+
recordPlatformFailure("generateRegistryCredentials", "no_success");
636649
throw new Error("Failed to generate registry credentials");
637650
}
638651

@@ -651,13 +664,7 @@ export async function enqueueBuild(
651664
if (!client) return undefined;
652665
const result = await client.enqueueBuild(projectId, { deploymentId, artifactKey, options });
653666
if (!result.success) {
654-
logger.error("Error enqueuing build", {
655-
error: result.error,
656-
projectId,
657-
deploymentId,
658-
artifactKey,
659-
options,
660-
});
667+
recordPlatformFailure("enqueueBuild", "no_success");
661668
throw new Error("Failed to enqueue build");
662669
}
663670

@@ -672,12 +679,12 @@ export async function getPrivateLinks(
672679
const [error, result] = await tryCatch(client.getPrivateLinks(organizationId));
673680

674681
if (error) {
675-
logger.error("Error getting private links", { organizationId, error });
682+
recordPlatformFailure("getPrivateLinks", "caught");
676683
return undefined;
677684
}
678685

679686
if (!result.success) {
680-
logger.error("Error getting private links - no success", { organizationId, error: result.error });
687+
recordPlatformFailure("getPrivateLinks", "no_success");
681688
return undefined;
682689
}
683690

@@ -693,12 +700,12 @@ export async function createPrivateLink(
693700
const [error, result] = await tryCatch(client.createPrivateLink(organizationId, body));
694701

695702
if (error) {
696-
logger.error("Error creating private link", { organizationId, error });
703+
recordPlatformFailure("createPrivateLink", "caught");
697704
throw error;
698705
}
699706

700707
if (!result.success) {
701-
logger.error("Error creating private link - no success", { organizationId, error: result.error });
708+
recordPlatformFailure("createPrivateLink", "no_success");
702709
throw new Error(result.error ?? "Failed to create private link");
703710
}
704711

@@ -714,12 +721,12 @@ export async function deletePrivateLink(
714721
const [error, result] = await tryCatch(client.deletePrivateLink(organizationId, connectionId));
715722

716723
if (error) {
717-
logger.error("Error deleting private link", { organizationId, connectionId, error });
724+
recordPlatformFailure("deletePrivateLink", "caught");
718725
throw error;
719726
}
720727

721728
if (!result.success) {
722-
logger.error("Error deleting private link - no success", { organizationId, connectionId, error: result.error });
729+
recordPlatformFailure("deletePrivateLink", "no_success");
723730
throw new Error(result.error ?? "Failed to delete private link");
724731
}
725732
}
@@ -732,12 +739,12 @@ export async function getPrivateLinkRegions(
732739
const [error, result] = await tryCatch(client.getPrivateLinkRegions(organizationId));
733740

734741
if (error) {
735-
logger.error("Error getting private link regions", { organizationId, error });
742+
recordPlatformFailure("getPrivateLinkRegions", "caught");
736743
return undefined;
737744
}
738745

739746
if (!result.success) {
740-
logger.error("Error getting private link regions - no success", { organizationId, error: result.error });
747+
recordPlatformFailure("getPrivateLinkRegions", "no_success");
741748
return undefined;
742749
}
743750

0 commit comments

Comments
 (0)