🔊 Add prisma metrics to prometheus endpoint (#1420)
This commit is contained in:
@ -4,6 +4,7 @@ import { whatsAppRuntime } from './runtimes/whatsapp'
|
|||||||
import { prometheus } from '@hono/prometheus'
|
import { prometheus } from '@hono/prometheus'
|
||||||
import { sentry } from '@hono/sentry'
|
import { sentry } from '@hono/sentry'
|
||||||
import { env } from '@typebot.io/env'
|
import { env } from '@typebot.io/env'
|
||||||
|
import prisma from '@typebot.io/lib/prisma'
|
||||||
|
|
||||||
const app = new Hono()
|
const app = new Hono()
|
||||||
|
|
||||||
@ -12,16 +13,21 @@ app.use(
|
|||||||
sentry({
|
sentry({
|
||||||
environment: env.NODE_ENV,
|
environment: env.NODE_ENV,
|
||||||
dsn: env.NEXT_PUBLIC_SENTRY_DSN,
|
dsn: env.NEXT_PUBLIC_SENTRY_DSN,
|
||||||
release: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA + '-chat-api',
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
const { printMetrics, registerMetrics } = prometheus()
|
const { printMetrics, registerMetrics } = prometheus()
|
||||||
app.use('*', registerMetrics)
|
app.use('*', registerMetrics)
|
||||||
app.get('/metrics', printMetrics)
|
app.get('/metrics', async (c) => {
|
||||||
|
const honoMetrics = await (await printMetrics(c)).text()
|
||||||
|
const prismaMetrics = await prisma.$metrics.prometheus()
|
||||||
|
return c.text(`${honoMetrics}\n\n${prismaMetrics}`, 200)
|
||||||
|
})
|
||||||
|
|
||||||
app.get('/ping', (c) => c.json({ status: 'ok' }, 200))
|
app.get('/ping', (c) => c.json({ status: 'ok' }, 200))
|
||||||
|
|
||||||
app.route('/', webRuntime)
|
app.route('/', webRuntime)
|
||||||
|
|
||||||
app.route('/', whatsAppRuntime)
|
app.route('/', whatsAppRuntime)
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import prisma from '@typebot.io/lib/prisma'
|
import prisma from '@typebot.io/lib/prisma'
|
||||||
|
import { Prisma } from '@typebot.io/prisma'
|
||||||
import { SessionState } from '@typebot.io/schemas'
|
import { SessionState } from '@typebot.io/schemas'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -6,7 +7,10 @@ type Props = {
|
|||||||
state: SessionState
|
state: SessionState
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createSession = async ({ id, state }: Props) =>
|
export const createSession = ({
|
||||||
|
id,
|
||||||
|
state,
|
||||||
|
}: Props): Prisma.PrismaPromise<any> =>
|
||||||
prisma.chatSession.create({
|
prisma.chatSession.create({
|
||||||
data: {
|
data: {
|
||||||
id,
|
id,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import prisma from '@typebot.io/lib/prisma'
|
import prisma from '@typebot.io/lib/prisma'
|
||||||
|
import { Prisma } from '@typebot.io/prisma'
|
||||||
import { SessionState } from '@typebot.io/schemas'
|
import { SessionState } from '@typebot.io/schemas'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -6,7 +7,10 @@ type Props = {
|
|||||||
state: SessionState
|
state: SessionState
|
||||||
}
|
}
|
||||||
|
|
||||||
export const updateSession = async ({ id, state }: Props) =>
|
export const updateSession = ({
|
||||||
|
id,
|
||||||
|
state,
|
||||||
|
}: Props): Prisma.PrismaPromise<any> =>
|
||||||
prisma.chatSession.updateMany({
|
prisma.chatSession.updateMany({
|
||||||
where: { id },
|
where: { id },
|
||||||
data: {
|
data: {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import prisma from '@typebot.io/lib/prisma'
|
import prisma from '@typebot.io/lib/prisma'
|
||||||
|
import { Prisma } from '@typebot.io/prisma'
|
||||||
import { TypebotInSession } from '@typebot.io/schemas'
|
import { TypebotInSession } from '@typebot.io/schemas'
|
||||||
import { filterVariablesWithValues } from '@typebot.io/variables/filterVariablesWithValues'
|
import { filterVariablesWithValues } from '@typebot.io/variables/filterVariablesWithValues'
|
||||||
|
|
||||||
@ -8,37 +9,27 @@ type Props = {
|
|||||||
hasStarted: boolean
|
hasStarted: boolean
|
||||||
isCompleted: boolean
|
isCompleted: boolean
|
||||||
}
|
}
|
||||||
export const upsertResult = async ({
|
export const upsertResult = ({
|
||||||
resultId,
|
resultId,
|
||||||
typebot,
|
typebot,
|
||||||
hasStarted,
|
hasStarted,
|
||||||
isCompleted,
|
isCompleted,
|
||||||
}: Props) => {
|
}: Props): Prisma.PrismaPromise<any> => {
|
||||||
const existingResult = await prisma.result.findUnique({
|
const variablesWithValue = filterVariablesWithValues(typebot.variables)
|
||||||
|
return prisma.result.upsert({
|
||||||
where: { id: resultId },
|
where: { id: resultId },
|
||||||
|
update: {
|
||||||
|
isCompleted: isCompleted ? true : undefined,
|
||||||
|
hasStarted,
|
||||||
|
variables: variablesWithValue,
|
||||||
|
},
|
||||||
|
create: {
|
||||||
|
id: resultId,
|
||||||
|
typebotId: typebot.id,
|
||||||
|
isCompleted: isCompleted ? true : false,
|
||||||
|
hasStarted,
|
||||||
|
variables: variablesWithValue,
|
||||||
|
},
|
||||||
select: { id: true },
|
select: { id: true },
|
||||||
})
|
})
|
||||||
const variablesWithValue = filterVariablesWithValues(typebot.variables)
|
|
||||||
|
|
||||||
if (existingResult) {
|
|
||||||
return prisma.result.updateMany({
|
|
||||||
where: { id: resultId },
|
|
||||||
data: {
|
|
||||||
isCompleted: isCompleted ? true : undefined,
|
|
||||||
hasStarted,
|
|
||||||
variables: variablesWithValue,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return prisma.result.createMany({
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
id: resultId,
|
|
||||||
typebotId: typebot.id,
|
|
||||||
isCompleted: isCompleted ? true : false,
|
|
||||||
hasStarted,
|
|
||||||
variables: variablesWithValue,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,8 @@ import { createSession } from './queries/createSession'
|
|||||||
import { deleteSession } from './queries/deleteSession'
|
import { deleteSession } from './queries/deleteSession'
|
||||||
import * as Sentry from '@sentry/nextjs'
|
import * as Sentry from '@sentry/nextjs'
|
||||||
import { saveVisitedEdges } from './queries/saveVisitedEdges'
|
import { saveVisitedEdges } from './queries/saveVisitedEdges'
|
||||||
import { VisitedEdge } from '@typebot.io/prisma'
|
import { Prisma, VisitedEdge } from '@typebot.io/prisma'
|
||||||
|
import prisma from '@typebot.io/lib/prisma'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
session: Pick<ChatSession, 'state'> & { id?: string }
|
session: Pick<ChatSession, 'state'> & { id?: string }
|
||||||
@ -36,11 +37,13 @@ export const saveStateToDatabase = async ({
|
|||||||
!input && !containsSetVariableClientSideAction && !hasCustomEmbedBubble
|
!input && !containsSetVariableClientSideAction && !hasCustomEmbedBubble
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const queries: Prisma.PrismaPromise<any>[] = []
|
||||||
|
|
||||||
const resultId = state.typebotsQueue[0].resultId
|
const resultId = state.typebotsQueue[0].resultId
|
||||||
|
|
||||||
if (id) {
|
if (id) {
|
||||||
if (isCompleted && resultId) await deleteSession(id)
|
if (isCompleted && resultId) queries.push(deleteSession(id))
|
||||||
else await updateSession({ id, state })
|
else queries.push(updateSession({ id, state }))
|
||||||
}
|
}
|
||||||
|
|
||||||
const session =
|
const session =
|
||||||
@ -48,18 +51,23 @@ export const saveStateToDatabase = async ({
|
|||||||
? { state, id }
|
? { state, id }
|
||||||
: await createSession({ id, state })
|
: await createSession({ id, state })
|
||||||
|
|
||||||
if (!resultId) return session
|
if (!resultId) {
|
||||||
|
if (queries.length > 0) await prisma.$transaction(queries)
|
||||||
|
return session
|
||||||
|
}
|
||||||
|
|
||||||
const answers = state.typebotsQueue[0].answers
|
const answers = state.typebotsQueue[0].answers
|
||||||
|
|
||||||
await upsertResult({
|
queries.push(
|
||||||
resultId,
|
upsertResult({
|
||||||
typebot: state.typebotsQueue[0].typebot,
|
resultId,
|
||||||
isCompleted: Boolean(
|
typebot: state.typebotsQueue[0].typebot,
|
||||||
!input && !containsSetVariableClientSideAction && answers.length > 0
|
isCompleted: Boolean(
|
||||||
),
|
!input && !containsSetVariableClientSideAction && answers.length > 0
|
||||||
hasStarted: answers.length > 0,
|
),
|
||||||
})
|
hasStarted: answers.length > 0,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
if (logs && logs.length > 0)
|
if (logs && logs.length > 0)
|
||||||
try {
|
try {
|
||||||
@ -75,7 +83,9 @@ export const saveStateToDatabase = async ({
|
|||||||
Sentry.captureException(e)
|
Sentry.captureException(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (visitedEdges.length > 0) await saveVisitedEdges(visitedEdges)
|
if (visitedEdges.length > 0) queries.push(saveVisitedEdges(visitedEdges))
|
||||||
|
|
||||||
|
await prisma.$transaction(queries)
|
||||||
|
|
||||||
return session
|
return session
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
generator client {
|
generator client {
|
||||||
provider = "prisma-client-js"
|
provider = "prisma-client-js"
|
||||||
|
previewFeatures = ["metrics"]
|
||||||
}
|
}
|
||||||
|
|
||||||
datasource db {
|
datasource db {
|
||||||
|
@ -14,12 +14,12 @@
|
|||||||
"db:migrate": "pnpm migrate:deploy"
|
"db:migrate": "pnpm migrate:deploy"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/client": "5.8.0"
|
"@prisma/client": "5.12.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "20.4.2",
|
"@types/node": "20.4.2",
|
||||||
"dotenv-cli": "7.2.1",
|
"dotenv-cli": "7.2.1",
|
||||||
"prisma": "5.8.0",
|
"prisma": "5.12.1",
|
||||||
"@typebot.io/tsconfig": "workspace:*",
|
"@typebot.io/tsconfig": "workspace:*",
|
||||||
"tsx": "3.12.7",
|
"tsx": "3.12.7",
|
||||||
"typescript": "5.3.2"
|
"typescript": "5.3.2"
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
generator client {
|
generator client {
|
||||||
provider = "prisma-client-js"
|
provider = "prisma-client-js"
|
||||||
|
previewFeatures = ["metrics"]
|
||||||
}
|
}
|
||||||
|
|
||||||
datasource db {
|
datasource db {
|
||||||
|
56
pnpm-lock.yaml
generated
56
pnpm-lock.yaml
generated
@ -1751,8 +1751,8 @@ importers:
|
|||||||
packages/prisma:
|
packages/prisma:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@prisma/client':
|
'@prisma/client':
|
||||||
specifier: 5.8.0
|
specifier: 5.12.1
|
||||||
version: 5.8.0(prisma@5.8.0)
|
version: 5.12.1(prisma@5.12.1)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@typebot.io/tsconfig':
|
'@typebot.io/tsconfig':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
@ -1764,8 +1764,8 @@ importers:
|
|||||||
specifier: 7.2.1
|
specifier: 7.2.1
|
||||||
version: 7.2.1
|
version: 7.2.1
|
||||||
prisma:
|
prisma:
|
||||||
specifier: 5.8.0
|
specifier: 5.12.1
|
||||||
version: 5.8.0
|
version: 5.12.1
|
||||||
tsx:
|
tsx:
|
||||||
specifier: 3.12.7
|
specifier: 3.12.7
|
||||||
version: 3.12.7
|
version: 3.12.7
|
||||||
@ -7848,8 +7848,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
|
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@prisma/client@5.8.0(prisma@5.8.0):
|
/@prisma/client@5.12.1(prisma@5.12.1):
|
||||||
resolution: {integrity: sha512-QxO6C4MaA/ysTIbC+EcAH1aX/YkpymhXtO6zPdk+FvA7+59tNibIYpd+7koPdViLg2iKES4ojsxWNUGNJaEcbA==}
|
resolution: {integrity: sha512-6/JnizEdlSBxDIdiLbrBdMW5NqDxOmhXAJaNXiPpgzAPr/nLZResT6MMpbOHLo5yAbQ1Vv5UU8PTPRzb0WIxdA==}
|
||||||
engines: {node: '>=16.13'}
|
engines: {node: '>=16.13'}
|
||||||
requiresBuild: true
|
requiresBuild: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -7858,35 +7858,35 @@ packages:
|
|||||||
prisma:
|
prisma:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
prisma: 5.8.0
|
prisma: 5.12.1
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@prisma/debug@5.8.0:
|
/@prisma/debug@5.12.1:
|
||||||
resolution: {integrity: sha512-ZqPpkvbovu/kQJ1bvy57NO4dw97fpQGcbQSCtsqlwSE1UNKJP75R3BKxdznk8ZPMY+GJdMRetWNv4oAvSbWn8Q==}
|
resolution: {integrity: sha512-kd/wNsR0klrv79o1ITsbWxYyh4QWuBidvxsXSParPsYSu0ircUmNk3q4ojsgNc3/81b0ozg76iastOG43tbf8A==}
|
||||||
|
|
||||||
/@prisma/engines-version@5.8.0-37.0a83d8541752d7582de2ebc1ece46519ce72a848:
|
/@prisma/engines-version@5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab:
|
||||||
resolution: {integrity: sha512-cXcoVweYbnv8xRfkWq9oj8BECOdzHUazrSpYCa0ehp5TNz4l5Spa8jbq/VROCTzj3ZncH5D9Q2TmySYTOUeKlw==}
|
resolution: {integrity: sha512-6yvO8s80Tym61aB4QNtYZfWVmE3pwqe807jEtzm8C5VDe7nw8O1FGX3TXUaXmWV0fQTIAfRbeL2Gwrndabp/0g==}
|
||||||
|
|
||||||
/@prisma/engines@5.8.0:
|
/@prisma/engines@5.12.1:
|
||||||
resolution: {integrity: sha512-Qhqm9WWLujNEC13AuZlUO14SQ15tNLe5puaz+tOk7UqINqJ3PtqMmuSuzomiw2diGVqZ+HYiSQzlR3+pPucVHA==}
|
resolution: {integrity: sha512-HQDdglLw2bZR/TXD2Y+YfDMvi5Q8H+acbswqOsWyq9pPjBLYJ6gzM+ptlTU/AV6tl0XSZLU1/7F4qaWa8bqpJA==}
|
||||||
requiresBuild: true
|
requiresBuild: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@prisma/debug': 5.8.0
|
'@prisma/debug': 5.12.1
|
||||||
'@prisma/engines-version': 5.8.0-37.0a83d8541752d7582de2ebc1ece46519ce72a848
|
'@prisma/engines-version': 5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab
|
||||||
'@prisma/fetch-engine': 5.8.0
|
'@prisma/fetch-engine': 5.12.1
|
||||||
'@prisma/get-platform': 5.8.0
|
'@prisma/get-platform': 5.12.1
|
||||||
|
|
||||||
/@prisma/fetch-engine@5.8.0:
|
/@prisma/fetch-engine@5.12.1:
|
||||||
resolution: {integrity: sha512-1CAuE+JoYsPNggMEn6qk0zos06Uc9bYZBJ0VBPHD6R7REL05614koAbOCmn52IaYz3nobb7f25hqW6AY7rLkIw==}
|
resolution: {integrity: sha512-qSs3KcX1HKcea1A+hlJVK/ljj0PNIUHDxAayGMvgJBqmaN32P9tCidlKz1EGv6WoRFICYnk3Dd/YFLBwnFIozA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@prisma/debug': 5.8.0
|
'@prisma/debug': 5.12.1
|
||||||
'@prisma/engines-version': 5.8.0-37.0a83d8541752d7582de2ebc1ece46519ce72a848
|
'@prisma/engines-version': 5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab
|
||||||
'@prisma/get-platform': 5.8.0
|
'@prisma/get-platform': 5.12.1
|
||||||
|
|
||||||
/@prisma/get-platform@5.8.0:
|
/@prisma/get-platform@5.12.1:
|
||||||
resolution: {integrity: sha512-Nk3rhTFZ1LYkFZJnpSvQcLPCaBWgJQfteHII6UEENOOkYlmP0k3FuswND54tzzEr4qs39wOdV9pbXKX9U2lv7A==}
|
resolution: {integrity: sha512-pgIR+pSvhYHiUcqXVEZS31NrFOTENC9yFUdEAcx7cdQBoZPmHVjtjN4Ss6NzVDMYPrKJJ51U14EhEoeuBlMioQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@prisma/debug': 5.8.0
|
'@prisma/debug': 5.12.1
|
||||||
|
|
||||||
/@radix-ui/colors@1.0.1:
|
/@radix-ui/colors@1.0.1:
|
||||||
resolution: {integrity: sha512-xySw8f0ZVsAEP+e7iLl3EvcBXX7gsIlC1Zso/sPBW9gIWerBTgz6axrjU+MZ39wD+WFi5h5zdWpsg3+hwt2Qsg==}
|
resolution: {integrity: sha512-xySw8f0ZVsAEP+e7iLl3EvcBXX7gsIlC1Zso/sPBW9gIWerBTgz6axrjU+MZ39wD+WFi5h5zdWpsg3+hwt2Qsg==}
|
||||||
@ -19692,13 +19692,13 @@ packages:
|
|||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/prisma@5.8.0:
|
/prisma@5.12.1:
|
||||||
resolution: {integrity: sha512-hDKoEqPt2qEUTH5yGO3l27CBnPtwvte0CGMKrpCr9+/A919JghfqJ3qgCGgMbOwdkXUOzdho0RH9tyUF3UhpMw==}
|
resolution: {integrity: sha512-SkMnb6wyIxTv9ACqiHBI2u9gD6y98qXRoCoLEnZsF6yee5Qg828G+ARrESN+lQHdw4maSZFFSBPPDpvSiVTo0Q==}
|
||||||
engines: {node: '>=16.13'}
|
engines: {node: '>=16.13'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
requiresBuild: true
|
requiresBuild: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@prisma/engines': 5.8.0
|
'@prisma/engines': 5.12.1
|
||||||
|
|
||||||
/prismjs@1.29.0:
|
/prismjs@1.29.0:
|
||||||
resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==}
|
resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==}
|
||||||
|
Reference in New Issue
Block a user