Skip to content

Commit

Permalink
chore: Calculate & Store MAC stats (#30439)
Browse files Browse the repository at this point in the history
  • Loading branch information
KevLehman authored Oct 4, 2023
1 parent eb416f7 commit 1d2c83b
Show file tree
Hide file tree
Showing 13 changed files with 207 additions and 1 deletion.
8 changes: 8 additions & 0 deletions .changeset/brown-comics-cheat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@rocket.chat/meteor": patch
"@rocket.chat/core-typings": patch
"@rocket.chat/model-typings": patch
---

chore: Calculate & Store MAC stats
Added new info to the stats: `omnichannelContactsBySource`, `uniqueContactsOfLastMonth`, `uniqueContactsOfLastWeek`, `uniqueContactsOfYesterday`
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ type WorkspaceRegistrationData<T> = {
setupComplete: boolean;
connectionDisable: boolean;
npsEnabled: SettingValue;
activeContactsBillingMonth: unknown;
activeContactsYesterday: unknown;
};

export async function buildWorkspaceRegistrationData<T extends string | undefined>(contactEmail: T): Promise<WorkspaceRegistrationData<T>> {
Expand Down Expand Up @@ -78,5 +80,7 @@ export async function buildWorkspaceRegistrationData<T extends string | undefine
setupComplete: setupWizardState === 'completed',
connectionDisable: !registerServer,
npsEnabled,
activeContactsBillingMonth: stats.omnichannelContactsBySource.contactsCount,
activeContactsYesterday: stats.uniqueContactsOfYesterday.contactsCount,
};
}
32 changes: 32 additions & 0 deletions apps/meteor/app/statistics/server/lib/statistics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ import {
LivechatCustomField,
Subscriptions,
Users,
LivechatRooms,
} from '@rocket.chat/models';
import { MongoInternals } from 'meteor/mongo';
import moment from 'moment';

import { getStatistics as getEnterpriseStatistics } from '../../../../ee/app/license/server';
import { readSecondaryPreferred } from '../../../../server/database/readSecondaryPreferred';
Expand Down Expand Up @@ -259,6 +261,36 @@ export const statistics = {
}),
);

const defaultValue = { contactsCount: 0, conversationsCount: 0, sources: [] };
const billablePeriod = moment.utc().format('YYYY-MM');
statsPms.push(
LivechatRooms.getMACStatisticsForPeriod(billablePeriod).then(([result]) => {
statistics.omnichannelContactsBySource = result || defaultValue;
}),
);

const monthAgo = moment.utc().subtract(30, 'days').toDate();
const today = moment.utc().toDate();
statsPms.push(
LivechatRooms.getMACStatisticsBetweenDates(monthAgo, today).then(([result]) => {
statistics.uniqueContactsOfLastMonth = result || defaultValue;
}),
);

const weekAgo = moment.utc().subtract(7, 'days').toDate();
statsPms.push(
LivechatRooms.getMACStatisticsBetweenDates(weekAgo, today).then(([result]) => {
statistics.uniqueContactsOfLastWeek = result || defaultValue;
}),
);

const yesterday = moment.utc().subtract(1, 'days').toDate();
statsPms.push(
LivechatRooms.getMACStatisticsBetweenDates(yesterday, today).then(([result]) => {
statistics.uniqueContactsOfYesterday = result || defaultValue;
}),
);

