Repository navigation
feat(crashlytics): add heap dump collection management commands #11225
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
Merged
anitdas
merged 13 commits into
firebase:main
from
anitdas:anitdas/crashlytics-heapdump-commands
Oct 9, 2026
+1,357
−48
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
6d1804c
feat(crashlytics): add heap dump collection management commands
anitdas 1018801
fix(crashlytics): address PR #11225 review feedback
anitdas ec15741
test(crashlytics): bypass requireAuth pre-action hook in command unit…
anitdas 8fba5a2
test(crashlytics): add full unit test coverage for heapdumps and stor…
anitdas 49d4800
test(crashlytics): explicitly type AndroidAppMetadata mocks in profil…
anitdas 69ae8ef
chore(crashlytics): resolve eslint warnings in heapdumps and command …
anitdas 81eb97d
fix(storage): include status code on FirebaseError in patchBucket
anitdas 4e4cffc
refactor(crashlytics): address PR review feedback and lint warnings
anitdas c9a40a4
refactor(crashlytics): revert loadCommand changes in commands/index.ts
anitdas 79243f5
Merge branch 'main' into anitdas/crashlytics-heapdump-commands
anitdas 8146ec2
refactor(crashlytics): remove confirmation prompt from heapdumps:disable
anitdas 25dd02d
Merge branch 'main' into anitdas/crashlytics-heapdump-commands
anitdas 391922b
Merge branch 'main' into anitdas/crashlytics-heapdump-commands
anitdas File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| - Added `crashlytics:heapdumps:{enable,disable,status}` commands to manage Crashlytics Android heap dump collection. (#11225) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| import * as clc from "colorette"; | ||
|
|
||
| import { Command } from "../command"; | ||
| import { logger } from "../logger"; | ||
| import { Options } from "../options"; | ||
| import { needProjectId } from "../projectUtils"; | ||
| import { requireAuth } from "../requireAuth"; | ||
| import { disableHeapDumpCollection, resolveAndroidAppId } from "../crashlytics/profilingManager"; | ||
|
|
||
| interface CommandOptions extends Options { | ||
| app?: string; | ||
| } | ||
|
|
||
| export const command = new Command("crashlytics:heapdumps:disable") | ||
| .description("disable Crashlytics heap dump collection for an Android app") | ||
| .option("--app <appID>", "the app id of your Firebase Android app") | ||
| .before(requireAuth) | ||
| .action(async (options: CommandOptions) => { | ||
| const projectId = needProjectId(options); | ||
| const appId = await resolveAndroidAppId(projectId, options); | ||
|
|
||
| await disableHeapDumpCollection(appId); | ||
|
|
||
| logger.info(""); | ||
| logger.info(clc.bold("Heap Dump Collection Details:")); | ||
| logger.info(` App ID: ${clc.cyan(appId)}`); | ||
| logger.info(` Status: ${clc.red("Disabled")}`); | ||
|
|
||
| return { | ||
| appId, | ||
| heapDumpCollectionEnabled: false, | ||
| }; | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| import * as clc from "colorette"; | ||
|
|
||
| import { Command } from "../command"; | ||
| import { FirebaseError } from "../error"; | ||
| import { logger } from "../logger"; | ||
| import { Options } from "../options"; | ||
| import { needProjectId } from "../projectUtils"; | ||
| import { confirm } from "../prompt"; | ||
| import { requireAuth } from "../requireAuth"; | ||
| import { consoleUrl } from "../utils"; | ||
| import * as cloudbilling from "../gcp/cloudbilling"; | ||
| import { | ||
| createBucketName, | ||
| DEFAULT_BUCKET_LOCATION, | ||
| DEFAULT_FILE_TTL_DAYS, | ||
| enableHeapDumpCollection, | ||
| resolveAndroidAppId, | ||
| } from "../crashlytics/profilingManager"; | ||
|
|
||
| interface CommandOptions extends Options { | ||
| app?: string; | ||
| location?: string; | ||
| } | ||
|
|
||
| export const command = new Command("crashlytics:heapdumps:enable") | ||
| .description("enable Crashlytics heap dump collection for an Android app") | ||
| .option("--app <appID>", "the app id of your Firebase Android app") | ||
| .option( | ||
| "--location <location>", | ||
| `the location for the Cloud Storage bucket (default: ${DEFAULT_BUCKET_LOCATION})`, | ||
| DEFAULT_BUCKET_LOCATION, | ||
| ) | ||
| .withForce("automatically configure without prompting for confirmation") | ||
| .before(requireAuth) | ||
| .action(async (options: CommandOptions) => { | ||
| const projectId = needProjectId(options); | ||
| const appId = await resolveAndroidAppId(projectId, options); | ||
| const location = options.location || DEFAULT_BUCKET_LOCATION; | ||
|
|
||
| // 1. Verify project billing is enabled (required for GCS bucket creation and storage) | ||
| const isBillingEnabled = await cloudbilling.checkBillingEnabled(projectId); | ||
| if (!isBillingEnabled) { | ||
| throw new FirebaseError( | ||
| `Project '${projectId}' is not on the Blaze (pay-as-you-go) plan. Crashlytics heap dump collection requires the Blaze plan for Google Cloud Storage.\n` + | ||
| `To upgrade your project, visit: ${consoleUrl(projectId, "/usage/details")}`, | ||
| ); | ||
| } | ||
|
|
||
| // 2. Derive deterministic bucket name | ||
| const bucketName = createBucketName(appId); | ||
|
|
||
| // 3. Confirm with user if running interactively without --force | ||
| const confirmed = await confirm({ | ||
| message: `Enable Crashlytics heap dump collection for ${appId} using Cloud Storage bucket '${bucketName}' in ${location} (with ${DEFAULT_FILE_TTL_DAYS}-day file TTL)?`, | ||
| default: true, | ||
| force: options.force, | ||
| nonInteractive: options.nonInteractive, | ||
| }); | ||
|
|
||
| if (!confirmed) { | ||
| logger.info("Heap dump collection enablement canceled."); | ||
| return; | ||
| } | ||
|
|
||
| // 4. Provision / configure GCS bucket, IAM roles, and Profiling Manager config | ||
| await enableHeapDumpCollection(projectId, appId, location); | ||
|
|
||
| logger.info(""); | ||
| logger.info(clc.bold("Heap Dump Collection Details:")); | ||
| logger.info(` App ID: ${clc.cyan(appId)}`); | ||
| logger.info(` GCS Bucket: ${clc.cyan(bucketName)}`); | ||
| logger.info(` File TTL: ${clc.cyan(`${DEFAULT_FILE_TTL_DAYS} days`)}`); | ||
| logger.info(` Status: ${clc.green("Enabled")}`); | ||
| logger.info(""); | ||
| logger.info( | ||
| `View collected heap dumps in the Firebase Console: ${consoleUrl(projectId, `/crashlytics/app/${appId}`)}`, | ||
| ); | ||
|
|
||
| return { | ||
| appId, | ||
| bucketName, | ||
| heapDumpCollectionEnabled: true, | ||
| }; | ||
| }); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| import * as clc from "colorette"; | ||
| import * as Table from "cli-table3"; | ||
|
anitdas marked this conversation as resolved.
|
||
|
|
||
| import { Command } from "../command"; | ||
| import { logger } from "../logger"; | ||
| import { Options } from "../options"; | ||
| import { needProjectId } from "../projectUtils"; | ||
| import { requireAuth } from "../requireAuth"; | ||
| import { getProfilingManagerConfig, resolveAndroidAppId } from "../crashlytics/profilingManager"; | ||
|
|
||
| interface CommandOptions extends Options { | ||
| app?: string; | ||
| } | ||
|
|
||
| export const command = new Command("crashlytics:heapdumps:status") | ||
| .description("get Crashlytics heap dump collection status and configuration for an Android app") | ||
| .option("--app <appID>", "the app id of your Firebase Android app") | ||
| .before(requireAuth) | ||
| .action(async (options: CommandOptions) => { | ||
| const projectId = needProjectId(options); | ||
| const appId = await resolveAndroidAppId(projectId, options); | ||
|
|
||
| const config = await getProfilingManagerConfig(appId); | ||
|
|
||
| const tableHead = ["App ID", "Collection Status", "Cloud Storage Bucket"]; | ||
| const table = new Table({ head: tableHead, style: { head: ["green"] } }); | ||
| table.push([ | ||
| appId, | ||
| config.heapDumpCollectionEnabled ? clc.green("Enabled") : clc.red("Disabled"), | ||
| config.gcsBucket || clc.yellow("(none)"), | ||
| ]); | ||
|
|
||
| logger.info(""); | ||
| logger.info(table.toString()); | ||
|
|
||
| return { | ||
| appId, | ||
| ...config, | ||
| }; | ||
| }); | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.