-
Notifications
You must be signed in to change notification settings - Fork 71
1040 Fix CW doc download including correlation ID #3515
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 1040-fix-cw-doc-download-log-id
Are you sure you want to change the base?
1040 Fix CW doc download including correlation ID #3515
Conversation
WalkthroughAdds await and error-reporting adjustments in CommonWell document download; centralizes and refines Lambda error handling in core; wraps document-downloader Lambda handler with try/catch to enrich capture context on MetriportError before rethrowing. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant API as API (document-query)
participant L as Lambda: document-downloader
participant CW as CommonWell API
API->>L: triggerDownloadDocument(request) [await]
alt Success
L->>CW: download(documentId, creds)
CW-->>L: file stream/data
L-->>API: File
else Error
L->>L: throw MetriportError/other with additionalInfo
L-->>API: error (rethrow)
API->>API: outer handler processes error (inner logging removed)
end
sequenceDiagram
autonumber
participant Core as core/aws/lambda.getLambdaResultPayload
participant Log as Logger
Core->>Core: isLambdaError(result)?
alt Yes
Core->>Log: log "Error calling lambda <name>" with errorDetails
opt Error type routing
alt BadRequest
Core->>Core: throw BadRequestError(msg, additionalInfo)
else NotFound
Core->>Core: throw NotFoundError(msg, additionalInfo)
else Other
Core->>Core: throw MetriportError(msg, additionalInfo)
end
end
else No
Core-->>Core: return payload (or undefined if failGraceful)
end
sequenceDiagram
autonumber
participant DL as document-downloader handler
participant Cap as capture
DL->>DL: initialExtra = { lambdaName }
DL->>Cap: setUser / setExtra(initialExtra)
DL->>DL: try main download flow
alt Error
DL->>DL: if isMetriportError(e) merge e.additionalInfo into extras
DL->>Cap: setExtra(merged)
DL->>DL: rethrow
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
✨ Finishing Touches
🧪 Generate unit tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
22c665a
to
941775a
Compare
…wnloader Ref. metriport/metriport-internal#1040 Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
Ref. metriport/metriport-internal#1040 Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
Ref. metriport/metriport-internal#1040 Signed-off-by: Rafael Leite <2132564+leite08@users.noreply.github.com>
941775a
to
1ea9b49
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/api/src/external/commonwell/document/document-query.ts (1)
627-641
: Preserve stack traces in Sentry by capturing the original error objectUsing capture.error(msg, { extra: { error } }) records a string as the exception and puts the actual error object in extra, which drops the stack trace in Sentry. Capture the error itself and move the message into extra to retain the stack and align with our guideline to keep the original error/cause.
Apply this diff:
- const msg = `Error downloading from CW and upserting to FHIR`; - log(`${msg}: (docId ${doc.id}): ${errorToString(error)}`); - capture.error(msg, { - extra: { - context: `cw.downloadDocsAndUpsertFHIR.downloadFromCWAndUploadToS3`, - patientId: patient.id, - documentReference: doc, - requestId, - error, - }, - }); + const msg = `Error downloading from CW and upserting to FHIR`; + log(`${msg}: (docId ${doc.id}): ${errorToString(error)}`); + capture.error(error, { + extra: { + context: `cw.downloadDocsAndUpsertFHIR.downloadFromCWAndUploadToS3`, + patientId: patient.id, + documentReference: doc, + requestId, + message: msg, + }, + });
🧹 Nitpick comments (1)
packages/lambdas/src/document-downloader.ts (1)
83-90
: Enrich error scope for MetriportError is good; ensure requestId is presentMerging error.additionalInfo with initialExtra before rethrow preserves context and lets Sentry pick it up via the wrapper. Once requestId is added to initialExtra (see above), it will be present for both MetriportError and non-MetriportError cases. Looks good otherwise.
If you want requestId present even when additionalInfo already contains another requestId key, prefer requestId from the request (initialExtra) to avoid mismatch: set it last in the spread.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled
- Linear integration is disabled
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (3)
packages/api/src/external/commonwell/document/document-query.ts
(2 hunks)packages/core/src/external/aws/lambda.ts
(2 hunks)packages/lambdas/src/document-downloader.ts
(2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{js,jsx,ts,tsx}
: Don’t use null inside the app, only on code interacting with external interfaces/services, like DB and HTTP; convert to undefined before sending inwards into the code
Useconst
whenever possible
Useasync/await
instead of.then()
Naming: classes, enums: PascalCase
Naming: constants, variables, functions: camelCase
Naming: file names: kebab-case
Naming: Don’t use negative names, likenotEnabled
, preferisDisabled
If possible, use decomposing objects for function parameters
Prefer Nullish Coalesce (??) than the OR operator (||) when you want to provide a default value
Avoid creating arrow functions
Use truthy syntax instead ofin
- i.e.,if (data.link)
notif ('link' in data)
While handling errors, keep the stack trace around: if you create a new Error (e.g., MetriportError), make sure to pass the original error as the new one’s cause so the stack trace is available upstream.
max column length is 100 chars
multi-line comments use/** */
top-level comments go after the import (save pre-import to basic file header, like license)
move literals to constants declared after imports when possible
Files:
packages/lambdas/src/document-downloader.ts
packages/core/src/external/aws/lambda.ts
packages/api/src/external/commonwell/document/document-query.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursorrules)
Use types whenever possible
Files:
packages/lambdas/src/document-downloader.ts
packages/core/src/external/aws/lambda.ts
packages/api/src/external/commonwell/document/document-query.ts
**/*.ts
⚙️ CodeRabbit configuration file
**/*.ts
: - Use the Onion Pattern to organize a package's code in layers
- Try to use immutable code and avoid sharing state across different functions, objects, and systems
- Try to build code that's idempotent whenever possible
- Prefer functional programming style functions: small, deterministic, 1 input, 1 output
- Minimize coupling / dependencies
- Avoid modifying objects received as parameter
- Only add comments to code to explain why something was done, not how it works
- Naming
- classes, enums:
PascalCase
- constants, variables, functions:
camelCase
- file names:
kebab-case
- table and column names:
snake_case
- Use meaningful names, so whoever is reading the code understands what it means
- Don’t use negative names, like
notEnabled
, preferisDisabled
- For numeric values, if the type doesn’t convey the unit, add the unit to the name
- Typescript
- Use types
- Prefer
const
instead oflet
- Avoid
any
and casting fromany
to other types- Type predicates: only applicable to narrow down the type, not to force a complete type conversion
- Prefer deconstructing parameters for functions instead of multiple parameters that might be of
the same type- Don’t use
null
inside the app, only on code interacting with external interfaces/services,
like DB and HTTP; convert toundefined
before sending inwards into the code- Use
async/await
instead of.then()
- Use the strict equality operator
===
, don’t use abstract equality operator==
- When calling a Promise-returning function asynchronously (i.e., not awaiting), use
.catch()
to
handle errors (seeprocessAsyncError
andemptyFunction
depending on the case)- Date and Time
- Always use
buildDayjs()
to createdayjs
instances- Prefer
dayjs.duration(...)
to create duration consts and keep them asduration
- Prefer Nullish Coalesce (??) than the OR operator (||) to provide a default value
- Avoid creating arrow functions
- U...
Files:
packages/lambdas/src/document-downloader.ts
packages/core/src/external/aws/lambda.ts
packages/api/src/external/commonwell/document/document-query.ts
🧠 Learnings (2)
📓 Common learnings
Learnt from: thomasyopes
PR: metriport/metriport#3608
File: packages/lambdas/src/ehr-compute-resource-diff-bundles.ts:58-62
Timestamp: 2025-04-23T19:00:49.707Z
Learning: For Lambda functions in the metriport codebase, the team prefers to let the default Lambda error handling catch JSON parsing errors rather than adding explicit try/catch blocks.
Learnt from: thomasyopes
PR: metriport/metriport#3572
File: packages/core/src/external/carequality/ihe-gateway-v2/outbound/ihe-gateway-v2-logic.ts:0-0
Timestamp: 2025-04-01T20:10:45.776Z
Learning: In the IHE Gateway V2 implementation, S3 write operations rely on AWS Lambda's built-in error handling infrastructure rather than explicit try-catch blocks in the code.
Learnt from: RamilGaripov
PR: metriport/metriport#4412
File: packages/commonwell-sdk/src/client/commonwell-member.ts:231-233
Timestamp: 2025-08-25T17:52:19.907Z
Learning: In packages/commonwell-sdk/src/client/commonwell-member.ts, the getOneOrg method currently returns undefined for all non-404 HTTP errors (instead of throwing MetriportError) as a temporary workaround while waiting for the service provider to fix issues on their end. This is tracked in TODO ENG-668 and will be reverted later once the external dependency is resolved.
Learnt from: leite08
PR: metriport/metriport#4013
File: packages/core/src/fhir-to-cda/cda-templates/components/procedures.ts:104-105
Timestamp: 2025-06-12T22:53:09.606Z
Learning: User leite08 prefers responses in English only.
Learnt from: leite08
PR: metriport/metriport#3991
File: packages/core/src/external/aws/s3.ts:621-630
Timestamp: 2025-06-10T22:20:21.203Z
Learning: User leite08 prefers that all review comments are written in English.
📚 Learning: 2025-04-23T19:00:49.707Z
Learnt from: thomasyopes
PR: metriport/metriport#3608
File: packages/lambdas/src/ehr-compute-resource-diff-bundles.ts:58-62
Timestamp: 2025-04-23T19:00:49.707Z
Learning: For Lambda functions in the metriport codebase, the team prefers to let the default Lambda error handling catch JSON parsing errors rather than adding explicit try/catch blocks.
Applied to files:
packages/core/src/external/aws/lambda.ts
🧬 Code graph analysis (2)
packages/lambdas/src/document-downloader.ts (3)
packages/lambdas/src/shared/capture.ts (1)
capture
(16-73)packages/core/src/external/commonwell/document/document-downloader-local.ts (1)
DocumentDownloaderLocal
(28-313)packages/shared/src/error/metriport-error.ts (1)
isMetriportError
(13-15)
packages/core/src/external/aws/lambda.ts (2)
packages/core/src/util/log.ts (1)
log
(9-22)packages/shared/src/error/metriport-error.ts (1)
MetriportError
(5-11)
🔇 Additional comments (3)
packages/api/src/external/commonwell/document/document-query.ts (1)
585-593
: Good catch: awaiting triggerDownloadDocument prevents downstream type/logic bugsAwaiting the download ensures file is a resolved File (not a pending Promise) before we read its fields. This removes a subtle race that could have surfaced as undefined properties or failed conversions.
packages/lambdas/src/document-downloader.ts (1)
13-13
: Import looks correct and scopedisMetriportError import is used solely for enriching context on MetriportError paths. No issues.
packages/core/src/external/aws/lambda.ts (1)
1-2
: Explicitly importing BadRequestError and NotFoundError is correctThe new imports clarify intent and avoid accidental circular imports. No concerns.
const msgBase = `calling lambda ${lambdaName}`; | ||
const msg = `Error ${msgBase}`; | ||
const lambdaError = getLambdaError(result); | ||
const errorDetails = JSON.stringify(lambdaError); | ||
log(`${msg} - ${errorDetails}`); | ||
if (failGracefully) return undefined; | ||
|
||
if (lambdaError?.errorType === "BadRequestError" && lambdaError?.errorMessage) { | ||
throw new BadRequestError(lambdaError.errorMessage); | ||
const additionalInfo = { lambdaName, errorDetails }; | ||
if (lambdaError?.errorType === "BadRequestError") { | ||
const errorMessage = lambdaError?.errorMessage ?? `BadRequestError ${msgBase}`; | ||
throw new BadRequestError(errorMessage, undefined, additionalInfo); | ||
} | ||
if (lambdaError?.errorType === "NotFoundError") { | ||
throw new NotFoundError(msg, undefined, { lambdaName, errorDetails }); | ||
throw new NotFoundError(`NotFoundError ${msgBase}`, undefined, additionalInfo); | ||
} | ||
throw new MetriportError(msg, undefined, { lambdaName, errorDetails }); | ||
throw new MetriportError(msg, undefined, additionalInfo); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Preserve original error details as the cause when rethrowing mapped errors
Per our guidelines, keep the stack/trace chain by passing the original error as cause. Here, lambdaError isn’t an Error instance, but it carries the details; passing it as cause preserves context upstream. Also ensures consistency across BadRequestError/NotFoundError/MetriportError paths.
- const additionalInfo = { lambdaName, errorDetails };
+ const additionalInfo = { lambdaName, errorDetails };
if (lambdaError?.errorType === "BadRequestError") {
const errorMessage = lambdaError?.errorMessage ?? `BadRequestError ${msgBase}`;
- throw new BadRequestError(errorMessage, undefined, additionalInfo);
+ throw new BadRequestError(errorMessage, lambdaError, additionalInfo);
}
if (lambdaError?.errorType === "NotFoundError") {
- throw new NotFoundError(`NotFoundError ${msgBase}`, undefined, additionalInfo);
+ throw new NotFoundError(`NotFoundError ${msgBase}`, lambdaError, additionalInfo);
}
- throw new MetriportError(msg, undefined, additionalInfo);
+ throw new MetriportError(msg, lambdaError, additionalInfo);
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const msgBase = `calling lambda ${lambdaName}`; | |
const msg = `Error ${msgBase}`; | |
const lambdaError = getLambdaError(result); | |
const errorDetails = JSON.stringify(lambdaError); | |
log(`${msg} - ${errorDetails}`); | |
if (failGracefully) return undefined; | |
if (lambdaError?.errorType === "BadRequestError" && lambdaError?.errorMessage) { | |
throw new BadRequestError(lambdaError.errorMessage); | |
const additionalInfo = { lambdaName, errorDetails }; | |
if (lambdaError?.errorType === "BadRequestError") { | |
const errorMessage = lambdaError?.errorMessage ?? `BadRequestError ${msgBase}`; | |
throw new BadRequestError(errorMessage, undefined, additionalInfo); | |
} | |
if (lambdaError?.errorType === "NotFoundError") { | |
throw new NotFoundError(msg, undefined, { lambdaName, errorDetails }); | |
throw new NotFoundError(`NotFoundError ${msgBase}`, undefined, additionalInfo); | |
} | |
throw new MetriportError(msg, undefined, { lambdaName, errorDetails }); | |
throw new MetriportError(msg, undefined, additionalInfo); | |
} | |
const msgBase = `calling lambda ${lambdaName}`; | |
const msg = `Error ${msgBase}`; | |
const lambdaError = getLambdaError(result); | |
const errorDetails = JSON.stringify(lambdaError); | |
log(`${msg} - ${errorDetails}`); | |
if (failGracefully) return undefined; | |
const additionalInfo = { lambdaName, errorDetails }; | |
if (lambdaError?.errorType === "BadRequestError") { | |
const errorMessage = lambdaError?.errorMessage ?? `BadRequestError ${msgBase}`; | |
throw new BadRequestError(errorMessage, lambdaError, additionalInfo); | |
} | |
if (lambdaError?.errorType === "NotFoundError") { | |
throw new NotFoundError(`NotFoundError ${msgBase}`, lambdaError, additionalInfo); | |
} | |
throw new MetriportError(msg, lambdaError, additionalInfo); | |
} |
🤖 Prompt for AI Agents
In packages/core/src/external/aws/lambda.ts around lines 115-131, the mapped
errors are rethrown without preserving the original lambda error as the cause;
capture the original lambdaError (or wrap it in an Error with its JSON/details)
and pass it as the cause when throwing BadRequestError, NotFoundError, and
MetriportError so the stack/trace chain is preserved; keep additionalInfo as-is
but include the original error as the cause argument to each thrown error.
export const handler = Sentry.AWSLambda.wrapHandler( | ||
async (req: DocumentDownloaderLambdaRequest): Promise<DownloadResult> => { | ||
const { orgName, orgOid, npi, cxId, fileInfo, document } = req; | ||
capture.setUser({ id: cxId }); | ||
capture.setExtra({ lambdaName }); | ||
console.log( | ||
`Running with envType: ${getEnvType()}, apiMode: ${apiMode}, region: ${region}, ` + | ||
`bucketName: ${bucketName}, orgName: ${orgName}, orgOid: ${orgOid}, ` + | ||
`npi: ${npi}, cxId: ${cxId}, fileInfo: ${JSON.stringify(fileInfo)}, ` + | ||
`document: ${JSON.stringify(document)}` | ||
); | ||
const initialExtra = { lambdaName }; | ||
try { | ||
const { orgName, orgOid, npi, cxId, fileInfo, document } = req; | ||
capture.setUser({ id: cxId }); | ||
capture.setExtra(initialExtra); | ||
console.log( | ||
`Running with envType: ${getEnvType()}, apiMode: ${apiMode}, region: ${region}, ` + | ||
`bucketName: ${bucketName}, orgName: ${orgName}, orgOid: ${orgOid}, ` + | ||
`npi: ${npi}, cxId: ${cxId}, fileInfo: ${JSON.stringify(fileInfo)}, ` + | ||
`document: ${JSON.stringify(document)}` | ||
); | ||
|
||
const cwOrgCertificate: string = (await getSecret(cwOrgCertificateSecret)) as string; | ||
if (!cwOrgCertificate) { | ||
throw new Error(`Config error - CW_ORG_CERTIFICATE doesn't exist`); | ||
} | ||
const cwOrgCertificate: string = (await getSecret(cwOrgCertificateSecret)) as string; | ||
if (!cwOrgCertificate) { | ||
throw new Error(`Config error - CW_ORG_CERTIFICATE doesn't exist`); | ||
} | ||
|
||
const cwOrgPrivateKey: string = (await getSecret(cwOrgPrivateKeySecret)) as string; | ||
if (!cwOrgPrivateKey) { | ||
throw new Error(`Config error - CW_ORG_PRIVATE_KEY doesn't exist`); | ||
} | ||
const cwOrgPrivateKey: string = (await getSecret(cwOrgPrivateKeySecret)) as string; | ||
if (!cwOrgPrivateKey) { | ||
throw new Error(`Config error - CW_ORG_PRIVATE_KEY doesn't exist`); | ||
} | ||
|
||
const commonWell = makeCommonWellAPI( | ||
cwOrgCertificate, | ||
cwOrgPrivateKey, | ||
orgName, | ||
addOidPrefix(orgOid) | ||
); | ||
const queryMeta = organizationQueryMeta(orgName, { npi: npi }); | ||
const commonWell = makeCommonWellAPI( | ||
cwOrgCertificate, | ||
cwOrgPrivateKey, | ||
orgName, | ||
addOidPrefix(orgOid) | ||
); | ||
const queryMeta = organizationQueryMeta(orgName, { npi: npi }); | ||
|
||
const docDownloader = new DocumentDownloaderLocal({ | ||
region, | ||
bucketName, | ||
commonWell: { | ||
api: commonWell, | ||
queryMeta, | ||
}, | ||
capture, | ||
}); | ||
const result = await docDownloader.download({ document, fileInfo }); | ||
const docDownloader = new DocumentDownloaderLocal({ | ||
region, | ||
bucketName, | ||
commonWell: { | ||
api: commonWell, | ||
queryMeta, | ||
}, | ||
capture, | ||
}); | ||
const result = await docDownloader.download({ document, fileInfo }); | ||
|
||
console.log(`Done - ${JSON.stringify(result)}`); | ||
return result; | ||
console.log(`Done - ${JSON.stringify(result)}`); | ||
return result; | ||
} catch (error) { | ||
if (isMetriportError(error)) { | ||
capture.setExtra({ | ||
...initialExtra, | ||
...error.additionalInfo, | ||
}); | ||
} | ||
throw error; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Confirm requestId exists on DocumentDownloaderLambdaRequest
To avoid a type error, verify that DocumentDownloaderLambdaRequest includes requestId. If it does not, we should extend the type and the caller to include it.
🏁 Script executed:
#!/bin/bash
# Verify that DocumentDownloaderLambdaRequest includes `requestId`
rg -nP "export\s+type\s+DocumentDownloaderLambdaRequest\b" -C3 \
packages | sed -n '1,200p'
rg -nP "\bDocumentDownloaderLambdaRequest\b" -C3 packages \
| rg -nP "requestId"
Length of output: 924
Add missing requestId
field to DocumentDownloaderLambdaRequest
It looks like the DocumentDownloaderLambdaRequest
type is currently defined with only the following properties:
orgName: string
orgOid: string
npi: string
There is no requestId
(and no cxId
, fileInfo
, or document
) on that type, yet the handler destructures and uses cxId
, fileInfo
, document
, and should also capture a requestId
for proper Sentry context. We need to update both the core type and the lambda caller to include requestId
.
Please update:
-
Type definition (
packages/core/src/external/commonwell/document/document-downloader-lambda.ts
):export type DocumentDownloaderLambdaRequest = { orgName: string; orgOid: string; npi: string; + requestId: string; + cxId: string; + fileInfo: SomeFileInfoType; // replace with actual fileInfo shape + document: SomeDocumentType; // replace with actual document shape };
-
Caller (wherever this lambda is invoked): ensure the payload includes
requestId
, alongside the other properties:{ orgName, orgOid, npi, + requestId: context.awsRequestId, // or however you obtain the Lambda request ID + cxId, + fileInfo, + document, }
Once the type and all invocations are updated, the handler’s destructuring will align with its input type, and you’ll be able to safely capture requestId
in Sentry for full traceability.
Committable suggestion skipped: line range outside the PR's diff.
const initialExtra = { lambdaName }; | ||
try { | ||
const { orgName, orgOid, npi, cxId, fileInfo, document } = req; | ||
capture.setUser({ id: cxId }); | ||
capture.setExtra(initialExtra); | ||
console.log( | ||
`Running with envType: ${getEnvType()}, apiMode: ${apiMode}, region: ${region}, ` + | ||
`bucketName: ${bucketName}, orgName: ${orgName}, orgOid: ${orgOid}, ` + | ||
`npi: ${npi}, cxId: ${cxId}, fileInfo: ${JSON.stringify(fileInfo)}, ` + | ||
`document: ${JSON.stringify(document)}` | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Include the correlation ID (requestId) in Sentry extras and logs
Goal of the PR is to carry correlation ID through the CW download flow. We receive requestId on the Lambda request but we’re not setting it in the scope extras or logs. Add it to initialExtra and to the log for consistent traceability across services.
- const initialExtra = { lambdaName };
+ const initialExtra = { lambdaName, requestId: req.requestId };
try {
- const { orgName, orgOid, npi, cxId, fileInfo, document } = req;
+ const { orgName, orgOid, npi, cxId, fileInfo, document, requestId } = req;
capture.setUser({ id: cxId });
capture.setExtra(initialExtra);
console.log(
- `Running with envType: ${getEnvType()}, apiMode: ${apiMode}, region: ${region}, ` +
- `bucketName: ${bucketName}, orgName: ${orgName}, orgOid: ${orgOid}, ` +
- `npi: ${npi}, cxId: ${cxId}, fileInfo: ${JSON.stringify(fileInfo)}, ` +
- `document: ${JSON.stringify(document)}`
+ `Running with envType: ${getEnvType()}, apiMode: ${apiMode}, region: ${region}, ` +
+ `bucketName: ${bucketName}, orgName: ${orgName}, orgOid: ${orgOid}, ` +
+ `npi: ${npi}, cxId: ${cxId}, requestId: ${requestId}, ` +
+ `fileInfo: ${JSON.stringify(fileInfo)}, document: ${JSON.stringify(document)}`
);
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const initialExtra = { lambdaName }; | |
try { | |
const { orgName, orgOid, npi, cxId, fileInfo, document } = req; | |
capture.setUser({ id: cxId }); | |
capture.setExtra(initialExtra); | |
console.log( | |
`Running with envType: ${getEnvType()}, apiMode: ${apiMode}, region: ${region}, ` + | |
`bucketName: ${bucketName}, orgName: ${orgName}, orgOid: ${orgOid}, ` + | |
`npi: ${npi}, cxId: ${cxId}, fileInfo: ${JSON.stringify(fileInfo)}, ` + | |
`document: ${JSON.stringify(document)}` | |
); | |
const initialExtra = { lambdaName, requestId: req.requestId }; | |
try { | |
const { orgName, orgOid, npi, cxId, fileInfo, document, requestId } = req; | |
capture.setUser({ id: cxId }); | |
capture.setExtra(initialExtra); | |
console.log( | |
`Running with envType: ${getEnvType()}, apiMode: ${apiMode}, region: ${region}, ` + | |
`bucketName: ${bucketName}, orgName: ${orgName}, orgOid: ${orgOid}, ` + | |
`npi: ${npi}, cxId: ${cxId}, requestId: ${requestId}, ` + | |
`fileInfo: ${JSON.stringify(fileInfo)}, document: ${JSON.stringify(document)}` | |
); |
🤖 Prompt for AI Agents
In packages/lambdas/src/document-downloader.ts around lines 39 to 49, add the
incoming correlation ID (requestId) from the Lambda request into the Sentry
extras and runtime log output: include requestId in the initialExtra object
before calling capture.setExtra (e.g., initialExtra = { lambdaName, requestId:
req.requestId }), keep calling capture.setUser as-is, and append requestId to
the console.log string so the printed context and Sentry extras both contain the
correlation ID for tracing.
Ticket: https://github.com/metriport/metriport-internal/issues/1040
Dependencies
Description
Fix CW doc download including correlation ID - context - sentry.
Testing
Release Plan
Summary by CodeRabbit
Bug Fixes
Refactor