Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(logger): calculate loading latency from iframe init to render #248

Merged
merged 9 commits into from
Mar 27, 2024
10 changes: 4 additions & 6 deletions src/App.res
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
@react.component
let make = () => {
let (logger, initTimestamp) = React.useMemo0(() => {
(OrcaLogger.make(), Date.now())
})
let url = RescriptReactRouter.useUrl()
let (integrateError, setIntegrateErrorError) = React.useState(() => false)
let setLoggerState = Recoil.useSetRecoilState(RecoilAtoms.loggerAtom)

let paymentMode = CardUtils.getQueryParamsDictforKey(url.search, "componentName")
let fullscreenMode = CardUtils.getQueryParamsDictforKey(url.search, "fullscreenType")

let logger = React.useMemo0(() => {
let log = OrcaLogger.make()
log
})

React.useEffect(() => {
setLoggerState(_ => logger)
None
Expand Down Expand Up @@ -41,7 +39,7 @@ let make = () => {
| "sepaBankTransfer" =>
<BankTransfersPopup transferType=fullscreenMode />
| _ =>
<LoaderController paymentMode setIntegrateErrorError logger>
<LoaderController paymentMode setIntegrateErrorError logger initTimestamp>
<Payment paymentMode integrateError logger />
</LoaderController>
}
Expand Down
53 changes: 43 additions & 10 deletions src/LoaderController.res
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
open Utils
@react.component
let make = (~children, ~paymentMode, ~setIntegrateErrorError, ~logger) => {
let make = (~children, ~paymentMode, ~setIntegrateErrorError, ~logger, ~initTimestamp) => {
open RecoilAtoms
//<...>//
let (configAtom, setConfig) = Recoil.useRecoilState(configAtom)
Expand All @@ -15,6 +15,7 @@ let make = (~children, ~paymentMode, ~setIntegrateErrorError, ~logger) => {
let setIsGooglePayReady = Recoil.useSetRecoilState(isGooglePayReady)
let setIsApplePayReady = Recoil.useSetRecoilState(isApplePayReady)
let (divH, setDivH) = React.useState(_ => 0.0)
let (launchTime, setLaunchTime) = React.useState(_ => 0.0)
let {showCardFormByDefault, paymentMethodOrder} = optionsPayment

let divRef = React.useRef(Nullable.null)
Expand Down Expand Up @@ -130,15 +131,28 @@ let make = (~children, ~paymentMode, ~setIntegrateErrorError, ~logger) => {
showCardFormByDefault && Utils.checkPriorityList(paymentMethodOrder) ? SemiLoaded : Loading
| x => x
}
let finalLoadLatency = Js.Date.now() -. launchTime
switch updatedState {
| Loaded(_) => logger.setLogInfo(~value="Loaded", ~eventName=LOADER_CHANGED, ())
| Loading => logger.setLogInfo(~value="Loading", ~eventName=LOADER_CHANGED, ())
| Loaded(_) =>
logger.setLogInfo(~value="Loaded", ~eventName=LOADER_CHANGED, ~latency=finalLoadLatency, ())
| Loading =>
logger.setLogInfo(~value="Loading", ~eventName=LOADER_CHANGED, ~latency=finalLoadLatency, ())
| SemiLoaded => {
setList(_ => updatedState)
logger.setLogInfo(~value="SemiLoaded", ~eventName=LOADER_CHANGED, ())
logger.setLogInfo(
~value="SemiLoaded",
~eventName=LOADER_CHANGED,
~latency=finalLoadLatency,
(),
)
}
| LoadError(x) =>
logger.setLogError(~value="LoadError: " ++ x->JSON.stringify, ~eventName=LOADER_CHANGED, ())
logger.setLogError(
~value="LoadError: " ++ x->JSON.stringify,
~eventName=LOADER_CHANGED,
~latency=finalLoadLatency,
(),
)
}
Window.addEventListener("click", ev =>
handleOnClickPostMessage(~targetOrigin=keys.parentURL, ev)
Expand Down Expand Up @@ -257,8 +271,14 @@ let make = (~children, ~paymentMode, ~setIntegrateErrorError, ~logger) => {
})
}
}

logger.setLogInfo(~value=Window.href, ~eventName=APP_RENDERED, ())
setLaunchTime(_ => dict->Utils.getFloat("launchTime", 0.0))
let initLoadlatency = Date.now() -. launchTime
logger.setLogInfo(
~value=Window.href,
~eventName=APP_RENDERED,
~latency=initLoadlatency,
(),
)
[
("iframeId", "no-element"->JSON.Encode.string),
("publishableKey", ""->JSON.Encode.string),
Expand All @@ -267,8 +287,13 @@ let make = (~children, ~paymentMode, ~setIntegrateErrorError, ~logger) => {
]->Array.forEach(keyPair => {
dict->CommonHooks.updateKeys(keyPair, setKeys)
})

logger.setLogInfo(~eventName=PAYMENT_OPTIONS_PROVIDED, ~value="", ())
let renderLatency = Date.now() -. initTimestamp
logger.setLogInfo(
~eventName=PAYMENT_OPTIONS_PROVIDED,
~latency=renderLatency,
~value="",
(),
)
}
} else if dict->getDictIsSome("paymentOptions") {
let paymentOptions = dict->Utils.getDictFromObj("paymentOptions")
Expand Down Expand Up @@ -340,6 +365,7 @@ let make = (~children, ~paymentMode, ~setIntegrateErrorError, ~logger) => {
}
if dict->getDictIsSome("paymentMethodList") {
let list = dict->getJsonObjectFromDict("paymentMethodList")
let finalLoadlatency = Js.Date.now() -. launchTime
let updatedState: PaymentType.loadType =
list == Dict.make()->JSON.Encode.object
? LoadError(list)
Expand All @@ -351,11 +377,18 @@ let make = (~children, ~paymentMode, ~setIntegrateErrorError, ~logger) => {
isNonEmptyPaymentMethodList ? Loaded(list) : LoadError(list)
}
switch updatedState {
| Loaded(_) => logger.setLogInfo(~value="Loaded", ~eventName=LOADER_CHANGED, ())
| Loaded(_) =>
logger.setLogInfo(
~value="Loaded",
~eventName=LOADER_CHANGED,
~latency=finalLoadlatency,
(),
)
| LoadError(x) =>
logger.setLogError(
~value="LoadError: " ++ x->JSON.stringify,
~eventName=LOADER_CHANGED,
~latency=finalLoadlatency,
(),
)
| _ => ()
Expand Down
2 changes: 2 additions & 0 deletions src/orca-loader/Elements.res
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ let make = (
let endpoint = ApiEndpoint.getApiEndPoint(~publishableKey, ())
let appearance =
localOptions->Dict.get("appearance")->Option.getOr(Dict.make()->JSON.Encode.object)
let launchTime = localOptions->getFloat("launchTime", 0.0)

let fonts =
localOptions
Expand Down Expand Up @@ -247,6 +248,7 @@ let make = (
("sdkHandleOneClickConfirmPayment", sdkHandleOneClickConfirmPayment->JSON.Encode.bool),
("parentURL", "*"->JSON.Encode.string),
("analyticsMetadata", analyticsMetadata),
("launchTime", launchTime->JSON.Encode.float),
]->Dict.fromArray

let handleApplePayMounted = (event: Types.event) => {
Expand Down
9 changes: 7 additions & 2 deletions src/orca-loader/Hyper.res
Original file line number Diff line number Diff line change
Expand Up @@ -348,12 +348,17 @@ let make = (publishableKey, options: option<JSON.t>, analyticsInfo: option<JSON.

let elements = elementsOptions => {
open Promise
let elementsOptionsDict = elementsOptions->JSON.Decode.object
elementsOptionsDict
->Option.forEach(x => x->Dict.set("launchTime", Date.now()->JSON.Encode.float))
->ignore

let clientSecretId =
elementsOptions
->JSON.Decode.object
elementsOptionsDict
->Option.flatMap(x => x->Dict.get("clientSecret"))
->Option.flatMap(JSON.Decode.string)
->Option.getOr("")
let elementsOptions = elementsOptionsDict->Option.mapOr(elementsOptions, JSON.Encode.object)
clientSecret := clientSecretId
Js.Promise.make((~resolve, ~reject as _) => {
logger.setClientSecret(clientSecretId)
Expand Down
15 changes: 13 additions & 2 deletions src/orca-log-catcher/OrcaLogger.res
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ type setLogInfo = (
~internalMetadata: string=?,
~eventName: eventName,
~timestamp: string=?,
~latency: float=?,
~logType: logType=?,
~logCategory: logCategory=?,
~paymentMethod: string=?,
Expand Down Expand Up @@ -198,6 +199,7 @@ let defaultLoggerConfig = {
~internalMetadata as _=?,
~eventName as _,
~timestamp as _=?,
~latency as _=?,
~logType as _=?,
~logCategory as _=?,
~paymentMethod as _=?,
Expand All @@ -219,6 +221,7 @@ let defaultLoggerConfig = {
~internalMetadata as _=?,
~eventName as _,
~timestamp as _=?,
~latency as _=?,
~logType as _=?,
~logCategory as _=?,
~paymentMethod as _=?,
Expand Down Expand Up @@ -558,14 +561,18 @@ let make = (
~internalMetadata="",
~eventName,
~timestamp=?,
~latency=?,
~logType=INFO,
~logCategory=USER_EVENT,
~paymentMethod="",
(),
) => {
let eventNameStr = eventName->eventNameToStrMapper
let firstEvent = events.contents->Dict.get(eventNameStr)->Option.isNone
let latency = calculateLatencyHook(~eventName, ())
let latency = switch latency {
| Some(lat) => lat->Float.toString
| None => calculateLatencyHook(~eventName, ())
}
let localTimestamp = timestamp->Option.getOr(Date.now()->Belt.Float.toString)
let localTimestampFloat = localTimestamp->Belt.Float.fromString->Option.getOr(Date.now())
{
Expand Down Expand Up @@ -657,14 +664,18 @@ let make = (
~internalMetadata="",
~eventName,
~timestamp=?,
~latency=?,
~logType=ERROR,
~logCategory=USER_ERROR,
~paymentMethod="",
(),
) => {
let eventNameStr = eventName->eventNameToStrMapper
let firstEvent = events.contents->Dict.get(eventNameStr)->Option.isNone
let latency = calculateLatencyHook(~eventName, ())
let latency = switch latency {
| Some(lat) => lat->Float.toString
| None => calculateLatencyHook(~eventName, ())
}
let localTimestamp = timestamp->Option.getOr(Date.now()->Belt.Float.toString)
let localTimestampFloat = localTimestamp->Belt.Float.fromString->Option.getOr(Date.now())
{
Expand Down
Loading