// Message statistics
statistics.totalChannelMessages = (await Rooms.findByType('c', { projection: { msgs: 1 } }).toArray()).reduce(
function _countChannelMessages(num: number, room: IRoom) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,10 @@ export default {
uniqueOSOfYesterday: { data: [], day: 0, month: 0, year: 0 },
uniqueOSOfLastWeek: { data: [], day: 0, month: 0, year: 0 },
uniqueOSOfLastMonth: { data: [], day: 0, month: 0, year: 0 },
omnichannelContactsBySource: { contactsCount: 0, conversationsCount: 0, sources: [] },
uniqueContactsOfLastMonth: { contactsCount: 0, conversationsCount: 0, sources: [] },
uniqueContactsOfLastWeek: { contactsCount: 0, conversationsCount: 0, sources: [] },
uniqueContactsOfYesterday: { contactsCount: 0, conversationsCount: 0, sources: [] },
apps: {
engineVersion: 'x.y.z',
enabled: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ export default {
uniqueOSOfYesterday: { data: [], day: 0, month: 0, year: 0 },
uniqueOSOfLastWeek: { data: [], day: 0, month: 0, year: 0 },
uniqueOSOfLastMonth: { data: [], day: 0, month: 0, year: 0 },
omnichannelContactsBySource: { contactsCount: 0, conversationsCount: 0, sources: [] },
uniqueContactsOfLastMonth: { contactsCount: 0, conversationsCount: 0, sources: [] },
uniqueContactsOfLastWeek: { contactsCount: 0, conversationsCount: 0, sources: [] },
uniqueContactsOfYesterday: { contactsCount: 0, conversationsCount: 0, sources: [] },
apps: {
engineVersion: 'x.y.z',
enabled: false,
Expand Down
4 changes: 4 additions & 0 deletions apps/meteor/client/views/admin/info/UsageCard.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ export default {
uniqueOSOfYesterday: { data: [], day: 0, month: 0, year: 0 },
uniqueOSOfLastWeek: { data: [], day: 0, month: 0, year: 0 },
uniqueOSOfLastMonth: { data: [], day: 0, month: 0, year: 0 },
omnichannelContactsBySource: { contactsCount: 0, conversationsCount: 0, sources: [] },
uniqueContactsOfLastMonth: { contactsCount: 0, conversationsCount: 0, sources: [] },
uniqueContactsOfLastWeek: { contactsCount: 0, conversationsCount: 0, sources: [] },
uniqueContactsOfYesterday: { contactsCount: 0, conversationsCount: 0, sources: [] },
apps: {
engineVersion: 'x.y.z',
enabled: false,
Expand Down
122 changes: 122 additions & 0 deletions apps/meteor/server/models/raw/LivechatRooms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type {
ILivechatPriority,
IOmnichannelServiceLevelAgreements,
ReportResult,
MACStats,
} from '@rocket.chat/core-typings';
import { UserStatus } from '@rocket.chat/core-typings';
import type { ILivechatRoomsModel } from '@rocket.chat/model-typings';
Expand Down Expand Up @@ -74,6 +75,7 @@ export class LivechatRoomsRaw extends BaseRaw<IOmnichannelRoom> implements ILive
{ key: { departmentId: 1, ts: 1 }, partialFilterExpression: { departmentId: { $exists: true }, t: 'l' } },
{ key: { 'tags.0': 1, 'ts': 1 }, partialFilterExpression: { 'tags.0': { $exists: true }, 't': 'l' } },
{ key: { servedBy: 1, ts: 1 }, partialFilterExpression: { servedBy: { $exists: true }, t: 'l' } },
{ key: { 'v.activity': 1, 'ts': 1 }, partialFilterExpression: { 'v.activity': { $exists: true }, 't': 'l' } },
];
}

Expand Down Expand Up @@ -2462,6 +2464,126 @@ export class LivechatRoomsRaw extends BaseRaw<IOmnichannelRoom> implements ILive
return this.updateOne(query, update);
}

async getMACStatisticsForPeriod(period: string): Promise<MACStats[]> {
return this.col
.aggregate<MACStats>([
{
$match: {
't': 'l',
'v.activity': period,
},
},
{
$group: {
_id: {
source: {
$ifNull: ['$source.alias', '$source.type'],
},
},
contactsCount: {
$addToSet: '$v._id',
},
conversationsCount: {
$sum: 1,
},
},
},
{
$group: {
_id: null,
sources: {
$push: {
source: '$_id.source',
contactsCount: {
$size: '$contactsCount',
},
conversationsCount: '$conversationsCount',
},
},
totalContactsCount: {
$sum: {
$size: '$contactsCount',
},
},
totalConversationsCount: {
$sum: '$conversationsCount',
},
},
},
{
$project: {
_id: 0,
contactsCount: '$totalContactsCount',
conversationsCount: '$totalConversationsCount',
sources: 1,
},
},
])
.toArray();
}

async getMACStatisticsBetweenDates(start: Date, end: Date): Promise<MACStats[]> {
return this.col
.aggregate<MACStats>([
{
$match: {
't': 'l',
'v.activity': { $exists: true },
'ts': {
$gte: start,
$lt: end,
},
},
},
{
$group: {
_id: {
source: {
$ifNull: ['$source.alias', '$source.type'],
},
},
contactsCount: {
$addToSet: '$v._id',
},
conversationsCount: {
$sum: 1,
},
},
},
{
$group: {
_id: null,
sources: {
$push: {
source: '$_id.source',
contactsCount: {
$size: '$contactsCount',
},
conversationsCount: '$conversationsCount',
},
},
totalContactsCount: {
$sum: {
$size: '$contactsCount',
},
},
totalConversationsCount: {
$sum: '$conversationsCount',
},
},
},
{
$project: {
_id: 0,
contactsCount: '$totalContactsCount',
conversationsCount: '$totalConversationsCount',
sources: 1,
},
},
])
.toArray();
}

async unsetAllPredictedVisitorAbandonment(): Promise<void> {
throw new Error('Method not implemented.');
}
Expand Down
6 changes: 6 additions & 0 deletions apps/meteor/server/models/raw/LivechatVisitors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,12 @@ export class LivechatVisitorsRaw extends BaseRaw<ILivechatVisitor> implements IL
},
);
}

countVisitorsOnPeriod(period: string): Promise<number> {
return this.countDocuments({
activity: period,
});
}
}

