Skip to content

Commit

Permalink
feat: upgrade gleap, collect peer logs and state
Browse files Browse the repository at this point in the history
  • Loading branch information
oliverlaz committed Dec 21, 2023
1 parent 8b0ea77 commit dec6691
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 16 deletions.
138 changes: 132 additions & 6 deletions sample-apps/react/react-dogfood/hooks/useGleap.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useEffect } from 'react';
import { useEffect, useRef, useState } from 'react';
import Gleap from 'gleap';
import {
Call,
Expand All @@ -8,22 +8,146 @@ import {
} from '@stream-io/video-react-sdk';
import { getLayoutSettings } from './useLayoutSwitcher';

type GleapReportPayload = {
type: 'gleap.report';
userId: string | undefined;
toUserId: string;
totalChunks: number;
chunkIndex: number;
data: string;
};

const MAX_LOGS_QUEUE_SIZE = 350;

export const useGleap = (
gleapApiKey: string | undefined,
client: StreamVideoClient | undefined,
call: Call | undefined,
user: User,
) => {
const [isInitialized, setIsInitialized] = useState(false);
useEffect(() => {
if (gleapApiKey) {
if (gleapApiKey && !isInitialized) {
Gleap.initialize(gleapApiKey);
Gleap.identify(user.name || user.id || '!anon', {
name: user.name,
});
setIsInitialized(true);
}
}, [gleapApiKey, user.name, user.id]);
}, [gleapApiKey, user.name, user.id, isInitialized]);

const logsQueue = useRef<string[]>([]);
const pushToLogQueue = (log: string) => {
if (logsQueue.current.length >= MAX_LOGS_QUEUE_SIZE) {
logsQueue.current.shift();
}
logsQueue.current.push(log);
};

useEffect(() => {
if (!gleapApiKey || !client) return;
if (!gleapApiKey || !call) return;

const originalLog = console.log;
const originalWarn = console.warn;
const originalError = console.error;
const stringify = (o: any) => {
if (typeof o !== 'object') return o;
try {
return JSON.stringify(o);
} catch (e) {
return o;
}
};
const timestamp = () => {
const d = new Date();
return `${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}.${d.getMilliseconds()}`;
};
console.log = (...args: any[]) => {
originalLog(...args);
pushToLogQueue(`[LOG: ${timestamp()}] ${args.map(stringify).join(' ')}`);
};
console.warn = (...args: any[]) => {
originalWarn(...args);
pushToLogQueue(`[WARN: ${timestamp()}] ${args.map(stringify).join(' ')}`);
};
console.error = (...args: any[]) => {
originalError(...args);
pushToLogQueue(`[ERR: ${timestamp()}] ${args.map(stringify).join(' ')}`);
};

const off = call.on('custom', async (event) => {
if (event.type !== 'custom') return;
const { type } = event.custom;
if (
type === 'gleap.collect-report' &&
event.user.id !== call.currentUserId
) {
const report = serializeCallState(call);
report.logs = logsQueue.current;
const serializedReport = JSON.stringify(report);
// split in 4.6k chunks - custom events have a 5k limit
const chunkSize = 4600;
const chunks = serializedReport.match(
new RegExp(`.{1,${chunkSize}}`, 'g'),
);
// send each chunk as a separate event
if (!chunks) return;
for (let i = 0; i < chunks.length; i++) {
const chunk = chunks[i];
await call.sendCustomEvent({
type: 'gleap.report',
userId: call.currentUserId,
toUserId: event.user.id,
totalChunks: chunks.length,
chunkIndex: i,
data: chunk,
} satisfies GleapReportPayload);
}
}
});
return () => {
off();
console.log = originalLog;
console.warn = originalWarn;
console.error = originalError;
};
}, [call, gleapApiKey]);

useEffect(() => {
if (!gleapApiKey || !call) return;
const cache = new Map<string, string[]>();
return call.on('custom', (event) => {
if (event.type !== 'custom') return;
const { custom } = event;
const { type, userId, toUserId, totalChunks, chunkIndex, data } =
custom as GleapReportPayload;
if (
type === 'gleap.report' &&
userId &&
toUserId === call.currentUserId
) {
if (!cache.has(userId)) {
cache.set(userId, Array.from({ length: totalChunks }));
}
const existingData = cache.get(userId)!;
existingData[chunkIndex] = data;
// wait until we have all chunks
if (existingData.every((d) => !!d)) {
const report = JSON.parse(existingData.join(''));
Gleap.attachCustomData({
[userId]: report,
});
}
}
});
}, [call, gleapApiKey]);

useEffect(() => {
if (!gleapApiKey || !client || !call) return;

Gleap.on('open', async () => {
await call.sendCustomEvent({ type: 'gleap.collect-report' });
});

Gleap.on('flow-started', () => {
try {
Expand Down Expand Up @@ -54,15 +178,17 @@ export const useGleap = (
// We want to detect this early and include the serialization error
// as part of the Gleap feedback item.
JSON.stringify(data);
Gleap.attachCustomData(data);
Gleap.attachCustomData({
me: data,
});
} catch (e) {
console.warn(e);
}
} catch (e) {
console.error(e);
}
});
}, [client, gleapApiKey]);
}, [call, client, gleapApiKey]);
};

