Merged in feature/wrap-logging (pull request #2511)

Feature/wrap logging

* feat: change all logging to go through our own logger function so that we can control log levels

* move packages/trpc to using our own logger

* merge


Approved-by: Linus Flood
This commit is contained in:
Joakim Jäderberg
2025-07-03 12:37:04 +00:00
parent 7e32ed294d
commit daf765f3d5
110 changed files with 681 additions and 441 deletions

View File

@@ -1,3 +1,5 @@
import { logger } from "@scandic-hotels/common/logger"
import { getFilteredJobs, getFiltersFromJobs } from "./utils"
import {
@@ -55,7 +57,7 @@ export function reducer(state: State, action: Action) {
}
default:
const unhandledActionType: never = type
console.info(`Unhandled type: ${unhandledActionType}`)
logger.info(`Unhandled JobylonFeed type: ${unhandledActionType}`)
return state
}
}

View File

@@ -10,6 +10,7 @@ import {
} from "react-aria-components"
import { useIntl } from "react-intl"
import { logger } from "@scandic-hotels/common/logger"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { trpc } from "@scandic-hotels/trpc/client"
@@ -177,7 +178,7 @@ function getRedeemFlow(reward: Reward, membershipNumber: string) {
case "Tier":
return <RedeemTier reward={reward} membershipNumber={membershipNumber} />
default:
console.warn("Unsupported reward type for redeem:", rewardType)
logger.warn("Unsupported reward type for redeem:", rewardType)
return null
}
}

View File

@@ -2,6 +2,7 @@
import { createContext, useCallback, useContext, useEffect } from "react"
import { logger } from "@scandic-hotels/common/logger"
import { trpc } from "@scandic-hotels/trpc/client"
import { getFirstRedeemableCoupon } from "@/utils/rewards"
@@ -41,7 +42,7 @@ export default function useRedeemFlow() {
setRedeemStep("redeemed")
},
onError(error) {
console.error("Failed to redeem", error)
logger.error("Failed to redeem", error)
},
}
)

View File

@@ -6,6 +6,7 @@ import { useState } from "react"
import { Button as ButtonRAC } from "react-aria-components"
import { useIntl } from "react-intl"
import { logger } from "@scandic-hotels/common/logger"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { PointOfInterestGroupEnum } from "@scandic-hotels/trpc/enums/pointOfInterest"
@@ -120,7 +121,7 @@ export default function Sidebar({
})
default:
const option: never = group
console.warn(`Unsupported group given: ${option}`)
logger.warn(`Unsupported group given: ${option}`)
return intl.formatMessage({
defaultMessage: "N/A",

View File

@@ -4,6 +4,8 @@ import "dialogshift-webchat-sdk/bundles/dialogshift-webchat-sdk.min.css"
import { useEffect, useRef } from "react"
import { logger } from "@scandic-hotels/common/logger"
import type { Lang } from "@scandic-hotels/common/constants/language"
interface DialogshiftWidgetClientProps {
@@ -26,7 +28,7 @@ export default function DialogshiftWidgetClient({
locale: language,
})
} catch (error) {
console.error("Failed to load Dialogshift chat:", error)
logger.error("Failed to load Dialogshift chat:", error)
}
}

View File

@@ -1,3 +1,5 @@
import { logger } from "@scandic-hotels/common/logger"
import { getIntl } from "@/i18n"
import { isFacilityCard, setFacilityCardGrids } from "@/utils/facilityCards"
@@ -55,7 +57,7 @@ export default async function Facilities({
defaultMessage: "Read more",
})
default:
console.warn(`Unsupported option given: ${text}`)
logger.warn(`Unsupported option given: ${text}`)
return intl.formatMessage({
defaultMessage: "Read more",
})

View File

@@ -1,3 +1,5 @@
import { logger } from "@scandic-hotels/common/logger"
import { getIntl } from "@/i18n"
import {
@@ -112,7 +114,7 @@ export async function translateWellnessDetails({
.sort()
default:
console.warn(`Unsupported type given: ${type}`)
logger.warn(`Unsupported type given: ${type}`)
}
}

View File

@@ -1,3 +1,5 @@
import { logger } from "@scandic-hotels/common/logger"
import type { Lang } from "@scandic-hotels/common/constants/language"
import type { Hotel, HotelData } from "@scandic-hotels/trpc/types/hotel"
import type { HotelPage } from "@scandic-hotels/trpc/types/hotelPage"
@@ -83,7 +85,7 @@ export function translateWellnessType(type: string, intl: IntlShape) {
defaultMessage: "Sauna",
})
default:
console.warn(`Unsupported group given: ${type}`)
logger.warn(`Unsupported wellnessType: ${type}`)
return intl.formatMessage({
defaultMessage: "Wellness",
})

View File

@@ -3,6 +3,8 @@
import { usePathname } from "next/navigation"
import { useCallback, useEffect } from "react"
import { logger } from "@scandic-hotels/common/logger"
import { webviews } from "@/constants/routes/webviews"
export default function CookieBotConsent() {
@@ -20,7 +22,7 @@ export default function CookieBotConsent() {
window.adobe.optIn.deny(window.adobe.OptInCategories.ANALYTICS, true)
}
window.adobe.optIn.complete()
console.warn("window.load event explicitly dispatched.")
logger.warn("window.load event explicitly dispatched.")
window.dispatchEvent(new Event("load"))
}
}, [isWebview])

