@salesforce/o11y-reporter
Version:
A wrapper service around o11y and o11y_schema for telemetry reporting.
3 lines (2 loc) • 9.19 kB
JavaScript
/* o11y-reporter - A wrapper service around o11y and o11y_schema for telemetry reporting */
var u=null,p=async()=>(u||(u=(async()=>{let[e,t,i,s,r]=await Promise.all([import("o11y/client"),import("o11y_schema/version"),import("o11y_schema/sf_a4dInstrumentation"),import("o11y/simple_collector"),import("o11y/collectors")]),{registerInstrumentedApp:o,ConsoleCollector:n,_version:a,getInstrumentation:l}=e,{version:d}=t;return{o11yClientVersion:a,getInstrumentation:l,o11ySchemaVersion:d,registerInstrumentedApp:o,ConsoleCollector:n,a4d_instrumentation:i.a4dInstrumentationSchema,simpleCollectorModule:s,collectorsModule:r}})()),u);var h=class e{constructor(){this.O11Y_UPLOAD_THRESHOLD_BYTES=5e4;this.environment={};this.getConnectionMethod=null;this.dynamicO11yUploadEndpointPath="/services/data/v65.0/connect/proxy/ui-telemetry";this.flushTimer=null;this.shutdownHandler=null}static{this.instances=new Map}static{this.sharedResourcesInitPromise=null}static{this.sharedInstrumentation=null}static{this.sharedInstrApp=null}static{this.sharedO11yModules=null}static{this.sharedProtoEncoderFunc=null}static{this.loggedProtoEncoderNotInitialized=!1}static getInstance(t){if(!e.instances.has(t)){let i=new e;e.instances.set(t,i)}return e.instances.get(t)}async initialize(t,i,s,r){if(this.extensionName=t,this.o11yUploadEndpoint=i,this.getConnectionMethod=s||null,r?.dynamicO11yUploadEndpointPath&&(this.dynamicO11yUploadEndpointPath=r.dynamicO11yUploadEndpointPath.startsWith("/")?r.dynamicO11yUploadEndpointPath:`/${r.dynamicO11yUploadEndpointPath}`),e.sharedInstrApp||(e.sharedResourcesInitPromise||(e.sharedResourcesInitPromise=this.runInitializeSharedResourcesOnce()),await e.sharedResourcesInitPromise),!e.sharedO11yModules||!e.sharedInstrumentation){console.error("O11yService: Telemetry initialization failed - continuing without telemetry");return}this.instrumentation=e.sharedInstrumentation,this.a4dO11ySchema=e.sharedO11yModules.a4d_instrumentation;let{o11yClientVersion:o,o11ySchemaVersion:n}=e.sharedO11yModules;Object.assign(this.environment,{appName:"o11y-reporter-extensions",extensionName:this.extensionName,o11ySchemaVersion:n,sdkVersion:`${o}:${n}`})}runInitializeSharedResourcesOnce(){return this.initializeSharedResources().finally(()=>{e.sharedInstrApp||(e.sharedResourcesInitPromise=null)})}async initializeSharedResources(){try{if(e.sharedO11yModules=await p(),!e.sharedO11yModules){console.error("Failed to load O11y modules");return}let{o11yClientVersion:t,o11ySchemaVersion:i,getInstrumentation:s,registerInstrumentedApp:r}=e.sharedO11yModules,o="o11y-reporter-extensions-instrumentation";if(e.sharedInstrumentation=s(o),!e.sharedInstrumentation){console.error("Failed to create shared instrumentation:",o);return}let n="o11y-reporter-extensions";if(e.sharedInstrApp=r(n,{isProduction:!1,enableBuffering:!0}),!e.sharedInstrApp){console.error("Failed to register shared app:",n);return}if(e.sharedInstrApp&&(e.sharedInstrApp.simpleCollector=this.initSimpleCollector(e.sharedInstrApp,{appName:n,sdkVersion:`${t}:${i}`},e.sharedO11yModules)),e.sharedO11yModules){let{collectorsModule:a}=e.sharedO11yModules,l=a.default??a;if(typeof l.encodeCoreEnvelopeContentsRaw=="function")e.sharedProtoEncoderFunc=l.encodeCoreEnvelopeContentsRaw;else{console.error("Failed to initialize proto encoder function - encodeCoreEnvelopeContentsRaw is not a function");return}}else{console.error("sharedO11yModules is null after loading");return}}catch(t){console.error("Failed to initialize shared O11y resources:",t),e.sharedInstrApp=null,e.sharedO11yModules=null,e.sharedInstrumentation=null,e.sharedProtoEncoderFunc=null}}logEvent(t){if(!this.isInitialized()){console.error("O11yService: Cannot log event - Service not fully initialized"),console.error("Initialization status:",this.getInitializationStatus());return}this.instrumentation?this.instrumentation.log(this.a4dO11ySchema,{message:JSON.stringify(t)}):console.error("O11yService: Unable to log event - Instrumentation not initialized")}logEventWithSchema(t,i){if(!this.isInitialized()){console.error("O11yService: Cannot log event - Service not fully initialized"),console.error("Initialization status:",this.getInitializationStatus());return}if(!i){console.error("O11yService: Schema not provided to logEventWithSchema");return}this.instrumentation?this.instrumentation.log(i,t):console.error("O11yService: Unable to log event - Instrumentation not initialized")}isInitialized(){return!!(e.sharedProtoEncoderFunc&&e.sharedInstrApp&&e.sharedO11yModules&&this.instrumentation)}getInitializationStatus(){return{sharedProtoEncoderFunc:!!e.sharedProtoEncoderFunc,sharedInstrApp:!!e.sharedInstrApp,sharedO11yModules:!!e.sharedO11yModules,instrumentation:!!this.instrumentation}}async waitForInitialization(t=5e3){let i=Date.now();if(this.isInitialized())return!0;let s=5;for(;!this.isInitialized();){if(Date.now()-i>t)return console.error("O11yService: Initialization timeout after",t,"ms"),console.error("Final initialization status:",this.getInitializationStatus()),!1;await new Promise(r=>setTimeout(r,s)),s=Math.min(s*2,100)}return!0}async upload(){if(!this.isInitialized()){console.error("O11yService: Cannot upload - Service not fully initialized");return}try{await this.uploadAsNeededAsync(!0)}catch(t){console.error("Telemetry upload failed:",t)}}initSimpleCollector(t,i,s){if(!s)throw new Error("o11yModules is null");let{simpleCollectorModule:r}=s,o=r.default?.SimpleCollector??r.SimpleCollector,n=new o({environment:i});return t.registerLogCollector(n,{retroactive:!0}),t.registerMetricsCollector(n),n}uploadAsNeededAsync(t=!1){let i=[];if(!e.sharedProtoEncoderFunc)return e.loggedProtoEncoderNotInitialized||(e.loggedProtoEncoderNotInitialized=!0,console.error("O11yService: sharedProtoEncoderFunc is not initialized (shared telemetry init likely failed); uploads skipped.")),Promise.resolve([]);let s=e.sharedInstrApp?.simpleCollector,r=this.configuredThresholdBytes??this.O11Y_UPLOAD_THRESHOLD_BYTES;if(s?.hasData&&(t||s.estimatedByteSize>=r))try{let o=s.getRawContentsOfCoreEnvelope(),n=e.sharedProtoEncoderFunc(o);i.push(this.uploadToFalconAsync(n))}catch(o){return console.error("[O11yService][uploadAsNeededAsync] Error during upload encoding:",o),Promise.resolve([])}return Promise.allSettled(i).then(async o=>{for(let n of o)if(n.status==="fulfilled"){let a=n.value;(a.status<200||a.status>=300)&&console.error(`[O11yService][uploadAsNeededAsync] \u2717 Upload FAILED with status ${a.status} ${a.statusText}. Events may not be in Splunk.`)}else console.error("[O11yService][uploadAsNeededAsync] \u2717 Upload FAILED:",n.reason),n.reason instanceof Error&&console.error("[O11yService][uploadAsNeededAsync] Error stack:",n.reason.stack);return o})}async uploadToFalconAsync(t){let s={base64Env:Buffer.from(t).toString("base64")};if(this.getConnectionMethod)try{let n=await this.getConnectionMethod();if(n?.requestPost)return await n.requestPost(this.dynamicO11yUploadEndpointPath,s),{status:200,ok:!0}}catch{}let r=this.o11yUploadEndpoint||"";return r?this.postRequest(r,s):Promise.reject(new Error("o11yUploadEndpoint is not defined"))}postRequest(t,i){let s=JSON.stringify(i);return fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:s}).catch(o=>{throw console.error(`[O11yService][postRequest] \u2717 POST Request FAILED for ${t}:`,o),o instanceof Error&&console.error("[O11yService][postRequest] Error details:",o.message,o.stack),o})}async forceFlush(){if(this.getBatchStatus().hasData)return this.upload()}enableAutoBatching(t){let i=t?.flushInterval??3e4,s=t?.checkInterval??2e3,r=t?.enableShutdownHook??!0;this.configuredThresholdBytes=t?.thresholdBytes??this.O11Y_UPLOAD_THRESHOLD_BYTES,this.flushTimer&&clearInterval(this.flushTimer);let o=Date.now();if(this.flushTimer=setInterval(async()=>{try{let n=Date.now();await this.uploadAsNeededAsync(!1),n-o>=i&&(await this.uploadAsNeededAsync(!0),o=n)}catch(n){console.error("[O11yService] Auto-batching flush failed:",n)}},s),r){let n=t?.enableBeforeExitHook!==!1,a=m=>async()=>{try{this.getBatchStatus().hasData&&await this.uploadAsNeededAsync(!0)}catch(c){console.error(`[O11yService] Shutdown flush failed for ${m}:`,c),c instanceof Error&&console.error("[O11yService] Error stack:",c.stack)}},l=a("SIGINT"),d=a("SIGTERM");process.on("SIGINT",l),process.on("SIGTERM",d),n&&(this.shutdownHandler=a("beforeExit"),process.on("beforeExit",this.shutdownHandler)),this.shutdownHandlers={SIGINT:l,SIGTERM:d,...n&&this.shutdownHandler?{beforeExit:this.shutdownHandler}:{}}}return()=>{this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=null),r&&this.shutdownHandlers&&(this.shutdownHandlers.beforeExit&&process.removeListener("beforeExit",this.shutdownHandlers.beforeExit),process.removeListener("SIGINT",this.shutdownHandlers.SIGINT),process.removeListener("SIGTERM",this.shutdownHandlers.SIGTERM),this.shutdownHandler=null,this.shutdownHandlers=void 0)}}getBatchStatus(){let t=e.sharedInstrApp?.simpleCollector,i=t?.hasData||!1,s=t?.estimatedByteSize||0,r=this.configuredThresholdBytes??this.O11Y_UPLOAD_THRESHOLD_BYTES,o=s>=r;return{hasData:i,estimatedByteSize:s,thresholdBytes:r,isOverThreshold:o}}};export{h as O11yService};