Skip to content

Commit

Permalink
fix(analytics): improve dapp details tracking and SDK RPC request ana…
Browse files Browse the repository at this point in the history
…lytics (#1179)

* feat: add analytics tracking for SDK RPC requests

- Implemented analytics tracking for SDK RPC requests when not sending via network.
- Integrated SendAnalytics function to log SDK_RPC_REQUEST events with relevant parameters.

* refactor: improve analytics event handling and caching logic

- Removed deprecated SDK version ID and updated channelId declaration to use const.
- Enhanced caching logic for channel information, ensuring validation of cached data.
- Added logging for cases with empty cached channel info to improve debugging.
- Refactored incrementRedisCacheOperation calls for better readability.
  • Loading branch information
abretonc7s authored Dec 17, 2024
1 parent 86052b0 commit ba1bee1
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 8 deletions.
33 changes: 25 additions & 8 deletions packages/sdk-socket-server-next/src/analytics-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ import {

const logger = getLogger();

// SDK version prev 0.27.0 uses 'sdk' as the default id, below value is the sha1 hash of 'sdk'
const SDK_EXTENSION_DEFAULT_ID = '5a374dcd2e5eb762b527af3a5bab6072a4d24493';

// Initialize Redis Cluster client
let redisNodes: {
host: string;
Expand Down Expand Up @@ -246,7 +243,7 @@ app.post('/evt', evtMetricsMiddleware, async (_req, res) => {
return res.status(400).json({ error: 'wrong event name' });
}

let channelId: string = body.id || 'sdk';
const channelId: string = body.id || 'sdk';
// Prevent caching of events coming from extension since they are not re-using the same id and prevent increasing redis queue size.
let isExtensionEvent = body.from === 'extension';

Expand All @@ -272,7 +269,10 @@ app.post('/evt', evtMetricsMiddleware, async (_req, res) => {
? crypto.createHash('sha1').update(channelId).digest('hex')
: await pubClient.get(channelId);

incrementRedisCacheOperation('analytics-get-channel-id', !!userIdHash);
incrementRedisCacheOperation(
'analytics-get-channel-id',
Boolean(userIdHash),
);

if (!userIdHash) {
userIdHash = crypto.createHash('sha1').update(channelId).digest('hex');
Expand All @@ -294,23 +294,40 @@ app.post('/evt', evtMetricsMiddleware, async (_req, res) => {
await inspectRedis(channelId);
}

let channelInfo: ChannelInfo | null;
let channelInfo: ChannelInfo | null = null;
const cachedChannelInfo = isAnonUser
? null
: await pubClient.get(userIdHash);

// Potential issue because we may have a cached channel info but the url inside may be empty and dappId "N/A".
// We then need to actually fully parse the string and extract the channelInfo object to validate the url and dappId.
const hasCachedChannelInfo = Boolean(cachedChannelInfo);

incrementRedisCacheOperation(
'analytics-get-channel-info',
!!cachedChannelInfo,
hasCachedChannelInfo,
);

let hasValidCachedChannelInfo = false;

if (cachedChannelInfo) {
logger.debug(
`Found cached channel info for ${userIdHash}`,
cachedChannelInfo,
);
channelInfo = JSON.parse(cachedChannelInfo);
} else {
hasValidCachedChannelInfo =
channelInfo !== null &&
Boolean(channelInfo.url && channelInfo.url.length > 0);

if (!hasValidCachedChannelInfo) {
logger.warn(
`event: ${body.event} channelId: ${channelId} - empty cached channel info for ${userIdHash} dAppId=${channelInfo?.dappId}`,
);
}
}

if (!hasValidCachedChannelInfo) {
logger.info(
`event: ${body.event} channelId: ${channelId} - No cached channel info found for ${userIdHash}`,
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import {
TrackingEvents,
SendAnalytics,
DEFAULT_SERVER_URL,
} from '@metamask/sdk-communication-layer';
import { RemoteCommunicationPostMessageStream } from '../../PostMessageStream/RemoteCommunicationPostMessageStream';
import { METHODS_TO_REDIRECT, RPC_METHODS } from '../../config';
import {
Expand Down Expand Up @@ -67,6 +72,24 @@ export async function write(
.catch((err: unknown) => {
logger(`[RCPMS: _write()] error sending message`, err);
});
} else {
try {
// Only send analytics if we are not sending via network.
await SendAnalytics(
{
id: channelId,
event: TrackingEvents.SDK_RPC_REQUEST,
params: {
method: targetMethod,
from: 'mobile',
},
},
instance.state.remote?.state.communicationServerUrl ??
DEFAULT_SERVER_URL,
);
} catch (error) {
logger(`[RCPMS: _write()] error sending analytics`, error);
}
}

if (!isSecure) {
Expand Down

0 comments on commit ba1bee1

Please sign in to comment.