View File

@@ -1,3 +1,5 @@
import { logger } from "@scandic-hotels/common/logger"
import List from "./List"
import Puffs from "./Puffs"
import Text from "./Text"
@@ -24,7 +26,7 @@ export default function Blocks({ blocks }: BlocksProps) {
case BlocksTypenameEnum.CurrentBlocksPageBlocksText:
return <Text key={`${block.__typename}-${idx}`} {...block} />
default:
console.log(`Unknown type: (${type})`)
logger.error(`Unknown type: (${type})`)
return null
}
})}

View File

@@ -3,6 +3,8 @@
import { usePathname, useSearchParams } from "next/navigation"
import { useEffect } from "react"
import { logger } from "@scandic-hotels/common/logger"
import type {
SiteSectionObject,
TrackingData,
@@ -82,7 +84,7 @@ export default function Tracking({ pageData }: TrackingProps) {
window.adobe.optIn.deny(window.adobe.OptInCategories.ANALYTICS, true)
}
window.adobe.optIn.complete()
console.warn("window.load event explicitly dispatched.")
logger.warn("window.load event explicitly dispatched.")
window.dispatchEvent(new Event("load"))
}
}

View File

@@ -1,6 +1,8 @@
import * as Sentry from "@sentry/nextjs"
import React from "react"
import { logger } from "@scandic-hotels/common/logger"
type ErrorBoundaryProps = {
children: React.ReactNode
fallback?: React.ReactNode
@@ -21,7 +23,7 @@ class ErrorBoundary extends React.Component<
}
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
console.error("ErrorBoundary caught an error:", error, errorInfo)
logger.error("ErrorBoundary caught an error:", error, errorInfo)
Sentry.captureException(error, { extra: { errorInfo } })
}

View File

@@ -6,6 +6,7 @@ import { type ChangeEvent, type FormEvent, useId } from "react"
import { useFormContext, useWatch } from "react-hook-form"
import { useIntl } from "react-intl"
import { logger } from "@scandic-hotels/common/logger"
import { Button } from "@scandic-hotels/design-system/Button"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
@@ -78,7 +79,7 @@ export function Search({
setValue("city", undefined)
break
default:
console.error("Unhandled type:", selectedItem.type)
logger.error("Unhandled type:", selectedItem.type)
break
}

View File

@@ -6,6 +6,7 @@ import { FormProvider, useForm } from "react-hook-form"
import { useIntl } from "react-intl"
import { profile } from "@scandic-hotels/common/constants/routes/myPages"
import { logger } from "@scandic-hotels/common/logger"
import { trpc } from "@scandic-hotels/trpc/client"
import { langToApiLang } from "@scandic-hotels/trpc/constants/apiLang"
@@ -84,7 +85,7 @@ export default function Form({ user }: EditFormProps) {
case Status.error:
if (response.issues?.length) {
response.issues.forEach((issue) => {
console.error(issue)
logger.error("Profile edit error:", issue)
})
}
toast.error(response.message)

View File

@@ -6,6 +6,7 @@ import { useRouter } from "next/navigation"
import { FormProvider, useForm } from "react-hook-form"
import { useIntl } from "react-intl"
import { logger } from "@scandic-hotels/common/logger"
import { Button } from "@scandic-hotels/design-system/Button"
import Checkbox from "@scandic-hotels/design-system/Form/Checkbox"
import { Typography } from "@scandic-hotels/design-system/Typography"
@@ -69,7 +70,7 @@ export default function SignupForm({ title }: SignUpFormProps) {
defaultMessage: "Something went wrong!",
})
)
console.error("Component Signup error:", error)
logger.error("Component Signup error:", error)
},
})

