Skip to content

Commit c03686a

Browse files
fix(telemetry): better hostname parsing for telemetry COMPASS-8148 (#6101)
* fix(telemetry): seeing port information (postfix) in the hostnames in Compass telemetry COMPASS-8148 * fix: handle IPv6
1 parent b8b86ac commit c03686a

File tree

2 files changed

+153
-6
lines changed

2 files changed

+153
-6
lines changed

packages/compass/src/app/utils/telemetry.spec.ts

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,148 @@ describe('connection tracking', function () {
717717
expect(properties.topology_type).to.equal('Sharded');
718718
});
719719

720+
it('tracks hostname without port', async function () {
721+
const mockDataService: Pick<
722+
DataService,
723+
'instance' | 'getCurrentTopologyType'
724+
> = {
725+
instance: () => {
726+
return Promise.resolve({
727+
dataLake: {
728+
isDataLake: true,
729+
version: '1.2.3',
730+
},
731+
genuineMongoDB: {
732+
dbType: 'mongo',
733+
isGenuine: false,
734+
},
735+
host: {
736+
arch: 'darwin',
737+
os_family: 'mac',
738+
},
739+
build: {
740+
isEnterprise: true,
741+
version: '4.3.2',
742+
},
743+
isAtlas: true,
744+
isLocalAtlas: false,
745+
featureCompatibilityVersion: null,
746+
} as any);
747+
},
748+
getCurrentTopologyType: () => 'Unknown',
749+
};
750+
const trackEvent = once(process, 'compass:track');
751+
const connection: ConnectionInfo = {
752+
...connectionInfo,
753+
connectionOptions: {
754+
connectionString:
755+
'mongodb://test-000-shard-00-00.test.mongodb.net:27017',
756+
},
757+
};
758+
trackNewConnectionEvent(connection, mockDataService, logger, track);
759+
const [{ properties }] = await trackEvent;
760+
761+
expect(properties.is_atlas).to.equal(true);
762+
expect(properties.atlas_hostname).to.equal(
763+
'test-000-shard-00-00.test.mongodb.net'
764+
);
765+
});
766+
767+
it('tracks IPv6 hostname without port', async function () {
768+
const mockDataService: Pick<
769+
DataService,
770+
'instance' | 'getCurrentTopologyType'
771+
> = {
772+
instance: () => {
773+
return Promise.resolve({
774+
dataLake: {
775+
isDataLake: true,
776+
version: '1.2.3',
777+
},
778+
genuineMongoDB: {
779+
dbType: 'mongo',
780+
isGenuine: false,
781+
},
782+
host: {
783+
arch: 'darwin',
784+
os_family: 'mac',
785+
},
786+
build: {
787+
isEnterprise: true,
788+
version: '4.3.2',
789+
},
790+
isAtlas: true,
791+
isLocalAtlas: false,
792+
featureCompatibilityVersion: null,
793+
} as any);
794+
},
795+
getCurrentTopologyType: () => 'Unknown',
796+
};
797+
const trackEvent = once(process, 'compass:track');
798+
const connection: ConnectionInfo = {
799+
...connectionInfo,
800+
connectionOptions: {
801+
connectionString: 'mongodb://[3fff:0:a88:15a3::ac2f]:8001/',
802+
},
803+
};
804+
trackNewConnectionEvent(connection, mockDataService, logger, track);
805+
const [{ properties }] = await trackEvent;
806+
807+
expect(properties.is_atlas).to.equal(true);
808+
expect(properties.atlas_hostname).to.equal('3fff:0:a88:15a3::ac2f');
809+
});
810+
811+
it('falls back to original url if cannot resolve srv', async function () {
812+
const mockDataService: Pick<
813+
DataService,
814+
'instance' | 'getCurrentTopologyType'
815+
> = {
816+
instance: () => {
817+
return Promise.resolve({
818+
dataLake: {
819+
isDataLake: true,
820+
version: '1.2.3',
821+
},
822+
genuineMongoDB: {
823+
dbType: 'mongo',
824+
isGenuine: false,
825+
},
826+
host: {
827+
arch: 'darwin',
828+
os_family: 'mac',
829+
},
830+
build: {
831+
isEnterprise: true,
832+
version: '4.3.2',
833+
},
834+
isAtlas: true,
835+
isLocalAtlas: false,
836+
featureCompatibilityVersion: null,
837+
} as any);
838+
},
839+
getCurrentTopologyType: () => 'Unknown',
840+
};
841+
const trackEvent = once(process, 'compass:track');
842+
843+
// The fake srv connection string cannot be resolved,
844+
// But expected to fall back to the original hostname from uri
845+
// When retrieving atlas_hostname for telemetry
846+
const connection: ConnectionInfo = {
847+
...connectionInfo,
848+
connectionOptions: {
849+
connectionString:
850+
'mongodb+srv://test-000-shard-00-00.test.mongodb.net:27017',
851+
},
852+
};
853+
trackNewConnectionEvent(connection, mockDataService, logger, track);
854+
const [{ properties }] = await trackEvent;
855+
856+
expect(properties.is_atlas).to.equal(true);
857+
expect(properties.atlas_hostname).to.equal(
858+
'test-000-shard-00-00.test.mongodb.net'
859+
);
860+
});
861+
720862
it('tracks connection error event', async function () {
721863
const trackEvent = once(process, 'compass:track');
722864
const connection: ConnectionInfo = {

packages/compass/src/app/utils/telemetry.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,15 +115,20 @@ async function getHostnameForConnection(
115115
return null;
116116
}
117117
);
118-
if (!uri) {
119-
return null;
118+
if (uri) {
119+
connectionStringData = new ConnectionString(uri, {
120+
looseValidation: true,
121+
});
120122
}
121-
connectionStringData = new ConnectionString(uri, {
122-
looseValidation: true,
123-
});
124123
}
125124

126-
return connectionStringData.hosts[0];
125+
const firstHost = connectionStringData.hosts[0] ?? '';
126+
127+
if (firstHost.startsWith('[')) {
128+
return firstHost.slice(1).split(']')[0]; // IPv6
129+
}
130+
131+
return firstHost.split(':')[0];
127132
}
128133

129134
async function getConnectionData(

0 commit comments

Comments
 (0)