-
Notifications
You must be signed in to change notification settings - Fork 106
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
chore: [#176778467] Track loading services details stats #2785
Changes from 9 commits
4fb30d8
5f2715f
b3424c5
9c26c7d
a39160b
c8b14b7
a3308d4
d553fc2
607d2fc
29baf38
fa1bf5f
16b1481
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
import { readableReport } from "italia-ts-commons/lib/reporters"; | ||
import { call, Effect, fork, put, take } from "redux-saga/effects"; | ||
import { call, Effect, fork, put, take, takeLatest } from "redux-saga/effects"; | ||
import { ActionType, getType } from "typesafe-actions"; | ||
import { buffers, channel, Channel } from "redux-saga"; | ||
import { Millisecond } from "italia-ts-commons/lib/units"; | ||
import { BackendClient } from "../../api/backend"; | ||
import { | ||
loadServiceDetail, | ||
|
@@ -11,6 +12,8 @@ import { SagaCallReturnType } from "../../types/utils"; | |
import { handleOrganizationNameUpdateSaga } from "../services/handleOrganizationNameUpdateSaga"; | ||
import { handleServiceReadabilitySaga } from "../services/handleServiceReadabilitySaga"; | ||
import { totServiceFetchWorkers } from "../../config"; | ||
import { applicationChangeState } from "../../store/actions/application"; | ||
import { mixpanelTrack } from "../../mixpanel"; | ||
|
||
/** | ||
* A generator to load the service details from the Backend | ||
|
@@ -77,6 +80,9 @@ function* handleServiceLoadRequest( | |
export function* watchServicesDetailLoadSaga( | ||
getService: ReturnType<typeof BackendClient>["getService"] | ||
) { | ||
// start a saga to track services detail load stats | ||
yield fork(watchLoadServicesDetailToTrack); | ||
|
||
// Create the channel used for the communication with the handlers. | ||
const requestsChannel: Channel<ActionType< | ||
typeof loadServiceDetail.request | ||
|
@@ -100,3 +106,109 @@ export function* watchServicesDetailLoadSaga( | |
); | ||
} | ||
} | ||
|
||
/** | ||
* listen for loading services details events to extract some track information | ||
* like amount of details to load and how much time they take | ||
*/ | ||
function* watchLoadServicesDetailToTrack() { | ||
yield takeLatest( | ||
[loadServicesDetail, loadServiceDetail.success, applicationChangeState], | ||
action => { | ||
switch (action.type) { | ||
// request to load a set of services detail | ||
// copying object is needed to avoid "immutable" error on frozen objects | ||
case getType(loadServicesDetail): | ||
const stats: ServicesDetailLoadTrack = { | ||
...servicesDetailLoadTrack, | ||
kind: undefined, | ||
startTime: new Date().getTime() as Millisecond, | ||
servicesId: new Set([...action.payload]), | ||
loaded: 0, | ||
toLoad: servicesDetailLoadTrack.servicesId.size | ||
}; | ||
servicesDetailLoadTrack = stats; | ||
break; | ||
// single service detail is been loaded | ||
case getType(loadServiceDetail.success): | ||
servicesDetailLoadTrack.servicesId.delete(action.payload.service_id); | ||
const statsServiceLoad: ServicesDetailLoadTrack = { | ||
...servicesDetailLoadTrack, | ||
loaded: | ||
servicesDetailLoadTrack.toLoad - | ||
servicesDetailLoadTrack.servicesId.size | ||
}; | ||
servicesDetailLoadTrack = statsServiceLoad; | ||
if (statsServiceLoad.servicesId.size === 0) { | ||
// all service are been loaded | ||
trackServicesDetailLoad({ | ||
...servicesDetailLoadTrack, | ||
kind: "COMPLETE", | ||
loadingTime: (new Date().getTime() - | ||
servicesDetailLoadTrack.startTime) as Millisecond | ||
}); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With some multiple tries on Android, I ran into this case (kind My proposal: const calculateLoadingTime = (startTime: Millisecond): Millisecond =>
(startTime !== 0 ? new Date().getTime() - startTime : 0) as Millisecond; and use it at line There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe this scenario is when the app changes state but actually it is not loading any service |
||
} | ||
|
||
break; | ||
// app changes state | ||
case getType(applicationChangeState): | ||
/** | ||
* if the app went in inactive or background state these measurements | ||
* could be not valid since the OS could apply a freeze or a limitation around the app context | ||
* so the app could run but with few limitations | ||
*/ | ||
if (action.payload !== "active") { | ||
trackServicesDetailLoad({ | ||
...servicesDetailLoadTrack, | ||
loadingTime: (new Date().getTime() - | ||
servicesDetailLoadTrack.startTime) as Millisecond, | ||
kind: "PARTIAL" | ||
}); | ||
} | ||
// app comes back active, restore stats | ||
else if (action.payload === "active") { | ||
servicesDetailLoadTrack = { | ||
...servicesDetailLoadTrack, | ||
kind: undefined, | ||
startTime: new Date().getTime() as Millisecond, | ||
loaded: 0, | ||
toLoad: servicesDetailLoadTrack.servicesId.size | ||
}; | ||
} | ||
break; | ||
} | ||
} | ||
); | ||
} | ||
|
||
type ServicesDetailLoadTrack = { | ||
// when loading starts | ||
startTime: Millisecond; | ||
// the amount of loading millis | ||
loadingTime: Millisecond; | ||
// the amount of services detail to load | ||
toLoad: number; | ||
// the amount of services detail loaded | ||
loaded: number; | ||
// the set of the services id that remain to be loaded | ||
servicesId: Set<string>; | ||
// COMPLETE: all services detail are been loaded | ||
// PARTIAL: a sub-set of services detail to load are been loaded | ||
kind?: "COMPLETE" | "PARTIAL"; | ||
}; | ||
// eslint-disable-next-line functional/no-let | ||
let servicesDetailLoadTrack: ServicesDetailLoadTrack = { | ||
startTime: 0 as Millisecond, | ||
loadingTime: 0 as Millisecond, | ||
toLoad: 0, | ||
loaded: 0, | ||
servicesId: new Set<string>() | ||
}; | ||
|
||
const trackServicesDetailLoad = (trackingStats: ServicesDetailLoadTrack) => { | ||
void mixpanelTrack("SERVICES_DETAIL_LOADING_STATS", { | ||
...trackingStats, | ||
// drop servicesId since it is not serialized in mixpanel and it could be an extra overhead on sending | ||
servicesId: undefined | ||
}); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the current implementation
toLoad
is always0
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's a bug, due to refactoring!
Good catch!
fixed
29baf38