View File

@@ -3,6 +3,7 @@ import { createEvent } from "ics"
import { useIntl } from "react-intl"
import { dt } from "@scandic-hotels/common/dt"
import { logger } from "@scandic-hotels/common/logger"
import { toast } from "@/components/TempDesignSystem/Toasts"
import useLang from "@/hooks/useLang"
@@ -25,7 +26,7 @@ export default function AddToCalendar({
createEvent(event, (error, value) => {
if (error) {
console.error("ICS Error:", error)
logger.error("ICS Error:", error)
toast.error(
intl.formatMessage({
defaultMessage: "Failed to add to calendar",
@@ -45,7 +46,7 @@ export default function AddToCalendar({
URL.revokeObjectURL(url)
})
} catch (error) {
console.error("Download error:", error)
logger.error("Download error:", error)
toast.error(
intl.formatMessage({
defaultMessage: "Failed to add to calendar",

View File

@@ -1,5 +1,7 @@
import "client-only"
import { logger } from "@scandic-hotels/common/logger"
export const glaStorageName = "gla-storage"
type GlaSessionData = {
@@ -15,7 +17,7 @@ export function readGlaFromSessionStorage(): GlaSessionData | null {
if (!glaSessionData) return null
return JSON.parse(glaSessionData)
} catch (error) {
console.error("Error reading from session storage:", error)
logger.error("Error reading from session storage:", error)
return null
}
}
@@ -37,7 +39,7 @@ export function writeGlaToSessionStorage(
})
)
} catch (error) {
console.error("Error writing to session storage:", error)
logger.error("Error writing to session storage:", error)
}
}

View File

@@ -10,6 +10,7 @@ import { useIntl } from "react-intl"
import { PaymentMethodEnum } from "@scandic-hotels/common/constants/paymentMethod"
import { selectRate } from "@scandic-hotels/common/constants/routes/hotelReservation"
import { logger } from "@scandic-hotels/common/logger"
import Body from "@scandic-hotels/design-system/Body"
import { Button } from "@scandic-hotels/design-system/Button"
import Checkbox from "@scandic-hotels/design-system/Form/Checkbox"
@@ -180,7 +181,7 @@ export default function PaymentClient({
}
},
onError: (error) => {
console.error("Error", error)
logger.error("Booking error", error)
handlePaymentError(error.message)
},
})
@@ -195,7 +196,7 @@ export default function PaymentClient({
setPriceChangeData(null)
},
onError: (error) => {
console.error("Error", error)
logger.error("Price change error", error)
setPriceChangeData(null)
handlePaymentError(error.message)
},

View File

@@ -1,4 +1,5 @@
import { PaymentMethodEnum } from "@scandic-hotels/common/constants/paymentMethod"
import { logger } from "@scandic-hotels/common/logger"
import type { RoomState } from "@/types/stores/enter-details"
@@ -63,7 +64,7 @@ export function readPaymentInfoFromSessionStorage():
if (!paymentInfoSessionData) return undefined
return JSON.parse(paymentInfoSessionData)
} catch (error) {
console.error("Error reading from session storage:", error)
logger.error("Error reading from session storage:", error)
return undefined
}
}
@@ -81,7 +82,7 @@ export function writePaymentInfoToSessionStorage(
})
)
} catch (error) {
console.error("Error writing to session storage:", error)
logger.error("Error writing to session storage:", error)
}
}

View File

@@ -1,3 +1,5 @@
import { logger } from "@scandic-hotels/common/logger"
import { sumPackages } from "@/components/HotelReservation/utils"
import type { RoomState } from "@/types/stores/enter-details"
@@ -133,7 +135,7 @@ export function mapToPrice(rooms: RoomState[], isMember: boolean) {
}
}
console.error(room.roomRate)
logger.error("Unknown roomRate", room.roomRate)
throw new Error(`Unknown roomRate`)
})
}

