Skip to content
This repository was archived by the owner on Oct 3, 2023. It is now read-only.

Commit f6c8afa

Browse files
Remove clock sync and initial load trace ID assignment code (#29)
1 parent 27cb768 commit f6c8afa

5 files changed

Lines changed: 47 additions & 213 deletions

File tree

packages/opencensus-web-all/src/export-initial-load.ts

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414
* limitations under the License.
1515
*/
1616

17-
import {adjustPerfTimeOrigin, tracing} from '@opencensus/web-core';
17+
import {tracing} from '@opencensus/web-core';
1818
import {OCAgentExporter} from '@opencensus/web-exporter-ocagent';
1919
import {clearPerfEntries, getInitialLoadRootSpan, getPerfEntries} from '@opencensus/web-instrumentation-perf';
2020

21-
import {OpenCensusWebConfig, WindowWithOcwGlobals} from './types';
21+
import {WindowWithOcwGlobals} from './types';
2222

2323
const windowWithOcwGlobals = window as WindowWithOcwGlobals;
2424

@@ -34,42 +34,32 @@ const TRACE_ENDPOINT = '/v1/trace';
3434

3535
/**
3636
* Waits until after the document `load` event fires, and then uses the
37-
* `window.ocwConfig` settings to configure an OpenCensus agent exporter and
37+
* `window.ocwAgent` setting to configure an OpenCensus agent exporter and
3838
* export the spans for the initial page load.
3939
*/
4040
export function exportRootSpanAfterLoadEvent() {
41-
const config = windowWithOcwGlobals.ocwConfig;
42-
if (!config || !config.agent || !config.sampled) {
41+
if (!windowWithOcwGlobals.ocwAgent) {
4342
console.log('Not configured to export page load spans.');
4443
return;
4544
}
4645

47-
tracing.registerExporter(
48-
new OCAgentExporter({agentEndpoint: `${config.agent}${TRACE_ENDPOINT}`}));
46+
tracing.registerExporter(new OCAgentExporter(
47+
{agentEndpoint: `${windowWithOcwGlobals.ocwAgent}${TRACE_ENDPOINT}`}));
4948

5049
if (document.readyState === 'complete') {
51-
exportInitialLoadSpans(config);
50+
exportInitialLoadSpans();
5251
} else {
5352
window.addEventListener('load', () => {
54-
exportInitialLoadSpans(config);
53+
exportInitialLoadSpans();
5554
});
5655
}
5756
}
5857

59-
function exportInitialLoadSpans(config: OpenCensusWebConfig) {
58+
function exportInitialLoadSpans() {
6059
setTimeout(() => {
6160
const perfEntries = getPerfEntries();
6261

63-
// Adjust the performance time origin with server time if we have it.
64-
if (perfEntries.navigationTiming && config.reqStartTime &&
65-
config.reqDuration) {
66-
adjustPerfTimeOrigin(
67-
config.reqStartTime, config.reqDuration,
68-
perfEntries.navigationTiming);
69-
}
70-
71-
const root = getInitialLoadRootSpan(
72-
tracing.tracer, perfEntries, config.spanId, config.traceId);
62+
const root = getInitialLoadRootSpan(tracing.tracer, perfEntries);
7363

7464
clearPerfEntries();
7565
// Notify that the span has ended to trigger export.

packages/opencensus-web-all/src/types.ts

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,41 +16,35 @@
1616

1717
import {PerformanceLongTaskTiming, WindowWithLongTasks} from '@opencensus/web-instrumentation-perf';
1818

19-
/** OpenCensus Web configuration that can be set on `window`. */
20-
export declare interface OpenCensusWebConfig {
21-
/**
22-
* Whether the initial load root span should be sampled for trace. This is
23-
* only a hint and should not be used to enforce sampling since clients could
24-
* simply ignore this field.
25-
*/
26-
sampled?: boolean;
27-
/** Trace ID for the initial load spans. */
28-
traceId?: string;
29-
/** Span ID for the initial load fetch client span. */
30-
spanId?: string;
19+
/** Type for `window` object with variables OpenCensus Web interacts with. */
20+
export declare interface WindowWithOcwGlobals extends WindowWithLongTasks {
3121
/**
32-
* Start time of server fetch request for initial navigation HTML in server
33-
* time epoch milliseconds. This is used to correct for clock skew between
34-
* client and server before exporting spans.
22+
* HTTP root URL of the agent endpoint to write traces to.
23+
* Example 'https://my-oc-agent-deployment.com:55678'
3524
*/
36-
reqStartTime?: number;
25+
ocwAgent?: string;
3726
/**
38-
* Duration of the server fetch request for initial HTML in server
39-
* milliseconds. This is also used to correct for clock skew.
27+
* For the initial page load, web browsers do not send any custom headers,
28+
* which means that the server will not receive trace context headers.
29+
* However, we still want the server side request for the initial page load to
30+
* be recorded as a child span of the client side web timing span. So we can
31+
* have servers programmatically set a `traceparent` header to give their
32+
* request span a parent span ID. That simulated trace context header can then
33+
* be sent back to the client as a global variable to use for setting its
34+
* trace ID and request load client span ID, as well as for making a sampling
35+
* decision.
36+
* This header value is in the format of
37+
* [version]-[trace ID in hex]-[span ID in hex]-[trace flags]
38+
* For example:
39+
* 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01
40+
* See https://www.w3.org/TR/trace-context/ for details.
4041
*/
41-
reqDuration?: number;
42+
traceparent?: string;
4243
/**
43-
* HTTP root URL of the agent endpoint to write traces to.
44-
* Example 'https://my-oc-agent-deployment.com:55678'
44+
* List to collect long task timings as they are observed. This is on the
45+
* window so that the code to instrument the long tasks and the code that
46+
* exports it can be in different JS bundles. This enables deferring loading
47+
* the export code until it is needed.
4548
*/
46-
agent?: string;
47-
}
48-
49-
/**
50-
* Type for the `window` object with the variables OpenCensus Web interacts
51-
* with.
52-
*/
53-
export declare interface WindowWithOcwGlobals extends WindowWithLongTasks {
5449
ocwLt?: PerformanceLongTaskTiming[];
55-
ocwConfig?: OpenCensusWebConfig;
5650
}

packages/opencensus-web-all/test/test-export-initial-load.ts

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,43 +15,35 @@
1515
*/
1616

1717
import {exportRootSpanAfterLoadEvent} from '../src/export-initial-load';
18-
import {OpenCensusWebConfig, WindowWithOcwGlobals} from '../src/types';
18+
import {WindowWithOcwGlobals} from '../src/types';
1919

2020
const windowWithOcwGlobals = window as WindowWithOcwGlobals;
2121

2222
describe('exportRootSpanAfterLoadEvent', () => {
23-
let realOcwConfig: OpenCensusWebConfig|undefined;
23+
let realOcwAgent: string|undefined;
2424
beforeEach(() => {
2525
jasmine.clock().install();
2626
spyOn(XMLHttpRequest.prototype, 'open');
2727
spyOn(XMLHttpRequest.prototype, 'send');
2828
spyOn(XMLHttpRequest.prototype, 'setRequestHeader');
29-
realOcwConfig = windowWithOcwGlobals.ocwConfig;
29+
realOcwAgent = windowWithOcwGlobals.ocwAgent;
3030
});
3131
afterEach(() => {
3232
jasmine.clock().uninstall();
33-
windowWithOcwGlobals.ocwConfig = realOcwConfig;
33+
windowWithOcwGlobals.ocwAgent = realOcwAgent;
3434
});
3535

36-
it('exports spans to agent if sampled and agent configured', () => {
37-
windowWithOcwGlobals.ocwConfig = {sampled: true, agent: 'http://agent'};
36+
it('exports spans to agent if agent is configured', () => {
37+
windowWithOcwGlobals.ocwAgent = 'http://agent';
3838
exportRootSpanAfterLoadEvent();
3939
jasmine.clock().tick(300000);
4040
expect(XMLHttpRequest.prototype.open)
4141
.toHaveBeenCalledWith('POST', 'http://agent/v1/trace');
4242
expect(XMLHttpRequest.prototype.send).toHaveBeenCalled();
4343
});
4444

45-
it('does not export if not sampled', () => {
46-
windowWithOcwGlobals.ocwConfig = {agent: 'http://agent'};
47-
exportRootSpanAfterLoadEvent();
48-
jasmine.clock().tick(300000);
49-
expect(XMLHttpRequest.prototype.open).not.toHaveBeenCalled();
50-
expect(XMLHttpRequest.prototype.send).not.toHaveBeenCalled();
51-
});
52-
5345
it('does not export if agent not configured', () => {
54-
windowWithOcwGlobals.ocwConfig = {sampled: true};
46+
windowWithOcwGlobals.ocwAgent = undefined;
5547
exportRootSpanAfterLoadEvent();
5648
jasmine.clock().tick(300000);
5749
expect(XMLHttpRequest.prototype.open).not.toHaveBeenCalled();

packages/opencensus-web-core/src/common/time-util.ts

Lines changed: 1 addition & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -14,62 +14,10 @@
1414
* limitations under the License.
1515
*/
1616

17-
/** Polyfill value of `performance.timeOrigin` for browser that lack support. */
1817
let perfOriginPolyfill = 0;
19-
/** If non-zero, the approximate peformance clock origin in server time. */
20-
let perfOriginInServerTime = 0;
2118

22-
/**
23-
* Returns the origin of the browser performance clock in epoch millis.
24-
* This can be adjusted to align more closely with the server's clock using the
25-
* `adjustPerfTimeOrigin` function.
26-
*/
19+
/** Returns the origin of the browser performance clock in epoch millis. */
2720
export function getPerfTimeOrigin(): number {
28-
return perfOriginInServerTime ? perfOriginInServerTime :
29-
getClientPerfTimeOrigin();
30-
}
31-
32-
/**
33-
* Adjusts the performance clock time origin based on server clock times for the
34-
* start and duration of the navigation fetch (the initial HTML load request).
35-
*
36-
* This adjusts the client clock such that the network time is evenly spread on
37-
* both sides of the request, so that the server's span will be positioned right
38-
* in the middle of the client's span. This enables visualizing the server and
39-
* client spans no the same timeline even if they have clock skew.
40-
*
41-
* @param serverNavFetchStartTime The server's measurement of the request start
42-
* in epoch milliseconds from the server clock. This would be sent back to
43-
* the client in a <script> in the rendered HTML.
44-
* @param serverNavFetchDuration The server's measurement of the request
45-
* duration in milliseconds. This would also be sent to the client.
46-
* @param perfNavTiming The performance navigation timing, which can be
47-
* retrieved by `performance.getEntriesByType('navigation')[0]`, provided
48-
* that the browser supports it.
49-
*/
50-
export function adjustPerfTimeOrigin(
51-
serverNavFetchStartTime: number, serverNavFetchDuration: number,
52-
perfNavTiming: PerformanceNavigationTiming) {
53-
const clientStart = perfNavTiming.requestStart;
54-
const clientEnd = perfNavTiming.responseStart;
55-
const clientNavFetchDuration = clientEnd - clientStart;
56-
57-
// Server time is more than client time, which we don't expect, so don't try
58-
// to adjust the time origin.
59-
if (serverNavFetchDuration > clientNavFetchDuration) return;
60-
61-
const networkTime = clientNavFetchDuration - serverNavFetchDuration;
62-
const halfNetworkTime = networkTime / 2;
63-
const clientStartInServerTime = serverNavFetchStartTime - halfNetworkTime;
64-
perfOriginInServerTime = clientStartInServerTime - clientStart;
65-
}
66-
67-
/** Helper function used for testing. */
68-
function clearAdjustedPerfTime() {
69-
perfOriginInServerTime = 0;
70-
}
71-
72-
function getClientPerfTimeOrigin() {
7321
if (performance.timeOrigin) return performance.timeOrigin;
7422
if (!perfOriginPolyfill) {
7523
perfOriginPolyfill = Date.now() - performance.now();
@@ -111,5 +59,3 @@ function wholeAndFraction(num: number): [number, number] {
11159
const fraction = num - whole;
11260
return [whole, fraction];
11361
}
114-
115-
export const TEST_ONLY = {clearAdjustedPerfTime};

packages/opencensus-web-core/test/test-time-util.ts

Lines changed: 5 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
import {adjustPerfTimeOrigin, getDateForPerfTime, getIsoDateStrForPerfTime, getPerfTimeOrigin, TEST_ONLY} from '../src/common/time-util';
17+
import {getDateForPerfTime, getIsoDateStrForPerfTime, getPerfTimeOrigin} from '../src/common/time-util';
1818
import {mockGetterOrValue, restoreGetterOrValue} from './util';
1919

2020
describe('time utils', () => {
@@ -29,112 +29,23 @@ describe('time utils', () => {
2929
describe('getPerfTimeOrigin', () => {
3030
it('returns `performance.timeOrigin` if set', () => {
3131
mockGetterOrValue(performance, 'timeOrigin', 1548000000000);
32+
3233
expect(getPerfTimeOrigin()).toBe(1548000000000);
3334
});
3435

3536
it('calculates via polyfill if `performance.timeOrigin` unset', () => {
3637
mockGetterOrValue(performance, 'timeOrigin', undefined);
3738
spyOn(Date, 'now').and.returnValue(1548000009999);
3839
spyOn(performance, 'now').and.returnValue(9999);
39-
});
40-
});
41-
42-
describe('adjustPerfTimeOrigin', () => {
43-
function createNavTiming({requestStart, responseStart}:
44-
{requestStart: number, responseStart: number}):
45-
PerformanceNavigationTiming {
46-
return {
47-
// This are used by the time adjustment function below.
48-
requestStart, // Client start time in performance clock millis.
49-
responseStart, // Client end time in performance clock millis.
50-
// These are needed to satisfy the interface.
51-
connectEnd: 0,
52-
connectStart: 0,
53-
decodedBodySize: 0,
54-
domComplete: 0,
55-
domContentLoadedEventEnd: 0,
56-
domContentLoadedEventStart: 0,
57-
domInteractive: 0,
58-
domainLookupEnd: 0,
59-
domainLookupStart: 0,
60-
duration: 0,
61-
encodedBodySize: 0,
62-
entryType: '',
63-
fetchStart: 0,
64-
initiatorType: '',
65-
loadEventEnd: 0,
66-
loadEventStart: 0,
67-
name: '',
68-
nextHopProtocol: '',
69-
redirectCount: 0,
70-
redirectEnd: 0,
71-
redirectStart: 0,
72-
responseEnd: 0,
73-
secureConnectionStart: 0,
74-
startTime: 0,
75-
toJSON: () => ({}),
76-
transferSize: 0,
77-
type: 'navigate',
78-
unloadEventEnd: 0,
79-
unloadEventStart: 0,
80-
workerStart: 0,
81-
};
82-
}
83-
84-
const CLIENT_TIME_ORIGIN = 1548000000000;
85-
beforeEach(() => {
86-
mockGetterOrValue(performance, 'timeOrigin', CLIENT_TIME_ORIGIN);
87-
});
88-
afterEach(() => {
89-
TEST_ONLY.clearAdjustedPerfTime();
90-
});
91-
92-
it('keeps client time origin if server time longer than client', () => {
93-
// Client nav fetch duration is 5ms
94-
const perfNavTiming =
95-
createNavTiming({requestStart: 10.1, responseStart: 15.1});
96-
97-
// Server nav fetch duration is 10ms
98-
adjustPerfTimeOrigin(
99-
1548000001000.2, /* serverNavFetchDuration */ 10, perfNavTiming);
10040

101-
expect(getPerfTimeOrigin()).toBe(CLIENT_TIME_ORIGIN);
102-
});
103-
104-
it('adjusts origin to center server span in client span', () => {
105-
const clientNavFetchStartInPerfTime = 10;
106-
const clientNavFetchEndInPerfTime = 18;
107-
const perfNavTiming = createNavTiming({
108-
requestStart: clientNavFetchStartInPerfTime,
109-
responseStart: clientNavFetchEndInPerfTime,
110-
});
111-
const serverNavFetchStartEpochMillis = 1500000001000; // Epoch millis.
112-
const serverNavFetchDuration = 6; // Duration millis
113-
114-
adjustPerfTimeOrigin(
115-
serverNavFetchStartEpochMillis, serverNavFetchDuration,
116-
perfNavTiming);
117-
118-
// Calculations to make the expectation clearer:
119-
const clientNavFetchDuration =
120-
clientNavFetchEndInPerfTime - clientNavFetchStartInPerfTime;
121-
expect(clientNavFetchDuration).toBe(8); // Duration millis
122-
const networkTime = clientNavFetchDuration - serverNavFetchDuration;
123-
expect(networkTime).toBe(2); // Duration millis
124-
const clientNavStartInEpochMillis =
125-
serverNavFetchStartEpochMillis - networkTime / 2;
126-
expect(clientNavStartInEpochMillis).toBe(1500000000999);
127-
const perfOriginInEpochMillis =
128-
clientNavStartInEpochMillis - clientNavFetchStartInPerfTime;
129-
expect(perfOriginInEpochMillis).toBe(1500000000989);
130-
131-
expect(getPerfTimeOrigin()).toBe(perfOriginInEpochMillis);
41+
expect(getPerfTimeOrigin()).toBe(1548000000000);
13242
});
13343
});
13444

13545
describe('getDateForPerfTime', () => {
13646
it('calculates date for perf time based on time origin', () => {
13747
mockGetterOrValue(performance, 'timeOrigin', 1548000000000);
48+
13849
expect(getDateForPerfTime(999.6).getTime()).toBe(1548000000999);
13950
});
14051
});
@@ -148,6 +59,7 @@ describe('time utils', () => {
14859

14960
it('accurately combines milliseconds from origin and perf times', () => {
15061
mockGetterOrValue(performance, 'timeOrigin', 1535683887441.586);
62+
15163
expect(getIsoDateStrForPerfTime(658867.8000000073))
15264
.toEqual('2018-08-31T03:02:26.309385938Z');
15365
});

0 commit comments

Comments
 (0)