netlify/functions/stack/index.ts (43 lines of code) (raw):
import type { Config, Context } from "@netlify/functions";
import { BigQuery } from "@google-cloud/bigquery";
const query = `
select
TO_JSON_STRING(stack) as stack,
TO_JSON_STRING(metrics.object.crash_java_exception) as java_exception
from moz-fx-data-shared-prod.crash_ping_ingest_external.ingest_output
left join fenix.crash using (document_id, submission_timestamp)
where document_id = @id and DATE(submission_timestamp) = @date
`;
const BIGQUERY_PROJECT_ID = "moz-fx-data-shared-prod";
export default async (_req: Request, context: Context): Promise<Response> => {
const { date, id } = context.params;
const credentials_json = process.env["GOOGLE_APPLICATION_CREDENTIALS_JSON"];
if (!credentials_json) {
throw new Error("no google application credentials");
}
const credentials = JSON.parse(credentials_json);
const bq = new BigQuery({ projectId: BIGQUERY_PROJECT_ID, credentials });
const stream = bq.createQueryStream({ query, params: { date, id } });
const result: { stack: string, java_exception: string }[] = await new Promise((resolve, reject) => {
const rows: any[] = [];
stream.on('error', reject);
stream.on('data', row => rows.push(row));
stream.on('end', () => resolve(rows));
});
let data: string = "{}";
if (result.length > 0) {
if (result.length > 1) {
console.warn(`more than one result for document_id ${id}, using the first`);
}
data = `{ "stack": ${result[0].stack}, "java_exception": ${result[0].java_exception} }`;
}
return new Response(data, {
headers: {
"Content-Type": "application/json",
}
});
};
export const config: Config = {
path: ["/stack/:date/:id"],
method: ["GET"]
};