View File

@@ -6,6 +6,7 @@ import { FormProvider, useForm } from "react-hook-form"
import { useIntl } from "react-intl"
import { myStay } from "@scandic-hotels/common/constants/routes/myStay"
import { logger } from "@scandic-hotels/common/logger"
import Body from "@scandic-hotels/design-system/Body"
import Caption from "@scandic-hotels/design-system/Caption"
import { trpc } from "@scandic-hotels/trpc/client"
@@ -48,7 +49,7 @@ export default function FindMyBooking() {
router.push(`${myStay[lang]}?RefId=${encodeURIComponent(result.refId)}`)
},
onError: (error) => {
console.error("Failed to create ref id", error)
logger.error("Failed to create ref id", error)
toast.error(
intl.formatMessage({
defaultMessage: "Failed to submit form, please try again later.",

View File

@@ -1,3 +1,5 @@
import { logger } from "@scandic-hotels/common/logger"
import type {
Ancillary,
SelectedAncillary,
@@ -59,7 +61,7 @@ export const getAncillarySessionData = ():
const storedData = sessionStorage.getItem(ancillarySessionKey)
return storedData ? JSON.parse(storedData) : undefined
} catch (error) {
console.error("Error reading from session storage:", error)
logger.error("Error reading from session storage:", error)
return undefined
}
}
@@ -96,7 +98,7 @@ export function setAncillarySessionData({
})
)
} catch (error) {
console.error("Error writing to session storage:", error)
logger.error("Error writing to session storage:", error)
}
}

View File

@@ -4,6 +4,7 @@ import { useIntl } from "react-intl"
import { CurrencyEnum } from "@scandic-hotels/common/constants/currency"
import { dt } from "@scandic-hotels/common/dt"
import { logger } from "@scandic-hotels/common/logger"
import Body from "@scandic-hotels/design-system/Body"
import Caption from "@scandic-hotels/design-system/Caption"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
@@ -122,7 +123,7 @@ export default function SelectedRoomPanel() {
}
if (!selectedProduct) {
console.error("Selected product is unknown")
logger.error("Selected product is unknown")
return null
}

View File

@@ -5,6 +5,7 @@ import { useEffect, useRef } from "react"
import { useIntl } from "react-intl"
import { partnerSas } from "@scandic-hotels/common/constants/routes/myPages"
import { logger } from "@scandic-hotels/common/logger"
import { trpc } from "@scandic-hotels/trpc/client"
import { TIER_TO_FRIEND_MAP } from "@/constants/membershipLevels"
@@ -42,7 +43,7 @@ export function SASLevelUpgradeCheck() {
}
},
onError() {
console.log("[sas] something went wrong")
logger.error("[sas] something went wrong")
},
})

View File

