From d49dde0420842215e10fdfd0a89191367444c3dc Mon Sep 17 00:00:00 2001 From: Karlie Li Date: Wed, 1 May 2024 14:25:44 -0700 Subject: [PATCH 1/5] fix 1ds offline support --- channels/1ds-post-js/src/PostChannel.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/channels/1ds-post-js/src/PostChannel.ts b/channels/1ds-post-js/src/PostChannel.ts index 2ad6015ec..ad189e51b 100644 --- a/channels/1ds-post-js/src/PostChannel.ts +++ b/channels/1ds-post-js/src/PostChannel.ts @@ -247,9 +247,11 @@ export class PostChannel extends BaseTelemetryPlugin implements IChannelControls return !_disableTelemetry; }, createPayload: (evt) => { + // should get new url headers based on payload directly + let curDetails = _httpManager && _httpManager.getOfflineRequestDetails(); return { - urlString: details.url, - headers: details.hdrs, + urlString: curDetails.url, + headers: curDetails.hdrs, data: evt } as IPayloadData; } From 50e5627251a1f60753b8ad21736a6f7862ef9270 Mon Sep 17 00:00:00 2001 From: Karlie Li Date: Fri, 3 May 2024 15:28:58 -0700 Subject: [PATCH 2/5] update --- channels/1ds-post-js/src/HttpManager.ts | 64 ++++++++++++++++++- channels/1ds-post-js/src/PostChannel.ts | 23 ++++--- .../offline-channel-js/src/OfflineChannel.ts | 10 ++- .../IChannelControls.ts | 7 ++ 4 files changed, 92 insertions(+), 12 deletions(-) diff --git a/channels/1ds-post-js/src/HttpManager.ts b/channels/1ds-post-js/src/HttpManager.ts index da5dedccd..e36989cbd 100644 --- a/channels/1ds-post-js/src/HttpManager.ts +++ b/channels/1ds-post-js/src/HttpManager.ts @@ -10,7 +10,7 @@ import { _IInternalXhrOverride, _ISendPostMgrConfig, _ISenderOnComplete, _eExtendedInternalMessageId, _eInternalMessageId, _getAllResponseHeaders, _throwInternal, _warnToConsole, arrForEach, dateNow, doPerf, dumpObj, eLoggingSeverity, extend, getCommonSchemaMetaData, getNavigator, getResponseText, getTime, hasOwnProperty, isBeaconsSupported, isFetchSupported, isNullOrUndefined, isReactNative, isUndefined, - isValueAssigned, objForEachKey, objKeys, onConfigChange, prependTransports, strUndefined + isValueAssigned, objForEachKey, objKeys, onConfigChange, optimizeObject, prependTransports, strUndefined } from "@microsoft/1ds-core-js"; import { arrAppend } from "@nevware21/ts-utils"; import { BatchNotificationAction, BatchNotificationActions } from "./BatchNotificationActions"; @@ -331,9 +331,55 @@ export class HttpManager { } _self.getOfflineRequestDetails = () => { + return null; + } + + _self.createOneDSPayload = (evts: ITelemetryItem[], optimize?: boolean) => { try { - let payload = _serializer && _serializer.createPayload(0, false, false, false, SendRequestReason.NormalSchedule, EventSendType.Batched); - return _buildRequestDetails(payload, _useHeaders); + // TODO: optimize + let theBatches: EventBatch[] = []; + // create a eventBatch for each event + arrForEach(evts, (evt) => { + if (optimize) { + evt = optimizeObject(evt) + } + let batch = EventBatch.create(evt.iKey, [evt]); + theBatches.push(batch); + }) + + let thePayload: ISerializedPayload = null; + + while (theBatches && theBatches.length && _serializer) { + let theBatch = theBatches.shift(); + if (theBatch && theBatch.count() > 0) { + thePayload = thePayload || _serializer.createPayload(0, false, false, false, SendRequestReason.NormalSchedule, EventSendType.Batched); + _serializer.appendPayload(thePayload, theBatch, maxEventsPerBatch) + } + } + + let requestDetails = _buildRequestDetails(thePayload, _useHeaders); + + let payloadData: IPayloadData = { + data: thePayload.payloadBlob, + urlString: requestDetails.url, + headers: requestDetails.hdrs, + timeout: _xhrTimeout, + disableXhrSync: _disableXhrSync, + disableFetchKeepAlive: _disableFetchKeepAlive + }; + + // Only automatically add the following headers if already sending headers and we are not attempting to avoid an options call + if (_useHeaders) { + if (!_hasHeader(payloadData.headers, STR_CACHE_CONTROL)) { + payloadData.headers[STR_CACHE_CONTROL] = DEFAULT_CACHE_CONTROL; + } + + if (!_hasHeader(payloadData.headers, STR_CONTENT_TYPE_HEADER)) { + payloadData.headers[STR_CONTENT_TYPE_HEADER] = DEFAULT_CONTENT_TYPE; + } + } + + return payloadData; } catch (e) { // eslint-disable-next-line no-empty @@ -342,6 +388,8 @@ export class HttpManager { return null; } + + // Special internal method to allow the DebugPlugin to hook embedded objects function _getSenderInterface(transports: TransportType[], syncSupport: boolean): _IInternalXhrOverride { try { @@ -1355,4 +1403,14 @@ export class HttpManager { // @DynamicProtoStub - DO NOT add any code as this will be removed during packaging return null; } + + /** + * Create payload data + * @param evts telemetry events + * @returns payload + */ + public createOneDSPayload(evts?: ITelemetryItem[], optimize?: boolean): IPayloadData { + // @DynamicProtoStub - DO NOT add any code as this will be removed during packaging + return null; + } } diff --git a/channels/1ds-post-js/src/PostChannel.ts b/channels/1ds-post-js/src/PostChannel.ts index ad189e51b..2d5ab1000 100644 --- a/channels/1ds-post-js/src/PostChannel.ts +++ b/channels/1ds-post-js/src/PostChannel.ts @@ -236,7 +236,7 @@ export class PostChannel extends BaseTelemetryPlugin implements IChannelControls _self.getOfflineSupport = () => { try { let details = _httpManager && _httpManager.getOfflineRequestDetails(); - if (details) { + if (_httpManager) { return { getUrl: () => { return details.url @@ -246,14 +246,21 @@ export class PostChannel extends BaseTelemetryPlugin implements IChannelControls shouldProcess: (evt) => { return !_disableTelemetry; }, - createPayload: (evt) => { + createPayload: (evt, ikeys?: string[]) => { + return null; // should get new url headers based on payload directly - let curDetails = _httpManager && _httpManager.getOfflineRequestDetails(); - return { - urlString: curDetails.url, - headers: curDetails.hdrs, - data: evt - } as IPayloadData; + // let curDetails = _httpManager && _httpManager.getOfflineRequestDetails(); + // return { + // urlString: curDetails.url, + // headers: curDetails.hdrs, + // data: evt + // } as IPayloadData; + }, + createOneDSPayload: (evts: ITelemetryItem[]) => { + if (_httpManager.createOneDSPayload) { + return _httpManager.createOneDSPayload(evts, _optimizeObject); + } + } } as IInternalOfflineSupport; diff --git a/channels/offline-channel-js/src/OfflineChannel.ts b/channels/offline-channel-js/src/OfflineChannel.ts index c3faec0ab..828515981 100644 --- a/channels/offline-channel-js/src/OfflineChannel.ts +++ b/channels/offline-channel-js/src/OfflineChannel.ts @@ -347,8 +347,16 @@ export class OfflineChannel extends BaseTelemetryPlugin implements IChannelContr let sentItems = evts.slice(0, idx + 1); _inMemoBatch = _inMemoBatch.createNew(_endpoint, inMemo.getItems().slice(idx + 1), _evtsLimitInMemo); + + let payloadData: IStorageTelemetryItem = null; + if (_offineSupport && _offineSupport.createOneDSPayload) { + payloadData = _offineSupport.createOneDSPayload(sentItems); + payloadData.criticalCnt = criticalCnt + } else { + payloadData = _constructPayloadData(payloadArr, criticalCnt); + } - let payloadData = _constructPayloadData(payloadArr, criticalCnt); + let callback: OfflineBatchStoreCallback = (res) => { if (!res || !res.state) { return null; diff --git a/shared/AppInsightsCore/src/JavaScriptSDK.Interfaces/IChannelControls.ts b/shared/AppInsightsCore/src/JavaScriptSDK.Interfaces/IChannelControls.ts index 4165dbe4c..68632534b 100644 --- a/shared/AppInsightsCore/src/JavaScriptSDK.Interfaces/IChannelControls.ts +++ b/shared/AppInsightsCore/src/JavaScriptSDK.Interfaces/IChannelControls.ts @@ -47,6 +47,13 @@ export interface IInternalOfflineSupport { */ shouldProcess?: (evt: ITelemetryItem) => boolean; + /** + * Create 1ds payload data + * @param evts ITelemetryItems + * @returns IPayloadData + */ + createOneDSPayload?: (evts: ITelemetryItem[]) => IPayloadData; + } /** From 0630123e868ad5b009f6039d1a2adb8b82f1cfec Mon Sep 17 00:00:00 2001 From: Karlie Li Date: Mon, 6 May 2024 08:50:21 -0700 Subject: [PATCH 3/5] update --- channels/1ds-post-js/src/HttpManager.ts | 2 +- channels/1ds-post-js/src/PostChannel.ts | 9 +----- .../test/Unit/src/HttpManagerTest.ts | 28 ++++++++++++++++--- .../test/Unit/src/PostChannelTest.ts | 5 ++-- .../offline-channel-js/src/OfflineChannel.ts | 2 +- 5 files changed, 30 insertions(+), 16 deletions(-) diff --git a/channels/1ds-post-js/src/HttpManager.ts b/channels/1ds-post-js/src/HttpManager.ts index e36989cbd..4c5760cde 100644 --- a/channels/1ds-post-js/src/HttpManager.ts +++ b/channels/1ds-post-js/src/HttpManager.ts @@ -349,7 +349,7 @@ export class HttpManager { let thePayload: ISerializedPayload = null; - while (theBatches && theBatches.length && _serializer) { + while (theBatches && theBatches.length > 0 && _serializer) { let theBatch = theBatches.shift(); if (theBatch && theBatch.count() > 0) { thePayload = thePayload || _serializer.createPayload(0, false, false, false, SendRequestReason.NormalSchedule, EventSendType.Batched); diff --git a/channels/1ds-post-js/src/PostChannel.ts b/channels/1ds-post-js/src/PostChannel.ts index 2d5ab1000..2760af12d 100644 --- a/channels/1ds-post-js/src/PostChannel.ts +++ b/channels/1ds-post-js/src/PostChannel.ts @@ -246,15 +246,8 @@ export class PostChannel extends BaseTelemetryPlugin implements IChannelControls shouldProcess: (evt) => { return !_disableTelemetry; }, - createPayload: (evt, ikeys?: string[]) => { + createPayload: (evt) => { return null; - // should get new url headers based on payload directly - // let curDetails = _httpManager && _httpManager.getOfflineRequestDetails(); - // return { - // urlString: curDetails.url, - // headers: curDetails.hdrs, - // data: evt - // } as IPayloadData; }, createOneDSPayload: (evts: ITelemetryItem[]) => { if (_httpManager.createOneDSPayload) { diff --git a/channels/1ds-post-js/test/Unit/src/HttpManagerTest.ts b/channels/1ds-post-js/test/Unit/src/HttpManagerTest.ts index 0df51376d..4545fff52 100644 --- a/channels/1ds-post-js/test/Unit/src/HttpManagerTest.ts +++ b/channels/1ds-post-js/test/Unit/src/HttpManagerTest.ts @@ -222,10 +222,30 @@ export class HttpManagerTest extends AITestClass { QUnit.assert.equal(evtStr, `{"name":"testEvent","iKey":"o:testKey","data":{"baseData":{}}}`,"Event should be serialized"); QUnit.assert.ok(manager.getOfflineRequestDetails, "request details function should exist"); - let details = manager.getOfflineRequestDetails(); - QUnit.assert.equal(details.url, "testEndpoint?cors=true&content-type=application/x-json-stream&w=0", "get expected Url"); - QUnit.assert.ok(details.hdrs, "get headers Url"); - QUnit.assert.ok(details.useHdrs, "should use headers"); + QUnit.assert.equal(manager.getOfflineRequestDetails(), null, "request details function should return null for 1ds"); + let details = manager.createOneDSPayload([evt]); + let headers = details.headers || {}; + let apiKey = headers["apikey"]; + QUnit.assert.equal(apiKey, "testKey-123", "should get expected api key"); + QUnit.assert.equal(details.data, `{"name":"testEvent","iKey":"o:testKey","data":{"baseData":{}}}`, "should return expected data"); + + let evt1 = this._createEvent(); + evt1.iKey = "testKey-12345"; + evt1.name = "testEvent1"; + details = manager.createOneDSPayload([evt, evt1]); + headers = details.headers || {}; + apiKey = headers["apikey"]; + QUnit.assert.equal(apiKey, "testKey-123,testKey-12345", "should get expected api keys test1"); + QUnit.assert.equal(details.data, `{"name":"testEvent","iKey":"o:testKey","data":{"baseData":{}}}\n{"name":"testEvent1","iKey":"o:testKey","data":{"baseData":{}}}`, "should return expected data test1"); + + let evt2 = this._createEvent(); + evt2.iKey = "testKey-123"; + evt2.name = "testEvent2"; + details = manager.createOneDSPayload([evt, evt2]); + headers = details.headers || {}; + apiKey = headers["apikey"]; + QUnit.assert.equal(apiKey, "testKey-123", "should get expected api keys test2"); + QUnit.assert.equal(details.data, `{"name":"testEvent","iKey":"o:testKey","data":{"baseData":{}}}\n{"name":"testEvent2","iKey":"o:testKey","data":{"baseData":{}}}`, "should return expected data test2"); } }); diff --git a/channels/1ds-post-js/test/Unit/src/PostChannelTest.ts b/channels/1ds-post-js/test/Unit/src/PostChannelTest.ts index 30ab76194..195e9c5ed 100644 --- a/channels/1ds-post-js/test/Unit/src/PostChannelTest.ts +++ b/channels/1ds-post-js/test/Unit/src/PostChannelTest.ts @@ -311,10 +311,11 @@ export class PostChannelTest extends AITestClass { QUnit.assert.equal(offlineSupport.shouldProcess(event), true, "should process"); QUnit.assert.ok(offlineSupport.createPayload, "createPayload should exit"); - let details = offlineSupport.createPayload("test"); + QUnit.assert.equal(offlineSupport.createPayload("test"), null, "createPayload should return null now"); + let details = offlineSupport.createOneDSPayload([event]); QUnit.assert.equal(details.urlString, "https://testEndpoint?cors=true&content-type=application/x-json-stream&w=0", "get expected Url"); QUnit.assert.ok(details.headers, "get headers Url"); - QUnit.assert.equal(details.data, "test", "get expected data"); + QUnit.assert.equal(details.data, expectedStr, "get expected data"); this.core.config.extensionConfig = this.core.config.extensionConfig || {}; this.core.config.extensionConfig[postId].disableTelemetry = true; diff --git a/channels/offline-channel-js/src/OfflineChannel.ts b/channels/offline-channel-js/src/OfflineChannel.ts index 828515981..70a1fe190 100644 --- a/channels/offline-channel-js/src/OfflineChannel.ts +++ b/channels/offline-channel-js/src/OfflineChannel.ts @@ -351,7 +351,7 @@ export class OfflineChannel extends BaseTelemetryPlugin implements IChannelContr let payloadData: IStorageTelemetryItem = null; if (_offineSupport && _offineSupport.createOneDSPayload) { payloadData = _offineSupport.createOneDSPayload(sentItems); - payloadData.criticalCnt = criticalCnt + payloadData.criticalCnt = criticalCnt; } else { payloadData = _constructPayloadData(payloadArr, criticalCnt); } From c87b66e7d13015c33fee422af169702accd3acd9 Mon Sep 17 00:00:00 2001 From: Karlie Li Date: Mon, 6 May 2024 08:57:55 -0700 Subject: [PATCH 4/5] update --- channels/1ds-post-js/src/HttpManager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/channels/1ds-post-js/src/HttpManager.ts b/channels/1ds-post-js/src/HttpManager.ts index 4c5760cde..3c86ff214 100644 --- a/channels/1ds-post-js/src/HttpManager.ts +++ b/channels/1ds-post-js/src/HttpManager.ts @@ -349,7 +349,7 @@ export class HttpManager { let thePayload: ISerializedPayload = null; - while (theBatches && theBatches.length > 0 && _serializer) { + while (theBatches.length > 0 && _serializer) { let theBatch = theBatches.shift(); if (theBatch && theBatch.count() > 0) { thePayload = thePayload || _serializer.createPayload(0, false, false, false, SendRequestReason.NormalSchedule, EventSendType.Batched); From 6ce608f1b078421cdd81ec5ec227b95e0e613963 Mon Sep 17 00:00:00 2001 From: Karlie Li Date: Mon, 6 May 2024 09:05:36 -0700 Subject: [PATCH 5/5] update --- channels/offline-channel-js/src/OfflineChannel.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/channels/offline-channel-js/src/OfflineChannel.ts b/channels/offline-channel-js/src/OfflineChannel.ts index 70a1fe190..28dba8828 100644 --- a/channels/offline-channel-js/src/OfflineChannel.ts +++ b/channels/offline-channel-js/src/OfflineChannel.ts @@ -351,7 +351,10 @@ export class OfflineChannel extends BaseTelemetryPlugin implements IChannelContr let payloadData: IStorageTelemetryItem = null; if (_offineSupport && _offineSupport.createOneDSPayload) { payloadData = _offineSupport.createOneDSPayload(sentItems); - payloadData.criticalCnt = criticalCnt; + if (payloadData) { + payloadData.criticalCnt = criticalCnt; + } + } else { payloadData = _constructPayloadData(payloadArr, criticalCnt); }