Skip to content

Commit

Permalink
📈 Track workspace limit reached event
Browse files Browse the repository at this point in the history
  • Loading branch information
baptisteArno committed Apr 17, 2023
1 parent 7e937e1 commit c203a4e
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 6 deletions.
13 changes: 13 additions & 0 deletions packages/schemas/features/telemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,26 @@ const newResultsCollectedEventSchema = typebotEvent.merge(
})
)

const workspaceLimitReachedEventSchema = workspaceEvent.merge(
z.object({
name: z.literal('Workspace limit reached'),
data: z.object({
chatsLimit: z.number(),
storageLimit: z.number(),
totalChatsUsed: z.number(),
totalStorageUsed: z.number(),
}),
})
)

export const eventSchema = z.discriminatedUnion('name', [
workspaceCreatedEventSchema,
userCreatedEventSchema,
typebotCreatedEventSchema,
publishedTypebotEventSchema,
subscriptionUpdatedEventSchema,
newResultsCollectedEventSchema,
workspaceLimitReachedEventSchema,
])

export type TelemetryEvent = z.infer<typeof eventSchema>
126 changes: 120 additions & 6 deletions packages/scripts/sendTotalResultsDigest.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { PrismaClient, WorkspaceRole } from '@typebot.io/prisma'
import {
MemberInWorkspace,
PrismaClient,
WorkspaceRole,
} from '@typebot.io/prisma'
import { isDefined } from '@typebot.io/lib'
import { getChatsLimit, getStorageLimit } from '@typebot.io/lib/pricing'
import { promptAndSetEnvironment } from './utils'
import { TelemetryEvent } from '@typebot.io/schemas/features/telemetry'
import { sendTelemetryEvents } from '@typebot.io/lib/telemetry/sendTelemetryEvent'
import { Workspace } from '@typebot.io/schemas'

const prisma = new PrismaClient()

Expand Down Expand Up @@ -48,6 +54,11 @@ export const sendTotalResultsDigest = async () => {
id: true,
typebots: { select: { id: true } },
members: { select: { userId: true, role: true } },
additionalChatsIndex: true,
additionalStorageIndex: true,
customChatsLimit: true,
customStorageLimit: true,
plan: true,
},
})

Expand All @@ -61,20 +72,28 @@ export const sendTotalResultsDigest = async () => {
.filter((member) => member.role !== WorkspaceRole.GUEST)
.map((member, memberIndex) => ({
userId: member.userId,
workspaceId: workspace.id,
workspace: workspace,
typebotId: result.typebotId,
totalResultsYesterday: result._count._all,
isFirstOfKind: memberIndex === 0 ? (true as const) : undefined,
}))
})
.filter(isDefined)

