try debug event controller
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import { logger, logInfo } from '@/utils/logger';
|
||||||
import { getClientIp, parseIp } from '@/utils/parseIp';
|
import { getClientIp, parseIp } from '@/utils/parseIp';
|
||||||
import { getReferrerWithQuery, parseReferrer } from '@/utils/parseReferrer';
|
import { getReferrerWithQuery, parseReferrer } from '@/utils/parseReferrer';
|
||||||
import { isUserAgentSet, parseUserAgent } from '@/utils/parseUserAgent';
|
import { isUserAgentSet, parseUserAgent } from '@/utils/parseUserAgent';
|
||||||
@@ -61,6 +62,21 @@ function isSameDomain(url1: string | undefined, url2: string | undefined) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function withTiming<T>(name: string, promise: T) {
|
||||||
|
try {
|
||||||
|
const start = Date.now();
|
||||||
|
const res = await promise;
|
||||||
|
const end = Date.now();
|
||||||
|
if (end - start > 1000) {
|
||||||
|
logInfo(`${name} took too long: ${end - start}ms`);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(error, `Failed to execute ${name}`);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function postEvent(
|
export async function postEvent(
|
||||||
request: FastifyRequest<{
|
request: FastifyRequest<{
|
||||||
Body: PostEventPayload;
|
Body: PostEventPayload;
|
||||||
@@ -109,8 +125,11 @@ export async function postEvent(
|
|||||||
const isServerEvent = !ip && !origin && !isUserAgentSet(ua);
|
const isServerEvent = !ip && !origin && !isUserAgentSet(ua);
|
||||||
|
|
||||||
if (isServerEvent) {
|
if (isServerEvent) {
|
||||||
const [event] = await getEvents(
|
const [event] = await withTiming(
|
||||||
`SELECT * FROM events WHERE name = 'screen_view' AND profile_id = '${profileId}' AND project_id = '${projectId}' ORDER BY created_at DESC LIMIT 1`
|
'Get last event (server-event)',
|
||||||
|
getEvents(
|
||||||
|
`SELECT * FROM events WHERE name = 'screen_view' AND profile_id = '${profileId}' AND project_id = '${projectId}' ORDER BY created_at DESC LIMIT 1`
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
eventsQueue.add('event', {
|
eventsQueue.add('event', {
|
||||||
@@ -153,10 +172,10 @@ export async function postEvent(
|
|||||||
return reply.status(200).send('');
|
return reply.status(200).send('');
|
||||||
}
|
}
|
||||||
|
|
||||||
const [geo, eventsJobs] = await Promise.all([
|
const [geo, eventsJobs] = await withTiming(
|
||||||
parseIp(ip),
|
'Get geo and job from queue',
|
||||||
eventsQueue.getJobs(['delayed']),
|
Promise.all([parseIp(ip), eventsQueue.getJobs(['delayed'])])
|
||||||
]);
|
);
|
||||||
|
|
||||||
// find session_end job
|
// find session_end job
|
||||||
const sessionEndJobCurrentDeviceId = findJobByPrefix(
|
const sessionEndJobCurrentDeviceId = findJobByPrefix(
|
||||||
@@ -200,8 +219,11 @@ export async function postEvent(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const [sessionStartEvent] = await getEvents(
|
const [sessionStartEvent] = await withTiming(
|
||||||
`SELECT * FROM events WHERE name = 'session_start' AND device_id = '${deviceId}' AND project_id = '${projectId}' ORDER BY created_at DESC LIMIT 1`
|
'Get session start event',
|
||||||
|
getEvents(
|
||||||
|
`SELECT * FROM events WHERE name = 'session_start' AND device_id = '${deviceId}' AND project_id = '${projectId}' ORDER BY created_at DESC LIMIT 1`
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
request.log.info(
|
request.log.info(
|
||||||
@@ -272,26 +294,36 @@ export async function postEvent(
|
|||||||
},
|
},
|
||||||
'duration is wrong'
|
'duration is wrong'
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
// Skip update duration if it's wrong
|
||||||
|
// Seems like request is not in right order
|
||||||
|
await withTiming(
|
||||||
|
'Update previous job with duration',
|
||||||
|
job.updateData({
|
||||||
|
type: 'createEvent',
|
||||||
|
payload: {
|
||||||
|
...prevEvent,
|
||||||
|
duration,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
await job.updateData({
|
|
||||||
type: 'createEvent',
|
await withTiming('Promote previous job', job.promote());
|
||||||
payload: {
|
|
||||||
...prevEvent,
|
|
||||||
duration,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
await job.promote();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (createSessionStart) {
|
if (createSessionStart) {
|
||||||
// We do not need to queue session_start
|
// We do not need to queue session_start
|
||||||
await createEvent({
|
await withTiming(
|
||||||
...payload,
|
'Create session start event',
|
||||||
name: 'session_start',
|
createEvent({
|
||||||
// @ts-expect-error
|
...payload,
|
||||||
createdAt: toISOString(getTime(payload.createdAt) - 100),
|
name: 'session_start',
|
||||||
});
|
// @ts-expect-error
|
||||||
|
createdAt: toISOString(getTime(payload.createdAt) - 100),
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const options: JobsOptions = {};
|
const options: JobsOptions = {};
|
||||||
@@ -302,13 +334,16 @@ export async function postEvent(
|
|||||||
|
|
||||||
request.log.info(payload, 'queue event');
|
request.log.info(payload, 'queue event');
|
||||||
// Queue current event
|
// Queue current event
|
||||||
eventsQueue.add(
|
await withTiming(
|
||||||
'event',
|
'Add current to event queue',
|
||||||
{
|
eventsQueue.add(
|
||||||
type: 'createEvent',
|
'event',
|
||||||
payload,
|
{
|
||||||
},
|
type: 'createEvent',
|
||||||
options
|
payload,
|
||||||
|
},
|
||||||
|
options
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
reply.status(202).send(deviceId);
|
reply.status(202).send(deviceId);
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import type { FastifyRequest } from 'fastify';
|
import type { FastifyRequest } from 'fastify';
|
||||||
|
|
||||||
|
import { logger } from './logger';
|
||||||
|
|
||||||
interface RemoteIpLookupResponse {
|
interface RemoteIpLookupResponse {
|
||||||
country: string | undefined;
|
country: string | undefined;
|
||||||
city: string | undefined;
|
city: string | undefined;
|
||||||
@@ -41,7 +43,9 @@ export async function parseIp(ip?: string): Promise<GeoLocation> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const geo = await fetch(`${process.env.GEO_IP_HOST}/${ip}`);
|
const geo = await fetch(`${process.env.GEO_IP_HOST}/${ip}`, {
|
||||||
|
signal: AbortSignal.timeout(2000),
|
||||||
|
});
|
||||||
const res = (await geo.json()) as RemoteIpLookupResponse;
|
const res = (await geo.json()) as RemoteIpLookupResponse;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -51,7 +55,7 @@ export async function parseIp(ip?: string): Promise<GeoLocation> {
|
|||||||
continent: res.continent,
|
continent: res.continent,
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('Failed to parse ip', e);
|
logger.error('Failed to fetch geo location for ip', e);
|
||||||
return geo;
|
return geo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user