mirror of
https://github.com/Litlyx/litlyx
synced 2025-12-10 07:48:37 +01:00
add flow-hash
This commit is contained in:
@@ -51,7 +51,7 @@ async function processStreamEvent(data: Record<string, string>) {
|
|||||||
|
|
||||||
async function process_visit(data: Record<string, string>, sessionHash: string) {
|
async function process_visit(data: Record<string, string>, sessionHash: string) {
|
||||||
|
|
||||||
const { pid, ip, website, page, referrer, userAgent } = data;
|
const { pid, ip, website, page, referrer, userAgent, flowHash } = data;
|
||||||
|
|
||||||
const projectLimits = await ProjectLimitModel.findOne({ project_id: pid });
|
const projectLimits = await ProjectLimitModel.findOne({ project_id: pid });
|
||||||
if (!projectLimits) return;
|
if (!projectLimits) return;
|
||||||
@@ -78,6 +78,7 @@ async function process_visit(data: Record<string, string>, sessionHash: string)
|
|||||||
os: userAgentParsed.os.name || 'NO_OS',
|
os: userAgentParsed.os.name || 'NO_OS',
|
||||||
device: userAgentParsed.device.type,
|
device: userAgentParsed.device.type,
|
||||||
session: sessionHash,
|
session: sessionHash,
|
||||||
|
flowHash,
|
||||||
continent: geoLocation[0],
|
continent: geoLocation[0],
|
||||||
country: geoLocation[1],
|
country: geoLocation[1],
|
||||||
});
|
});
|
||||||
@@ -93,16 +94,18 @@ async function process_visit(data: Record<string, string>, sessionHash: string)
|
|||||||
|
|
||||||
async function process_keep_alive(data: Record<string, string>, sessionHash: string) {
|
async function process_keep_alive(data: Record<string, string>, sessionHash: string) {
|
||||||
|
|
||||||
const { pid, instant } = data;
|
const { pid, instant, flowHash } = data;
|
||||||
|
|
||||||
if (instant == "true") {
|
if (instant == "true") {
|
||||||
await SessionModel.updateOne({ project_id: pid, session: sessionHash, }, {
|
await SessionModel.updateOne({ project_id: pid, session: sessionHash, }, {
|
||||||
$inc: { duration: 0 },
|
$inc: { duration: 0 },
|
||||||
|
flowHash,
|
||||||
updated_at: Date.now()
|
updated_at: Date.now()
|
||||||
}, { upsert: true });
|
}, { upsert: true });
|
||||||
} else {
|
} else {
|
||||||
await SessionModel.updateOne({ project_id: pid, session: sessionHash, }, {
|
await SessionModel.updateOne({ project_id: pid, session: sessionHash, }, {
|
||||||
$inc: { duration: 1 },
|
$inc: { duration: 1 },
|
||||||
|
flowHash,
|
||||||
updated_at: Date.now()
|
updated_at: Date.now()
|
||||||
}, { upsert: true });
|
}, { upsert: true });
|
||||||
}
|
}
|
||||||
@@ -112,7 +115,7 @@ async function process_keep_alive(data: Record<string, string>, sessionHash: str
|
|||||||
|
|
||||||
async function process_event(data: Record<string, string>, sessionHash: string) {
|
async function process_event(data: Record<string, string>, sessionHash: string) {
|
||||||
|
|
||||||
const { name, metadata, pid } = data;
|
const { name, metadata, pid, flowHash } = data;
|
||||||
|
|
||||||
let metadataObject;
|
let metadataObject;
|
||||||
try {
|
try {
|
||||||
@@ -121,7 +124,7 @@ async function process_event(data: Record<string, string>, sessionHash: string)
|
|||||||
metadataObject = { error: 'Error parsing metadata' }
|
metadataObject = { error: 'Error parsing metadata' }
|
||||||
}
|
}
|
||||||
|
|
||||||
const event = new EventModel({ project_id: pid, name, metadata: metadataObject, session: sessionHash });
|
const event = new EventModel({ project_id: pid, name, flowHash, metadata: metadataObject, session: sessionHash });
|
||||||
await event.save();
|
await event.save();
|
||||||
|
|
||||||
await ProjectCountModel.updateOne({ project_id: pid }, { $inc: { 'events': 1 } }, { upsert: true });
|
await ProjectCountModel.updateOne({ project_id: pid }, { $inc: { 'events': 1 } }, { upsert: true });
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { RedisStreamService } from "@services/RedisStreamService";
|
|||||||
|
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import cors from 'cors';
|
import cors from 'cors';
|
||||||
import { createSessionHash, getIPFromRequest } from "./utils";
|
import { createFlowSessionHash, createSessionHash, getIPFromRequest } from "./utils";
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
app.use(cors());
|
app.use(cors());
|
||||||
@@ -20,7 +20,8 @@ app.post('/event', express.json(jsonOptions), async (req, res) => {
|
|||||||
try {
|
try {
|
||||||
const ip = getIPFromRequest(req);
|
const ip = getIPFromRequest(req);
|
||||||
const sessionHash = createSessionHash(req.body.website, ip, req.body.userAgent);
|
const sessionHash = createSessionHash(req.body.website, ip, req.body.userAgent);
|
||||||
await RedisStreamService.addToStream(streamName, { ...req.body, _type: 'event', sessionHash, ip });
|
const flowHash = createFlowSessionHash(req.body.pid, ip, req.body.userAgent);
|
||||||
|
await RedisStreamService.addToStream(streamName, { ...req.body, _type: 'event', sessionHash, ip, flowHash });
|
||||||
return res.sendStatus(200);
|
return res.sendStatus(200);
|
||||||
} catch (ex: any) {
|
} catch (ex: any) {
|
||||||
return res.status(500).json({ error: ex.message });
|
return res.status(500).json({ error: ex.message });
|
||||||
@@ -31,7 +32,8 @@ app.post('/visit', express.json(jsonOptions), async (req, res) => {
|
|||||||
try {
|
try {
|
||||||
const ip = getIPFromRequest(req);
|
const ip = getIPFromRequest(req);
|
||||||
const sessionHash = createSessionHash(req.body.website, ip, req.body.userAgent);
|
const sessionHash = createSessionHash(req.body.website, ip, req.body.userAgent);
|
||||||
await RedisStreamService.addToStream(streamName, { ...req.body, _type: 'visit', sessionHash, ip });
|
const flowHash = createFlowSessionHash(req.body.pid, ip, req.body.userAgent);
|
||||||
|
await RedisStreamService.addToStream(streamName, { ...req.body, _type: 'visit', sessionHash, ip, flowHash });
|
||||||
return res.sendStatus(200);
|
return res.sendStatus(200);
|
||||||
} catch (ex: any) {
|
} catch (ex: any) {
|
||||||
return res.status(500).json({ error: ex.message });
|
return res.status(500).json({ error: ex.message });
|
||||||
@@ -42,9 +44,11 @@ app.post('/keep_alive', express.json(jsonOptions), async (req, res) => {
|
|||||||
try {
|
try {
|
||||||
const ip = getIPFromRequest(req);
|
const ip = getIPFromRequest(req);
|
||||||
const sessionHash = createSessionHash(req.body.website, ip, req.body.userAgent);
|
const sessionHash = createSessionHash(req.body.website, ip, req.body.userAgent);
|
||||||
|
const flowHash = createFlowSessionHash(req.body.pid, ip, req.body.userAgent);
|
||||||
await RedisStreamService.addToStream(streamName, {
|
await RedisStreamService.addToStream(streamName, {
|
||||||
...req.body, _type: 'keep_alive', sessionHash, ip,
|
...req.body, _type: 'keep_alive', sessionHash, ip,
|
||||||
instant: req.body.instant + ''
|
instant: req.body.instant + '',
|
||||||
|
flowHash
|
||||||
});
|
});
|
||||||
return res.sendStatus(200);
|
return res.sendStatus(200);
|
||||||
} catch (ex: any) {
|
} catch (ex: any) {
|
||||||
|
|||||||
@@ -14,3 +14,12 @@ export function createSessionHash(website: string, ip: string, userAgent: string
|
|||||||
const sessionHash = crypto.createHash('md5').update(sessionClean).digest("hex");
|
const sessionHash = crypto.createHash('md5').update(sessionClean).digest("hex");
|
||||||
return sessionHash;
|
return sessionHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Track user flow from referrers to cto
|
||||||
|
export function createFlowSessionHash(project_id: string, ip: string, userAgent: string) {
|
||||||
|
const dailySalt = new Date().toLocaleDateString('it-IT');
|
||||||
|
const sessionClean = dailySalt + project_id + ip + userAgent;
|
||||||
|
const sessionHash = crypto.createHash('md5').update(sessionClean).digest("hex");
|
||||||
|
return sessionHash;
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ export type TEvent = {
|
|||||||
name: string,
|
name: string,
|
||||||
metadata: Record<string, string>,
|
metadata: Record<string, string>,
|
||||||
session: string,
|
session: string,
|
||||||
|
flowHash: string,
|
||||||
created_at: Date
|
created_at: Date
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13,6 +14,7 @@ const EventSchema = new Schema<TEvent>({
|
|||||||
name: { type: String, required: true },
|
name: { type: String, required: true },
|
||||||
metadata: Schema.Types.Mixed,
|
metadata: Schema.Types.Mixed,
|
||||||
session: { type: String },
|
session: { type: String },
|
||||||
|
flowHash: { type: String },
|
||||||
created_at: { type: Date, default: () => Date.now() },
|
created_at: { type: Date, default: () => Date.now() },
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { model, Schema, Types } from 'mongoose';
|
|||||||
export type TSession = {
|
export type TSession = {
|
||||||
project_id: Schema.Types.ObjectId,
|
project_id: Schema.Types.ObjectId,
|
||||||
session: string,
|
session: string,
|
||||||
|
flowHash: string,
|
||||||
duration: number,
|
duration: number,
|
||||||
updated_at: Date,
|
updated_at: Date,
|
||||||
created_at: Date,
|
created_at: Date,
|
||||||
@@ -12,6 +13,7 @@ export type TSession = {
|
|||||||
const SessionSchema = new Schema<TSession>({
|
const SessionSchema = new Schema<TSession>({
|
||||||
project_id: { type: Types.ObjectId, index: 1 },
|
project_id: { type: Types.ObjectId, index: 1 },
|
||||||
session: { type: String, required: true },
|
session: { type: String, required: true },
|
||||||
|
flowHash: { type: String },
|
||||||
duration: { type: Number, required: true, default: 0 },
|
duration: { type: Number, required: true, default: 0 },
|
||||||
updated_at: { type: Date, default: () => Date.now() },
|
updated_at: { type: Date, default: () => Date.now() },
|
||||||
created_at: { type: Date, default: () => Date.now() },
|
created_at: { type: Date, default: () => Date.now() },
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ export type TVisit = {
|
|||||||
country: string,
|
country: string,
|
||||||
|
|
||||||
session: string,
|
session: string,
|
||||||
|
flowHash: string,
|
||||||
device: string,
|
device: string,
|
||||||
|
|
||||||
website: string,
|
website: string,
|
||||||
@@ -29,7 +30,7 @@ const VisitSchema = new Schema<TVisit>({
|
|||||||
country: { type: String },
|
country: { type: String },
|
||||||
|
|
||||||
session: { type: String },
|
session: { type: String },
|
||||||
|
flowHash: { type: String },
|
||||||
device: { type: String },
|
device: { type: String },
|
||||||
|
|
||||||
website: { type: String, required: true },
|
website: { type: String, required: true },
|
||||||
|
|||||||
Reference in New Issue
Block a user