@@ -12,11 +12,23 @@ import { BaseTelemetryReporter, ReplacementOption } from "../common/baseTelemetr
1212import { BaseTelemetrySender } from "../common/baseTelemetrySender" ;
1313import { TelemetryUtil } from "../common/util" ;
1414
15+ /**
16+ * A custom fetcher function that can be used to send telemetry data.
17+ * Compatible with the Node.js fetch API signature.
18+ * @param url The URL to send the request to
19+ * @param init The request initialization options including method, headers, and body
20+ * @returns A promise that resolves to a Response object
21+ */
22+ export type CustomFetcher = (
23+ url : string ,
24+ init ?: { method : "POST" ; headers ?: Record < string , string > ; body ?: string }
25+ ) => Promise < { text : ( ) => Promise < string > ; status : number ; headers : Iterable < [ string , string ] > } > ;
26+
1527/**
1628 * Create a replacement for the XHTMLRequest object utilizing nodes HTTP module.
1729 * @returns A XHR override object used to override the XHTMLRequest object in the 1DS SDK
1830 */
19- function getXHROverride ( ) {
31+ function getDefaultXHROverride ( ) : IXHROverride {
2032 // Override the way events get sent since node doesn't have XHTMLRequest
2133 const customHttpXHROverride : IXHROverride = {
2234 sendPOST : ( payload : IPayloadData , oncomplete ) => {
@@ -31,7 +43,7 @@ function getXHROverride() {
3143 try {
3244 const req = https . request ( payload . urlString , options , res => {
3345 res . on ( "data" , function ( responseData ) {
34- oncomplete ( res . statusCode ?? 200 , res . headers as Record < string , any > , responseData . toString ( ) ) ;
46+ oncomplete ( res . statusCode ?? 200 , res . headers as Record < string , string > , responseData . toString ( ) ) ;
3547 } ) ;
3648 // On response with error send status of 0 and a blank response to oncomplete so we can retry events
3749 res . on ( "error" , function ( ) {
@@ -53,12 +65,46 @@ function getXHROverride() {
5365 return customHttpXHROverride ;
5466}
5567
68+ /**
69+ * Create an XHR override from a custom fetcher function.
70+ * @param fetcher The custom fetcher function to use for sending telemetry data
71+ * @returns A XHR override object used to override the XHTMLRequest object in the 1DS SDK
72+ */
73+ function createXHROverrideFromFetcher ( fetcher : CustomFetcher ) : IXHROverride {
74+ const xhrOverride : IXHROverride = {
75+ sendPOST : ( payload : IPayloadData , oncomplete ) => {
76+ const dataString = typeof payload . data === "string" ? payload . data : Buffer . from ( payload . data ) . toString ( ) ;
77+
78+ fetcher ( payload . urlString , { method : "POST" , headers : payload . headers , body : dataString } )
79+ . then ( async ( response ) => {
80+ const responseHeaders : Record < string , string > = { } ;
81+ for ( const [ key , value ] of response . headers ) {
82+ responseHeaders [ key ] = value ;
83+ }
84+ const body = await response . text ( ) ;
85+ oncomplete ( response . status , responseHeaders , body ) ;
86+ } )
87+ . catch ( ( ) => {
88+ // If it errors out, send status of 0 and a blank response to oncomplete so we can retry events
89+ oncomplete ( 0 , { } ) ;
90+ } ) ;
91+ }
92+ } ;
93+ return xhrOverride ;
94+ }
95+
5696export class TelemetryReporter extends BaseTelemetryReporter {
57- constructor ( connectionString : string , replacementOptions ?: ReplacementOption [ ] , initializationOptions ?: vscode . TelemetryLoggerOptions ) {
58- let clientFactory = ( connectionString : string ) => appInsightsClientFactory ( connectionString , vscode . env . machineId , vscode . env . sessionId , getXHROverride ( ) , replacementOptions ) ;
97+ constructor (
98+ connectionString : string ,
99+ replacementOptions ?: ReplacementOption [ ] ,
100+ initializationOptions ?: vscode . TelemetryLoggerOptions ,
101+ customFetcher ?: CustomFetcher
102+ ) {
103+ const xhrOverride = customFetcher ? createXHROverrideFromFetcher ( customFetcher ) : getDefaultXHROverride ( ) ;
104+ let clientFactory = ( connectionString : string ) => appInsightsClientFactory ( connectionString , vscode . env . machineId , vscode . env . sessionId , xhrOverride , replacementOptions ) ;
59105 // If connection string is usable by 1DS use the 1DS SDk
60106 if ( TelemetryUtil . shouldUseOneDataSystemSDK ( connectionString ) ) {
61- clientFactory = ( key : string ) => oneDataSystemClientFactory ( key , vscode , getXHROverride ( ) ) ;
107+ clientFactory = ( key : string ) => oneDataSystemClientFactory ( key , vscode , xhrOverride ) ;
62108 }
63109
64110 const osShim = {
0 commit comments