refactor: use structured logger in video adapters (#26285)

- Remove debug console.log/console.error statements
- Add logger.debug for observability (meeting lifecycle events)
- Add logger.error with safe error pattern (message + name only)
- Fix error messages to avoid exposing response details
- Remove redundant try/catch blocks (errors propagate naturally)
This commit is contained in:
Pedro Castro
2026-01-06 22:29:17 -03:00
committed by GitHub
parent 0df161ef26
commit 30ef38804c
2 changed files with 55 additions and 59 deletions
@@ -1,6 +1,7 @@
import { z } from "zod";
import { triggerDelegationCredentialErrorWebhook } from "@calcom/features/webhooks/lib/triggerDelegationCredentialErrorWebhook";
import logger from "@calcom/lib/logger";
import {
CalendarAppDelegationCredentialConfigurationError,
CalendarAppDelegationCredentialInvalidGrantError,
@@ -266,10 +267,12 @@ const TeamsVideoApiAdapter = (credential: CredentialForCalendarServiceWithTenant
if (!resultObject.id || !resultObject.joinUrl || !resultObject.joinWebUrl) {
throw new HttpError({
statusCode: 500,
message: `Error creating MS Teams meeting: ${resultObject.error.message}`,
message: `Error creating MS Teams meeting: ${resultObject.error?.message || "missing required fields in response"}`,
});
}
logger.debug("Teams meeting created", { meetingId: resultObject.id });
return Promise.resolve({
type: "office365_video",
id: resultObject.id,
+51 -58
View File
@@ -1,7 +1,8 @@
import { z } from "zod";
import dayjs from "@calcom/dayjs";
import prisma from "@calcom/prisma";
import logger from "@calcom/lib/logger";
import { prisma } from "@calcom/prisma";
import type { Credential } from "@calcom/prisma/client";
import type { CalendarEvent } from "@calcom/types/Calendar";
import type { CredentialPayload } from "@calcom/types/Credential";
@@ -170,47 +171,43 @@ const WebexVideoApiAdapter = (credential: CredentialPayload): VideoApiAdapter =>
start: meeting.start,
end: meeting.end,
}));
} catch (err) {
console.error(err);
} catch {
logger.error("Error fetching Webex availability");
return [];
}
},
createMeeting: async (event: CalendarEvent): Promise<VideoCallData> => {
/** @link https://developer.webex.com/docs/api/v1/meetings/create-a-meeting */
try {
const response = await fetchWebexApi("meetings", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(translateEvent(event)),
});
if (response.error) {
if (response.error === "invalid_grant") {
await invalidateCredential(credential.id);
return Promise.reject(new Error("Invalid grant for Cal.com webex app"));
}
const response = await fetchWebexApi("meetings", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(translateEvent(event)),
});
if (response.error) {
if (response.error === "invalid_grant") {
await invalidateCredential(credential.id);
return Promise.reject(new Error("Invalid grant for Cal.com webex app"));
}
const result = webexEventResultSchema.parse(response);
if (result.id && result.webLink) {
return {
type: "webex_video",
id: result.id.toString(),
password: result.password || "",
url: result.webLink,
};
}
throw new Error(`Failed to create meeting. Response is ${JSON.stringify(result)}`);
} catch (err) {
console.error(err);
throw new Error("Unexpected error");
}
const result = webexEventResultSchema.parse(response);
if (result.id && result.webLink) {
logger.debug("Webex meeting created", { meetingId: result.id });
return {
type: "webex_video",
id: result.id.toString(),
password: result.password || "",
url: result.webLink,
};
}
throw new Error("Failed to create meeting: missing id or webLink in response");
},
deleteMeeting: async (uid: string): Promise<void> => {
/** @link https://developer.webex.com/docs/api/v1/meetings/delete-a-meeting */
try {
logger.debug("Deleting Webex meeting", { meetingId: uid });
const response = await fetchWebexApi(`meetings/${uid}`, {
method: "DELETE",
});
@@ -220,6 +217,7 @@ const WebexVideoApiAdapter = (credential: CredentialPayload): VideoApiAdapter =>
return Promise.reject(new Error("Invalid grant for Cal.com webex app"));
}
}
logger.debug("Webex meeting deleted", { meetingId: uid });
return Promise.resolve();
} catch {
return Promise.reject(new Error("Failed to delete meeting"));
@@ -227,35 +225,30 @@ const WebexVideoApiAdapter = (credential: CredentialPayload): VideoApiAdapter =>
},
updateMeeting: async (bookingRef: PartialReference, event: CalendarEvent): Promise<VideoCallData> => {
/** @link https://developer.webex.com/docs/api/v1/meetings/update-a-meeting */
try {
const response = await fetchWebexApi(`meetings/${bookingRef.uid}`, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(translateEvent(event)),
});
if (response.error) {
if (response.error === "invalid_grant") {
await invalidateCredential(credential.id);
return Promise.reject(new Error("Invalid grant for Cal.com webex app"));
}
const response = await fetchWebexApi(`meetings/${bookingRef.uid}`, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(translateEvent(event)),
});
if (response.error) {
if (response.error === "invalid_grant") {
await invalidateCredential(credential.id);
return Promise.reject(new Error("Invalid grant for Cal.com webex app"));
}
const result = webexEventResultSchema.parse(response);
if (result.id && result.webLink) {
return {
type: "webex_video",
id: bookingRef.meetingId as string,
password: result.password || "",
url: result.webLink,
};
}
throw new Error(`Failed to create meeting. Response is ${JSON.stringify(result)}`);
} catch (err) {
console.error(err);
throw new Error("Unexpected error");
}
const result = webexEventResultSchema.parse(response);
if (result.id && result.webLink) {
return {
type: "webex_video",
id: bookingRef.meetingId as string,
password: result.password || "",
url: result.webLink,
};
}
throw new Error("Failed to update meeting: missing id or webLink in response");
},
};
};