@opentelemetry/web-common
Version:
Common utilities for web instrumentation
131 lines • 4.19 kB
JavaScript
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* SessionManager is responsible for managing the active session including starting,
* resetting, and persisting.
*/
export class SessionManager {
_session;
_idGenerator;
_store;
_observers;
_maxDuration;
_maxDurationTimeoutId;
_inactivityTimeout;
_inactivityTimeoutId;
_lastActivityTimestamp = 0;
_inactivityResetDelay = 5000; // minimum time in ms between activities before timer is reset
constructor(config) {
this._idGenerator = config.sessionIdGenerator;
this._store = config.sessionStore;
this._maxDuration = config.maxDuration;
this._inactivityTimeout = config.inactivityTimeout;
this._observers = [];
}
async start() {
this._session = await this._store.get();
if (!this._session) {
this._session = await this.startSession();
}
this.resetTimers();
}
addObserver(observer) {
this._observers.push(observer);
}
getSessionId() {
return this.getSession().id;
}
getSession() {
if (!this._session) {
this._session = this.startSession();
this.resetTimers();
}
if (this._inactivityTimeout) {
if (Date.now() - this._lastActivityTimestamp >
this._inactivityResetDelay) {
this.resetInactivityTimer();
this._lastActivityTimestamp = Date.now();
}
}
return this._session;
}
shutdown() {
if (this._inactivityTimeoutId) {
clearTimeout(this._inactivityTimeoutId);
}
if (this._maxDurationTimeoutId) {
clearTimeout(this._maxDurationTimeoutId);
}
}
startSession() {
const sessionId = this._idGenerator.generateSessionId();
const session = {
id: sessionId,
startTimestamp: Date.now(),
};
// this is async call, but we don't wait for it
void this._store.save(session);
for (const observer of this._observers) {
observer.onSessionStarted(session, this._session ?? undefined);
}
this._session = session;
return session;
}
endSession() {
if (this._session) {
for (const observer of this._observers) {
observer.onSessionEnded(this._session);
}
}
if (this._inactivityTimeoutId) {
clearTimeout(this._inactivityTimeoutId);
this._inactivityTimeoutId = undefined;
}
}
resetSession() {
this.endSession();
this.startSession();
this.resetTimers();
}
resetTimers() {
this.resetInactivityTimer();
this.resetMaxDurationTimer();
}
resetInactivityTimer() {
if (!this._inactivityTimeout) {
return;
}
if (this._inactivityTimeoutId) {
clearTimeout(this._inactivityTimeoutId);
}
this._inactivityTimeoutId = setTimeout(() => {
this.resetSession();
}, this._inactivityTimeout * 1000);
}
resetMaxDurationTimer() {
if (!this._maxDuration || !this._session) {
return;
}
if (this._maxDurationTimeoutId) {
clearTimeout(this._maxDurationTimeoutId);
}
const timeoutIn = this._maxDuration * 1000 - (Date.now() - this._session?.startTimestamp);
this._maxDurationTimeoutId = setTimeout(() => {
this.resetSession();
}, timeoutIn);
}
}
//# sourceMappingURL=SessionManager.js.map