@@ -7,6 +7,7 @@ import { Dialog, Modal, ModalOverlay } from "react-aria-components"
import { useIntl } from "react-intl"
import { benefits } from "@scandic-hotels/common/constants/routes/myPages"
import { logger } from "@scandic-hotels/common/logger"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { trpc } from "@scandic-hotels/trpc/client"
@@ -91,7 +92,7 @@ export default function SurprisesNotification({
)
},
onError: (error) => {
console.error("Failed to unwrap surprise", error)
logger.error("Failed to unwrap surprise", error)
toast.error(
<>
{intl.formatMessage(

View File

@@ -2,6 +2,7 @@ import { headers } from "next/headers"
import { redirect } from "next/navigation"
import { overview } from "@scandic-hotels/common/constants/routes/myPages"
import { logger } from "@scandic-hotels/common/logger"
import { isValidSession } from "@scandic-hotels/trpc/utils/session"
import { getProfile } from "@/lib/trpc/memoizedRequests"
@@ -26,7 +27,9 @@ export async function ProtectedLayout({ children }: React.PropsWithChildren) {
const redirectURL = `/${lang}/login?redirectTo=${redirectTo}`
if (!isValidSession(session)) {
console.log(`[layout:protected] no session, redirecting to: ${redirectURL}`)
logger.debug(
`[layout:protected] no session, redirecting to: ${redirectURL}`
)
redirect(redirectURL)
}
@@ -34,27 +37,23 @@ export async function ProtectedLayout({ children }: React.PropsWithChildren) {
if (user && "error" in user) {
// redirect(redirectURL)
console.error("[layout:protected] error in user", user)
console.error(
"[layout:protected] full user: ",
JSON.stringify(user, null, 4)
)
logger.error("[layout:protected] error in user", user)
switch (user.cause) {
case "unauthorized": // fall through
case "forbidden": // fall through
case "token_expired":
console.error(
logger.error(
`[layout:protected] user error, redirecting to: ${redirectURL}`
)
redirect(redirectURL)
case "notfound":
console.error(`[layout:protected] notfound user loading error`)
logger.error(`[layout:protected] notfound user loading error`)
break
case "unknown":
console.error(`[layout:protected] unknown user loading error`)
logger.error(`[layout:protected] unknown user loading error`)
break
default:
console.error(`[layout:protected] unhandled user loading error`)
logger.error(`[layout:protected] unhandled user loading error`)
break
}
return (
@@ -67,7 +66,7 @@ export async function ProtectedLayout({ children }: React.PropsWithChildren) {
}
if (!user) {
console.error(
logger.error(
"[layout:protected] no user found, redirecting to: ",
redirectURL
)

View File

@@ -6,6 +6,7 @@ import { useIntl } from "react-intl"
import { useMediaQuery } from "usehooks-ts"
import { dt } from "@scandic-hotels/common/dt"
import { logger } from "@scandic-hotels/common/logger"
import { Select } from "@scandic-hotels/design-system/Select"
import useLang from "@/hooks/useLang"
@@ -104,7 +105,7 @@ export default function DateSelect({ name, registerOptions = {} }: DateProps) {
? parseDate(currentDateValue)
: null
} catch (error) {
console.warn("Known error for parse date in DateSelect: ", error)
logger.warn("Known error for parse date in DateSelect: ", error)
}
useEffect(() => {

View File

@@ -1,3 +1,4 @@
import { logger } from "@scandic-hotels/common/logger"
import { phoneErrors } from "@scandic-hotels/common/utils/zod/phoneValidator"
import { signupErrors } from "@scandic-hotels/trpc/routers/user/schemas"
@@ -182,7 +183,7 @@ export function getErrorMessage(intl: IntlShape, errorCode?: string) {
"Reward nights can't be combined with codes or vouchers.",
})
default:
console.warn("Error code not supported:", errorCode)
logger.warn("Error code not supported:", errorCode)
return errorCode
}
}

View File

@@ -1,3 +1,5 @@
import { logger } from "@scandic-hotels/common/logger"
import type { IntlShape } from "react-intl/src/types"
import { RoomLighting, SeatingType } from "@/types/enums/meetingRooms"
@@ -33,7 +35,7 @@ export function translateRoomLighting(option: string, intl: IntlShape) {
defaultMessage: "Windows natural daylight and excellent view",
})
default:
console.warn(`Unsupported conference room ligthing option: ${option}`)
logger.warn(`Unsupported conference room ligthing option: ${option}`)
return intl.formatMessage({
defaultMessage: "N/A",
})
@@ -75,7 +77,7 @@ export function translateSeatingType(type: string, intl: IntlShape) {
defaultMessage: "U-shape",
})
default:
console.warn(`Unsupported conference room type : ${type}`)
logger.warn(`Unsupported conference room type : ${type}`)
return intl.formatMessage({
defaultMessage: "N/A",
})

View File

@@ -15,6 +15,7 @@ import {
type UseFromSubscribe,
} from "react-hook-form"
import { logger } from "@scandic-hotels/common/logger"
import { trpc } from "@scandic-hotels/trpc/client"
import useRouterTransitionStore from "@/stores/router-transition"
@@ -215,13 +216,13 @@ const trackPerformance = async ({
try {
pageLoadTime = await promiseWithTimeout(getPageLoadTimeEntry(), 3000)
} catch (error) {
console.error("Error obtaining pageLoadTime:", error)
logger.error("Error obtaining pageLoadTime:", error)
}
try {
lcpTime = await promiseWithTimeout(getLCPTimeEntry(), 3000)
} catch (error) {
console.error("Error obtaining lcpTime:", error)
logger.error("Error obtaining lcpTime:", error)
}
const trackingData = {