feat: add metrics
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
import { stat } from "fs"
|
||||
|
||||
import * as api from "@/lib/api"
|
||||
import { initiateSaveCardSchema } from "@/server/routers/user/output"
|
||||
import { protectedProcedure, router } from "@/server/trpc"
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { metrics } from "@opentelemetry/api"
|
||||
|
||||
import { Lang } from "@/constants/languages"
|
||||
import { env } from "@/env/server"
|
||||
import * as api from "@/lib/api"
|
||||
@@ -32,12 +34,62 @@ import type {
|
||||
TrackingSDKUserData,
|
||||
} from "@/types/components/tracking"
|
||||
|
||||
// OpenTelemetry metrics: User
|
||||
const meter = metrics.getMeter("trpc.user")
|
||||
const getVerifiedUserCounter = meter.createCounter("trpc.user.get")
|
||||
const getVerifiedUserSuccessCounter = meter.createCounter(
|
||||
"trpc.user.get-success"
|
||||
)
|
||||
const getVerifiedUserFailCounter = meter.createCounter("trpc.user.get-fail")
|
||||
const getProfileCounter = meter.createCounter("trpc.user.profile")
|
||||
const getProfileSuccessCounter = meter.createCounter(
|
||||
"trpc.user.profile-success"
|
||||
)
|
||||
const getProfileFailCounter = meter.createCounter("trpc.user.profile-fail")
|
||||
|
||||
// OpenTelemetry metrics: Stays
|
||||
const getPreviousStaysCounter = meter.createCounter("trpc.user.stays.previous")
|
||||
const getPreviousStaysSuccessCounter = meter.createCounter(
|
||||
"trpc.user.stays.previous-success"
|
||||
)
|
||||
const getPreviousStaysFailCounter = meter.createCounter(
|
||||
"trpc.user.stays.previous-fail"
|
||||
)
|
||||
const getUpcomingStaysCounter = meter.createCounter("trpc.user.stays.upcoming")
|
||||
const getUpcomingStaysSuccessCounter = meter.createCounter(
|
||||
"trpc.user.stays.upcoming-success"
|
||||
)
|
||||
const getUpcomingStaysFailCounter = meter.createCounter(
|
||||
"trpc.user.stays.upcoming-fail"
|
||||
)
|
||||
|
||||
// OpenTelemetry metrics: Transactions
|
||||
const getFriendTransactionsCounter = meter.createCounter(
|
||||
"trpc.user.transactions.friendTransactions"
|
||||
)
|
||||
const getFriendTransactionsSuccessCounter = meter.createCounter(
|
||||
"trpc.user.transactions.friendTransactions-success"
|
||||
)
|
||||
const getFriendTransactionsFailCounter = meter.createCounter(
|
||||
"trpc.user.transactions.friendTransactions-fail"
|
||||
)
|
||||
|
||||
// OpenTelemetry metrics: Credit Cards
|
||||
const getCreditCardsCounter = meter.createCounter("trpc.user.creditCards")
|
||||
const getCreditCardsSuccessCounter = meter.createCounter(
|
||||
"trpc.user.creditCards-success"
|
||||
)
|
||||
const getCreditCardsFailCounter = meter.createCounter(
|
||||
"trpc.user.creditCards-fail"
|
||||
)
|
||||
|
||||
async function getVerifiedUser({ session }: { session: Session }) {
|
||||
const now = Date.now()
|
||||
|
||||
if (session.token.expires_at && session.token.expires_at < now) {
|
||||
return { error: true, cause: "token_expired" } as const
|
||||
}
|
||||
getVerifiedUserCounter.add(1)
|
||||
console.info("api.user.profile start", JSON.stringify({}))
|
||||
const apiResponse = await api.get(api.endpoints.v1.profile, {
|
||||
cache: "no-store",
|
||||
@@ -48,6 +100,14 @@ async function getVerifiedUser({ session }: { session: Session }) {
|
||||
|
||||
if (!apiResponse.ok) {
|
||||
const text = await apiResponse.text()
|
||||
getVerifiedUserFailCounter.add(1, {
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
}),
|
||||
})
|
||||
console.error(
|
||||
"api.user.profile error",
|
||||
JSON.stringify({
|
||||
@@ -74,12 +134,17 @@ async function getVerifiedUser({ session }: { session: Session }) {
|
||||
|
||||
const apiJson = await apiResponse.json()
|
||||
if (!apiJson.data?.attributes) {
|
||||
getVerifiedUserFailCounter.add(1, { error_type: "data_error" })
|
||||
console.error("api.user.profile data error", JSON.stringify({})) // not passing the data to avoid logging sensitive data
|
||||
return null
|
||||
}
|
||||
|
||||
const verifiedData = getUserSchema.safeParse(apiJson.data.attributes)
|
||||
if (!verifiedData.success) {
|
||||
getVerifiedUserFailCounter.add(1, {
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(verifiedData.error),
|
||||
})
|
||||
console.error(
|
||||
"api.user.profile validation error",
|
||||
JSON.stringify({
|
||||
@@ -88,6 +153,7 @@ async function getVerifiedUser({ session }: { session: Session }) {
|
||||
)
|
||||
return null
|
||||
}
|
||||
getVerifiedUserSuccessCounter.add(1)
|
||||
console.info("api.user.profile success", JSON.stringify({}))
|
||||
return verifiedData
|
||||
}
|
||||
@@ -118,6 +184,7 @@ async function updateStaysBookingUrl(
|
||||
lang: Lang
|
||||
) {
|
||||
// Tenporary API call needed till we have user name in ctx session data
|
||||
getProfileCounter.add(1)
|
||||
console.info("api.user.profile start", JSON.stringify({}))
|
||||
const apiResponse = await api.get(api.endpoints.v1.profile, {
|
||||
cache: "no-store",
|
||||
@@ -155,6 +222,7 @@ async function updateStaysBookingUrl(
|
||||
}
|
||||
|
||||
if (apiResponse.ok) {
|
||||
getProfileSuccessCounter.add(1)
|
||||
console.info("api.user.profile success", JSON.stringify({}))
|
||||
const apiJson = await apiResponse.json()
|
||||
if (apiJson.data?.attributes) {
|
||||
@@ -181,6 +249,7 @@ async function updateStaysBookingUrl(
|
||||
})
|
||||
}
|
||||
}
|
||||
getProfileFailCounter.add(1, { error: JSON.stringify(apiResponse) })
|
||||
console.info("api.user.profile error", JSON.stringify({ error: apiResponse }))
|
||||
|
||||
return data
|
||||
@@ -300,7 +369,7 @@ export const userQueryRouter = router({
|
||||
|
||||
const params = new URLSearchParams()
|
||||
params.set("limit", "1")
|
||||
|
||||
getPreviousStaysCounter.add(1, { params: params.toString() })
|
||||
console.info(
|
||||
"api.booking.stays.past start",
|
||||
JSON.stringify({ query: { params } })
|
||||
@@ -316,6 +385,13 @@ export const userQueryRouter = router({
|
||||
)
|
||||
|
||||
if (!previousStaysResponse.ok) {
|
||||
getPreviousStaysFailCounter.add(1, {
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: previousStaysResponse.status,
|
||||
statusText: previousStaysResponse.statusText,
|
||||
}),
|
||||
})
|
||||
console.error(
|
||||
"api.booking.stays.past error",
|
||||
JSON.stringify({
|
||||
@@ -332,12 +408,17 @@ export const userQueryRouter = router({
|
||||
const verifiedPreviousStaysData =
|
||||
getStaysSchema.safeParse(previousStaysApiJson)
|
||||
if (!verifiedPreviousStaysData.success) {
|
||||
getPreviousStaysFailCounter.add(1, {
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(verifiedPreviousStaysData.error),
|
||||
})
|
||||
console.error(
|
||||
"api.booking.stays.past validation error, ",
|
||||
JSON.stringify({ error: verifiedPreviousStaysData.error })
|
||||
)
|
||||
return notLoggedInUserTrackingData
|
||||
}
|
||||
getPreviousStaysSuccessCounter.add(1)
|
||||
console.info("api.booking.stays.past success", JSON.stringify({}))
|
||||
|
||||
const membership = getMembership(verifiedUserData.data.memberships)
|
||||
@@ -373,6 +454,7 @@ export const userQueryRouter = router({
|
||||
if (cursor) {
|
||||
params.offset = cursor
|
||||
}
|
||||
getPreviousStaysCounter.add(1, { params: params.toString() })
|
||||
console.info(
|
||||
"api.booking.stays.past start",
|
||||
JSON.stringify({ query: { params: params.toString() } })
|
||||
@@ -390,6 +472,15 @@ export const userQueryRouter = router({
|
||||
|
||||
if (!apiResponse.ok) {
|
||||
const text = await apiResponse.text()
|
||||
getPreviousStaysFailCounter.add(1, {
|
||||
query: JSON.stringify({ params: params.toString() }),
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
}),
|
||||
})
|
||||
console.error(
|
||||
"api.booking.stays.past error ",
|
||||
JSON.stringify({
|
||||
@@ -408,6 +499,11 @@ export const userQueryRouter = router({
|
||||
|
||||
const verifiedData = getStaysSchema.safeParse(apiJson)
|
||||
if (!verifiedData.success) {
|
||||
getPreviousStaysFailCounter.add(1, {
|
||||
query: JSON.stringify({ params: params.toString() }),
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(verifiedData.error),
|
||||
})
|
||||
console.error(
|
||||
"api.booking.stays.past validation error ",
|
||||
JSON.stringify({
|
||||
@@ -418,6 +514,9 @@ export const userQueryRouter = router({
|
||||
|
||||
return null
|
||||
}
|
||||
getPreviousStaysSuccessCounter.add(1, {
|
||||
query: JSON.stringify({ params: params.toString() }),
|
||||
})
|
||||
console.info(
|
||||
"api.booking.stays.past success",
|
||||
JSON.stringify({ query: { params: params.toString() } })
|
||||
@@ -449,6 +548,9 @@ export const userQueryRouter = router({
|
||||
if (cursor) {
|
||||
params.offset = cursor
|
||||
}
|
||||
getUpcomingStaysCounter.add(1, {
|
||||
query: JSON.stringify({ params: params.toString() }),
|
||||
})
|
||||
console.info(
|
||||
"api.booking.stays.future start",
|
||||
JSON.stringify({ query: { params: params.toString() } })
|
||||
@@ -465,10 +567,20 @@ export const userQueryRouter = router({
|
||||
|
||||
if (!apiResponse.ok) {
|
||||
const text = await apiResponse.text()
|
||||
getUpcomingStaysFailCounter.add(1, {
|
||||
query: JSON.stringify({ params: params.toString() }),
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
}),
|
||||
})
|
||||
console.error(
|
||||
"api.booking.stays.future error ",
|
||||
JSON.stringify({
|
||||
query: { params: params.toString() },
|
||||
error_type: "http_error",
|
||||
error: {
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
@@ -482,6 +594,11 @@ export const userQueryRouter = router({
|
||||
const apiJson = await apiResponse.json()
|
||||
const verifiedData = getStaysSchema.safeParse(apiJson)
|
||||
if (!verifiedData.success) {
|
||||
getUpcomingStaysFailCounter.add(1, {
|
||||
query: JSON.stringify({ params: params.toString() }),
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(verifiedData.error),
|
||||
})
|
||||
console.error(
|
||||
"api.booking.stays.future validation error ",
|
||||
JSON.stringify({
|
||||
@@ -491,6 +608,9 @@ export const userQueryRouter = router({
|
||||
)
|
||||
return null
|
||||
}
|
||||
getUpcomingStaysSuccessCounter.add(1, {
|
||||
query: JSON.stringify({ params: params.toString() }),
|
||||
})
|
||||
console.info("api.booking.stays.future success", {
|
||||
query: { params: params.toString() },
|
||||
})
|
||||
@@ -517,6 +637,7 @@ export const userQueryRouter = router({
|
||||
.input(friendTransactionsInput)
|
||||
.query(async ({ ctx, input }) => {
|
||||
const { limit, page } = input
|
||||
getFriendTransactionsCounter.add(1)
|
||||
console.info(
|
||||
"api.transaction.friendTransactions start",
|
||||
JSON.stringify({})
|
||||
@@ -541,6 +662,14 @@ export const userQueryRouter = router({
|
||||
// throw internalServerError()
|
||||
// }
|
||||
const text = await apiResponse.text()
|
||||
getFriendTransactionsFailCounter.add(1, {
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
}),
|
||||
})
|
||||
console.error(
|
||||
"api.transaction.friendTransactions error ",
|
||||
JSON.stringify({
|
||||
@@ -557,6 +686,10 @@ export const userQueryRouter = router({
|
||||
const apiJson = await apiResponse.json()
|
||||
const verifiedData = getFriendTransactionsSchema.safeParse(apiJson)
|
||||
if (!verifiedData.success) {
|
||||
getFriendTransactionsFailCounter.add(1, {
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(verifiedData.error),
|
||||
})
|
||||
console.error(
|
||||
"api.transaction.friendTransactions validation error ",
|
||||
JSON.stringify({ error: verifiedData.error })
|
||||
@@ -564,6 +697,7 @@ export const userQueryRouter = router({
|
||||
return null
|
||||
}
|
||||
|
||||
getFriendTransactionsSuccessCounter.add(1)
|
||||
console.info(
|
||||
"api.transaction.friendTransactions success",
|
||||
JSON.stringify({})
|
||||
@@ -624,6 +758,7 @@ export const userQueryRouter = router({
|
||||
}),
|
||||
|
||||
creditCards: protectedProcedure.query(async function ({ ctx }) {
|
||||
getCreditCardsCounter.add(1)
|
||||
console.info("api.profile.creditCards start", JSON.stringify({}))
|
||||
const apiResponse = await api.get(api.endpoints.v1.creditCards, {
|
||||
cache: "no-store",
|
||||
@@ -634,6 +769,14 @@ export const userQueryRouter = router({
|
||||
|
||||
if (!apiResponse.ok) {
|
||||
const text = await apiResponse.text()
|
||||
getCreditCardsFailCounter.add(1, {
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
}),
|
||||
})
|
||||
console.error(
|
||||
"api.profile.creditCards error ",
|
||||
JSON.stringify({
|
||||
@@ -650,17 +793,23 @@ export const userQueryRouter = router({
|
||||
const apiJson = await apiResponse.json()
|
||||
const verifiedData = creditCardsSchema.safeParse(apiJson)
|
||||
if (!verifiedData.success) {
|
||||
getCreditCardsFailCounter.add(1, {
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(verifiedData.error),
|
||||
})
|
||||
console.error(
|
||||
"api.profile.creditCards validation error ",
|
||||
JSON.stringify({ error: verifiedData.error })
|
||||
)
|
||||
return null
|
||||
}
|
||||
getCreditCardsSuccessCounter.add(1)
|
||||
console.info("api.profile.creditCards success", JSON.stringify({}))
|
||||
return verifiedData.data.data
|
||||
}),
|
||||
|
||||
membershipCards: protectedProcedure.query(async function ({ ctx }) {
|
||||
getProfileCounter.add(1)
|
||||
console.info("api.profile start", JSON.stringify({}))
|
||||
const apiResponse = await api.get(api.endpoints.v1.profile, {
|
||||
cache: "no-store",
|
||||
@@ -681,7 +830,15 @@ export const userQueryRouter = router({
|
||||
// throw internalServerError()
|
||||
// }
|
||||
const text = await apiResponse.text()
|
||||
console.log(
|
||||
getProfileFailCounter.add(1, {
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
}),
|
||||
})
|
||||
console.error(
|
||||
"api.profile error",
|
||||
JSON.stringify({
|
||||
error: {
|
||||
@@ -700,12 +857,17 @@ export const userQueryRouter = router({
|
||||
)
|
||||
|
||||
if (!verifiedData.success) {
|
||||
getProfileFailCounter.add(1, {
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(verifiedData),
|
||||
})
|
||||
console.error(
|
||||
"api.profile validation error",
|
||||
JSON.stringify({ error: verifiedData })
|
||||
)
|
||||
return null
|
||||
}
|
||||
getProfileSuccessCounter.add(1)
|
||||
console.info("api.profile success", JSON.stringify({}))
|
||||
const cards = getMembershipCards(verifiedData.data)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user