From 77cdb1b7c9882188eb9523bafa4c54a383a01e3a Mon Sep 17 00:00:00 2001 From: Tyler Hendrickson <1851017+TylerHendrickson@users.noreply.github.com> Date: Thu, 10 Oct 2024 09:19:05 -0700 Subject: [PATCH] Add tracing instrumentation for ARPA `POST /api/uploads` handler (#3624) * Instrument spans for persist-upload helpers * Annotate express traces with authenticated user info --- .../arpa_reporter/services/persist-upload.js | 58 ++++++++++--------- packages/server/src/lib/access-helpers.js | 16 +++++ 2 files changed, 48 insertions(+), 26 deletions(-) diff --git a/packages/server/src/arpa_reporter/services/persist-upload.js b/packages/server/src/arpa_reporter/services/persist-upload.js index 6fbb7afbf..378f87797 100644 --- a/packages/server/src/arpa_reporter/services/persist-upload.js +++ b/packages/server/src/arpa_reporter/services/persist-upload.js @@ -49,11 +49,13 @@ const jsonFSName = (upload) => { * @throws {ValidationError} */ async function validateBuffer(buffer) { - try { - await XLSX.read(buffer, { type: 'buffer' }); - } catch (e) { - throw new ValidationError(`Cannot parse XLSX from supplied data: ${e}`); - } + return tracer.trace('validateBuffer', async () => { + try { + await XLSX.read(buffer, { type: 'buffer' }); + } catch (e) { + throw new ValidationError(`Cannot parse XLSX from supplied data: ${e}`); + } + }); } /** @@ -111,19 +113,21 @@ function ensureValidNotes(notes) { * @throws {ValidationError} */ async function ensureValidAgencyId(agencyId, userId) { - // If agencyId is null, it's ok. We derive this later from the spreadsheet - // itself in validate-upload. We leave it as null here. - if (!agencyId) { - return null; - } - // Otherwise, we need to make sure the user is associated with the agency - const userRecord = await getUser(userId); - const tenantAgencies = await getTenantAgencies(userRecord.tenant_id); - const agency = tenantAgencies.find((a) => a.id === Number(agencyId)); - if (!agency) { - throw new ValidationError(`Supplied agency ID ${agencyId} does not correspond to an agency in the user's tenant ${userRecord.tenant_id}. Please report this issue to USDR.`); - } - return agencyId; + return tracer.trace('ensureValidAgencyId', async () => { + // If agencyId is null, it's ok. We derive this later from the spreadsheet + // itself in validate-upload. We leave it as null here. + if (!agencyId) { + return null; + } + // Otherwise, we need to make sure the user is associated with the agency + const userRecord = await getUser(userId); + const tenantAgencies = await getTenantAgencies(userRecord.tenant_id); + const agency = tenantAgencies.find((a) => a.id === Number(agencyId)); + if (!agency) { + throw new ValidationError(`Supplied agency ID ${agencyId} does not correspond to an agency in the user's tenant ${userRecord.tenant_id}. Please report this issue to USDR.`); + } + return agencyId; + }); } /** @@ -133,14 +137,16 @@ async function ensureValidAgencyId(agencyId, userId) { * @throws {ValidationError} */ async function ensureValidReportingPeriodId(reportingPeriodId) { - // Get the current reporting period. Passing an undefined value - // defaults to the current period. - const reportingPeriod = await getReportingPeriod(reportingPeriodId); - - if (!reportingPeriod) { - throw new ValidationError(`Supplied reporting period ID ${reportingPeriodId} does not correspond to any existing reporting period. Please report this issue to USDR.`); - } - return reportingPeriod.id; + return tracer.trace('ensureValidReportingPeriodId', async () => { + // Get the current reporting period. Passing an undefined value + // defaults to the current period. + const reportingPeriod = await getReportingPeriod(reportingPeriodId); + + if (!reportingPeriod) { + throw new ValidationError(`Supplied reporting period ID ${reportingPeriodId} does not correspond to any existing reporting period. Please report this issue to USDR.`); + } + return reportingPeriod.id; + }); } /** diff --git a/packages/server/src/lib/access-helpers.js b/packages/server/src/lib/access-helpers.js index baca36150..ce0f5eb0a 100755 --- a/packages/server/src/lib/access-helpers.js +++ b/packages/server/src/lib/access-helpers.js @@ -1,3 +1,4 @@ +const tracer = require('dd-trace'); const { getUser, inTenant } = require('../db'); const { log } = require('./logging'); @@ -83,6 +84,14 @@ async function requireAdminUser(req, res, next) { try { const { user, selectedAgency } = await getAdminAuthInfo(req); req.session = { ...req.session, user, selectedAgency }; + tracer.setUser({ + id: user.id, + agency_id: user.agency_id, + tenant_id: user.tenant_id, + role_name: user.role_name, + selected_agency_id: selectedAgency, + is_user_super_admin: isUSDRSuperAdmin(user), + }); } catch (err) { res.sendStatus(403); return; @@ -116,6 +125,13 @@ async function requireUser(req, res, next) { req.session = { ...req.session, user, selectedAgency: user.agency_id }; + tracer.setUser({ + id: req.session.user?.id, + role: req.session.user?.role.name, + tenant_id: req.session.user?.tenant?.id, + agency_id: req.session.user?.agency?.id, + }); + next(); }