Skip to content

feat: update connectionString appName param - [MCP-68] #406

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

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open

Conversation

blva
Copy link
Collaborator

@blva blva commented Jul 28, 2025

Proposed changes

  • Refactored telemetry to use centralized device ID utility
  • Extended appName format to appName--deviceId--clientName
  • Created src/helpers/deviceId.ts utility for device ID retrieval
  • Updated setAppNameParamIfMissing function to support extended format
  • Modified Session and Atlas connect tools to use new format
  • Added unit tests

Checklist

@coveralls
Copy link
Collaborator

coveralls commented Jul 28, 2025

Pull Request Test Coverage Report for Build 16673953200

Details

  • 58 of 58 (100.0%) changed or added relevant lines in 5 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.2%) to 81.181%

Totals Coverage Status
Change from base Build 16649286152: 0.2%
Covered Lines: 3301
Relevant Lines: 4029

💛 - Coveralls
@blva blva marked this pull request as ready for review July 31, 2025 13:13
@Copilot Copilot AI review requested due to automatic review settings July 31, 2025 13:13
@blva blva requested a review from a team as a code owner July 31, 2025 13:13
Copilot

This comment was marked as outdated.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
}

// Build the extended appName format: appName--deviceId--clientName
const extendedAppName = `${components.appName}--${deviceId}--${clientName}`;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[q] what if components.appName is empty? should it be unknown like the others?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the code we are getting packageInfo stuff, should we not make it a parameter and get package info straight away?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the previous behaviour is that we would set it to appName: ${packageInfo.mcpServerName} ${packageInfo.version}, if it's not defined, so we always send it. I could move that logic here, is that what you mean with the packageInfo question?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how would appName be defined? is it really a parameter? is there an env var?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

components.appName seems to be fixed as ${packageInfo.mcpServerName} ${packageInfo.version} always

@blva blva requested a review from Copilot July 31, 2025 14:34
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refactors telemetry device ID handling by extracting device ID generation logic into a centralized utility and extending the MongoDB connection string appName parameter format to include device ID and client name components.

  • Centralizes device ID retrieval logic into a reusable helper utility
  • Extends appName format from simple name to appName--deviceId--clientName structure
  • Updates telemetry and connection handling to use the new centralized approach

Reviewed Changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/helpers/deviceId.ts New centralized utility for device ID generation with error handling
src/helpers/connectionOptions.ts Enhanced appName parameter setting with extended format support
src/common/session.ts Updated to use extended appName format with client name
src/telemetry/telemetry.ts Refactored to use centralized device ID utility
src/tools/atlas/connect/connectCluster.ts Updated Atlas connection to use extended appName format
tests/ Comprehensive test coverage for new functionality
Comments suppressed due to low confidence (2)

tests/unit/helpers/connectionOptions.test.ts:34

  • The test comment mentions URL normalization but doesn't verify the exact appName value. Consider adding an assertion that explicitly checks the appName parameter value to ensure it remains 'ExistingApp' and hasn't been modified.
            // The ConnectionString library normalizes URLs, so we need to check the content rather than exact equality

tests/unit/helpers/deviceId.test.ts:109

  • This test uses fake timers but doesn't actually test timeout behavior since the mock immediately calls the onError callback. Consider creating a test that truly exercises the timeout mechanism by having the getDeviceId promise not resolve within the timeout period.
            vi.useFakeTimers();
blva and others added 2 commits July 31, 2025 15:46
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@blva blva requested a review from fmenezes July 31, 2025 15:34
*/
export async function getDeviceIdForConnection(): Promise<string> {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), DEVICE_ID_TIMEOUT);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need timeout? getDeviceId has a timeout builtin

});

it("should timeout if machine ID resolution takes too long", async () => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are we removing the timeout test? I think it is useful to have

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

didn't remove, moved it to deviceId unit tests

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah saw this now, nevermind, ty!


private constructor(
private readonly session: Session,
private readonly userConfig: UserConfig,
private readonly commonProperties: CommonProperties,
{ eventCache, getRawMachineId }: { eventCache: EventCache; getRawMachineId: () => Promise<string> }
{ eventCache }: { eventCache: EventCache }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think it'd still be good to pass getDeviceIdForConnection for explicit DI. It also helps us avoid mocking the file which is a bit of JavaScript magic

Copy link
Collaborator

@gagik gagik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's important in my opinion to avoid double device ID resolution

}

const deviceId = components.deviceId || (await getDeviceIdForConnection());
Copy link
Collaborator

@gagik gagik Aug 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we shouldn't end up awaiting device ID a second time, can we organize it so this device ID gets passed from one point of entry and we never fallback to this function? deviceId doesn't get passed in connectToMongoDB right now.

if (!searchParams.has("appName") && defaultAppName !== undefined) {
searchParams.set("appName", defaultAppName);
// Only set appName if it's not already present
if (searchParams.has("appName")) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Compass / mongosh we only pass the device ID if it's an Atlas host to minimize visibility of this, can we also do this here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
4 participants