type DeepWriteable<T> = { -readonly [P in keyof T]: DeepWriteable<T[P]> };
5 changes: 5 additions & 0 deletions packages/core-typings/src/IStats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { CpuInfo } from 'os';
import type { DeviceSessionAggregationResult, OSSessionAggregationResult, UserSessionAggregationResult } from './ISession';
import type { ISettingStatisticsObject } from './ISetting';
import type { ITeamStats } from './ITeam';
import type { MACStats } from './omnichannel';

export interface IStats {
_id: string;
Expand Down Expand Up @@ -85,6 +86,10 @@ export interface IStats {
mongoStorageEngine: string;
pushQueue: number;
omnichannelSources: { [key: string]: number | string }[];
omnichannelContactsBySource: MACStats;
uniqueContactsOfLastMonth: MACStats;
uniqueContactsOfLastWeek: MACStats;
uniqueContactsOfYesterday: MACStats;
departments: number;
archivedDepartments: number;
routingAlgorithm: string;
Expand Down
1 change: 1 addition & 0 deletions packages/core-typings/src/omnichannel/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './sms';
export * from './routing';
export * from './queue';
export * from './reports';
export * from './mac';
5 changes: 5 additions & 0 deletions packages/core-typings/src/omnichannel/mac.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export type MACStats = {
contactsCount: number;
conversationsCount: number;
sources: { source: string; contactsCount: number; conversationsCount: number }[];
};
11 changes: 10 additions & 1 deletion packages/model-typings/src/models/ILivechatRoomsModel.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import type { IMessage, IOmnichannelRoom, IOmnichannelRoomClosingInfo, ISetting, ILivechatVisitor } from '@rocket.chat/core-typings';
import type {
IMessage,
IOmnichannelRoom,
IOmnichannelRoomClosingInfo,
ISetting,
ILivechatVisitor,
MACStats,
} from '@rocket.chat/core-typings';
import type { FindCursor, UpdateResult, AggregationCursor, Document, FindOptions, DeleteResult, Filter } from 'mongodb';

import type { FindPaginated } from '..';
Expand Down Expand Up @@ -235,4 +242,6 @@ export interface ILivechatRoomsModel extends IBaseModel<IOmnichannelRoom> {
changeVisitorByRoomId(roomId: string, visitor: { _id: string; username: string; token: string }): Promise<UpdateResult>;
unarchiveOneById(roomId: string): Promise<UpdateResult>;
markVisitorActiveForPeriod(rid: string, period: string): Promise<UpdateResult>;
getMACStatisticsForPeriod(period: string): Promise<MACStats[]>;
getMACStatisticsBetweenDates(start: Date, end: Date): Promise<MACStats[]>;
}
2 changes: 2 additions & 0 deletions packages/model-typings/src/models/ILivechatVisitorsModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,6 @@ export interface ILivechatVisitorsModel extends IBaseModel<ILivechatVisitor> {
disableById(_id: string): Promise<UpdateResult>;

findEnabled(query: Filter<ILivechatVisitor>, options?: FindOptions<ILivechatVisitor>): FindCursor<ILivechatVisitor>;

countVisitorsOnPeriod(period: string): Promise<number>;
}

0 comments on commit 1d2c83b

Please sign in to comment.