export const serializeCallState = (call: Call) => {
Expand Down
2 changes: 1 addition & 1 deletion sample-apps/react/react-dogfood/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"dotenv": "^16.3.1",
"framer-motion": "^10.12.16",
"geojson": "^0.5.0",
"gleap": "^12.1.2",
"gleap": "^13.1.1",
"hotkeys-js": "^3.12.0",
"mapbox-gl": "^2.15.0",
"mobile-device-detect": "^0.4.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export default function GuestCallRoom(props: GuestCallRoomProps) {
});
}, [call]);

useGleap(gleapApiKey, client, user);
useGleap(gleapApiKey, client, call, user);

if (!client || !call) {
return null;
Expand Down
2 changes: 1 addition & 1 deletion sample-apps/react/react-dogfood/pages/join/[callId].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ const CallRoom = (props: ServerSideCredentialsProps) => {
}
}, []);

useGleap(gleapApiKey, client, user);
useGleap(gleapApiKey, client, call, user);

if (!client || !call) return null;

Expand Down
2 changes: 1 addition & 1 deletion sample-apps/react/react-video-demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"classnames": "^2.3.2",
"date-fns": "^2.29.3",
"geojson": "^0.5.0",
"gleap": "^12.1.2",
"gleap": "^13.1.1",
"hotkeys-js": "^3.12.0",
"mapbox-gl": "^2.15.0",
"mobile-device-detect": "^0.4.3",
Expand Down
12 changes: 6 additions & 6 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7279,7 +7279,7 @@ __metadata:
concurrently: ^7.6.0
date-fns: ^2.29.3
geojson: ^0.5.0
gleap: ^12.1.2
gleap: ^13.1.1
hotkeys-js: ^3.12.0
mapbox-gl: ^2.15.0
mobile-device-detect: ^0.4.3
Expand Down Expand Up @@ -7459,7 +7459,7 @@ __metadata:
dotenv: ^16.3.1
framer-motion: ^10.12.16
geojson: ^0.5.0
gleap: ^12.1.2
gleap: ^13.1.1
hotkeys-js: ^3.12.0
mapbox-gl: ^2.15.0
mobile-device-detect: ^0.4.3
Expand Down Expand Up @@ -17030,10 +17030,10 @@ __metadata:
languageName: node
linkType: hard

"gleap@npm:^12.1.2":
version: 12.1.2
resolution: "gleap@npm:12.1.2"
checksum: cf2d811057daaec78c5a7c3d9896a5984bb44bb8b6428495ddac0ee84b81028efa7af831ab723834bef5035442e68e740f1b58614b5df8415e96200b3e003fee
"gleap@npm:^13.1.1":
version: 13.1.1
resolution: "gleap@npm:13.1.1"
checksum: 5b6e8974c7c25f3f5d6428fc2035019b39c50393cca90c8f6698d5c27d2dd4937b5d75f8c443c5c24aef3803d16af39d306a4f9029fcdb9284d07a1570d0b39c
languageName: node
linkType: hard

Expand Down

0 comments on commit dec6691

Please sign in to comment.