feat: harmonize log and metrics
This commit is contained in:
@@ -6,6 +6,7 @@ import { Lang } from "@/constants/languages"
|
||||
import { env } from "@/env/server"
|
||||
import * as api from "@/lib/api"
|
||||
import { badRequestError } from "@/server/errors/trpc"
|
||||
import { createCounter } from "@/server/telemetry"
|
||||
import { toApiLang } from "@/server/utils"
|
||||
|
||||
import { generateChildrenString } from "@/components/HotelReservation/utils"
|
||||
@@ -13,8 +14,7 @@ import { getCacheClient } from "@/services/dataCache"
|
||||
import { cache } from "@/utils/cache"
|
||||
|
||||
import { getHotelPageUrls } from "../contentstack/hotelPage/utils"
|
||||
import { type RoomFeaturesInput, roomPackagesInputSchema } from "./input"
|
||||
import { metrics } from "./metrics"
|
||||
import { type RoomFeaturesInput } from "./input"
|
||||
import {
|
||||
type Cities,
|
||||
citiesByCountrySchema,
|
||||
@@ -38,12 +38,12 @@ import type {
|
||||
DestinationPagesHotelData,
|
||||
Room as RoomCategory,
|
||||
} from "@/types/hotel"
|
||||
import type { PackagesInput } from "@/types/requests/packages"
|
||||
import type { PackagesOutput } from "@/types/requests/packages"
|
||||
import type {
|
||||
HotelsAvailabilityInputSchema,
|
||||
HotelsByHotelIdsAvailabilityInputSchema,
|
||||
RoomsAvailabilityInputRoom,
|
||||
RoomsAvailabilityInputSchema,
|
||||
RoomsAvailabilityOutputSchema,
|
||||
} from "@/types/trpc/routers/hotel/availability"
|
||||
import type { HotelInput } from "@/types/trpc/routers/hotel/hotel"
|
||||
import type {
|
||||
@@ -332,18 +332,23 @@ export async function getHotelIdsByCityId({
|
||||
cityId: string
|
||||
serviceToken: string
|
||||
}) {
|
||||
const getHotelIdsByCityIdCounter = createCounter(
|
||||
"hotel",
|
||||
"getHotelIdsByCityId"
|
||||
)
|
||||
const metricsGetHotelIdsByCityId = getHotelIdsByCityIdCounter.init({
|
||||
cityId,
|
||||
})
|
||||
|
||||
metricsGetHotelIdsByCityId.start()
|
||||
|
||||
const cacheClient = await getCacheClient()
|
||||
return await cacheClient.cacheOrGet(
|
||||
const result = await cacheClient.cacheOrGet(
|
||||
`${cityId}:hotelsByCityId`,
|
||||
async () => {
|
||||
const searchParams = new URLSearchParams({
|
||||
city: cityId,
|
||||
})
|
||||
metrics.hotelIds.counter.add(1, { params: searchParams.toString() })
|
||||
console.info(
|
||||
"api.hotel.hotel-ids start",
|
||||
JSON.stringify({ params: searchParams.toString() })
|
||||
)
|
||||
|
||||
const apiResponse = await api.get(
|
||||
api.endpoints.v1.Hotel.hotels,
|
||||
@@ -356,59 +361,25 @@ export async function getHotelIdsByCityId({
|
||||
)
|
||||
|
||||
if (!apiResponse.ok) {
|
||||
const responseMessage = await apiResponse.text()
|
||||
metrics.hotelIds.fail.add(1, {
|
||||
params: searchParams.toString(),
|
||||
error_type: "http_error",
|
||||
error: responseMessage,
|
||||
})
|
||||
console.error(
|
||||
"api.hotel.hotel-ids fetch error",
|
||||
JSON.stringify({
|
||||
params: searchParams.toString(),
|
||||
error: {
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text: responseMessage,
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
await metricsGetHotelIdsByCityId.httpError(apiResponse)
|
||||
throw new Error("Unable to fetch hotelIds by cityId")
|
||||
}
|
||||
|
||||
const apiJson = await apiResponse.json()
|
||||
const validatedHotelIds = getHotelIdsSchema.safeParse(apiJson)
|
||||
if (!validatedHotelIds.success) {
|
||||
metrics.hotelIds.fail.add(1, {
|
||||
params: searchParams.toString(),
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(validatedHotelIds.error),
|
||||
})
|
||||
console.error(
|
||||
"api.hotel.hotel-ids validation error",
|
||||
JSON.stringify({
|
||||
params: searchParams.toString(),
|
||||
error: validatedHotelIds.error,
|
||||
})
|
||||
)
|
||||
|
||||
metricsGetHotelIdsByCityId.validationError(validatedHotelIds.error)
|
||||
throw new Error("Unable to parse data for hotelIds by cityId")
|
||||
}
|
||||
|
||||
metrics.hotelIds.success.add(1, { cityId })
|
||||
console.info(
|
||||
"api.hotel.hotel-ids success",
|
||||
JSON.stringify({
|
||||
params: searchParams.toString(),
|
||||
response: validatedHotelIds.data,
|
||||
})
|
||||
)
|
||||
|
||||
return validatedHotelIds.data
|
||||
},
|
||||
env.CACHE_TIME_HOTELS
|
||||
)
|
||||
|
||||
metricsGetHotelIdsByCityId.success()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
export async function getHotelIdsByCountry({
|
||||
@@ -418,17 +389,22 @@ export async function getHotelIdsByCountry({
|
||||
country: string
|
||||
serviceToken: string
|
||||
}) {
|
||||
const getHotelIdsByCountryCounter = createCounter(
|
||||
"hotel",
|
||||
"getHotelIdsByCountry"
|
||||
)
|
||||
|
||||
const metricsGetHotelIdsByCountry = getHotelIdsByCountryCounter.init({
|
||||
country,
|
||||
})
|
||||
|
||||
metricsGetHotelIdsByCountry.start()
|
||||
|
||||
const cacheClient = await getCacheClient()
|
||||
|
||||
return await cacheClient.cacheOrGet(
|
||||
const result = await cacheClient.cacheOrGet(
|
||||
`${country}:hotelsByCountry`,
|
||||
async () => {
|
||||
metrics.hotelIds.counter.add(1, { country })
|
||||
console.info(
|
||||
"api.hotel.hotel-ids start",
|
||||
JSON.stringify({ query: { country } })
|
||||
)
|
||||
|
||||
const hotelIdsParams = new URLSearchParams({
|
||||
country,
|
||||
})
|
||||
@@ -444,55 +420,25 @@ export async function getHotelIdsByCountry({
|
||||
)
|
||||
|
||||
if (!apiResponse.ok) {
|
||||
const responseMessage = await apiResponse.text()
|
||||
metrics.hotelIds.fail.add(1, {
|
||||
country,
|
||||
error_type: "http_error",
|
||||
error: responseMessage,
|
||||
})
|
||||
console.error(
|
||||
"api.hotel.hotel-ids fetch error",
|
||||
JSON.stringify({
|
||||
query: { country },
|
||||
error: {
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text: responseMessage,
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
await metricsGetHotelIdsByCountry.httpError(apiResponse)
|
||||
throw new Error("Unable to fetch hotelIds by country")
|
||||
}
|
||||
|
||||
const apiJson = await apiResponse.json()
|
||||
const validatedHotelIds = getHotelIdsSchema.safeParse(apiJson)
|
||||
if (!validatedHotelIds.success) {
|
||||
metrics.hotelIds.fail.add(1, {
|
||||
country,
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(validatedHotelIds.error),
|
||||
})
|
||||
console.error(
|
||||
"api.hotel.hotel-ids validation error",
|
||||
JSON.stringify({
|
||||
query: { country },
|
||||
error: validatedHotelIds.error,
|
||||
})
|
||||
)
|
||||
metricsGetHotelIdsByCountry.validationError(validatedHotelIds.error)
|
||||
throw new Error("Unable to parse hotelIds by country")
|
||||
}
|
||||
|
||||
metrics.hotelIds.success.add(1, { country })
|
||||
console.info(
|
||||
"api.hotel.hotel-ids success",
|
||||
JSON.stringify({ query: { country } })
|
||||
)
|
||||
|
||||
return validatedHotelIds.data
|
||||
},
|
||||
env.CACHE_TIME_HOTELS
|
||||
)
|
||||
|
||||
metricsGetHotelIdsByCountry.success()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
export async function getHotelIdsByCityIdentifier(
|
||||
@@ -631,128 +577,84 @@ function findProduct(product: Products, rateDefinition: RateDefinition) {
|
||||
|
||||
export const getHotel = cache(
|
||||
async (input: HotelInput, serviceToken: string) => {
|
||||
const callable = async function (
|
||||
hotelId: HotelInput["hotelId"],
|
||||
language: HotelInput["language"],
|
||||
isCardOnlyPayment?: HotelInput["isCardOnlyPayment"]
|
||||
) {
|
||||
/**
|
||||
* Since API expects the params appended and not just
|
||||
* a comma separated string we need to initialize the
|
||||
* SearchParams with a sequence of pairs
|
||||
* (include=City&include=NearbyHotels&include=Restaurants etc.)
|
||||
**/
|
||||
const params = new URLSearchParams([
|
||||
["include", "AdditionalData"],
|
||||
["include", "City"],
|
||||
["include", "NearbyHotels"],
|
||||
["include", "Restaurants"],
|
||||
["include", "RoomCategories"],
|
||||
["language", toApiLang(language)],
|
||||
])
|
||||
metrics.hotel.counter.add(1, {
|
||||
hotelId,
|
||||
language,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.hotelData start",
|
||||
JSON.stringify({ query: { hotelId, params: params.toString() } })
|
||||
)
|
||||
const { hotelId, language, isCardOnlyPayment } = input
|
||||
|
||||
const apiResponse = await api.get(
|
||||
api.endpoints.v1.Hotel.Hotels.hotel(hotelId),
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${serviceToken}`,
|
||||
},
|
||||
},
|
||||
params
|
||||
)
|
||||
const getHotelCounter = createCounter("hotel", "getHotel")
|
||||
const metricsGetHotel = getHotelCounter.init({
|
||||
hotelId,
|
||||
language,
|
||||
isCardOnlyPayment,
|
||||
})
|
||||
|
||||
if (!apiResponse.ok) {
|
||||
const text = await apiResponse.text()
|
||||
metrics.hotel.fail.add(1, {
|
||||
hotelId,
|
||||
language,
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
}),
|
||||
})
|
||||
console.error(
|
||||
"api.hotels.hotelData error",
|
||||
JSON.stringify({
|
||||
query: { hotelId, params: params.toString() },
|
||||
error: {
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
},
|
||||
})
|
||||
)
|
||||
return null
|
||||
}
|
||||
|
||||
const apiJson = await apiResponse.json()
|
||||
const validateHotelData = hotelSchema.safeParse(apiJson)
|
||||
|
||||
if (!validateHotelData.success) {
|
||||
metrics.hotel.fail.add(1, {
|
||||
hotelId,
|
||||
language,
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(validateHotelData.error),
|
||||
})
|
||||
|
||||
console.error(
|
||||
"api.hotels.hotelData validation error",
|
||||
JSON.stringify({
|
||||
query: { hotelId, params: params.toString() },
|
||||
error: validateHotelData.error,
|
||||
})
|
||||
)
|
||||
throw badRequestError()
|
||||
}
|
||||
|
||||
metrics.hotel.success.add(1, {
|
||||
hotelId,
|
||||
language,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.hotelData success",
|
||||
JSON.stringify({
|
||||
query: { hotelId, params: params.toString() },
|
||||
})
|
||||
)
|
||||
const hotelData = validateHotelData.data
|
||||
|
||||
if (isCardOnlyPayment) {
|
||||
hotelData.hotel.merchantInformationData.alternatePaymentOptions = []
|
||||
}
|
||||
|
||||
const gallery = hotelData.additionalData?.gallery
|
||||
if (gallery) {
|
||||
const smallerImages = gallery.smallerImages
|
||||
const hotelGalleryImages =
|
||||
hotelData.hotel.hotelType === HotelTypeEnum.Signature
|
||||
? smallerImages.slice(0, 10)
|
||||
: smallerImages.slice(0, 6)
|
||||
hotelData.hotel.galleryImages = hotelGalleryImages
|
||||
}
|
||||
|
||||
return hotelData
|
||||
}
|
||||
metricsGetHotel.start()
|
||||
|
||||
const cacheClient = await getCacheClient()
|
||||
return await cacheClient.cacheOrGet(
|
||||
|
||||
const result = await cacheClient.cacheOrGet(
|
||||
`${input.language}:hotel:${input.hotelId}:${!!input.isCardOnlyPayment}`,
|
||||
async () => {
|
||||
return callable(input.hotelId, input.language, input.isCardOnlyPayment)
|
||||
/**
|
||||
* Since API expects the params appended and not just
|
||||
* a comma separated string we need to initialize the
|
||||
* SearchParams with a sequence of pairs
|
||||
* (include=City&include=NearbyHotels&include=Restaurants etc.)
|
||||
**/
|
||||
const params = new URLSearchParams([
|
||||
["include", "AdditionalData"],
|
||||
["include", "City"],
|
||||
["include", "NearbyHotels"],
|
||||
["include", "Restaurants"],
|
||||
["include", "RoomCategories"],
|
||||
["language", toApiLang(language)],
|
||||
])
|
||||
|
||||
const apiResponse = await api.get(
|
||||
api.endpoints.v1.Hotel.Hotels.hotel(hotelId),
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${serviceToken}`,
|
||||
},
|
||||
},
|
||||
params
|
||||
)
|
||||
|
||||
if (!apiResponse.ok) {
|
||||
await metricsGetHotel.httpError(apiResponse)
|
||||
return null
|
||||
}
|
||||
|
||||
const apiJson = await apiResponse.json()
|
||||
const validateHotelData = hotelSchema.safeParse(apiJson)
|
||||
|
||||
if (!validateHotelData.success) {
|
||||
metricsGetHotel.validationError(validateHotelData.error)
|
||||
throw badRequestError()
|
||||
}
|
||||
|
||||
const hotelData = validateHotelData.data
|
||||
|
||||
if (isCardOnlyPayment) {
|
||||
hotelData.hotel.merchantInformationData.alternatePaymentOptions = []
|
||||
}
|
||||
|
||||
const gallery = hotelData.additionalData?.gallery
|
||||
if (gallery) {
|
||||
const smallerImages = gallery.smallerImages
|
||||
const hotelGalleryImages =
|
||||
hotelData.hotel.hotelType === HotelTypeEnum.Signature
|
||||
? smallerImages.slice(0, 10)
|
||||
: smallerImages.slice(0, 6)
|
||||
hotelData.hotel.galleryImages = hotelGalleryImages
|
||||
}
|
||||
|
||||
return hotelData
|
||||
},
|
||||
env.CACHE_TIME_HOTELS
|
||||
)
|
||||
|
||||
metricsGetHotel.success()
|
||||
|
||||
return result
|
||||
}
|
||||
)
|
||||
|
||||
@@ -781,19 +683,25 @@ export async function getHotelsAvailabilityByCity(
|
||||
...(redemption ? { isRedemption: "true" } : {}),
|
||||
language: apiLang,
|
||||
}
|
||||
metrics.hotelsAvailability.counter.add(1, {
|
||||
cityId,
|
||||
roomStayStartDate,
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
bookingCode,
|
||||
redemption,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.hotelsAvailability start",
|
||||
JSON.stringify({ query: { cityId, params } })
|
||||
|
||||
const getHotelsAvailabilityByCityCounter = createCounter(
|
||||
"hotel",
|
||||
"getHotelsAvailabilityByCity"
|
||||
)
|
||||
const metricsGetHotelsAvailabilityByCity =
|
||||
getHotelsAvailabilityByCityCounter.init({
|
||||
apiLang,
|
||||
cityId,
|
||||
roomStayStartDate,
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
bookingCode,
|
||||
redemption,
|
||||
})
|
||||
|
||||
metricsGetHotelsAvailabilityByCity.start()
|
||||
|
||||
const apiResponse = await api.get(
|
||||
api.endpoints.v1.Availability.city(cityId),
|
||||
{
|
||||
@@ -804,74 +712,19 @@ export async function getHotelsAvailabilityByCity(
|
||||
params
|
||||
)
|
||||
if (!apiResponse.ok) {
|
||||
const text = await apiResponse.text()
|
||||
metrics.hotelsAvailability.fail.add(1, {
|
||||
cityId,
|
||||
roomStayStartDate,
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
bookingCode,
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
}),
|
||||
})
|
||||
console.error(
|
||||
"api.hotels.hotelsAvailability error",
|
||||
JSON.stringify({
|
||||
query: { cityId, params },
|
||||
error: {
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
await metricsGetHotelsAvailabilityByCity.httpError(apiResponse)
|
||||
throw new Error("Failed to fetch hotels availability by city")
|
||||
}
|
||||
|
||||
const apiJson = await apiResponse.json()
|
||||
const validateAvailabilityData = hotelsAvailabilitySchema.safeParse(apiJson)
|
||||
if (!validateAvailabilityData.success) {
|
||||
metrics.hotelsAvailability.fail.add(1, {
|
||||
cityId,
|
||||
roomStayStartDate,
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
bookingCode,
|
||||
redemption,
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(validateAvailabilityData.error),
|
||||
})
|
||||
console.error(
|
||||
"api.hotels.hotelsAvailability validation error",
|
||||
JSON.stringify({
|
||||
query: { cityId, params },
|
||||
error: validateAvailabilityData.error,
|
||||
})
|
||||
metricsGetHotelsAvailabilityByCity.validationError(
|
||||
validateAvailabilityData.error
|
||||
)
|
||||
throw badRequestError()
|
||||
}
|
||||
metrics.hotelsAvailability.success.add(1, {
|
||||
cityId,
|
||||
roomStayStartDate,
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
bookingCode,
|
||||
redemption,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.hotelsAvailability success",
|
||||
JSON.stringify({
|
||||
query: { cityId, params: params },
|
||||
})
|
||||
)
|
||||
|
||||
if (redemption) {
|
||||
validateAvailabilityData.data.data.forEach((data) => {
|
||||
data.attributes.productType?.redemptions?.forEach((r) => {
|
||||
@@ -880,11 +733,15 @@ export async function getHotelsAvailabilityByCity(
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
const result = {
|
||||
availability: validateAvailabilityData.data.data.flatMap(
|
||||
(hotels) => hotels.attributes
|
||||
),
|
||||
}
|
||||
|
||||
metricsGetHotelsAvailabilityByCity.success()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
export async function getHotelsAvailabilityByHotelIds(
|
||||
@@ -910,8 +767,26 @@ export async function getHotelsAvailabilityByHotelIds(
|
||||
["language", apiLang],
|
||||
])
|
||||
|
||||
const getHotelsAvailabilityByHotelIdsCounter = createCounter(
|
||||
"hotel",
|
||||
"getHotelsAvailabilityByHotelIds"
|
||||
)
|
||||
const metricsGetHotelsAvailabilityByHotelIds =
|
||||
getHotelsAvailabilityByHotelIdsCounter.init({
|
||||
apiLang,
|
||||
hotelIds,
|
||||
roomStayStartDate,
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
bookingCode,
|
||||
})
|
||||
|
||||
metricsGetHotelsAvailabilityByHotelIds.start()
|
||||
|
||||
const cacheClient = await getCacheClient()
|
||||
return cacheClient.cacheOrGet(
|
||||
|
||||
const result = cacheClient.cacheOrGet(
|
||||
`${apiLang}:hotels:availability:${hotelIds.join(",")}:${roomStayStartDate}:${roomStayEndDate}:${adults}:${children}:${bookingCode}`,
|
||||
async () => {
|
||||
/**
|
||||
@@ -924,18 +799,7 @@ export async function getHotelsAvailabilityByHotelIds(
|
||||
hotelIds.forEach((hotelId) =>
|
||||
params.append("hotelIds", hotelId.toString())
|
||||
)
|
||||
metrics.hotelsByHotelIdAvailability.counter.add(1, {
|
||||
hotelIds,
|
||||
roomStayStartDate,
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
bookingCode,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.hotelsByHotelIdAvailability start",
|
||||
JSON.stringify({ query: { params } })
|
||||
)
|
||||
|
||||
const apiResponse = await api.get(
|
||||
api.endpoints.v1.Availability.hotels(),
|
||||
{
|
||||
@@ -946,72 +810,20 @@ export async function getHotelsAvailabilityByHotelIds(
|
||||
params
|
||||
)
|
||||
if (!apiResponse.ok) {
|
||||
const text = await apiResponse.text()
|
||||
metrics.hotelsByHotelIdAvailability.fail.add(1, {
|
||||
hotelIds,
|
||||
roomStayStartDate,
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
bookingCode,
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
}),
|
||||
})
|
||||
console.error(
|
||||
"api.hotels.hotelsByHotelIdAvailability error",
|
||||
JSON.stringify({
|
||||
query: { params },
|
||||
error: {
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
await metricsGetHotelsAvailabilityByHotelIds.httpError(apiResponse)
|
||||
throw new Error("Failed to fetch hotels availability by hotelIds")
|
||||
}
|
||||
|
||||
const apiJson = await apiResponse.json()
|
||||
const validateAvailabilityData =
|
||||
hotelsAvailabilitySchema.safeParse(apiJson)
|
||||
if (!validateAvailabilityData.success) {
|
||||
metrics.hotelsByHotelIdAvailability.fail.add(1, {
|
||||
hotelIds,
|
||||
roomStayStartDate,
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
bookingCode,
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(validateAvailabilityData.error),
|
||||
})
|
||||
console.error(
|
||||
"api.hotels.hotelsByHotelIdAvailability validation error",
|
||||
JSON.stringify({
|
||||
query: { params },
|
||||
error: validateAvailabilityData.error,
|
||||
})
|
||||
metricsGetHotelsAvailabilityByHotelIds.validationError(
|
||||
validateAvailabilityData.error
|
||||
)
|
||||
throw badRequestError()
|
||||
}
|
||||
metrics.hotelsByHotelIdAvailability.success.add(1, {
|
||||
hotelIds,
|
||||
roomStayStartDate,
|
||||
roomStayEndDate,
|
||||
adults,
|
||||
children,
|
||||
bookingCode,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.hotelsByHotelIdAvailability success",
|
||||
JSON.stringify({
|
||||
query: { params },
|
||||
})
|
||||
)
|
||||
|
||||
return {
|
||||
availability: validateAvailabilityData.data.data.flatMap(
|
||||
(hotels) => hotels.attributes
|
||||
@@ -1020,6 +832,10 @@ export async function getHotelsAvailabilityByHotelIds(
|
||||
},
|
||||
env.CACHE_TIME_CITY_SEARCH
|
||||
)
|
||||
|
||||
metricsGetHotelsAvailabilityByHotelIds.success()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
async function getRoomFeaturesInventory(
|
||||
@@ -1034,23 +850,32 @@ async function getRoomFeaturesInventory(
|
||||
roomFeatureCodes,
|
||||
startDate,
|
||||
} = input
|
||||
|
||||
const params = {
|
||||
adults,
|
||||
hotelId,
|
||||
roomFeatureCode: roomFeatureCodes,
|
||||
roomStayEndDate: endDate,
|
||||
roomStayStartDate: startDate,
|
||||
...(childrenInRoom?.length && {
|
||||
children: generateChildrenString(childrenInRoom),
|
||||
}),
|
||||
}
|
||||
|
||||
const getRoomFeaturesInventoryCounter = createCounter(
|
||||
"hotel",
|
||||
"getRoomFeaturesInventory"
|
||||
)
|
||||
const metricsGetRoomFeaturesInventory =
|
||||
getRoomFeaturesInventoryCounter.init(params)
|
||||
|
||||
metricsGetRoomFeaturesInventory.start()
|
||||
|
||||
const cacheClient = await getCacheClient()
|
||||
return cacheClient.cacheOrGet(
|
||||
|
||||
const result = cacheClient.cacheOrGet(
|
||||
stringify(input),
|
||||
async function () {
|
||||
const params = {
|
||||
adults,
|
||||
hotelId,
|
||||
roomFeatureCode: roomFeatureCodes,
|
||||
roomStayEndDate: endDate,
|
||||
roomStayStartDate: startDate,
|
||||
...(childrenInRoom?.length && {
|
||||
children: generateChildrenString(childrenInRoom),
|
||||
}),
|
||||
}
|
||||
|
||||
metrics.roomFeatures.counter.add(1, params)
|
||||
|
||||
const apiResponse = await api.get(
|
||||
api.endpoints.v1.Availability.roomFeatures(hotelId),
|
||||
{
|
||||
@@ -1062,67 +887,45 @@ async function getRoomFeaturesInventory(
|
||||
)
|
||||
|
||||
if (!apiResponse.ok) {
|
||||
const text = apiResponse.text()
|
||||
console.error(
|
||||
"api.availability.roomfeature error",
|
||||
JSON.stringify({
|
||||
query: { hotelId, params },
|
||||
error: {
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
text,
|
||||
},
|
||||
})
|
||||
)
|
||||
metrics.roomFeatures.fail.add(1, params)
|
||||
await metricsGetRoomFeaturesInventory.httpError(apiResponse)
|
||||
return null
|
||||
}
|
||||
|
||||
const data = await apiResponse.json()
|
||||
const validatedRoomFeaturesData = roomFeaturesSchema.safeParse(data)
|
||||
if (!validatedRoomFeaturesData.success) {
|
||||
console.error(
|
||||
"api.availability.roomfeature error",
|
||||
JSON.stringify({
|
||||
query: { hotelId, params },
|
||||
error: validatedRoomFeaturesData.error,
|
||||
})
|
||||
metricsGetRoomFeaturesInventory.validationError(
|
||||
validatedRoomFeaturesData.error
|
||||
)
|
||||
return null
|
||||
}
|
||||
|
||||
metrics.roomFeatures.success.add(1, params)
|
||||
|
||||
return validatedRoomFeaturesData.data
|
||||
},
|
||||
"5m"
|
||||
)
|
||||
|
||||
metricsGetRoomFeaturesInventory.success()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
export async function getPackages(
|
||||
rawInput: PackagesInput,
|
||||
serviceToken: string
|
||||
) {
|
||||
const parsedInput = roomPackagesInputSchema.safeParse(rawInput)
|
||||
if (!parsedInput.success) {
|
||||
console.info(`Failed to parse input for Get Packages`)
|
||||
console.error(parsedInput.error)
|
||||
return null
|
||||
}
|
||||
const input = parsedInput.data
|
||||
export async function getPackages(input: PackagesOutput, serviceToken: string) {
|
||||
const { adults, children, endDate, hotelId, lang, packageCodes, startDate } =
|
||||
input
|
||||
|
||||
const getPackagesCounter = createCounter("hotel", "getPackages")
|
||||
const metricsGetPackages = getPackagesCounter.init({
|
||||
input,
|
||||
})
|
||||
|
||||
metricsGetPackages.start()
|
||||
|
||||
const cacheClient = await getCacheClient()
|
||||
return cacheClient.cacheOrGet(
|
||||
|
||||
const result = cacheClient.cacheOrGet(
|
||||
stringify(input),
|
||||
async function () {
|
||||
const {
|
||||
adults,
|
||||
children,
|
||||
endDate,
|
||||
hotelId,
|
||||
lang,
|
||||
packageCodes,
|
||||
startDate,
|
||||
} = input
|
||||
const apiLang = toApiLang(lang)
|
||||
|
||||
const searchParams = new URLSearchParams({
|
||||
@@ -1137,16 +940,6 @@ export async function getPackages(
|
||||
searchParams.append("packageCodes", code)
|
||||
})
|
||||
|
||||
const params = searchParams.toString()
|
||||
|
||||
metrics.packages.counter.add(1, {
|
||||
hotelId,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.packages start",
|
||||
JSON.stringify({ query: { hotelId, params } })
|
||||
)
|
||||
|
||||
const apiResponse = await api.get(
|
||||
api.endpoints.v1.Package.Packages.hotel(hotelId),
|
||||
{
|
||||
@@ -1158,56 +951,29 @@ export async function getPackages(
|
||||
)
|
||||
|
||||
if (!apiResponse.ok) {
|
||||
metrics.packages.fail.add(1, {
|
||||
hotelId,
|
||||
error_type: "http_error",
|
||||
error: JSON.stringify({
|
||||
status: apiResponse.status,
|
||||
statusText: apiResponse.statusText,
|
||||
}),
|
||||
})
|
||||
console.error(
|
||||
"api.hotels.packages error",
|
||||
JSON.stringify({ query: { hotelId, params } })
|
||||
)
|
||||
await metricsGetPackages.httpError(apiResponse)
|
||||
return null
|
||||
}
|
||||
|
||||
const apiJson = await apiResponse.json()
|
||||
const validatedPackagesData = packagesSchema.safeParse(apiJson)
|
||||
if (!validatedPackagesData.success) {
|
||||
metrics.packages.fail.add(1, {
|
||||
hotelId,
|
||||
error_type: "validation_error",
|
||||
error: JSON.stringify(validatedPackagesData.error),
|
||||
})
|
||||
|
||||
console.error(
|
||||
"api.hotels.packages validation error",
|
||||
JSON.stringify({
|
||||
query: { hotelId, params },
|
||||
error: validatedPackagesData.error,
|
||||
})
|
||||
)
|
||||
metricsGetPackages.validationError(validatedPackagesData.error)
|
||||
return null
|
||||
}
|
||||
|
||||
metrics.packages.success.add(1, {
|
||||
hotelId,
|
||||
})
|
||||
console.info(
|
||||
"api.hotels.packages success",
|
||||
JSON.stringify({ query: { hotelId, params: params } })
|
||||
)
|
||||
|
||||
return validatedPackagesData.data
|
||||
},
|
||||
"3h"
|
||||
)
|
||||
|
||||
metricsGetPackages.success()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
export async function getRoomsAvailability(
|
||||
input: RoomsAvailabilityInputSchema,
|
||||
input: RoomsAvailabilityOutputSchema,
|
||||
token: string,
|
||||
serviceToken: string,
|
||||
userPoints: number | undefined
|
||||
@@ -1219,27 +985,18 @@ export async function getRoomsAvailability(
|
||||
|
||||
const redemption = searchType === REDEMPTION
|
||||
|
||||
const apiLang = toApiLang(lang)
|
||||
|
||||
const kids = rooms
|
||||
.map((r) => r.childrenInRoom)
|
||||
.filter(Boolean)
|
||||
.map((kid) => JSON.stringify(kid))
|
||||
const metricsData = {
|
||||
adultsCount: rooms.map((r) => r.adults),
|
||||
bookingCode,
|
||||
childArray: kids.length ? kids : undefined,
|
||||
hotelId,
|
||||
roomStayEndDate: toDate,
|
||||
roomStayStartDate: fromDate,
|
||||
}
|
||||
|
||||
metrics.roomsAvailability.counter.add(1, metricsData)
|
||||
|
||||
console.info(
|
||||
"api.hotels.roomsAvailability start",
|
||||
JSON.stringify({ query: { hotelId, params: metricsData } })
|
||||
const getRoomsAvailabilityCounter = createCounter(
|
||||
"hotel",
|
||||
"getRoomsAvailability"
|
||||
)
|
||||
const metricsGetRoomsAvailability = getRoomsAvailabilityCounter.init({
|
||||
input,
|
||||
redemption,
|
||||
})
|
||||
|
||||
metricsGetRoomsAvailability.start()
|
||||
|
||||
const apiLang = toApiLang(lang)
|
||||
|
||||
const baseCacheKey = {
|
||||
bookingCode,
|
||||
@@ -1257,7 +1014,7 @@ export async function getRoomsAvailability(
|
||||
...baseCacheKey,
|
||||
room,
|
||||
}
|
||||
return cacheClient.cacheOrGet(
|
||||
const result = cacheClient.cacheOrGet(
|
||||
stringify(cacheKey),
|
||||
async function () {
|
||||
{
|
||||
@@ -1287,9 +1044,8 @@ export async function getRoomsAvailability(
|
||||
)
|
||||
|
||||
if (!apiResponse.ok) {
|
||||
await metricsGetRoomsAvailability.httpError(apiResponse)
|
||||
const text = await apiResponse.text()
|
||||
metrics.roomsAvailability.fail.add(1, metricsData)
|
||||
console.error("Failed API call", { params, text })
|
||||
return { error: "http_error", details: text }
|
||||
}
|
||||
|
||||
@@ -1297,11 +1053,10 @@ export async function getRoomsAvailability(
|
||||
const validateAvailabilityData =
|
||||
roomsAvailabilitySchema.safeParse(apiJson)
|
||||
if (!validateAvailabilityData.success) {
|
||||
console.error("Validation error", {
|
||||
params,
|
||||
error: validateAvailabilityData.error,
|
||||
})
|
||||
metrics.roomsAvailability.fail.add(1, metricsData)
|
||||
metricsGetRoomsAvailability.validationError(
|
||||
validateAvailabilityData.error
|
||||
)
|
||||
|
||||
return {
|
||||
error: "validation_error",
|
||||
details: validateAvailabilityData.error,
|
||||
@@ -1323,7 +1078,7 @@ export async function getRoomsAvailability(
|
||||
const roomFeatures = await getPackages(
|
||||
{
|
||||
adults: room.adults,
|
||||
children: room.childrenInRoom?.length,
|
||||
children: room.childrenInRoom?.length || 0,
|
||||
endDate: input.booking.toDate,
|
||||
hotelId: input.booking.hotelId,
|
||||
lang,
|
||||
@@ -1387,9 +1142,10 @@ export async function getRoomsAvailability(
|
||||
},
|
||||
"1m"
|
||||
)
|
||||
|
||||
return result
|
||||
})
|
||||
)
|
||||
metrics.roomsAvailability.success.add(1, metricsData)
|
||||
|
||||
const data = availabilityResponses.map((availability) => {
|
||||
if (availability.status === "fulfilled") {
|
||||
@@ -1401,6 +1157,8 @@ export async function getRoomsAvailability(
|
||||
}
|
||||
})
|
||||
|
||||
metricsGetRoomsAvailability.success()
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user