feat: improve billing logging

This commit is contained in:
Móricz Gergő 2024-12-17 22:01:41 +01:00
parent ac187452c3
commit 780442d73b
3 changed files with 31 additions and 13 deletions

View File

@ -265,9 +265,10 @@ export async function scrapeController(req: Request, res: Response) {
} }
if (creditsToBeBilled > 0) { if (creditsToBeBilled > 0) {
// billing for doc done on queue end, bill only for llm extraction // billing for doc done on queue end, bill only for llm extraction
billTeam(team_id, chunk?.sub_id, creditsToBeBilled).catch((error) => { billTeam(team_id, chunk?.sub_id, creditsToBeBilled, logger).catch((error) => {
logger.error( logger.error(
`Failed to bill team ${team_id} for ${creditsToBeBilled} credits: ${error}`, `Failed to bill team ${team_id} for ${creditsToBeBilled} credits`,
{ error }
); );
// Optionally, you could notify an admin or add to a retry queue here // Optionally, you could notify an admin or add to a retry queue here
}); });
@ -312,7 +313,7 @@ export async function scrapeController(req: Request, res: Response) {
return res.status(result.returnCode).json(result); return res.status(result.returnCode).json(result);
} catch (error) { } catch (error) {
Sentry.captureException(error); Sentry.captureException(error);
logger.error(error); logger.error("Scrape error occcurred", { error });
return res.status(500).json({ return res.status(500).json({
error: error:
error instanceof ZodError error instanceof ZodError

View File

@ -7,7 +7,7 @@ import {
import { billTeam } from "../services/billing/credit_billing"; import { billTeam } from "../services/billing/credit_billing";
import { Document } from "../controllers/v1/types"; import { Document } from "../controllers/v1/types";
import { supabase_service } from "../services/supabase"; import { supabase_service } from "../services/supabase";
import { logger } from "../lib/logger"; import { logger as _logger } from "../lib/logger";
import { ScrapeEvents } from "../lib/scrape-events"; import { ScrapeEvents } from "../lib/scrape-events";
import { configDotenv } from "dotenv"; import { configDotenv } from "dotenv";
import { import {
@ -66,6 +66,12 @@ export async function runWebScraper({
is_scrape = false, is_scrape = false,
is_crawl = false, is_crawl = false,
}: RunWebScraperParams): Promise<ScrapeUrlResponse> { }: RunWebScraperParams): Promise<ScrapeUrlResponse> {
const logger = _logger.child({
method: "runWebScraper",
module: "runWebscraper",
scrapeId: bull_job_id,
jobId: bull_job_id,
})
const tries = is_crawl ? 3 : 1; const tries = is_crawl ? 3 : 1;
let response: ScrapeUrlResponse | undefined = undefined; let response: ScrapeUrlResponse | undefined = undefined;
@ -75,10 +81,6 @@ export async function runWebScraper({
for (let i = 0; i < tries; i++) { for (let i = 0; i < tries; i++) {
if (i > 0) { if (i > 0) {
logger.debug("Retrying scrape...", { logger.debug("Retrying scrape...", {
scrapeId: bull_job_id,
jobId: bull_job_id,
method: "runWebScraper",
module: "runWebScraper",
tries, tries,
i, i,
previousStatusCode: (response as any)?.document?.metadata?.statusCode, previousStatusCode: (response as any)?.document?.metadata?.statusCode,
@ -171,9 +173,10 @@ export async function runWebScraper({
creditsToBeBilled = 5; creditsToBeBilled = 5;
} }
billTeam(team_id, undefined, creditsToBeBilled).catch((error) => { billTeam(team_id, undefined, creditsToBeBilled, logger).catch((error) => {
logger.error( logger.error(
`Failed to bill team ${team_id} for ${creditsToBeBilled} credits: ${error}`, `Failed to bill team ${team_id} for ${creditsToBeBilled} credits`,
{ error }
); );
// Optionally, you could notify an admin or add to a retry queue here // Optionally, you could notify an admin or add to a retry queue here
}); });
@ -232,6 +235,11 @@ const saveJob = async (
} }
ScrapeEvents.logJobEvent(job, "completed"); ScrapeEvents.logJobEvent(job, "completed");
} catch (error) { } catch (error) {
logger.error(`🐂 Failed to update job status: ${error}`); _logger.error(`🐂 Failed to update job status`, {
module: "runWebScraper",
method: "saveJob",
jobId: job.id,
scrapeId: job.id,
});
} }
}; };

View File

@ -10,6 +10,7 @@ import { issueCredits } from "./issue_credits";
import { redlock } from "../redlock"; import { redlock } from "../redlock";
import { autoCharge } from "./auto_charge"; import { autoCharge } from "./auto_charge";
import { getValue, setValue } from "../redis"; import { getValue, setValue } from "../redis";
import type { Logger } from "winston";
const FREE_CREDITS = 500; const FREE_CREDITS = 500;
@ -20,22 +21,30 @@ export async function billTeam(
team_id: string, team_id: string,
subscription_id: string | null | undefined, subscription_id: string | null | undefined,
credits: number, credits: number,
logger?: Logger,
) { ) {
return withAuth(supaBillTeam, { success: true, message: "No DB, bypassed." })( return withAuth(supaBillTeam, { success: true, message: "No DB, bypassed." })(
team_id, team_id,
subscription_id, subscription_id,
credits, credits,
logger,
); );
} }
export async function supaBillTeam( export async function supaBillTeam(
team_id: string, team_id: string,
subscription_id: string | null | undefined, subscription_id: string | null | undefined,
credits: number, credits: number,
__logger?: Logger,
) { ) {
const _logger = (__logger ?? logger).child({
module: "credit_billing",
method: "supaBillTeam",
});
if (team_id === "preview") { if (team_id === "preview") {
return { success: true, message: "Preview team, no credits used" }; return { success: true, message: "Preview team, no credits used" };
} }
logger.info(`Billing team ${team_id} for ${credits} credits`); _logger.info(`Billing team ${team_id} for ${credits} credits`, { team_id, credits });
const { data, error } = await supabase_service.rpc("bill_team", { const { data, error } = await supabase_service.rpc("bill_team", {
_team_id: team_id, _team_id: team_id,
@ -46,7 +55,7 @@ export async function supaBillTeam(
if (error) { if (error) {
Sentry.captureException(error); Sentry.captureException(error);
logger.error("Failed to bill team: " + JSON.stringify(error)); _logger.error("Failed to bill team.", { error });
return; return;
} }