Skip to content

Commit

Permalink
Support cookie names unique to appmonitor. (#82)
Browse files Browse the repository at this point in the history
  • Loading branch information
qhanam committed Feb 7, 2022
1 parent ece1306 commit 143f6f0
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 6 deletions.
3 changes: 2 additions & 1 deletion docs/cdn_installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ The snippet below shows several configuration options with the body of the snipp
| pageIdFormat | String | `'PATH'` | The portion of the `window.location` that will be used as the page ID. Options include `PATH`, `HASH` and `PATH_AND_HASH`.<br/><br/>For example, consider the URL `https://amazonaws.com/home?param=true#content`<br/><br/>`PATH`: `/home`<br/>`HASH`: `#content`<br/>`PATH_AND_HASH`: `/home#content` |
| pagesToInclude | RegExp[] | `[]` | A list of regular expressions which specify the `window.location` values for which the web client will record data. Pages are matched using the `RegExp.test()` function.<br/><br/>For example, when `pagesToInclude: [ /\/home/ ]`, then data from `https://amazonaws.com/home` will be included, and `https://amazonaws.com/` will not be included. |
| pagesToExclude | RegExp[] | `[]` | A list of regular expressions which specify the `window.location` values for which the web client will record data. Pages are matched using the `RegExp.test()` function.<br/><br/>For example, when `pagesToExclude: [ /\/home/ ]`, then data from `https://amazonaws.com/home` will be excluded, and `https://amazonaws.com/` will not be excluded. |
| recordResourceUrl | Boolean | `true` | When this field is `false`, the web client will not record the URLs of resources downloaded by your appliation.<br/><br/> Some types of resources (e.g., profile images) may be referenced by URLs which contain PII. If this applies to your application, you must set this field to `false` to comply with CloudWatch RUM's shared responsibility model. |
| recordResourceUrl | Boolean | `true` | When this field is `false`, the web client will not record the URLs of resources downloaded by your application.<br/><br/> Some types of resources (e.g., profile images) may be referenced by URLs which contain PII. If this applies to your application, you must set this field to `false` to comply with CloudWatch RUM's shared responsibility model. |
| sessionEventLimit | Number | `200` | The maximum number of events to record during a single session. |
| sessionSampleRate | Number | `1` | The proportion of sessions that will be recorded by the web client, specified as a unit interval (a number greater than or equal to 0 and less than or equal to 1). When this field is `0`, no sessions will be recorded. When this field is `1`, all sessions will be recorded. |
| telemetries | [Telemetry Config Array](#telemetry-config-array) | `[]` | See [Telemetry Config Array](#telemetry-config-array) |
Expand All @@ -90,6 +90,7 @@ The snippet below shows several configuration options with the body of the snipp
| path | String | `/` | See https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#define_where_cookies_are_sent |
| sameSite | Boolean | `true` | See https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#define_where_cookies_are_sent |
| secure | Boolean | `true` | See https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#define_where_cookies_are_sent |
| unique | Boolean | `false` | When this field is `false`, the session cookie name is `cwr_s`. When this field is true `true`, the session cookie name is `cwr_s_[AppMonitor Id]`.<br/><br/>Set this field to `true` when multiple AppMonitors will monitor the same page. For example, this might be the case if one AppMonitor is used for logged-in users, and a second AppMonitor is used for guest users. |

## Telemetry Config Array

Expand Down
2 changes: 1 addition & 1 deletion src/event-cache/EventCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { Config } from '../orchestration/Orchestration';
import { PageManager } from '../sessions/PageManager';
import {
AppMonitorDetails,
PutRumEventsRequest,
UserDetails,
RumEvent
} from '../dispatch/dataplane';
Expand Down Expand Up @@ -41,6 +40,7 @@ export class EventCache {
this.enabled = true;
this.pageManager = new PageManager(config, this.recordEvent);
this.sessionManager = new SessionManager(
applicationDetails,
config,
this.recordSessionInitEvent,
this.pageManager
Expand Down
3 changes: 3 additions & 0 deletions src/orchestration/Orchestration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export enum PAGE_ID_FORMAT {
}

export type PartialCookieAttributes = {
unique?: boolean;
domain?: string;
path?: string;
sameSite?: string;
Expand Down Expand Up @@ -88,6 +89,7 @@ export type PartialConfig = {

export const defaultCookieAttributes = (): CookieAttributes => {
return {
unique: false,
domain: window.location.hostname,
path: '/',
sameSite: 'Strict',
Expand Down Expand Up @@ -120,6 +122,7 @@ export const defaultConfig = (cookieAttributes: CookieAttributes): Config => {
};

export type CookieAttributes = {
unique: boolean;
domain: string;
path: string;
sameSite: string;
Expand Down
3 changes: 2 additions & 1 deletion src/orchestration/__tests__/Orchestration.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Config, Orchestration } from '../Orchestration';
import { Orchestration } from '../Orchestration';
import { Dispatch } from '../../dispatch/Dispatch';
import { EventCache } from '../../event-cache/EventCache';
import { DomEventPlugin } from '../../plugins/event-plugins/DomEventPlugin';
Expand Down Expand Up @@ -133,6 +133,7 @@ describe('Orchestration tests', () => {
allowCookies: false,
batchLimit: 100,
cookieAttributes: {
unique: false,
domain: window.location.hostname,
path: '/',
sameSite: 'Strict',
Expand Down
15 changes: 13 additions & 2 deletions src/sessions/SessionManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Page, PageManager } from './PageManager';

import { UAParser } from 'ua-parser-js';
import { SESSION_COOKIE_NAME, USER_COOKIE_NAME } from '../utils/constants';
import { AppMonitorDetails } from '../dispatch/dataplane';

export const NIL_UUID = '00000000-0000-0000-0000-000000000000';

Expand Down Expand Up @@ -58,6 +59,7 @@ export type Attributes = {
export class SessionManager {
private pageManager: PageManager;

private appMonitorDetails: AppMonitorDetails;
private userExpiry: Date;
private sessionExpiry: Date;
private userId!: string;
Expand All @@ -67,10 +69,12 @@ export class SessionManager {
private attributes: Attributes;

constructor(
appMonitorDetails: AppMonitorDetails,
config: Config,
record: RecordSessionInitEvent,
pageManager: PageManager
) {
this.appMonitorDetails = appMonitorDetails;
this.config = config;
this.record = record;
this.pageManager = pageManager;
Expand Down Expand Up @@ -155,7 +159,7 @@ export class SessionManager {
private createOrRenewSessionCookie(session: Session, expires: Date) {
if (btoa) {
storeCookie(
SESSION_COOKIE_NAME,
this.sessionCookieName(),
btoa(JSON.stringify(session)),
this.config.cookieAttributes,
undefined,
Expand All @@ -180,7 +184,7 @@ export class SessionManager {

private getSessionFromCookie() {
if (this.useCookies()) {
const cookie: string = getCookie(SESSION_COOKIE_NAME);
const cookie: string = getCookie(this.sessionCookieName());

if (cookie && atob) {
try {
Expand Down Expand Up @@ -262,4 +266,11 @@ export class SessionManager {
private sample(): boolean {
return Math.random() < this.config.sessionSampleRate;
}

private sessionCookieName(): string {
if (this.config.cookieAttributes.unique) {
return `${SESSION_COOKIE_NAME}_${this.appMonitorDetails.id}`;
}
return SESSION_COOKIE_NAME;
}
}
35 changes: 34 additions & 1 deletion src/sessions/__tests__/SessionManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ import { Config } from '../../orchestration/Orchestration';
import { mockRandom } from 'jest-mock-random';
import { PageManager } from '../PageManager';
import { SESSION_COOKIE_NAME, USER_COOKIE_NAME } from '../../utils/constants';
import { DEFAULT_CONFIG } from '../../test-utils/test-utils';
import {
APPLICATION_ID,
APP_MONITOR_DETAILS,
DEFAULT_CONFIG
} from '../../test-utils/test-utils';

const NAVIGATION = 'navigation';
const SESSION_COOKIE_EXPIRES = 30 * 60;
Expand Down Expand Up @@ -54,6 +58,7 @@ const mockRecord = jest.fn();

const defaultSessionManager = (config) => {
return new SessionManager(
APP_MONITOR_DETAILS,
config,
mockRecord,
new PageManager(config, mockRecord)
Expand Down Expand Up @@ -347,6 +352,7 @@ describe('SessionManager tests', () => {
...{ sessionLengthSeconds: 3600, allowCookies: true }
};
const sessionManager = new SessionManager(
APP_MONITOR_DETAILS,
config,
mockRecord,
new PageManager(config, mockRecord)
Expand Down Expand Up @@ -632,4 +638,31 @@ describe('SessionManager tests', () => {
expect(userIdFromCookie1).toEqual('');
expect(userIdFromCookie2).toEqual(sessionManager.getUserId());
});

test('when unique cookie names are used then the application id is appended to the cookie names', async () => {
// Init
const config = {
...DEFAULT_CONFIG,
...{
allowCookies: true,
userIdRetentionDays: 1,
cookieAttributes: {
...DEFAULT_CONFIG.cookieAttributes,
...{ unique: true }
}
}
};

const sessionManager = defaultSessionManager(config);

sessionManager.getSession();
const sessionIdFromCookie = JSON.parse(
atob(getCookie(`${SESSION_COOKIE_NAME}_${APPLICATION_ID}`))
).sessionId;

// Assert
expect(sessionIdFromCookie).toEqual(
sessionManager.getSession().sessionId
);
});
});
5 changes: 5 additions & 0 deletions src/utils/__tests__/cookies-utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as utils from '../../utils/cookies-utils';
const COOKIE_PREFIX = 'rum_cookies_util_test';

const COOKIE_ATTRIBUTES = {
unique: false,
domain: 'amazon.com',
path: '/',
sameSite: 'Strict',
Expand Down Expand Up @@ -62,13 +63,15 @@ describe('Cookies utils tests', () => {
const cookieValueB = 'valueB';

const COOKIE_ATTRIBUTES_A = {
unique: false,
domain: 'amazon.com',
path: '/',
sameSite: 'Strict',
secure: true
};

const COOKIE_ATTRIBUTES_B = {
unique: false,
domain: 'aws.amazon.com',
path: '/',
sameSite: 'Strict',
Expand Down Expand Up @@ -96,13 +99,15 @@ describe('Cookies utils tests', () => {
const cookieValueB = 'valueB';

const COOKIE_ATTRIBUTES_A = {
unique: false,
domain: 'amazon.com',
path: '/',
sameSite: 'Strict',
secure: true
};

const COOKIE_ATTRIBUTES_B = {
unique: false,
domain: 'amazon.com',
path: '/console',
sameSite: 'Strict',
Expand Down

0 comments on commit 143f6f0

Please sign in to comment.