feat: add metrics

This commit is contained in:
Arvid Norlin
2024-08-22 16:50:55 +02:00
parent fac0d7acdc
commit 0b2936159f
9 changed files with 507 additions and 11 deletions
-2
View File
@@ -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"
+164 -2
View File
@@ -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)