const events = resultsWithWorkspaces.map(
console.log('Computing workspaces limits...')

const workspaceLimitReachedEvents = await sendAlertIfLimitReached(
resultsWithWorkspaces
.filter((result) => result.isFirstOfKind)
.map((result) => result.workspace)
)

const newResultsCollectedEvents = resultsWithWorkspaces.map(
(result) =>
({
name: 'New results collected',
userId: result.userId,
workspaceId: result.workspaceId,
workspaceId: result.workspace.id,
typebotId: result.typebotId,
data: {
total: result.totalResultsYesterday,
Expand All @@ -83,8 +102,103 @@ export const sendTotalResultsDigest = async () => {
} satisfies TelemetryEvent)
)

await sendTelemetryEvents(events)
console.log(`Sent ${events.length} events.`)
await sendTelemetryEvents(
workspaceLimitReachedEvents.concat(newResultsCollectedEvents)
)

console.log(
`Sent ${workspaceLimitReachedEvents.length} workspace limit reached events.`
)
console.log(
`Sent ${newResultsCollectedEvents.length} new results collected events.`
)
}

const sendAlertIfLimitReached = async (
workspaces: (Pick<
Workspace,
| 'id'
| 'plan'
| 'customChatsLimit'
| 'customStorageLimit'
| 'additionalChatsIndex'
| 'additionalStorageIndex'
> & { members: Pick<MemberInWorkspace, 'userId' | 'role'>[] })[]
): Promise<TelemetryEvent[]> => {
const events: TelemetryEvent[] = []
for (const workspace of workspaces) {
const { totalChatsUsed, totalStorageUsed } = await getUsage(workspace.id)
const chatsLimit = getChatsLimit(workspace)
const storageLimit = getStorageLimit(workspace)
if (totalChatsUsed >= chatsLimit || totalStorageUsed >= storageLimit) {
events.push(
...workspace.members
.filter((member) => member.role !== WorkspaceRole.GUEST)
.map(
(member) =>
({
name: 'Workspace limit reached',
userId: member.userId,
workspaceId: workspace.id,
data: {
totalChatsUsed,
totalStorageUsed,
chatsLimit,
storageLimit,
},
} satisfies TelemetryEvent)
)
)
}
}
return events
}

const getUsage = async (workspaceId: string) => {
const now = new Date()
const firstDayOfMonth = new Date(now.getFullYear(), now.getMonth(), 1)
const firstDayOfNextMonth = new Date(now.getFullYear(), now.getMonth() + 1, 1)
const [
totalChatsUsed,
{
_sum: { storageUsed: totalStorageUsed },
},
] = await prisma.$transaction(async (tx) => {
const typebots = await tx.typebot.findMany({
where: {
workspace: {
id: workspaceId,
},
},
})

return Promise.all([
prisma.result.count({
where: {
typebotId: { in: typebots.map((typebot) => typebot.id) },
hasStarted: true,
createdAt: {
gte: firstDayOfMonth,
lt: firstDayOfNextMonth,
},
},
}),
prisma.answer.aggregate({
where: {
storageUsed: { gt: 0 },
result: {
typebotId: { in: typebots.map((typebot) => typebot.id) },
},
},
_sum: { storageUsed: true },
}),
])
})

return {
totalChatsUsed,
totalStorageUsed: totalStorageUsed ?? 0,
}
}

sendTotalResultsDigest().then()

4 comments on commit c203a4e

@vercel
Copy link

@vercel vercel bot commented on c203a4e Apr 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

docs – ./apps/docs

docs-typebot-io.vercel.app
docs-git-main-typebot-io.vercel.app
docs.typebot.io

@vercel
Copy link

@vercel vercel bot commented on c203a4e Apr 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

viewer-v2 – ./apps/viewer

facelabko.com
filmylogy.com
goldorayo.com
rabbit.cr8.ai
signup.cr8.ai
start.taxt.co
turkey.cr8.ai
vhpage.cr8.ai
vitamyway.com
am.nigerias.io
an.nigerias.io
app.yvon.earth
ar.nigerias.io
bot.enreso.org
bot.rslabs.pro
bots.bridge.ai
chat.hayuri.id
chat.uprize.hu
chatgpt.lam.ee
chicken.cr8.ai
gollum.riku.ai
gsbulletin.com
journey.cr8.ai
panther.cr7.ai
panther.cr8.ai
pay.sifuim.com
penguin.cr8.ai
talk.gocare.io
test.bot.gives
ticketfute.com
unicorn.cr8.ai
apo.nigerias.io
apr.nigerias.io
aso.nigerias.io
blackcan.cr8.ai
bot.4display.nl
bot.ageenda.com
bot.artiweb.app
bot.devitus.com
bot.jesopizz.it
bot.reeplai.com
bot.scayver.com
bot.tc-mail.com
chat.lalmon.com
chat.sureb4.com
eventhub.com.au
fitness.riku.ai
games.klujo.com
wordsandimagery.com
88584434.therpm.club
92109660.therpm.club
abbonamento.bwell.it
assistent.m-vogel.de
bium.gratirabbit.com
bot.ansuraniphone.my
bot.barrettamario.it
bot.cotemeuplano.com
bot.leadbooster.help
bot.mycompay.reviews
chat.hayurihijab.com
chatbee.agfunnel.com
click.sevenoways.com
connect.growthguy.in
forms.bonanza.design
hello.advergreen.com
kuiz.sistemniaga.com
menu.numero-primo.it
menukb.wpwakanda.com
offer.botscientis.us
sellmycarglasgow.com
talkbot.agfunnel.com
tenorioadvogados.com
uppity.wpwakanda.com
abutton.wpwakanda.com
acelera.maxbot.com.br
aidigitalmarketing.kr
bbutton.wpwakanda.com
bot.coachayongzul.com
bot.digitalpointer.id
bot.eikju.photography
bot.incusservices.com
bot.meuesocial.com.br
bot.mycompany.reviews
bot.outstandbrand.com
bot.ramonmatos.com.br
bot.robertohairlab.it
bot.sharemyreview.net
bot.truongnguyen.live
botz.cloudsiteapp.com
cdd.searchcube.com.sg
chat.missarkansas.org
chatbot.ownacademy.co
chats.maisefetivo.com
criar.somaperuzzo.com
homerun.wpwakanda.com
sbutton.wpwakanda.com
rsvp.virtuesocialmedia.com
tarian.theiofoundation.org
ted.meujalecobrasil.com.br
type.dericsoncalari.com.br

@vercel
Copy link

@vercel vercel bot commented on c203a4e Apr 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

builder-v2 – ./apps/builder

app.typebot.io
builder-v2-git-main-typebot-io.vercel.app
builder-v2-typebot-io.vercel.app

@vercel
Copy link

@vercel vercel bot commented on c203a4e Apr 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.