Skip to content

Commit

Permalink
Add tracker.getQueueName method (close #1215)
Browse files Browse the repository at this point in the history
  • Loading branch information
igneel64 committed Jun 29, 2023
1 parent 265234f commit d27ef2d
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@snowplow/browser-tracker-core",
"comment": "Expose getQueueName method",
"type": "none"
}
],
"packageName": "@snowplow/browser-tracker-core"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@snowplow/browser-tracker",
"comment": "Add getQueueName tracker method",
"type": "none"
}
],
"packageName": "@snowplow/browser-tracker"
}
2 changes: 2 additions & 0 deletions libraries/browser-tracker-core/src/tracker/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1283,6 +1283,8 @@ export function Tracker(
},

clearUserData: clearUserDataAndCookies,

getQueueName: outQueue.getName,
};

return {
Expand Down
26 changes: 19 additions & 7 deletions libraries/browser-tracker-core/src/tracker/out_queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,27 @@ import { SharedState } from '../state';
import { localStorageAccessible } from '../detectors';
import { LOG, Payload } from '@snowplow/tracker-core';
import { PAYLOAD_DATA_SCHEMA } from './schemata';
import { EventMethod } from './types';

export interface OutQueue {
enqueueRequest: (request: Payload, url: string) => void;
executeQueue: () => void;
setUseLocalStorage: (localStorage: boolean) => void;
setAnonymousTracking: (anonymous: boolean) => void;
setCollectorUrl: (url: string) => void;
setBufferSize: (bufferSize: number) => void;
setBufferSize: (newBufferSize: number) => void;
/**
* Returns the currently used queue name or if the `eventMethod` argument is provided, the queue name for the eventMethod.
*/
getName: (eventMethod?: Exclude<EventMethod, 'beacon'>) => string;
}

/**
* Object handling sending events to a collector.
* Instantiated once per tracker instance.
*
* @param id - The Snowplow function name (used to generate the localStorage key)
* @param sharedSate - Stores reference to the outbound queue so it can unload the page when all queues are empty
* @param sharedState - Stores reference to the outbound queue so it can unload the page when all queues are empty
* @param useLocalStorage - Whether to use localStorage at all
* @param eventMethod - if null will use 'beacon' otherwise can be set to 'post', 'get', or 'beacon' to force.
* @param postPath - The path where events are to be posted
Expand All @@ -67,7 +72,7 @@ export interface OutQueue {
*/
export function OutQueueManager(
id: string,
sharedSate: SharedState,
sharedState: SharedState,
useLocalStorage: boolean,
eventMethod: string | boolean,
postPath: string,
Expand Down Expand Up @@ -114,7 +119,7 @@ export function OutQueueManager(
// Resolve all options and capabilities and decide path
path = usePost ? postPath : '/i',
// Different queue names for GET and POST since they are stored differently
queueName = `snowplowOutQueue_${id}_${usePost ? 'post2' : 'get'}`;
queueName = getQueueName(id, usePost ? 'post' : 'get');

// Ensure we don't set headers when beacon is the requested eventMethod as we might fallback to POST
// and end up sending them in older browsers which don't support beacon leading to inconsistencies
Expand All @@ -128,7 +133,9 @@ export function OutQueueManager(
try {
const localStorageQueue = window.localStorage.getItem(queueName);
outQueue = localStorageQueue ? JSON.parse(localStorageQueue) : [];
} catch (e) {}
} catch (e) {
LOG.error('Failed to access window.localStorage queue.');
}
}

// Initialize to and empty array if we didn't get anything out of localStorage
Expand All @@ -137,16 +144,20 @@ export function OutQueueManager(
}

// Used by pageUnloadGuard
sharedSate.outQueues.push(outQueue);
sharedState.outQueues.push(outQueue);

if (useXhr && bufferSize > 1) {
sharedSate.bufferFlushers.push(function (sync) {
sharedState.bufferFlushers.push(function (sync) {
if (!executingQueue) {
executeQueue(sync);
}
});
}

function getQueueName(id: string, method: Exclude<EventMethod, 'beacon'>) {
return `snowplowOutQueue_${id}_${method === 'post' ? 'post2' : 'get'}`;
}

/*
* Convert a dictionary to a querystring
* The context field is the last in the querystring
Expand Down Expand Up @@ -535,6 +546,7 @@ export function OutQueueManager(
setBufferSize: (newBufferSize: number) => {
bufferSize = newBufferSize;
},
getName: (method?: Exclude<EventMethod, 'beacon'>) => (method ? getQueueName(id, method) : queueName),
};

function hasWebKitBeaconBug(useragent: string) {
Expand Down
5 changes: 5 additions & 0 deletions libraries/browser-tracker-core/src/tracker/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,11 @@ export interface BrowserTracker {
*/
clearUserData: (configuration?: ClearUserDataConfiguration) => void;

/**
* Returns the currently used queue name or if the `eventMethod` argument is provided, the queue name for the eventMethod.
*/
getQueueName: (eventMethod?: 'post' | 'get' | undefined) => string;

/**
* Add a plugin into the plugin collection after Tracker has already been initialised
* @param configuration - The plugin to add
Expand Down
48 changes: 48 additions & 0 deletions libraries/browser-tracker-core/test/out_queue.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,54 @@ describe('OutQueueManager', () => {
(xhrMock as any).onreadystatechange();
};

describe('API', () => {
it('returns the correct queue name', () => {
const postOutQueue = OutQueueManager(
'sp',
new SharedState(),
true,
'post',
'/com.snowplowanalytics.snowplow/tp2',
1,
40000,
0, // maxGetBytes – 0 for no limit
false,
maxQueueSize,
5000,
false,
{},
true,
[401], // retry status codes - override don't retry ones
[401, 505] // don't retry status codes
);

expect(postOutQueue.getName()).toBe('snowplowOutQueue_sp_post2');
expect(postOutQueue.getName('get')).toBe('snowplowOutQueue_sp_get');

const getOutQueue = OutQueueManager(
'sp',
new SharedState(),
true,
'get',
'/com.snowplowanalytics.snowplow/tp2',
1,
40000,
0,
false,
maxQueueSize,
5000,
false,
{},
true,
[],
[]
);

expect(getOutQueue.getName()).toBe('snowplowOutQueue_sp_get');
expect(getOutQueue.getName('post')).toBe('snowplowOutQueue_sp_post2');
});
});

describe('POST requests', () => {
var outQueue: OutQueue;

Expand Down
1 change: 1 addition & 0 deletions trackers/browser-tracker/docs/browser-tracker.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export interface BrowserTracker {
getDomainUserId: () => void;
getDomainUserInfo: () => void;
getPageViewId: () => string;
getQueueName: (eventMethod?: "post" | "get" | undefined) => string;
getTabId: () => string | null;
getUserId: () => void;
id: string;
Expand Down
6 changes: 6 additions & 0 deletions trackers/browser-tracker/test/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { SharedState, TrackerConfiguration, addTracker } from '@snowplow/browser-tracker-core';

export function createTracker(configuration?: TrackerConfiguration) {
const id = 'sp-' + Math.random();
return addTracker(id, id, '', '', new SharedState(), configuration);
}
22 changes: 22 additions & 0 deletions trackers/browser-tracker/test/tracker.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

import { SharedState, addTracker } from '@snowplow/browser-tracker-core';
import F from 'lodash/fp';
import { createTracker } from './helpers';

jest.useFakeTimers('modern');

Expand Down Expand Up @@ -276,3 +277,24 @@ describe('Activity tracker behaviour', () => {
expect(secondPageId).toBe(extractPageId(ppl));
});
});

describe('API', () => {
it('getQueueName does return the queue name', () => {
let rand = Math.random();
const mathSpy = jest.spyOn(global.Math, 'random');
mathSpy.mockReturnValueOnce(rand);

const postTracker = createTracker();
expect(postTracker?.getQueueName()).toBe(`snowplowOutQueue_sp-${rand}_post2`);
expect(postTracker?.getQueueName('get')).toBe(`snowplowOutQueue_sp-${rand}_get`);

rand = Math.random();
mathSpy.mockReturnValueOnce(rand);

const getTracker = createTracker({ eventMethod: 'get' });
expect(getTracker?.getQueueName()).toBe(`snowplowOutQueue_sp-${rand}_get`);
expect(getTracker?.getQueueName('post')).toBe(`snowplowOutQueue_sp-${rand}_post2`);

mathSpy.mockRestore();
});
});

0 comments on commit d27ef2d

Please sign in to comment.