31 lines
1.4 KiB
JavaScript
31 lines
1.4 KiB
JavaScript
import { ANALYTICS_ACTIVE_SESSION_TTL_SECONDS, ANALYTICS_MAX_REALTIME_DURATION_SECONDS, ANALYTICS_NEW_VISIT_IDLE_SECONDS } from './analytics-shared.js'
|
|
|
|
/**
|
|
* heartbeat 실행이 끊긴 긴 구간을 제외하는 페이지별 시간 측정기를 만든다.
|
|
* @param {number} [startedAt] - 측정 시작 시각(ms)
|
|
* @returns {(now?: number) => { durationSeconds: number, restarted: boolean }} 접속 시간과 새 방문 여부를 반환하는 측정 함수
|
|
*/
|
|
export const createAnalyticsDurationTracker = (startedAt = Date.now()) => {
|
|
let lastSampleAt = startedAt
|
|
let durationMs = 0
|
|
|
|
/**
|
|
* 직전 측정 이후 실행이 이어진 구간만 누적한다.
|
|
* @param {number} [now] - 현재 시각(ms)
|
|
* @returns {{ durationSeconds: number, restarted: boolean }} 중단 구간을 제외한 시간과 새 방문 여부
|
|
*/
|
|
const sample = (now = Date.now()) => {
|
|
if (!Number.isFinite(now)) return { durationSeconds: Math.floor(durationMs / 1000), restarted: false }
|
|
const gapMs = now - lastSampleAt
|
|
lastSampleAt = now
|
|
const restarted = gapMs >= ANALYTICS_NEW_VISIT_IDLE_SECONDS * 1000
|
|
if (restarted) durationMs = 0
|
|
else if (gapMs > 0 && gapMs < ANALYTICS_ACTIVE_SESSION_TTL_SECONDS * 1000) {
|
|
durationMs = Math.min(durationMs + gapMs, ANALYTICS_MAX_REALTIME_DURATION_SECONDS * 1000)
|
|
}
|
|
return { durationSeconds: Math.floor(durationMs / 1000), restarted }
|
|
}
|
|
|
|
return sample
|
|
}
|