@grafana/faro-transport-otlp-http 1.3.4 → 1.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/README.md +62 -0
  2. package/dist/bundle/faro-transport-otlp-http.iife.js +1 -1
  3. package/dist/bundle/types/payload/OtelPayload.d.ts +9 -2
  4. package/dist/bundle/types/payload/transform/index.d.ts +1 -1
  5. package/dist/bundle/types/payload/transform/transform.d.ts +2 -1
  6. package/dist/bundle/types/payload/transform/types.d.ts +3 -0
  7. package/dist/bundle/types/transport.d.ts +1 -1
  8. package/dist/bundle/types/types.d.ts +5 -0
  9. package/dist/cjs/payload/OtelPayload.js +3 -3
  10. package/dist/cjs/payload/OtelPayload.js.map +1 -1
  11. package/dist/cjs/payload/transform/index.js.map +1 -1
  12. package/dist/cjs/payload/transform/transform.js +12 -15
  13. package/dist/cjs/payload/transform/transform.js.map +1 -1
  14. package/dist/cjs/payload/transform/types.js.map +1 -1
  15. package/dist/cjs/transport.js +8 -3
  16. package/dist/cjs/transport.js.map +1 -1
  17. package/dist/cjs/types.js.map +1 -1
  18. package/dist/esm/payload/OtelPayload.js +2 -3
  19. package/dist/esm/payload/OtelPayload.js.map +1 -1
  20. package/dist/esm/payload/transform/index.js.map +1 -1
  21. package/dist/esm/payload/transform/transform.js +12 -15
  22. package/dist/esm/payload/transform/transform.js.map +1 -1
  23. package/dist/esm/payload/transform/types.js.map +1 -1
  24. package/dist/esm/transport.js +8 -3
  25. package/dist/esm/transport.js.map +1 -1
  26. package/dist/esm/types.js.map +1 -1
  27. package/dist/types/payload/OtelPayload.d.ts +9 -2
  28. package/dist/types/payload/transform/index.d.ts +1 -1
  29. package/dist/types/payload/transform/transform.d.ts +2 -1
  30. package/dist/types/payload/transform/types.d.ts +3 -0
  31. package/dist/types/transport.d.ts +1 -1
  32. package/dist/types/types.d.ts +5 -0
  33. package/package.json +3 -3
package/README.md CHANGED
@@ -41,6 +41,63 @@ initializeFaro({
41
41
  The Faro OtlpHttpTransport converts the Faro model to the Otlp schema, so you can send Faro data to
42
42
  compatible Otel Receivers.
43
43
 
44
+ ### Optional `body` property in Logs of type `Measurement` and `Exception`
45
+
46
+ The `body` field is optional as defined by the Otel Log spec.
47
+ Because of this we only add the body property only to signals which have a body value.
48
+ This is all signals besides of `Measurement` and `Exception`
49
+
50
+ This can cause issues with some Otel Collector components.
51
+
52
+ Faro provides the `createErrorLogBody` and `createMeasurementLogBody` functions which you can use
53
+ to create a body string for these logs.
54
+ Both properties are part of the `otlpTransform` object in `OtlpHttpTransportOptions`.
55
+
56
+ As a parameter each function gets the transport item of the log which is currently in transformation.
57
+ You can use values from this object to built a custom string.
58
+
59
+ #### Example
60
+
61
+ ```ts
62
+ initializeFaro({
63
+ // ...
64
+ instrumentations: [
65
+ // Load the default Web instrumentations
66
+ ...getWebInstrumentations(),
67
+ ],
68
+ transports: [
69
+ new OtlpHttpTransport({
70
+ apiKey: env.faro.apiKey,
71
+ logsURL: 'https://example.com/v1/logs',
72
+ tracesURL: 'https://example.com/v1/traces',
73
+
74
+ // customize logs transformation
75
+ otlpTransform: {
76
+ // create custom body string for measurement logs
77
+ createMeasurementLogBody(item) {
78
+ // Note: It's not advisable to built big strings which contain redundant data because
79
+ // it ads unnecessary bytes to the requests and your storage solution
80
+ // This example is to show how we can use the transport-item to built a custom string
81
+ const { payload } = item;
82
+ const [measurementName, measurementValue] = Object.entries(payload.values).flat();
83
+ const body = `faro.signal.measurement: type=${payload.type} name=${measurementName} value=${measurementValue}`;
84
+ return body;
85
+ },
86
+ // create custom body string for error logs
87
+ createErrorLogBody(item) {
88
+ // Note: It's not advisable to built big strings which contain redundant data because
89
+ // it ads unnecessary bytes to the requests and your storage solution
90
+ // This example is to show how we can use the transport-item to built a custom string
91
+ const { payload } = item;
92
+ const body = `faro.signal.error: type=${payload.type} message=${payload.value}`;
93
+ return body;
94
+ },
95
+ },
96
+ }),
97
+ ],
98
+ });
99
+ ```
100
+
44
101
  ### Config Options
45
102
 
46
103
  - `apiKey?: string`: Will be added as `x-api-key` header.
@@ -53,3 +110,8 @@ compatible Otel Receivers.
53
110
  sending the data.
54
111
  - `tracesURL?: string`: Endpoint to send Traces to.
55
112
  - `logsURL?: string`: Endpoint to send Logs to.
113
+ - `otlpTransform?:`: Customize parts of logs transformation.
114
+ - `otlpTransform.createErrorLogBody?: (item: TransportItem<ExceptionEvent>) => string`:
115
+ create custom body for error logs.
116
+ `otlpTransform.createMeasurementLogBody?: (item: TransportItem<MeasurementEvent>) => string;`:
117
+ create custom body for measurement logs.
@@ -1 +1 @@
1
- var GrafanaFaroTransportOtlpHttp=function(e){"use strict";function t(e,t){var r={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.indexOf(n)<0&&(r[n]=e[n]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var o=0;for(n=Object.getOwnPropertySymbols(e);o<n.length;o++)t.indexOf(n[o])<0&&Object.prototype.propertyIsEnumerable.call(e,n[o])&&(r[n[o]]=e[n[o]])}return r}function r(e,t){return typeof e===t}"function"==typeof SuppressedError&&SuppressedError;const n=e=>r(e,"number")&&!isNaN(e)||r(e,"bigint"),o=e=>!(e=>r(e,"null"))(e)&&r(e,"object"),s=e=>function(e,t){return Object.prototype.toString.call(e)===`[object ${t}]`}(e,"Array");var i,a,l;function u(){}!function(e){e.TRACE="trace",e.DEBUG="debug",e.INFO="info",e.LOG="log",e.WARN="warn",e.ERROR="error"}(i||(i={})),i.LOG,i.TRACE,i.DEBUG,i.INFO,i.LOG,i.WARN,i.ERROR,function(e){e.EXCEPTION="exception",e.LOG="log",e.MEASUREMENT="measurement",e.TRACE="trace",e.EVENT="event"}(a||(a={})),a.EXCEPTION,a.LOG,a.MEASUREMENT,a.TRACE,a.EVENT,function(e){e[e.OFF=0]="OFF",e[e.ERROR=1]="ERROR",e[e.WARN=2]="WARN",e[e.INFO=3]="INFO",e[e.VERBOSE=4]="VERBOSE"}(l||(l={}));const c={debug:u,error:u,info:u,prefix:"Faro",warn:u};l.ERROR;const d=Object.assign({},console);class g{constructor(){this.unpatchedConsole=d,this.internalLogger=c,this.config={},this.metas={}}logDebug(...e){this.internalLogger.debug(`${this.name}\n`,...e)}logInfo(...e){this.internalLogger.info(`${this.name}\n`,...e)}logWarn(...e){this.internalLogger.warn(`${this.name}\n`,...e)}logError(...e){this.internalLogger.error(`${this.name}\n`,...e)}}class v extends g{isBatched(){return!1}getIgnoreUrls(){return[]}}const p="1.3.4";var f="exception.type",m="exception.message",h="enduser.id",b="http.url",y="deployment.environment",R="service.name",E="service.version",O="telemetry.sdk.name",L="telemetry.sdk.language",N="telemetry.sdk.version",T="webjs";function w(e){return(e=>r(e,"string"))(e)?{stringValue:e}:(e=>n(e)&&Number.isInteger(e))(e)?{intValue:e}:n(e)?{doubleValue:e}:(e=>r(e,"boolean"))(e)?{boolValue:e}:s(e)?{arrayValue:{values:e.map(w)}}:e instanceof Uint8Array?{bytesValue:e}:o(e)?{kvlistValue:{values:Object.entries(e).map((([e,t])=>I(e,t))).filter(U)}}:{}}function I(e,t){if(null!=t&&""!==t)return{key:e,value:w(t)}}function U(e){return Boolean(e)&&"string"==typeof(null==e?void 0:e.key)&&void 0!==(null==e?void 0:e.value)}const S="browser.brands",x="browser.mobile",k="browser.user_agent",D="browser.language";function A(e){function t(e){return{scope:{name:"@grafana/faro-web-sdk",version:p},logRecords:[r(e)]}}function r(t){const{type:r}=t;switch(r){case a.LOG:return function(e){var t,r;const{meta:s,payload:a}=e,l=o(a.timestamp),u=w(a.message);function c(e){switch(e){case i.TRACE:return{severityNumber:1,severityText:"TRACE"};case i.DEBUG:return{severityNumber:5,severityText:"DEBUG"};case i.INFO:return{severityNumber:9,severityText:"INFO"};case i.LOG:return{severityNumber:10,severityText:"INFO2"};case i.WARN:return{severityNumber:13,severityText:"WARN"};case i.ERROR:return{severityNumber:17,severityText:"ERROR"}}}return Object.assign(Object.assign({timeUnixNano:l},c(a.level)),{body:u,attributes:[...n(s),I("faro.log.context",a.context)].filter(U),traceId:null===(t=a.trace)||void 0===t?void 0:t.trace_id,spanId:null===(r=a.trace)||void 0===r?void 0:r.span_id})}(t);case a.EXCEPTION:return function(e){var t,r;const{meta:s,payload:i}=e;return{timeUnixNano:o(i.timestamp),attributes:[...n(s),I(f,i.type),I(m,i.value),I("faro.error.stacktrace",i.stacktrace),I("faro.error.context",i.context)].filter(U),traceId:null===(t=i.trace)||void 0===t?void 0:t.trace_id,spanId:null===(r=i.trace)||void 0===r?void 0:r.span_id}}(t);case a.EVENT:return function(e){var t,r;const{meta:s,payload:i}=e,a=o(i.timestamp),l=w(i.name);return{timeUnixNano:a,body:l,attributes:[...n(s),I("event.name",i.name),I("event.domain",i.domain),I("event.attributes",i.attributes)].filter(U),traceId:null===(t=i.trace)||void 0===t?void 0:t.trace_id,spanId:null===(r=i.trace)||void 0===r?void 0:r.span_id}}(t);case a.MEASUREMENT:return function(e){var t,r;const{meta:s,payload:i}=e,a=o(i.timestamp),[l,u]=Object.entries(i.values).flat();return{timeUnixNano:a,attributes:[...n(s),I("measurement.type",i.type),I("measurement.name",l),I("measurement.value",u),I("faro.measurement.context",i.context)].filter(U),traceId:null===(t=i.trace)||void 0===t?void 0:t.trace_id,spanId:null===(r=i.trace)||void 0===r?void 0:r.span_id}}(t);default:return null==e||e.error(`Unknown TransportItemType: ${r}`),{}}}function n(e){const{view:t,page:r,session:n,user:o}=e;return[I("view.name",null==t?void 0:t.name),I(b,null==r?void 0:r.url),I("page.id",null==r?void 0:r.id),I("page.attributes",null==r?void 0:r.attributes),I("session.id",null==n?void 0:n.id),I("session.attributes",null==n?void 0:n.attributes),I(h,null==o?void 0:o.id),I("enduser.name",null==o?void 0:o.username),I("enduser.email",null==o?void 0:o.email),I("enduser.attributes",null==o?void 0:o.attributes)].filter(U)}function o(e){return 1e6*Date.parse(e)}return{toResourceLog:function(e){return{resource:j(e),scopeLogs:[t(e)]}},toScopeLog:t,toLogRecord:r}}function j(e){const{browser:t,sdk:r,app:n}=e.meta;return{attributes:[I(x,null==t?void 0:t.mobile),I(k,null==t?void 0:t.userAgent),I(D,null==t?void 0:t.language),I(S,null==t?void 0:t.brands),I("browser.os",null==t?void 0:t.os),I("browser.name",null==t?void 0:t.name),I("browser.version",null==t?void 0:t.version),I(O,null==r?void 0:r.name),I(N,null==r?void 0:r.version),Boolean(r)?I(L,T):void 0,I(R,null==n?void 0:n.name),I(E,null==n?void 0:n.version),I(y,null==n?void 0:n.environment)].filter(U)}}class B{constructor(e,t){this.internalLogger=e,this.resourceSpans=[],this.internalLogger=e,this.resourceLogs=[],this.getLogTransforms=A(this.internalLogger),this.getTraceTransforms=(this.internalLogger,{toResourceSpan:function(e){var t,r;const n=j(e),o=null===(r=null===(t=e.payload.resourceSpans)||void 0===t?void 0:t[0])||void 0===r?void 0:r.scopeSpans;return{resource:n,scopeSpans:null!=o?o:[]}}}),t&&this.addResourceItem(t)}getPayload(){return{resourceLogs:this.resourceLogs,resourceSpans:this.resourceSpans}}addResourceItem(e){var t,r,n,o;const{type:s}=e;try{switch(s){case a.LOG:case a.EXCEPTION:case a.EVENT:case a.MEASUREMENT:const{toLogRecord:o,toResourceLog:i}=this.getLogTransforms;0===this.resourceLogs.length?this.resourceLogs=[i(e)]:null===(r=null===(t=this.resourceLogs[0])||void 0===t?void 0:t.scopeLogs[0])||void 0===r||r.logRecords.push(o(e));break;case a.TRACE:const{toResourceSpan:l}=this.getTraceTransforms;this.resourceSpans.push(l(e));break;default:null===(n=this.internalLogger)||void 0===n||n.error(`Unknown TransportItemType: ${s}`)}}catch(e){null===(o=this.internalLogger)||void 0===o||o.error(e)}}}return e.OtlpHttpTransport=class extends v{constructor(e){var t,r,n;super(),this.options=e,this.name="@grafana/faro-web-sdk:transport-otlp-http",this.version=p,this.sendingTracesDisabledUntil=new Date,this.sendingLogsDisabledUntil=new Date,this.rateLimitBackoffMs=null!==(t=e.defaultRateLimitBackoffMs)&&void 0!==t?t:5e3,this.promiseBuffer=function(e){const{size:t,concurrency:r}=e,n=[];let o=0;const s=()=>{if(o<r&&n.length){const{producer:e,resolve:t,reject:r}=n.shift();o++,e().then((e=>{o--,s(),t(e)}),(e=>{o--,s(),r(e)}))}};return{add:e=>{if(n.length+o>=t)throw new Error("Task buffer full");return new Promise(((t,r)=>{n.push({producer:e,resolve:t,reject:r}),s()}))}}}({size:null!==(r=null==e?void 0:e.bufferSize)&&void 0!==r?r:30,concurrency:null!==(n=null==e?void 0:e.concurrency)&&void 0!==n?n:5})}getIgnoreUrls(){const{tracesURL:e="",logsURL:t=""}=this.options;return[e,t].filter(Boolean)}isBatched(){return!0}send(e){const t=new B(this.internalLogger);e.forEach((e=>t.addResourceItem(e))),this.sendPayload(t.getPayload())}sendPayload(e){try{const{tracesURL:r="",logsURL:n=""}=this.options;for(const[o,i]of Object.entries(e)){if(!(s(i)&&i.length>0))continue;let e,a=e=>{},l="";switch(o){case"resourceSpans":l=r,e=this.sendingTracesDisabledUntil,a=e=>{this.sendingTracesDisabledUntil=e};break;case"resourceLogs":l=n,e=this.sendingLogsDisabledUntil,a=e=>{this.sendingLogsDisabledUntil=e}}if(e&&e>new Date(Date.now()))return void this.logWarn(`Dropping transport item due to too many requests. Backoff until ${e}`);const u=JSON.stringify({[o]:i}),{requestOptions:c,apiKey:d}=this.options,g=null!=c?c:{},{headers:v}=g,p=t(g,["headers"]);this.promiseBuffer.add((()=>fetch(l,Object.assign({method:"POST",headers:Object.assign(Object.assign({"Content-Type":"application/json"},null!=v?v:{}),d?{"x-api-key":d}:{}),body:u,keepalive:!0},null!=p?p:{})).then((t=>(429===t.status&&(a(this.getRetryAfterDate(t)),this.logWarn(`Too many requests, backing off until ${e}`)),t))).catch((e=>{this.logError("Failed sending payload to the receiver\n",JSON.parse(u),e)}))))}}catch(e){this.logError(e)}}getRetryAfterDate(e){const t=Date.now(),r=e.headers.get("Retry-After");if(r){const e=Number(r);if(!isNaN(e))return new Date(1e3*e+t);const n=Date.parse(r);if(!isNaN(n))return new Date(n)}return new Date(t+this.rateLimitBackoffMs)}},e}({});
1
+ var GrafanaFaroTransportOtlpHttp=function(e){"use strict";function t(e,t){var r={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.indexOf(n)<0&&(r[n]=e[n]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var o=0;for(n=Object.getOwnPropertySymbols(e);o<n.length;o++)t.indexOf(n[o])<0&&Object.prototype.propertyIsEnumerable.call(e,n[o])&&(r[n[o]]=e[n[o]])}return r}function r(e,t){return typeof e===t}"function"==typeof SuppressedError&&SuppressedError;const n=e=>r(e,"number")&&!isNaN(e)||r(e,"bigint"),o=e=>!(e=>r(e,"null"))(e)&&r(e,"object"),s=e=>function(e,t){return Object.prototype.toString.call(e)===`[object ${t}]`}(e,"Array");var i,a,l;function u(){}!function(e){e.TRACE="trace",e.DEBUG="debug",e.INFO="info",e.LOG="log",e.WARN="warn",e.ERROR="error"}(i||(i={})),i.LOG,i.TRACE,i.DEBUG,i.INFO,i.LOG,i.WARN,i.ERROR,function(e){e.EXCEPTION="exception",e.LOG="log",e.MEASUREMENT="measurement",e.TRACE="trace",e.EVENT="event"}(a||(a={})),a.EXCEPTION,a.LOG,a.MEASUREMENT,a.TRACE,a.EVENT,function(e){e[e.OFF=0]="OFF",e[e.ERROR=1]="ERROR",e[e.WARN=2]="WARN",e[e.INFO=3]="INFO",e[e.VERBOSE=4]="VERBOSE"}(l||(l={}));const c={debug:u,error:u,info:u,prefix:"Faro",warn:u};l.ERROR;const d=Object.assign({},console);class g{constructor(){this.unpatchedConsole=d,this.internalLogger=c,this.config={},this.metas={}}logDebug(...e){this.internalLogger.debug(`${this.name}\n`,...e)}logInfo(...e){this.internalLogger.info(`${this.name}\n`,...e)}logWarn(...e){this.internalLogger.warn(`${this.name}\n`,...e)}logError(...e){this.internalLogger.error(`${this.name}\n`,...e)}}class p extends g{isBatched(){return!1}getIgnoreUrls(){return[]}}const v="1.3.6";var f="exception.type",m="exception.message",h="enduser.id",b="http.url",y="deployment.environment",O="service.name",E="service.version",R="telemetry.sdk.name",L="telemetry.sdk.language",T="telemetry.sdk.version",N="webjs";function w(e){return(e=>r(e,"string"))(e)?{stringValue:e}:(e=>n(e)&&Number.isInteger(e))(e)?{intValue:e}:n(e)?{doubleValue:e}:(e=>r(e,"boolean"))(e)?{boolValue:e}:s(e)?{arrayValue:{values:e.map(w)}}:e instanceof Uint8Array?{bytesValue:e}:o(e)?{kvlistValue:{values:Object.entries(e).map((([e,t])=>I(e,t))).filter(U)}}:{}}function I(e,t){if(null!=t&&""!==t)return{key:e,value:w(t)}}function U(e){return Boolean(e)&&"string"==typeof(null==e?void 0:e.key)&&void 0!==(null==e?void 0:e.value)}const S="browser.brands",x="browser.mobile",j="browser.user_agent",k="browser.language";function D(e,t){function r(e){return{scope:{name:"@grafana/faro-web-sdk",version:v},logRecords:[n(e)]}}function n(r){const{type:n}=r;switch(n){case a.LOG:return function(e){var t,r;const{meta:n,payload:a}=e,l=s(a.timestamp),u=w(a.message);function c(e){switch(e){case i.TRACE:return{severityNumber:1,severityText:"TRACE"};case i.DEBUG:return{severityNumber:5,severityText:"DEBUG"};case i.INFO:return{severityNumber:9,severityText:"INFO"};case i.LOG:return{severityNumber:10,severityText:"INFO2"};case i.WARN:return{severityNumber:13,severityText:"WARN"};case i.ERROR:return{severityNumber:17,severityText:"ERROR"}}}return Object.assign(Object.assign({timeUnixNano:l},c(a.level)),{body:u,attributes:[...o(n),I("faro.log.context",a.context)].filter(U),traceId:null===(t=a.trace)||void 0===t?void 0:t.trace_id,spanId:null===(r=a.trace)||void 0===r?void 0:r.span_id})}(r);case a.EXCEPTION:return function(e){var r,n;const{meta:i,payload:a}=e,l=s(a.timestamp),u=B(e,null==t?void 0:t.createErrorLogBody);return Object.assign(Object.assign({timeUnixNano:l},u?{body:u}:{}),{attributes:[...o(i),I(f,a.type),I(m,a.value),I("faro.error.stacktrace",a.stacktrace),I("faro.error.context",a.context)].filter(U),traceId:null===(r=a.trace)||void 0===r?void 0:r.trace_id,spanId:null===(n=a.trace)||void 0===n?void 0:n.span_id})}(r);case a.EVENT:return function(e){var t,r;const{meta:n,payload:i}=e,a=s(i.timestamp),l=w(i.name);return{timeUnixNano:a,body:l,attributes:[...o(n),I("event.name",i.name),I("event.domain",i.domain),I("event.attributes",i.attributes)].filter(U),traceId:null===(t=i.trace)||void 0===t?void 0:t.trace_id,spanId:null===(r=i.trace)||void 0===r?void 0:r.span_id}}(r);case a.MEASUREMENT:return function(e){var r,n;const{meta:i,payload:a}=e,l=s(a.timestamp),[u,c]=Object.entries(a.values).flat(),d=B(e,null==t?void 0:t.createMeasurementLogBody);return Object.assign(Object.assign({timeUnixNano:l},d?{body:d}:{}),{attributes:[...o(i),I("measurement.type",a.type),I("measurement.name",u),I("measurement.value",c),I("faro.measurement.context",a.context)].filter(U),traceId:null===(r=a.trace)||void 0===r?void 0:r.trace_id,spanId:null===(n=a.trace)||void 0===n?void 0:n.span_id})}(r);default:return null==e||e.error(`Unknown TransportItemType: ${n}`),{}}}function o(e){const{view:t,page:r,session:n,user:o}=e;return[I("view.name",null==t?void 0:t.name),I(b,null==r?void 0:r.url),I("page.id",null==r?void 0:r.id),I("page.attributes",null==r?void 0:r.attributes),I("session.id",null==n?void 0:n.id),I("session.attributes",null==n?void 0:n.attributes),I(h,null==o?void 0:o.id),I("enduser.name",null==o?void 0:o.username),I("enduser.email",null==o?void 0:o.email),I("enduser.attributes",null==o?void 0:o.attributes)].filter(U)}function s(e){return 1e6*Date.parse(e)}return{toResourceLog:function(e){return{resource:A(e),scopeLogs:[r(e)]}},toScopeLog:r,toLogRecord:n}}function A(e){const{browser:t,sdk:r,app:n}=e.meta;return{attributes:[I(x,null==t?void 0:t.mobile),I(j,null==t?void 0:t.userAgent),I(k,null==t?void 0:t.language),I(S,null==t?void 0:t.brands),I("browser.os",null==t?void 0:t.os),I("browser.name",null==t?void 0:t.name),I("browser.version",null==t?void 0:t.version),I(R,null==r?void 0:r.name),I(T,null==r?void 0:r.version),Boolean(r)?I(L,N):void 0,I(O,null==n?void 0:n.name),I(E,null==n?void 0:n.version),I(y,null==n?void 0:n.environment)].filter(U)}}function B(e,t){return"function"==typeof t?w(t(e)):void 0}class F{constructor({internalLogger:e,customOtlpTransform:t,transportItem:r}){this.resourceSpans=[],this.internalLogger=e,this.resourceLogs=[],this.getLogTransforms=D(this.internalLogger,t),this.getTraceTransforms=(this.internalLogger,{toResourceSpan:function(e){var t,r;const n=A(e),o=null===(r=null===(t=e.payload.resourceSpans)||void 0===t?void 0:t[0])||void 0===r?void 0:r.scopeSpans;return{resource:n,scopeSpans:null!=o?o:[]}}}),r&&this.addResourceItem(r)}getPayload(){return{resourceLogs:this.resourceLogs,resourceSpans:this.resourceSpans}}addResourceItem(e){var t,r,n,o;const{type:s}=e;try{switch(s){case a.LOG:case a.EXCEPTION:case a.EVENT:case a.MEASUREMENT:const{toLogRecord:o,toResourceLog:i}=this.getLogTransforms;0===this.resourceLogs.length?this.resourceLogs=[i(e)]:null===(r=null===(t=this.resourceLogs[0])||void 0===t?void 0:t.scopeLogs[0])||void 0===r||r.logRecords.push(o(e));break;case a.TRACE:const{toResourceSpan:l}=this.getTraceTransforms;this.resourceSpans.push(l(e));break;default:null===(n=this.internalLogger)||void 0===n||n.error(`Unknown TransportItemType: ${s}`)}}catch(e){null===(o=this.internalLogger)||void 0===o||o.error(e)}}}return e.OtlpHttpTransport=class extends p{constructor(e){var t,r,n;super(),this.options=e,this.name="@grafana/faro-web-sdk:transport-otlp-http",this.version=v,this.sendingTracesDisabledUntil=new Date,this.sendingLogsDisabledUntil=new Date,this.rateLimitBackoffMs=null!==(t=e.defaultRateLimitBackoffMs)&&void 0!==t?t:5e3,this.promiseBuffer=function(e){const{size:t,concurrency:r}=e,n=[];let o=0;const s=()=>{if(o<r&&n.length){const{producer:e,resolve:t,reject:r}=n.shift();o++,e().then((e=>{o--,s(),t(e)}),(e=>{o--,s(),r(e)}))}};return{add:e=>{if(n.length+o>=t)throw new Error("Task buffer full");return new Promise(((t,r)=>{n.push({producer:e,resolve:t,reject:r}),s()}))}}}({size:null!==(r=null==e?void 0:e.bufferSize)&&void 0!==r?r:30,concurrency:null!==(n=null==e?void 0:e.concurrency)&&void 0!==n?n:5})}getIgnoreUrls(){const{tracesURL:e="",logsURL:t=""}=this.options;return[e,t].filter(Boolean)}isBatched(){return!0}send(e){const t=new F({internalLogger:this.internalLogger,customOtlpTransform:this.options.otlpTransform});e.forEach((e=>t.addResourceItem(e))),this.sendPayload(t.getPayload())}sendPayload(e){try{const{tracesURL:r="",logsURL:n=""}=this.options;for(const[o,i]of Object.entries(e)){if(!(s(i)&&i.length>0))continue;let e,a=e=>{},l="";switch(o){case"resourceSpans":l=r,e=this.sendingTracesDisabledUntil,a=e=>{this.sendingTracesDisabledUntil=e};break;case"resourceLogs":l=n,e=this.sendingLogsDisabledUntil,a=e=>{this.sendingLogsDisabledUntil=e}}if(e&&e>new Date(Date.now()))return void this.logWarn(`Dropping transport item due to too many requests. Backoff until ${e}`);const u=JSON.stringify({[o]:i}),{requestOptions:c,apiKey:d}=this.options,g=null!=c?c:{},{headers:p}=g,v=t(g,["headers"]);this.promiseBuffer.add((()=>fetch(l,Object.assign({method:"POST",headers:Object.assign(Object.assign({"Content-Type":"application/json"},null!=p?p:{}),d?{"x-api-key":d}:{}),body:u,keepalive:u.length<=6e4},null!=v?v:{})).then((t=>(429===t.status&&(a(this.getRetryAfterDate(t)),this.logWarn(`Too many requests, backing off until ${e}`)),t))).catch((e=>{this.logError("Failed sending payload to the receiver\n",JSON.parse(u),e)}))))}}catch(e){this.logError(e)}}getRetryAfterDate(e){const t=Date.now(),r=e.headers.get("Retry-After");if(r){const e=Number(r);if(!isNaN(e))return new Date(1e3*e+t);const n=Date.parse(r);if(!isNaN(n))return new Date(n)}return new Date(t+this.rateLimitBackoffMs)}},e}({});
@@ -1,12 +1,19 @@
1
1
  import { InternalLogger, TransportItem } from '@grafana/faro-core';
2
+ import type { OtlpHttpTransportOptions } from '../types';
2
3
  import type { OtelTransportPayload } from './types';
4
+ type OtelPayloadParams = {
5
+ internalLogger: InternalLogger;
6
+ transportItem?: TransportItem;
7
+ customOtlpTransform?: OtlpHttpTransportOptions['otlpTransform'];
8
+ };
3
9
  export declare class OtelPayload {
4
- private internalLogger;
5
10
  private resourceLogs;
6
11
  private resourceSpans;
7
12
  private getLogTransforms;
8
13
  private getTraceTransforms;
9
- constructor(internalLogger: InternalLogger, transportItem?: TransportItem);
14
+ private internalLogger;
15
+ constructor({ internalLogger, customOtlpTransform, transportItem }: OtelPayloadParams);
10
16
  getPayload(): OtelTransportPayload;
11
17
  addResourceItem(transportItem: TransportItem): void;
12
18
  }
19
+ export {};
@@ -1,2 +1,2 @@
1
1
  export { getLogTransforms, getTraceTransforms } from './transform';
2
- export type { LogRecord, LogTransportItem, ResourceLogs, LogsTransform, Resource, ResourceLog, ResourceSpan, ResourceSpans, Scope, ScopeLog, TraceTransform, } from './types';
2
+ export type { LogRecord, LogTransportItem, ResourceLogs, LogsTransform, Resource, ResourceLog, ResourceSpan, ResourceSpans, Scope, ScopeLog, TraceTransform, StringValueNonNullable, } from './types';
@@ -1,4 +1,5 @@
1
1
  import type { InternalLogger } from '@grafana/faro-core';
2
+ import type { OtlpHttpTransportOptions } from '../../types';
2
3
  import type { LogsTransform, TraceTransform } from './types';
3
- export declare function getLogTransforms(internalLogger: InternalLogger): LogsTransform;
4
+ export declare function getLogTransforms(internalLogger: InternalLogger, customOtlpTransform?: OtlpHttpTransportOptions['otlpTransform']): LogsTransform;
4
5
  export declare function getTraceTransforms(_internalLogger?: InternalLogger): TraceTransform;
@@ -46,3 +46,6 @@ export type TraceTransform = {
46
46
  toResourceSpan: (transportItem: TransportItem<TraceEvent>) => ResourceSpan;
47
47
  };
48
48
  export type ResourceMeta = Pick<Meta, 'app' | 'browser' | 'sdk'>;
49
+ export type StringValueNonNullable = {
50
+ stringValue: string;
51
+ };
@@ -3,7 +3,7 @@ import type { OtlpHttpTransportOptions } from './types';
3
3
  export declare class OtlpHttpTransport extends BaseTransport {
4
4
  private options;
5
5
  readonly name = "@grafana/faro-web-sdk:transport-otlp-http";
6
- readonly version = "1.3.4";
6
+ readonly version = "1.3.6";
7
7
  private readonly promiseBuffer;
8
8
  private readonly rateLimitBackoffMs;
9
9
  private sendingTracesDisabledUntil;
@@ -1,3 +1,4 @@
1
+ import type { ExceptionEvent, MeasurementEvent, TransportItem } from '@grafana/faro-core';
1
2
  export interface OtlpTransportRequestOptions extends Omit<RequestInit, 'body' | 'headers'> {
2
3
  headers?: Record<string, string>;
3
4
  }
@@ -9,4 +10,8 @@ export interface OtlpHttpTransportOptions {
9
10
  requestOptions?: OtlpTransportRequestOptions;
10
11
  readonly tracesURL?: string;
11
12
  readonly logsURL?: string;
13
+ otlpTransform?: {
14
+ createErrorLogBody?: (item: TransportItem<ExceptionEvent>) => string;
15
+ createMeasurementLogBody?: (item: TransportItem<MeasurementEvent>) => string;
16
+ };
12
17
  }
@@ -4,12 +4,12 @@ exports.OtelPayload = void 0;
4
4
  var faro_core_1 = require("@grafana/faro-core");
5
5
  var transform_1 = require("./transform");
6
6
  var OtelPayload = /** @class */ (function () {
7
- function OtelPayload(internalLogger, transportItem) {
8
- this.internalLogger = internalLogger;
7
+ function OtelPayload(_a) {
8
+ var internalLogger = _a.internalLogger, customOtlpTransform = _a.customOtlpTransform, transportItem = _a.transportItem;
9
9
  this.resourceSpans = [];
10
10
  this.internalLogger = internalLogger;
11
11
  this.resourceLogs = [];
12
- this.getLogTransforms = (0, transform_1.getLogTransforms)(this.internalLogger);
12
+ this.getLogTransforms = (0, transform_1.getLogTransforms)(this.internalLogger, customOtlpTransform);
13
13
  this.getTraceTransforms = (0, transform_1.getTraceTransforms)(this.internalLogger);
14
14
  if (transportItem) {
15
15
  this.addResourceItem(transportItem);
@@ -1 +1 @@
1
- {"version":3,"file":"OtelPayload.js","sourceRoot":"","sources":["../../../src/payload/OtelPayload.ts"],"names":[],"mappings":";;;AAAA,gDAAkG;AAElG,yCAAkG;AAIlG;IAOE,qBACU,cAA8B,EACtC,aAA6B;QADrB,mBAAc,GAAd,cAAc,CAAgB;QANhC,kBAAa,GAAG,EAAmB,CAAC;QAS1C,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QAEvB,IAAI,CAAC,gBAAgB,GAAG,IAAA,4BAAgB,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC9D,IAAI,CAAC,kBAAkB,GAAG,IAAA,8BAAkB,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAElE,IAAI,aAAa,EAAE;YACjB,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;SACrC;IACH,CAAC;IAED,gCAAU,GAAV;QACE,OAAO;YACL,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,aAAa,EAAE,IAAI,CAAC,aAAa;SACzB,CAAC;IACb,CAAC;IAED,qCAAe,GAAf,UAAgB,aAA4B;;QAClC,IAAA,IAAI,GAAK,aAAa,KAAlB,CAAmB;QAE/B,IAAI;YACF,QAAQ,IAAI,EAAE;gBACZ,KAAK,6BAAiB,CAAC,GAAG,CAAC;gBAC3B,KAAK,6BAAiB,CAAC,SAAS,CAAC;gBACjC,KAAK,6BAAiB,CAAC,KAAK,CAAC;gBAC7B,KAAK,6BAAiB,CAAC,WAAW;oBAC1B,IAAA,KAAiC,IAAI,CAAC,gBAAgB,EAApD,WAAW,iBAAA,EAAE,aAAa,mBAA0B,CAAC;oBAE7D,2DAA2D;oBAC3D,6GAA6G;oBAC7G,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE;wBAClC,IAAI,CAAC,YAAY,GAAG,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC;qBACpD;yBAAM;wBACL,iGAAiG;wBACjG,kDAAkD;wBAClD,MAAA,MAAA,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,0CAAE,SAAS,CAAC,CAAC,CAAC,0CAAE,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC;qBACjF;oBACD,MAAM;gBACR,KAAK,6BAAiB,CAAC,KAAK;oBAClB,IAAA,cAAc,GAAK,IAAI,CAAC,kBAAkB,eAA5B,CAA6B;oBAEnD,4EAA4E;oBAC5E,+EAA+E;oBAC/E,0HAA0H;oBAC1H,0JAA0J;oBAC1J,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,aAA0C,CAAC,CAAC,CAAC;oBAEpF,MAAM;gBACR;oBACE,MAAA,IAAI,CAAC,cAAc,0CAAE,KAAK,CAAC,qCAA8B,IAAI,CAAE,CAAC,CAAC;oBACjE,MAAM;aACT;SACF;QAAC,OAAO,KAAK,EAAE;YACd,MAAA,IAAI,CAAC,cAAc,0CAAE,KAAK,CAAC,KAAK,CAAC,CAAC;SACnC;IACH,CAAC;IACH,kBAAC;AAAD,CAAC,AApED,IAoEC;AApEY,kCAAW","sourcesContent":["import { InternalLogger, TraceEvent, TransportItem, TransportItemType } from '@grafana/faro-core';\n\nimport { getLogTransforms, getTraceTransforms, LogsTransform, TraceTransform } from './transform';\nimport type { ResourceLogs, ResourceSpans } from './transform/types';\nimport type { OtelTransportPayload } from './types';\n\nexport class OtelPayload {\n private resourceLogs: ResourceLogs;\n private resourceSpans = [] as ResourceSpans;\n\n private getLogTransforms: LogsTransform;\n private getTraceTransforms: TraceTransform;\n\n constructor(\n private internalLogger: InternalLogger,\n transportItem?: TransportItem\n ) {\n this.internalLogger = internalLogger;\n this.resourceLogs = [];\n\n this.getLogTransforms = getLogTransforms(this.internalLogger);\n this.getTraceTransforms = getTraceTransforms(this.internalLogger);\n\n if (transportItem) {\n this.addResourceItem(transportItem);\n }\n }\n\n getPayload(): OtelTransportPayload {\n return {\n resourceLogs: this.resourceLogs,\n resourceSpans: this.resourceSpans,\n } as const;\n }\n\n addResourceItem(transportItem: TransportItem): void {\n const { type } = transportItem;\n\n try {\n switch (type) {\n case TransportItemType.LOG:\n case TransportItemType.EXCEPTION:\n case TransportItemType.EVENT:\n case TransportItemType.MEASUREMENT:\n const { toLogRecord, toResourceLog } = this.getLogTransforms;\n\n // Currently the scope is fixed to '@grafana/faro-web-sdk'.\n // Once we are able to drive the scope by instrumentation this will change and we need to align this function\n if (this.resourceLogs.length === 0) {\n this.resourceLogs = [toResourceLog(transportItem)];\n } else {\n // Faro takes care of the grouping with different metadata (or OTel attributes), so we can safely\n // use the just the first element of the resource.\n this.resourceLogs[0]?.scopeLogs[0]?.logRecords.push(toLogRecord(transportItem));\n }\n break;\n case TransportItemType.TRACE:\n const { toResourceSpan } = this.getTraceTransforms;\n\n // We use the Otel Model as it is to avoid unnecessary resource consumption.\n // This is because we don't need the same logic to add items as it is for logs.\n // Also the Otel library already applies the respective protocol transforms so there is no need for additional transforms.\n // We only transform the resource object to ensure that we are compliant with the respective Faro Metas which add a few more items to the resource object.\n this.resourceSpans.push(toResourceSpan(transportItem as TransportItem<TraceEvent>));\n\n break;\n default:\n this.internalLogger?.error(`Unknown TransportItemType: ${type}`);\n break;\n }\n } catch (error) {\n this.internalLogger?.error(error);\n }\n }\n}\n"]}
1
+ {"version":3,"file":"OtelPayload.js","sourceRoot":"","sources":["../../../src/payload/OtelPayload.ts"],"names":[],"mappings":";;;AAAA,gDAAkG;AAIlG,yCAAkG;AAUlG;IASE,qBAAY,EAAyE;YAAvE,cAAc,oBAAA,EAAE,mBAAmB,yBAAA,EAAE,aAAa,mBAAA;QAPxD,kBAAa,GAAG,EAAmB,CAAC;QAQ1C,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QAEvB,IAAI,CAAC,gBAAgB,GAAG,IAAA,4BAAgB,EAAC,IAAI,CAAC,cAAc,EAAE,mBAAmB,CAAC,CAAC;QACnF,IAAI,CAAC,kBAAkB,GAAG,IAAA,8BAAkB,EAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAElE,IAAI,aAAa,EAAE;YACjB,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;SACrC;IACH,CAAC;IAED,gCAAU,GAAV;QACE,OAAO;YACL,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,aAAa,EAAE,IAAI,CAAC,aAAa;SACzB,CAAC;IACb,CAAC;IAED,qCAAe,GAAf,UAAgB,aAA4B;;QAClC,IAAA,IAAI,GAAK,aAAa,KAAlB,CAAmB;QAE/B,IAAI;YACF,QAAQ,IAAI,EAAE;gBACZ,KAAK,6BAAiB,CAAC,GAAG,CAAC;gBAC3B,KAAK,6BAAiB,CAAC,SAAS,CAAC;gBACjC,KAAK,6BAAiB,CAAC,KAAK,CAAC;gBAC7B,KAAK,6BAAiB,CAAC,WAAW;oBAC1B,IAAA,KAAiC,IAAI,CAAC,gBAAgB,EAApD,WAAW,iBAAA,EAAE,aAAa,mBAA0B,CAAC;oBAE7D,2DAA2D;oBAC3D,6GAA6G;oBAC7G,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE;wBAClC,IAAI,CAAC,YAAY,GAAG,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC;qBACpD;yBAAM;wBACL,iGAAiG;wBACjG,kDAAkD;wBAClD,MAAA,MAAA,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,0CAAE,SAAS,CAAC,CAAC,CAAC,0CAAE,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC;qBACjF;oBACD,MAAM;gBACR,KAAK,6BAAiB,CAAC,KAAK;oBAClB,IAAA,cAAc,GAAK,IAAI,CAAC,kBAAkB,eAA5B,CAA6B;oBAEnD,4EAA4E;oBAC5E,+EAA+E;oBAC/E,0HAA0H;oBAC1H,0JAA0J;oBAC1J,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,aAA0C,CAAC,CAAC,CAAC;oBAEpF,MAAM;gBACR;oBACE,MAAA,IAAI,CAAC,cAAc,0CAAE,KAAK,CAAC,qCAA8B,IAAI,CAAE,CAAC,CAAC;oBACjE,MAAM;aACT;SACF;QAAC,OAAO,KAAK,EAAE;YACd,MAAA,IAAI,CAAC,cAAc,0CAAE,KAAK,CAAC,KAAK,CAAC,CAAC;SACnC;IACH,CAAC;IACH,kBAAC;AAAD,CAAC,AAnED,IAmEC;AAnEY,kCAAW","sourcesContent":["import { InternalLogger, TraceEvent, TransportItem, TransportItemType } from '@grafana/faro-core';\n\nimport type { OtlpHttpTransportOptions } from '../types';\n\nimport { getLogTransforms, getTraceTransforms, LogsTransform, TraceTransform } from './transform';\nimport type { ResourceLogs, ResourceSpans } from './transform/types';\nimport type { OtelTransportPayload } from './types';\n\ntype OtelPayloadParams = {\n internalLogger: InternalLogger;\n transportItem?: TransportItem;\n customOtlpTransform?: OtlpHttpTransportOptions['otlpTransform'];\n};\n\nexport class OtelPayload {\n private resourceLogs: ResourceLogs;\n private resourceSpans = [] as ResourceSpans;\n\n private getLogTransforms: LogsTransform;\n private getTraceTransforms: TraceTransform;\n\n private internalLogger: InternalLogger;\n\n constructor({ internalLogger, customOtlpTransform, transportItem }: OtelPayloadParams) {\n this.internalLogger = internalLogger;\n this.resourceLogs = [];\n\n this.getLogTransforms = getLogTransforms(this.internalLogger, customOtlpTransform);\n this.getTraceTransforms = getTraceTransforms(this.internalLogger);\n\n if (transportItem) {\n this.addResourceItem(transportItem);\n }\n }\n\n getPayload(): OtelTransportPayload {\n return {\n resourceLogs: this.resourceLogs,\n resourceSpans: this.resourceSpans,\n } as const;\n }\n\n addResourceItem(transportItem: TransportItem): void {\n const { type } = transportItem;\n\n try {\n switch (type) {\n case TransportItemType.LOG:\n case TransportItemType.EXCEPTION:\n case TransportItemType.EVENT:\n case TransportItemType.MEASUREMENT:\n const { toLogRecord, toResourceLog } = this.getLogTransforms;\n\n // Currently the scope is fixed to '@grafana/faro-web-sdk'.\n // Once we are able to drive the scope by instrumentation this will change and we need to align this function\n if (this.resourceLogs.length === 0) {\n this.resourceLogs = [toResourceLog(transportItem)];\n } else {\n // Faro takes care of the grouping with different metadata (or OTel attributes), so we can safely\n // use the just the first element of the resource.\n this.resourceLogs[0]?.scopeLogs[0]?.logRecords.push(toLogRecord(transportItem));\n }\n break;\n case TransportItemType.TRACE:\n const { toResourceSpan } = this.getTraceTransforms;\n\n // We use the Otel Model as it is to avoid unnecessary resource consumption.\n // This is because we don't need the same logic to add items as it is for logs.\n // Also the Otel library already applies the respective protocol transforms so there is no need for additional transforms.\n // We only transform the resource object to ensure that we are compliant with the respective Faro Metas which add a few more items to the resource object.\n this.resourceSpans.push(toResourceSpan(transportItem as TransportItem<TraceEvent>));\n\n break;\n default:\n this.internalLogger?.error(`Unknown TransportItemType: ${type}`);\n break;\n }\n } catch (error) {\n this.internalLogger?.error(error);\n }\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/payload/transform/index.ts"],"names":[],"mappings":";;;AAAA,yCAAmE;AAA1D,6GAAA,gBAAgB,OAAA;AAAE,+GAAA,kBAAkB,OAAA","sourcesContent":["export { getLogTransforms, getTraceTransforms } from './transform';\nexport type {\n LogRecord,\n LogTransportItem,\n ResourceLogs,\n LogsTransform,\n Resource,\n ResourceLog,\n ResourceSpan,\n ResourceSpans,\n Scope,\n ScopeLog,\n TraceTransform,\n} from './types';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/payload/transform/index.ts"],"names":[],"mappings":";;;AAAA,yCAAmE;AAA1D,6GAAA,gBAAgB,OAAA;AAAE,+GAAA,kBAAkB,OAAA","sourcesContent":["export { getLogTransforms, getTraceTransforms } from './transform';\nexport type {\n LogRecord,\n LogTransportItem,\n ResourceLogs,\n LogsTransform,\n Resource,\n ResourceLog,\n ResourceSpan,\n ResourceSpans,\n Scope,\n ScopeLog,\n TraceTransform,\n StringValueNonNullable,\n} from './types';\n"]}
@@ -37,7 +37,7 @@ var SemanticBrowserAttributes = {
37
37
  BROWSER_USER_AGENT: 'browser.user_agent',
38
38
  BROWSER_LANGUAGE: 'browser.language',
39
39
  };
40
- function getLogTransforms(internalLogger) {
40
+ function getLogTransforms(internalLogger, customOtlpTransform) {
41
41
  function toResourceLog(transportItem) {
42
42
  var resource = toResource(transportItem);
43
43
  return {
@@ -114,35 +114,27 @@ function getLogTransforms(internalLogger) {
114
114
  var _a, _b;
115
115
  var meta = transportItem.meta, payload = transportItem.payload;
116
116
  var timeUnixNano = toTimeUnixNano(payload.timestamp);
117
- return {
118
- timeUnixNano: timeUnixNano,
119
- attributes: __spreadArray(__spreadArray([], getCommonLogAttributes(meta), true), [
117
+ var body = getCustomLogBody(transportItem, customOtlpTransform === null || customOtlpTransform === void 0 ? void 0 : customOtlpTransform.createErrorLogBody);
118
+ return __assign(__assign({ timeUnixNano: timeUnixNano }, (body ? { body: body } : {})), { attributes: __spreadArray(__spreadArray([], getCommonLogAttributes(meta), true), [
120
119
  (0, attribute_1.toAttribute)(semantic_conventions_1.SemanticAttributes.EXCEPTION_TYPE, payload.type),
121
120
  (0, attribute_1.toAttribute)(semantic_conventions_1.SemanticAttributes.EXCEPTION_MESSAGE, payload.value),
122
121
  // toAttribute(SemanticAttributes.EXCEPTION_STACKTRACE, undefined),
123
122
  (0, attribute_1.toAttribute)('faro.error.stacktrace', payload.stacktrace),
124
123
  (0, attribute_1.toAttribute)('faro.error.context', payload.context),
125
- ], false).filter(attribute_1.isAttribute),
126
- traceId: (_a = payload.trace) === null || _a === void 0 ? void 0 : _a.trace_id,
127
- spanId: (_b = payload.trace) === null || _b === void 0 ? void 0 : _b.span_id,
128
- };
124
+ ], false).filter(attribute_1.isAttribute), traceId: (_a = payload.trace) === null || _a === void 0 ? void 0 : _a.trace_id, spanId: (_b = payload.trace) === null || _b === void 0 ? void 0 : _b.span_id });
129
125
  }
130
126
  function toMeasurementLogRecord(transportItem) {
131
127
  var _a, _b;
132
128
  var meta = transportItem.meta, payload = transportItem.payload;
133
129
  var timeUnixNano = toTimeUnixNano(payload.timestamp);
134
130
  var _c = Object.entries(payload.values).flat(), measurementName = _c[0], measurementValue = _c[1];
135
- return {
136
- timeUnixNano: timeUnixNano,
137
- attributes: __spreadArray(__spreadArray([], getCommonLogAttributes(meta), true), [
131
+ var body = getCustomLogBody(transportItem, customOtlpTransform === null || customOtlpTransform === void 0 ? void 0 : customOtlpTransform.createMeasurementLogBody);
132
+ return __assign(__assign({ timeUnixNano: timeUnixNano }, (body ? { body: body } : {})), { attributes: __spreadArray(__spreadArray([], getCommonLogAttributes(meta), true), [
138
133
  (0, attribute_1.toAttribute)('measurement.type', payload.type),
139
134
  (0, attribute_1.toAttribute)('measurement.name', measurementName),
140
135
  (0, attribute_1.toAttribute)('measurement.value', measurementValue),
141
136
  (0, attribute_1.toAttribute)('faro.measurement.context', payload.context),
142
- ], false).filter(attribute_1.isAttribute),
143
- traceId: (_a = payload.trace) === null || _a === void 0 ? void 0 : _a.trace_id,
144
- spanId: (_b = payload.trace) === null || _b === void 0 ? void 0 : _b.span_id,
145
- };
137
+ ], false).filter(attribute_1.isAttribute), traceId: (_a = payload.trace) === null || _a === void 0 ? void 0 : _a.trace_id, spanId: (_b = payload.trace) === null || _b === void 0 ? void 0 : _b.span_id });
146
138
  }
147
139
  function getCommonLogAttributes(meta) {
148
140
  var view = meta.view, page = meta.page, session = meta.session, user = meta.user;
@@ -206,4 +198,9 @@ function toResource(transportItem) {
206
198
  ].filter(attribute_1.isAttribute),
207
199
  };
208
200
  }
201
+ function getCustomLogBody(transportItem, createCustomLogBody) {
202
+ return typeof createCustomLogBody === 'function'
203
+ ? (0, attribute_1.toAttributeValue)(createCustomLogBody(transportItem))
204
+ : undefined;
205
+ }
209
206
  //# sourceMappingURL=transform.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"transform.js","sourceRoot":"","sources":["../../../../src/payload/transform/transform.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IKeyValue } from '@opentelemetry/otlp-transformer';\nimport {\n SemanticAttributes,\n SemanticResourceAttributes,\n TelemetrySdkLanguageValues,\n} from '@opentelemetry/semantic-conventions';\n\nimport {\n EventEvent,\n ExceptionEvent,\n LogEvent,\n LogLevel,\n MeasurementEvent,\n Meta,\n TransportItem,\n TransportItemType,\n VERSION,\n} from '@grafana/faro-core';\nimport type { InternalLogger, TraceEvent } from '@grafana/faro-core';\n\nimport { isAttribute, toAttribute, toAttributeValue } from '../attribute';\n\nimport type {\n LogRecord,\n LogsTransform,\n LogTransportItem,\n Resource,\n ResourceLog,\n ResourceMeta,\n ResourceSpan,\n ScopeLog,\n TraceTransform,\n} from './types';\n\n/**\n * Seems currently to be missing in the semantic-conventions npm package.\n * See: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#todos\n *\n * Attributes are as defined by the Otel docs\n */\nconst SemanticBrowserAttributes = {\n BROWSER_BRANDS: 'browser.brands',\n BROWSER_PLATFORM: 'browser.platform',\n BROWSER_MOBILE: 'browser.mobile',\n BROWSER_USER_AGENT: 'browser.user_agent',\n BROWSER_LANGUAGE: 'browser.language',\n} as const;\n\nexport function getLogTransforms(internalLogger: InternalLogger): LogsTransform {\n function toResourceLog(transportItem: LogTransportItem): ResourceLog {\n const resource = toResource(transportItem);\n\n return {\n resource,\n scopeLogs: [toScopeLog(transportItem)],\n };\n }\n\n function toScopeLog(transportItem: LogTransportItem): ScopeLog {\n return {\n scope: {\n name: '@grafana/faro-web-sdk',\n version: VERSION,\n },\n logRecords: [toLogRecord(transportItem)],\n };\n }\n\n function toLogRecord(transportItem: LogTransportItem): LogRecord {\n const { type } = transportItem;\n\n switch (type) {\n case TransportItemType.LOG:\n return toLogLogRecord(transportItem as TransportItem<LogEvent>);\n case TransportItemType.EXCEPTION:\n return toErrorLogRecord(transportItem as TransportItem<ExceptionEvent>);\n case TransportItemType.EVENT:\n return toEventLogRecord(transportItem as TransportItem<EventEvent>);\n case TransportItemType.MEASUREMENT:\n return toMeasurementLogRecord(transportItem as TransportItem<MeasurementEvent>);\n default:\n internalLogger?.error(`Unknown TransportItemType: ${type}`);\n return {};\n }\n }\n\n function toLogLogRecord(transportItem: TransportItem<LogEvent>): LogRecord {\n const { meta, payload } = transportItem;\n const timeUnixNano = toTimeUnixNano(payload.timestamp);\n const body = toAttributeValue(payload.message) as { stringValue: string; key: string };\n\n function getSeverityProperties(logLevel: LogLevel): { severityNumber: number; severityText: string } {\n switch (logLevel) {\n case LogLevel.TRACE:\n return { severityNumber: 1, severityText: 'TRACE' };\n case LogLevel.DEBUG:\n return { severityNumber: 5, severityText: 'DEBUG' };\n case LogLevel.INFO:\n return { severityNumber: 9, severityText: 'INFO' };\n case LogLevel.LOG:\n return { severityNumber: 10, severityText: 'INFO2' };\n case LogLevel.WARN:\n return { severityNumber: 13, severityText: 'WARN' };\n case LogLevel.ERROR:\n return { severityNumber: 17, severityText: 'ERROR' };\n }\n }\n\n return {\n timeUnixNano,\n ...getSeverityProperties(payload.level),\n body,\n attributes: [...getCommonLogAttributes(meta), toAttribute('faro.log.context', payload.context)].filter(\n isAttribute\n ),\n traceId: payload.trace?.trace_id,\n spanId: payload.trace?.span_id,\n } as const;\n }\n\n function toEventLogRecord(transportItem: TransportItem<EventEvent>): LogRecord {\n const { meta, payload } = transportItem;\n const timeUnixNano = toTimeUnixNano(payload.timestamp);\n const body = toAttributeValue(payload.name) as { stringValue: string; key: string };\n\n return {\n timeUnixNano,\n body,\n attributes: [\n ...getCommonLogAttributes(meta),\n toAttribute('event.name', payload.name), // This is a semantic attribute. But event.name constant is currently missing in sematic-conventions npm package\n toAttribute('event.domain', payload.domain), // This is a semantic attribute. But event.domain constant is currently missing in sematic-conventions npm package\n toAttribute('event.attributes', payload.attributes),\n ].filter(isAttribute),\n traceId: payload.trace?.trace_id,\n spanId: payload.trace?.span_id,\n } as const;\n }\n\n function toErrorLogRecord(transportItem: TransportItem<ExceptionEvent>): LogRecord {\n const { meta, payload } = transportItem;\n const timeUnixNano = toTimeUnixNano(payload.timestamp);\n\n return {\n timeUnixNano,\n attributes: [\n ...getCommonLogAttributes(meta),\n toAttribute(SemanticAttributes.EXCEPTION_TYPE, payload.type),\n toAttribute(SemanticAttributes.EXCEPTION_MESSAGE, payload.value),\n // toAttribute(SemanticAttributes.EXCEPTION_STACKTRACE, undefined),\n toAttribute('faro.error.stacktrace', payload.stacktrace),\n toAttribute('faro.error.context', payload.context),\n ].filter(isAttribute),\n traceId: payload.trace?.trace_id,\n spanId: payload.trace?.span_id,\n } as const;\n }\n\n function toMeasurementLogRecord(transportItem: TransportItem<MeasurementEvent>): LogRecord {\n const { meta, payload } = transportItem;\n const timeUnixNano = toTimeUnixNano(payload.timestamp);\n const [measurementName, measurementValue] = Object.entries(payload.values).flat();\n\n return {\n timeUnixNano,\n attributes: [\n ...getCommonLogAttributes(meta),\n toAttribute('measurement.type', payload.type),\n toAttribute('measurement.name', measurementName),\n toAttribute('measurement.value', measurementValue),\n toAttribute('faro.measurement.context', payload.context),\n ].filter(isAttribute),\n traceId: payload.trace?.trace_id,\n spanId: payload.trace?.span_id,\n } as const;\n }\n\n function getCommonLogAttributes(meta: Meta): IKeyValue[] {\n const { view, page, session, user } = meta;\n\n return [\n toAttribute('view.name', view?.name),\n toAttribute(SemanticAttributes.HTTP_URL, page?.url),\n toAttribute('page.id', page?.id),\n toAttribute('page.attributes', page?.attributes),\n toAttribute('session.id', session?.id),\n toAttribute('session.attributes', session?.attributes),\n toAttribute(SemanticAttributes.ENDUSER_ID, user?.id),\n toAttribute('enduser.name', user?.username),\n toAttribute('enduser.email', user?.email),\n toAttribute('enduser.attributes', user?.attributes),\n ].filter(isAttribute);\n }\n\n function toTimeUnixNano(timestamp: string): number {\n return Date.parse(timestamp) * 1e6;\n }\n\n return {\n toResourceLog,\n toScopeLog,\n toLogRecord,\n };\n}\n\nexport function getTraceTransforms(_internalLogger?: InternalLogger): TraceTransform {\n function toResourceSpan(transportItem: TransportItem<TraceEvent>): ResourceSpan {\n const resource = toResource(transportItem);\n const scopeSpans = transportItem.payload.resourceSpans?.[0]?.scopeSpans;\n\n return {\n resource,\n scopeSpans: scopeSpans ?? [],\n };\n }\n\n return {\n toResourceSpan,\n };\n}\n\nfunction toResource(transportItem: TransportItem): Readonly<Resource> {\n const { browser, sdk, app }: ResourceMeta = transportItem.meta;\n\n return {\n attributes: [\n toAttribute(SemanticBrowserAttributes.BROWSER_MOBILE, browser?.mobile),\n toAttribute(SemanticBrowserAttributes.BROWSER_USER_AGENT, browser?.userAgent),\n toAttribute(SemanticBrowserAttributes.BROWSER_LANGUAGE, browser?.language),\n toAttribute(SemanticBrowserAttributes.BROWSER_BRANDS, browser?.brands),\n toAttribute('browser.os', browser?.os),\n toAttribute('browser.name', browser?.name),\n toAttribute('browser.version', browser?.version),\n\n toAttribute(SemanticResourceAttributes.TELEMETRY_SDK_NAME, sdk?.name),\n toAttribute(SemanticResourceAttributes.TELEMETRY_SDK_VERSION, sdk?.version),\n Boolean(sdk)\n ? toAttribute(SemanticResourceAttributes.TELEMETRY_SDK_LANGUAGE, TelemetrySdkLanguageValues.WEBJS)\n : undefined,\n\n toAttribute(SemanticResourceAttributes.SERVICE_NAME, app?.name),\n toAttribute(SemanticResourceAttributes.SERVICE_VERSION, app?.version),\n toAttribute(SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT, app?.environment),\n ].filter(isAttribute),\n };\n}\n"]}
1
+ {"version":3,"file":"transform.js","sourceRoot":"","sources":["../../../../src/payload/transform/transform.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IKeyValue } from '@opentelemetry/otlp-transformer';\nimport {\n SemanticAttributes,\n SemanticResourceAttributes,\n TelemetrySdkLanguageValues,\n} from '@opentelemetry/semantic-conventions';\n\nimport {\n EventEvent,\n ExceptionEvent,\n LogEvent,\n LogLevel,\n MeasurementEvent,\n Meta,\n TransportItem,\n TransportItemType,\n VERSION,\n} from '@grafana/faro-core';\nimport type { InternalLogger, TraceEvent } from '@grafana/faro-core';\n\nimport type { OtlpHttpTransportOptions } from '../../types';\nimport { isAttribute, toAttribute, toAttributeValue } from '../attribute';\n\nimport type {\n LogRecord,\n LogsTransform,\n LogTransportItem,\n Resource,\n ResourceLog,\n ResourceMeta,\n ResourceSpan,\n ScopeLog,\n StringValueNonNullable,\n TraceTransform,\n} from './types';\n\n/**\n * Seems currently to be missing in the semantic-conventions npm package.\n * See: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#todos\n *\n * Attributes are as defined by the Otel docs\n */\nconst SemanticBrowserAttributes = {\n BROWSER_BRANDS: 'browser.brands',\n BROWSER_PLATFORM: 'browser.platform',\n BROWSER_MOBILE: 'browser.mobile',\n BROWSER_USER_AGENT: 'browser.user_agent',\n BROWSER_LANGUAGE: 'browser.language',\n} as const;\n\nexport function getLogTransforms(\n internalLogger: InternalLogger,\n customOtlpTransform?: OtlpHttpTransportOptions['otlpTransform']\n): LogsTransform {\n function toResourceLog(transportItem: LogTransportItem): ResourceLog {\n const resource = toResource(transportItem);\n\n return {\n resource,\n scopeLogs: [toScopeLog(transportItem)],\n };\n }\n\n function toScopeLog(transportItem: LogTransportItem): ScopeLog {\n return {\n scope: {\n name: '@grafana/faro-web-sdk',\n version: VERSION,\n },\n logRecords: [toLogRecord(transportItem)],\n };\n }\n\n function toLogRecord(transportItem: LogTransportItem): LogRecord {\n const { type } = transportItem;\n\n switch (type) {\n case TransportItemType.LOG:\n return toLogLogRecord(transportItem as TransportItem<LogEvent>);\n case TransportItemType.EXCEPTION:\n return toErrorLogRecord(transportItem as TransportItem<ExceptionEvent>);\n case TransportItemType.EVENT:\n return toEventLogRecord(transportItem as TransportItem<EventEvent>);\n case TransportItemType.MEASUREMENT:\n return toMeasurementLogRecord(transportItem as TransportItem<MeasurementEvent>);\n default:\n internalLogger?.error(`Unknown TransportItemType: ${type}`);\n return {};\n }\n }\n\n function toLogLogRecord(transportItem: TransportItem<LogEvent>): LogRecord {\n const { meta, payload } = transportItem;\n const timeUnixNano = toTimeUnixNano(payload.timestamp);\n const body = toAttributeValue(payload.message) as StringValueNonNullable;\n\n function getSeverityProperties(logLevel: LogLevel) {\n switch (logLevel) {\n case LogLevel.TRACE:\n return { severityNumber: 1, severityText: 'TRACE' };\n case LogLevel.DEBUG:\n return { severityNumber: 5, severityText: 'DEBUG' };\n case LogLevel.INFO:\n return { severityNumber: 9, severityText: 'INFO' };\n case LogLevel.LOG:\n return { severityNumber: 10, severityText: 'INFO2' };\n case LogLevel.WARN:\n return { severityNumber: 13, severityText: 'WARN' };\n case LogLevel.ERROR:\n return { severityNumber: 17, severityText: 'ERROR' };\n }\n }\n\n return {\n timeUnixNano,\n ...getSeverityProperties(payload.level),\n body,\n attributes: [...getCommonLogAttributes(meta), toAttribute('faro.log.context', payload.context)].filter(\n isAttribute\n ),\n traceId: payload.trace?.trace_id,\n spanId: payload.trace?.span_id,\n } as const;\n }\n\n function toEventLogRecord(transportItem: TransportItem<EventEvent>): LogRecord {\n const { meta, payload } = transportItem;\n const timeUnixNano = toTimeUnixNano(payload.timestamp);\n const body = toAttributeValue(payload.name) as StringValueNonNullable;\n\n return {\n timeUnixNano,\n body,\n attributes: [\n ...getCommonLogAttributes(meta),\n toAttribute('event.name', payload.name), // This is a semantic attribute. But event.name constant is currently missing in sematic-conventions npm package\n toAttribute('event.domain', payload.domain), // This is a semantic attribute. But event.domain constant is currently missing in sematic-conventions npm package\n toAttribute('event.attributes', payload.attributes),\n ].filter(isAttribute),\n traceId: payload.trace?.trace_id,\n spanId: payload.trace?.span_id,\n } as const;\n }\n\n function toErrorLogRecord(transportItem: TransportItem<ExceptionEvent>): LogRecord {\n const { meta, payload } = transportItem;\n const timeUnixNano = toTimeUnixNano(payload.timestamp);\n const body = getCustomLogBody(transportItem, customOtlpTransform?.createErrorLogBody);\n\n return {\n timeUnixNano,\n ...(body ? { body } : {}),\n attributes: [\n ...getCommonLogAttributes(meta),\n toAttribute(SemanticAttributes.EXCEPTION_TYPE, payload.type),\n toAttribute(SemanticAttributes.EXCEPTION_MESSAGE, payload.value),\n // toAttribute(SemanticAttributes.EXCEPTION_STACKTRACE, undefined),\n toAttribute('faro.error.stacktrace', payload.stacktrace),\n toAttribute('faro.error.context', payload.context),\n ].filter(isAttribute),\n traceId: payload.trace?.trace_id,\n spanId: payload.trace?.span_id,\n } as const;\n }\n\n function toMeasurementLogRecord(transportItem: TransportItem<MeasurementEvent>): LogRecord {\n const { meta, payload } = transportItem;\n const timeUnixNano = toTimeUnixNano(payload.timestamp);\n const [measurementName, measurementValue] = Object.entries(payload.values).flat();\n\n const body = getCustomLogBody(transportItem, customOtlpTransform?.createMeasurementLogBody);\n\n return {\n timeUnixNano,\n ...(body ? { body } : {}),\n attributes: [\n ...getCommonLogAttributes(meta),\n toAttribute('measurement.type', payload.type),\n toAttribute('measurement.name', measurementName),\n toAttribute('measurement.value', measurementValue),\n toAttribute('faro.measurement.context', payload.context),\n ].filter(isAttribute),\n traceId: payload.trace?.trace_id,\n spanId: payload.trace?.span_id,\n } as const;\n }\n\n function getCommonLogAttributes(meta: Meta): IKeyValue[] {\n const { view, page, session, user } = meta;\n\n return [\n toAttribute('view.name', view?.name),\n toAttribute(SemanticAttributes.HTTP_URL, page?.url),\n toAttribute('page.id', page?.id),\n toAttribute('page.attributes', page?.attributes),\n toAttribute('session.id', session?.id),\n toAttribute('session.attributes', session?.attributes),\n toAttribute(SemanticAttributes.ENDUSER_ID, user?.id),\n toAttribute('enduser.name', user?.username),\n toAttribute('enduser.email', user?.email),\n toAttribute('enduser.attributes', user?.attributes),\n ].filter(isAttribute);\n }\n\n function toTimeUnixNano(timestamp: string): number {\n return Date.parse(timestamp) * 1e6;\n }\n\n return {\n toResourceLog,\n toScopeLog,\n toLogRecord,\n };\n}\n\nexport function getTraceTransforms(_internalLogger?: InternalLogger): TraceTransform {\n function toResourceSpan(transportItem: TransportItem<TraceEvent>): ResourceSpan {\n const resource = toResource(transportItem);\n const scopeSpans = transportItem.payload.resourceSpans?.[0]?.scopeSpans;\n\n return {\n resource,\n scopeSpans: scopeSpans ?? [],\n };\n }\n\n return {\n toResourceSpan,\n };\n}\n\nfunction toResource(transportItem: TransportItem): Readonly<Resource> {\n const { browser, sdk, app }: ResourceMeta = transportItem.meta;\n\n return {\n attributes: [\n toAttribute(SemanticBrowserAttributes.BROWSER_MOBILE, browser?.mobile),\n toAttribute(SemanticBrowserAttributes.BROWSER_USER_AGENT, browser?.userAgent),\n toAttribute(SemanticBrowserAttributes.BROWSER_LANGUAGE, browser?.language),\n toAttribute(SemanticBrowserAttributes.BROWSER_BRANDS, browser?.brands),\n toAttribute('browser.os', browser?.os),\n toAttribute('browser.name', browser?.name),\n toAttribute('browser.version', browser?.version),\n\n toAttribute(SemanticResourceAttributes.TELEMETRY_SDK_NAME, sdk?.name),\n toAttribute(SemanticResourceAttributes.TELEMETRY_SDK_VERSION, sdk?.version),\n Boolean(sdk)\n ? toAttribute(SemanticResourceAttributes.TELEMETRY_SDK_LANGUAGE, TelemetrySdkLanguageValues.WEBJS)\n : undefined,\n\n toAttribute(SemanticResourceAttributes.SERVICE_NAME, app?.name),\n toAttribute(SemanticResourceAttributes.SERVICE_VERSION, app?.version),\n toAttribute(SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT, app?.environment),\n ].filter(isAttribute),\n };\n}\n\nfunction getCustomLogBody<T>(\n transportItem: T,\n createCustomLogBody?: (item: T) => string\n): StringValueNonNullable | undefined {\n return typeof createCustomLogBody === 'function'\n ? (toAttributeValue(createCustomLogBody(transportItem)) as StringValueNonNullable)\n : undefined;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/payload/transform/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { IKeyValue, IResource, IResourceSpans } from '@opentelemetry/otlp-transformer';\n\nimport type { APIEvent, Meta, TraceEvent, TransportItem } from '@grafana/faro-core';\n\nexport interface Resource extends Partial<Pick<IResource, 'droppedAttributesCount'>> {\n attributes: IKeyValue[];\n}\n\nexport interface LogRecord {\n timeUnixNano?: number;\n severityNumber?: number;\n severityText?: string;\n body?: { stringValue: string };\n attributes?: IKeyValue[];\n traceId?: string;\n spanId?: string;\n}\n\nexport type Scope = {\n name: string;\n version: string;\n};\n\nexport interface ScopeLog {\n scope: Scope;\n logRecords: LogRecord[];\n}\n\nexport interface ScopeSpan {\n scope: Scope;\n logRecords: LogRecord[];\n}\n\nexport interface ResourceLog {\n resource: Resource;\n scopeLogs: ScopeLog[];\n}\n\nexport type ResourceLogs = ResourceLog[];\n\nexport interface ResourceSpan extends Omit<IResourceSpans, 'resource'> {\n resource: Resource;\n}\n\nexport type ResourceSpans = ResourceSpan[];\n\nexport type LogTransportItem = TransportItem<Exclude<APIEvent, 'TraceEvent'>>;\nexport type TraceTransportItem = TransportItem<TraceEvent>;\n\nexport type LogsTransform = {\n toResourceLog: (transportItem: LogTransportItem) => ResourceLog;\n toScopeLog: (transportItem: LogTransportItem) => ScopeLog;\n toLogRecord: (transportItem: LogTransportItem) => LogRecord;\n};\n\nexport type TraceTransform = {\n toResourceSpan: (transportItem: TransportItem<TraceEvent>) => ResourceSpan;\n};\n\nexport type ResourceMeta = Pick<Meta, 'app' | 'browser' | 'sdk'>;\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/payload/transform/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { IKeyValue, IResource, IResourceSpans } from '@opentelemetry/otlp-transformer';\n\nimport type { APIEvent, Meta, TraceEvent, TransportItem } from '@grafana/faro-core';\n\nexport interface Resource extends Partial<Pick<IResource, 'droppedAttributesCount'>> {\n attributes: IKeyValue[];\n}\n\nexport interface LogRecord {\n timeUnixNano?: number;\n severityNumber?: number;\n severityText?: string;\n body?: { stringValue: string };\n attributes?: IKeyValue[];\n traceId?: string;\n spanId?: string;\n}\n\nexport type Scope = {\n name: string;\n version: string;\n};\n\nexport interface ScopeLog {\n scope: Scope;\n logRecords: LogRecord[];\n}\n\nexport interface ScopeSpan {\n scope: Scope;\n logRecords: LogRecord[];\n}\n\nexport interface ResourceLog {\n resource: Resource;\n scopeLogs: ScopeLog[];\n}\n\nexport type ResourceLogs = ResourceLog[];\n\nexport interface ResourceSpan extends Omit<IResourceSpans, 'resource'> {\n resource: Resource;\n}\n\nexport type ResourceSpans = ResourceSpan[];\n\nexport type LogTransportItem = TransportItem<Exclude<APIEvent, 'TraceEvent'>>;\nexport type TraceTransportItem = TransportItem<TraceEvent>;\n\nexport type LogsTransform = {\n toResourceLog: (transportItem: LogTransportItem) => ResourceLog;\n toScopeLog: (transportItem: LogTransportItem) => ScopeLog;\n toLogRecord: (transportItem: LogTransportItem) => LogRecord;\n};\n\nexport type TraceTransform = {\n toResourceSpan: (transportItem: TransportItem<TraceEvent>) => ResourceSpan;\n};\n\nexport type ResourceMeta = Pick<Meta, 'app' | 'browser' | 'sdk'>;\n\nexport type StringValueNonNullable = { stringValue: string };\n"]}
@@ -43,6 +43,8 @@ var payload_1 = require("./payload");
43
43
  var DEFAULT_BUFFER_SIZE = 30;
44
44
  var DEFAULT_CONCURRENCY = 5; // chrome supports 10 total, firefox 17
45
45
  var DEFAULT_RATE_LIMIT_BACKOFF_MS = 5000;
46
+ var BEACON_BODY_SIZE_LIMIT = 60000;
47
+ var TOO_MANY_REQUESTS = 429;
46
48
  var OtlpHttpTransport = /** @class */ (function (_super) {
47
49
  __extends(OtlpHttpTransport, _super);
48
50
  function OtlpHttpTransport(options) {
@@ -69,7 +71,10 @@ var OtlpHttpTransport = /** @class */ (function (_super) {
69
71
  return true;
70
72
  };
71
73
  OtlpHttpTransport.prototype.send = function (items) {
72
- var otelPayload = new payload_1.OtelPayload(this.internalLogger);
74
+ var otelPayload = new payload_1.OtelPayload({
75
+ internalLogger: this.internalLogger,
76
+ customOtlpTransform: this.options.otlpTransform,
77
+ });
73
78
  items.forEach(function (item) { return otelPayload.addResourceItem(item); });
74
79
  this.sendPayload(otelPayload.getPayload());
75
80
  };
@@ -109,9 +114,9 @@ var OtlpHttpTransport = /** @class */ (function (_super) {
109
114
  var _g = this_1.options, requestOptions = _g.requestOptions, apiKey = _g.apiKey;
110
115
  var _h = requestOptions !== null && requestOptions !== void 0 ? requestOptions : {}, headers = _h.headers, restOfRequestOptions = __rest(_h, ["headers"]);
111
116
  this_1.promiseBuffer.add(function () {
112
- return fetch(url, __assign({ method: 'POST', headers: __assign(__assign({ 'Content-Type': 'application/json' }, (headers !== null && headers !== void 0 ? headers : {})), (apiKey ? { 'x-api-key': apiKey } : {})), body: body, keepalive: true }, (restOfRequestOptions !== null && restOfRequestOptions !== void 0 ? restOfRequestOptions : {})))
117
+ return fetch(url, __assign({ method: 'POST', headers: __assign(__assign({ 'Content-Type': 'application/json' }, (headers !== null && headers !== void 0 ? headers : {})), (apiKey ? { 'x-api-key': apiKey } : {})), body: body, keepalive: body.length <= BEACON_BODY_SIZE_LIMIT }, (restOfRequestOptions !== null && restOfRequestOptions !== void 0 ? restOfRequestOptions : {})))
113
118
  .then(function (response) {
114
- if (response.status === 429) {
119
+ if (response.status === TOO_MANY_REQUESTS) {
115
120
  updateDisabledUntil(_this.getRetryAfterDate(response));
116
121
  _this.logWarn("Too many requests, backing off until ".concat(disabledUntil));
117
122
  }
@@ -1 +1 @@
1
- {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/transport.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseTransport, createPromiseBuffer, isArray, PromiseBuffer, TransportItem, VERSION } from '@grafana/faro-core';\n\nimport { OtelPayload, OtelTransportPayload } from './payload';\nimport type { OtlpHttpTransportOptions } from './types';\n\nconst DEFAULT_BUFFER_SIZE = 30;\nconst DEFAULT_CONCURRENCY = 5; // chrome supports 10 total, firefox 17\nconst DEFAULT_RATE_LIMIT_BACKOFF_MS = 5000;\n\nexport class OtlpHttpTransport extends BaseTransport {\n readonly name = '@grafana/faro-web-sdk:transport-otlp-http';\n readonly version = VERSION;\n\n private readonly promiseBuffer: PromiseBuffer<Response | void>;\n private readonly rateLimitBackoffMs: number;\n\n private sendingTracesDisabledUntil: Date = new Date();\n private sendingLogsDisabledUntil: Date = new Date();\n\n constructor(private options: OtlpHttpTransportOptions) {\n super();\n this.rateLimitBackoffMs = options.defaultRateLimitBackoffMs ?? DEFAULT_RATE_LIMIT_BACKOFF_MS;\n\n this.promiseBuffer = createPromiseBuffer({\n size: options?.bufferSize ?? DEFAULT_BUFFER_SIZE,\n concurrency: options?.concurrency ?? DEFAULT_CONCURRENCY,\n });\n }\n\n override getIgnoreUrls(): Array<string | RegExp> {\n const { tracesURL = '', logsURL = '' } = this.options;\n return [tracesURL, logsURL].filter(Boolean);\n }\n\n override isBatched(): boolean {\n return true;\n }\n\n send(items: TransportItem[]): void {\n const otelPayload = new OtelPayload(this.internalLogger);\n\n items.forEach((item) => otelPayload.addResourceItem(item));\n this.sendPayload(otelPayload.getPayload());\n }\n\n private sendPayload(payload: OtelTransportPayload): void {\n try {\n const { tracesURL = '', logsURL = '' } = this.options;\n\n for (const [key, value] of Object.entries(payload)) {\n if (!(isArray(value) && value.length > 0)) {\n continue;\n }\n\n let disabledUntil: Date | undefined;\n let updateDisabledUntil = (_: Date) => {};\n let url = '';\n\n switch (key) {\n case 'resourceSpans':\n url = tracesURL;\n disabledUntil = this.sendingTracesDisabledUntil;\n updateDisabledUntil = (retryAfterDate: Date) => {\n this.sendingTracesDisabledUntil = retryAfterDate;\n };\n break;\n case 'resourceLogs':\n url = logsURL;\n disabledUntil = this.sendingLogsDisabledUntil;\n updateDisabledUntil = (retryAfterDate: Date) => {\n this.sendingLogsDisabledUntil = retryAfterDate;\n };\n break;\n }\n\n if (disabledUntil && disabledUntil > new Date(Date.now())) {\n this.logWarn(`Dropping transport item due to too many requests. Backoff until ${disabledUntil}`);\n return undefined;\n }\n\n const body = JSON.stringify({ [key]: value });\n\n const { requestOptions, apiKey } = this.options;\n const { headers, ...restOfRequestOptions } = requestOptions ?? {};\n\n this.promiseBuffer.add(() => {\n return fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(headers ?? {}),\n ...(apiKey ? { 'x-api-key': apiKey } : {}),\n },\n body,\n keepalive: true,\n ...(restOfRequestOptions ?? {}),\n })\n .then((response) => {\n if (response.status === 429) {\n updateDisabledUntil(this.getRetryAfterDate(response));\n this.logWarn(`Too many requests, backing off until ${disabledUntil}`);\n }\n\n return response;\n })\n .catch((error) => {\n this.logError('Failed sending payload to the receiver\\n', JSON.parse(body), error);\n });\n });\n }\n } catch (error) {\n this.logError(error);\n }\n }\n\n private getRetryAfterDate(response: Response): Date {\n const now = Date.now();\n const retryAfterHeader = response.headers.get('Retry-After');\n\n if (retryAfterHeader) {\n const delay = Number(retryAfterHeader);\n\n if (!isNaN(delay)) {\n return new Date(delay * 1000 + now);\n }\n\n const date = Date.parse(retryAfterHeader);\n\n if (!isNaN(date)) {\n return new Date(date);\n }\n }\n\n return new Date(now + this.rateLimitBackoffMs);\n }\n}\n"]}
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/transport.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseTransport, createPromiseBuffer, isArray, PromiseBuffer, TransportItem, VERSION } from '@grafana/faro-core';\n\nimport { OtelPayload, OtelTransportPayload } from './payload';\nimport type { OtlpHttpTransportOptions } from './types';\n\nconst DEFAULT_BUFFER_SIZE = 30;\nconst DEFAULT_CONCURRENCY = 5; // chrome supports 10 total, firefox 17\nconst DEFAULT_RATE_LIMIT_BACKOFF_MS = 5000;\n\nconst BEACON_BODY_SIZE_LIMIT = 60000;\nconst TOO_MANY_REQUESTS = 429;\n\nexport class OtlpHttpTransport extends BaseTransport {\n readonly name = '@grafana/faro-web-sdk:transport-otlp-http';\n readonly version = VERSION;\n\n private readonly promiseBuffer: PromiseBuffer<Response | void>;\n private readonly rateLimitBackoffMs: number;\n\n private sendingTracesDisabledUntil: Date = new Date();\n private sendingLogsDisabledUntil: Date = new Date();\n\n constructor(private options: OtlpHttpTransportOptions) {\n super();\n this.rateLimitBackoffMs = options.defaultRateLimitBackoffMs ?? DEFAULT_RATE_LIMIT_BACKOFF_MS;\n\n this.promiseBuffer = createPromiseBuffer({\n size: options?.bufferSize ?? DEFAULT_BUFFER_SIZE,\n concurrency: options?.concurrency ?? DEFAULT_CONCURRENCY,\n });\n }\n\n override getIgnoreUrls(): Array<string | RegExp> {\n const { tracesURL = '', logsURL = '' } = this.options;\n return [tracesURL, logsURL].filter(Boolean);\n }\n\n override isBatched(): boolean {\n return true;\n }\n\n send(items: TransportItem[]): void {\n const otelPayload = new OtelPayload({\n internalLogger: this.internalLogger,\n customOtlpTransform: this.options.otlpTransform,\n });\n\n items.forEach((item) => otelPayload.addResourceItem(item));\n this.sendPayload(otelPayload.getPayload());\n }\n\n private sendPayload(payload: OtelTransportPayload): void {\n try {\n const { tracesURL = '', logsURL = '' } = this.options;\n\n for (const [key, value] of Object.entries(payload)) {\n if (!(isArray(value) && value.length > 0)) {\n continue;\n }\n\n let disabledUntil: Date | undefined;\n let updateDisabledUntil = (_: Date) => {};\n let url = '';\n\n switch (key) {\n case 'resourceSpans':\n url = tracesURL;\n disabledUntil = this.sendingTracesDisabledUntil;\n updateDisabledUntil = (retryAfterDate: Date) => {\n this.sendingTracesDisabledUntil = retryAfterDate;\n };\n break;\n case 'resourceLogs':\n url = logsURL;\n disabledUntil = this.sendingLogsDisabledUntil;\n updateDisabledUntil = (retryAfterDate: Date) => {\n this.sendingLogsDisabledUntil = retryAfterDate;\n };\n break;\n }\n\n if (disabledUntil && disabledUntil > new Date(Date.now())) {\n this.logWarn(`Dropping transport item due to too many requests. Backoff until ${disabledUntil}`);\n return undefined;\n }\n\n const body = JSON.stringify({ [key]: value });\n\n const { requestOptions, apiKey } = this.options;\n const { headers, ...restOfRequestOptions } = requestOptions ?? {};\n\n this.promiseBuffer.add(() => {\n return fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(headers ?? {}),\n ...(apiKey ? { 'x-api-key': apiKey } : {}),\n },\n body,\n keepalive: body.length <= BEACON_BODY_SIZE_LIMIT,\n ...(restOfRequestOptions ?? {}),\n })\n .then((response) => {\n if (response.status === TOO_MANY_REQUESTS) {\n updateDisabledUntil(this.getRetryAfterDate(response));\n this.logWarn(`Too many requests, backing off until ${disabledUntil}`);\n }\n\n return response;\n })\n .catch((error) => {\n this.logError('Failed sending payload to the receiver\\n', JSON.parse(body), error);\n });\n });\n }\n } catch (error) {\n this.logError(error);\n }\n }\n\n private getRetryAfterDate(response: Response): Date {\n const now = Date.now();\n const retryAfterHeader = response.headers.get('Retry-After');\n\n if (retryAfterHeader) {\n const delay = Number(retryAfterHeader);\n\n if (!isNaN(delay)) {\n return new Date(delay * 1000 + now);\n }\n\n const date = Date.parse(retryAfterHeader);\n\n if (!isNaN(date)) {\n return new Date(date);\n }\n }\n\n return new Date(now + this.rateLimitBackoffMs);\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"","sourcesContent":["export interface OtlpTransportRequestOptions extends Omit<RequestInit, 'body' | 'headers'> {\n headers?: Record<string, string>;\n}\n\nexport interface OtlpHttpTransportOptions {\n // will be added as `x-api-key` header\n apiKey?: string;\n\n // how many requests to buffer in total\n bufferSize?: number;\n\n // how many requests to execute concurrently\n concurrency?: number;\n\n // if rate limit response does not include a Retry-After header,\n // how many milliseconds to back off before attempting a request.\n // intermediate events will be dropped, not buffered\n defaultRateLimitBackoffMs?: number;\n\n // addition options for global.Fetch\n requestOptions?: OtlpTransportRequestOptions;\n\n // The Otel spec defines separate endpoints per signal\n readonly tracesURL?: string;\n readonly logsURL?: string;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ExceptionEvent, MeasurementEvent, TransportItem } from '@grafana/faro-core';\n\nexport interface OtlpTransportRequestOptions extends Omit<RequestInit, 'body' | 'headers'> {\n headers?: Record<string, string>;\n}\n\nexport interface OtlpHttpTransportOptions {\n // will be added as `x-api-key` header\n apiKey?: string;\n\n // how many requests to buffer in total\n bufferSize?: number;\n\n // how many requests to execute concurrently\n concurrency?: number;\n\n // if rate limit response does not include a Retry-After header,\n // how many milliseconds to back off before attempting a request.\n // intermediate events will be dropped, not buffered\n defaultRateLimitBackoffMs?: number;\n\n // addition options for global.Fetch\n requestOptions?: OtlpTransportRequestOptions;\n\n // The Otel spec defines separate endpoints per signal\n readonly tracesURL?: string;\n readonly logsURL?: string;\n\n // customize aspects about logs transformation\n otlpTransform?: {\n // Body field is optional in Otel Log spec, but can cause issues with Otel Collector components.\n // By default Faro does not send a body for logs of type error and measurement.\n // Users can define a body string by using the following functions.\n createErrorLogBody?: (item: TransportItem<ExceptionEvent>) => string;\n createMeasurementLogBody?: (item: TransportItem<MeasurementEvent>) => string;\n };\n}\n"]}
@@ -1,12 +1,11 @@
1
1
  import { TransportItemType } from '@grafana/faro-core';
2
2
  import { getLogTransforms, getTraceTransforms } from './transform';
3
3
  export class OtelPayload {
4
- constructor(internalLogger, transportItem) {
5
- this.internalLogger = internalLogger;
4
+ constructor({ internalLogger, customOtlpTransform, transportItem }) {
6
5
  this.resourceSpans = [];
7
6
  this.internalLogger = internalLogger;
8
7
  this.resourceLogs = [];
9
- this.getLogTransforms = getLogTransforms(this.internalLogger);
8
+ this.getLogTransforms = getLogTransforms(this.internalLogger, customOtlpTransform);
10
9
  this.getTraceTransforms = getTraceTransforms(this.internalLogger);
11
10
  if (transportItem) {
12
11
  this.addResourceItem(transportItem);
@@ -1 +1 @@
1
- {"version":3,"file":"OtelPayload.js","sourceRoot":"","sources":["../../../src/payload/OtelPayload.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6C,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAElG,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAiC,MAAM,aAAa,CAAC;AAIlG,MAAM,OAAO,WAAW;IAOtB,YACU,cAA8B,EACtC,aAA6B;QADrB,mBAAc,GAAd,cAAc,CAAgB;QANhC,kBAAa,GAAG,EAAmB,CAAC;QAS1C,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QAEvB,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC9D,IAAI,CAAC,kBAAkB,GAAG,kBAAkB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAElE,IAAI,aAAa,EAAE;YACjB,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;SACrC;IACH,CAAC;IAED,UAAU;QACR,OAAO;YACL,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,aAAa,EAAE,IAAI,CAAC,aAAa;SACzB,CAAC;IACb,CAAC;IAED,eAAe,CAAC,aAA4B;;QAC1C,MAAM,EAAE,IAAI,EAAE,GAAG,aAAa,CAAC;QAE/B,IAAI;YACF,QAAQ,IAAI,EAAE;gBACZ,KAAK,iBAAiB,CAAC,GAAG,CAAC;gBAC3B,KAAK,iBAAiB,CAAC,SAAS,CAAC;gBACjC,KAAK,iBAAiB,CAAC,KAAK,CAAC;gBAC7B,KAAK,iBAAiB,CAAC,WAAW;oBAChC,MAAM,EAAE,WAAW,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC;oBAE7D,2DAA2D;oBAC3D,6GAA6G;oBAC7G,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE;wBAClC,IAAI,CAAC,YAAY,GAAG,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC;qBACpD;yBAAM;wBACL,iGAAiG;wBACjG,kDAAkD;wBAClD,MAAA,MAAA,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,0CAAE,SAAS,CAAC,CAAC,CAAC,0CAAE,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC;qBACjF;oBACD,MAAM;gBACR,KAAK,iBAAiB,CAAC,KAAK;oBAC1B,MAAM,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC,kBAAkB,CAAC;oBAEnD,4EAA4E;oBAC5E,+EAA+E;oBAC/E,0HAA0H;oBAC1H,0JAA0J;oBAC1J,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,aAA0C,CAAC,CAAC,CAAC;oBAEpF,MAAM;gBACR;oBACE,MAAA,IAAI,CAAC,cAAc,0CAAE,KAAK,CAAC,8BAA8B,IAAI,EAAE,CAAC,CAAC;oBACjE,MAAM;aACT;SACF;QAAC,OAAO,KAAK,EAAE;YACd,MAAA,IAAI,CAAC,cAAc,0CAAE,KAAK,CAAC,KAAK,CAAC,CAAC;SACnC;IACH,CAAC;CACF","sourcesContent":["import { InternalLogger, TraceEvent, TransportItem, TransportItemType } from '@grafana/faro-core';\n\nimport { getLogTransforms, getTraceTransforms, LogsTransform, TraceTransform } from './transform';\nimport type { ResourceLogs, ResourceSpans } from './transform/types';\nimport type { OtelTransportPayload } from './types';\n\nexport class OtelPayload {\n private resourceLogs: ResourceLogs;\n private resourceSpans = [] as ResourceSpans;\n\n private getLogTransforms: LogsTransform;\n private getTraceTransforms: TraceTransform;\n\n constructor(\n private internalLogger: InternalLogger,\n transportItem?: TransportItem\n ) {\n this.internalLogger = internalLogger;\n this.resourceLogs = [];\n\n this.getLogTransforms = getLogTransforms(this.internalLogger);\n this.getTraceTransforms = getTraceTransforms(this.internalLogger);\n\n if (transportItem) {\n this.addResourceItem(transportItem);\n }\n }\n\n getPayload(): OtelTransportPayload {\n return {\n resourceLogs: this.resourceLogs,\n resourceSpans: this.resourceSpans,\n } as const;\n }\n\n addResourceItem(transportItem: TransportItem): void {\n const { type } = transportItem;\n\n try {\n switch (type) {\n case TransportItemType.LOG:\n case TransportItemType.EXCEPTION:\n case TransportItemType.EVENT:\n case TransportItemType.MEASUREMENT:\n const { toLogRecord, toResourceLog } = this.getLogTransforms;\n\n // Currently the scope is fixed to '@grafana/faro-web-sdk'.\n // Once we are able to drive the scope by instrumentation this will change and we need to align this function\n if (this.resourceLogs.length === 0) {\n this.resourceLogs = [toResourceLog(transportItem)];\n } else {\n // Faro takes care of the grouping with different metadata (or OTel attributes), so we can safely\n // use the just the first element of the resource.\n this.resourceLogs[0]?.scopeLogs[0]?.logRecords.push(toLogRecord(transportItem));\n }\n break;\n case TransportItemType.TRACE:\n const { toResourceSpan } = this.getTraceTransforms;\n\n // We use the Otel Model as it is to avoid unnecessary resource consumption.\n // This is because we don't need the same logic to add items as it is for logs.\n // Also the Otel library already applies the respective protocol transforms so there is no need for additional transforms.\n // We only transform the resource object to ensure that we are compliant with the respective Faro Metas which add a few more items to the resource object.\n this.resourceSpans.push(toResourceSpan(transportItem as TransportItem<TraceEvent>));\n\n break;\n default:\n this.internalLogger?.error(`Unknown TransportItemType: ${type}`);\n break;\n }\n } catch (error) {\n this.internalLogger?.error(error);\n }\n }\n}\n"]}
1
+ {"version":3,"file":"OtelPayload.js","sourceRoot":"","sources":["../../../src/payload/OtelPayload.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6C,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAIlG,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAiC,MAAM,aAAa,CAAC;AAUlG,MAAM,OAAO,WAAW;IAStB,YAAY,EAAE,cAAc,EAAE,mBAAmB,EAAE,aAAa,EAAqB;QAP7E,kBAAa,GAAG,EAAmB,CAAC;QAQ1C,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACrC,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QAEvB,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC,IAAI,CAAC,cAAc,EAAE,mBAAmB,CAAC,CAAC;QACnF,IAAI,CAAC,kBAAkB,GAAG,kBAAkB,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAElE,IAAI,aAAa,EAAE;YACjB,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;SACrC;IACH,CAAC;IAED,UAAU;QACR,OAAO;YACL,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,aAAa,EAAE,IAAI,CAAC,aAAa;SACzB,CAAC;IACb,CAAC;IAED,eAAe,CAAC,aAA4B;;QAC1C,MAAM,EAAE,IAAI,EAAE,GAAG,aAAa,CAAC;QAE/B,IAAI;YACF,QAAQ,IAAI,EAAE;gBACZ,KAAK,iBAAiB,CAAC,GAAG,CAAC;gBAC3B,KAAK,iBAAiB,CAAC,SAAS,CAAC;gBACjC,KAAK,iBAAiB,CAAC,KAAK,CAAC;gBAC7B,KAAK,iBAAiB,CAAC,WAAW;oBAChC,MAAM,EAAE,WAAW,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC;oBAE7D,2DAA2D;oBAC3D,6GAA6G;oBAC7G,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE;wBAClC,IAAI,CAAC,YAAY,GAAG,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC;qBACpD;yBAAM;wBACL,iGAAiG;wBACjG,kDAAkD;wBAClD,MAAA,MAAA,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,0CAAE,SAAS,CAAC,CAAC,CAAC,0CAAE,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC;qBACjF;oBACD,MAAM;gBACR,KAAK,iBAAiB,CAAC,KAAK;oBAC1B,MAAM,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC,kBAAkB,CAAC;oBAEnD,4EAA4E;oBAC5E,+EAA+E;oBAC/E,0HAA0H;oBAC1H,0JAA0J;oBAC1J,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,aAA0C,CAAC,CAAC,CAAC;oBAEpF,MAAM;gBACR;oBACE,MAAA,IAAI,CAAC,cAAc,0CAAE,KAAK,CAAC,8BAA8B,IAAI,EAAE,CAAC,CAAC;oBACjE,MAAM;aACT;SACF;QAAC,OAAO,KAAK,EAAE;YACd,MAAA,IAAI,CAAC,cAAc,0CAAE,KAAK,CAAC,KAAK,CAAC,CAAC;SACnC;IACH,CAAC;CACF","sourcesContent":["import { InternalLogger, TraceEvent, TransportItem, TransportItemType } from '@grafana/faro-core';\n\nimport type { OtlpHttpTransportOptions } from '../types';\n\nimport { getLogTransforms, getTraceTransforms, LogsTransform, TraceTransform } from './transform';\nimport type { ResourceLogs, ResourceSpans } from './transform/types';\nimport type { OtelTransportPayload } from './types';\n\ntype OtelPayloadParams = {\n internalLogger: InternalLogger;\n transportItem?: TransportItem;\n customOtlpTransform?: OtlpHttpTransportOptions['otlpTransform'];\n};\n\nexport class OtelPayload {\n private resourceLogs: ResourceLogs;\n private resourceSpans = [] as ResourceSpans;\n\n private getLogTransforms: LogsTransform;\n private getTraceTransforms: TraceTransform;\n\n private internalLogger: InternalLogger;\n\n constructor({ internalLogger, customOtlpTransform, transportItem }: OtelPayloadParams) {\n this.internalLogger = internalLogger;\n this.resourceLogs = [];\n\n this.getLogTransforms = getLogTransforms(this.internalLogger, customOtlpTransform);\n this.getTraceTransforms = getTraceTransforms(this.internalLogger);\n\n if (transportItem) {\n this.addResourceItem(transportItem);\n }\n }\n\n getPayload(): OtelTransportPayload {\n return {\n resourceLogs: this.resourceLogs,\n resourceSpans: this.resourceSpans,\n } as const;\n }\n\n addResourceItem(transportItem: TransportItem): void {\n const { type } = transportItem;\n\n try {\n switch (type) {\n case TransportItemType.LOG:\n case TransportItemType.EXCEPTION:\n case TransportItemType.EVENT:\n case TransportItemType.MEASUREMENT:\n const { toLogRecord, toResourceLog } = this.getLogTransforms;\n\n // Currently the scope is fixed to '@grafana/faro-web-sdk'.\n // Once we are able to drive the scope by instrumentation this will change and we need to align this function\n if (this.resourceLogs.length === 0) {\n this.resourceLogs = [toResourceLog(transportItem)];\n } else {\n // Faro takes care of the grouping with different metadata (or OTel attributes), so we can safely\n // use the just the first element of the resource.\n this.resourceLogs[0]?.scopeLogs[0]?.logRecords.push(toLogRecord(transportItem));\n }\n break;\n case TransportItemType.TRACE:\n const { toResourceSpan } = this.getTraceTransforms;\n\n // We use the Otel Model as it is to avoid unnecessary resource consumption.\n // This is because we don't need the same logic to add items as it is for logs.\n // Also the Otel library already applies the respective protocol transforms so there is no need for additional transforms.\n // We only transform the resource object to ensure that we are compliant with the respective Faro Metas which add a few more items to the resource object.\n this.resourceSpans.push(toResourceSpan(transportItem as TransportItem<TraceEvent>));\n\n break;\n default:\n this.internalLogger?.error(`Unknown TransportItemType: ${type}`);\n break;\n }\n } catch (error) {\n this.internalLogger?.error(error);\n }\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/payload/transform/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC","sourcesContent":["export { getLogTransforms, getTraceTransforms } from './transform';\nexport type {\n LogRecord,\n LogTransportItem,\n ResourceLogs,\n LogsTransform,\n Resource,\n ResourceLog,\n ResourceSpan,\n ResourceSpans,\n Scope,\n ScopeLog,\n TraceTransform,\n} from './types';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/payload/transform/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC","sourcesContent":["export { getLogTransforms, getTraceTransforms } from './transform';\nexport type {\n LogRecord,\n LogTransportItem,\n ResourceLogs,\n LogsTransform,\n Resource,\n ResourceLog,\n ResourceSpan,\n ResourceSpans,\n Scope,\n ScopeLog,\n TraceTransform,\n StringValueNonNullable,\n} from './types';\n"]}
@@ -14,7 +14,7 @@ const SemanticBrowserAttributes = {
14
14
  BROWSER_USER_AGENT: 'browser.user_agent',
15
15
  BROWSER_LANGUAGE: 'browser.language',
16
16
  };
17
- export function getLogTransforms(internalLogger) {
17
+ export function getLogTransforms(internalLogger, customOtlpTransform) {
18
18
  function toResourceLog(transportItem) {
19
19
  const resource = toResource(transportItem);
20
20
  return {
@@ -92,37 +92,29 @@ export function getLogTransforms(internalLogger) {
92
92
  var _a, _b;
93
93
  const { meta, payload } = transportItem;
94
94
  const timeUnixNano = toTimeUnixNano(payload.timestamp);
95
- return {
96
- timeUnixNano,
97
- attributes: [
95
+ const body = getCustomLogBody(transportItem, customOtlpTransform === null || customOtlpTransform === void 0 ? void 0 : customOtlpTransform.createErrorLogBody);
96
+ return Object.assign(Object.assign({ timeUnixNano }, (body ? { body } : {})), { attributes: [
98
97
  ...getCommonLogAttributes(meta),
99
98
  toAttribute(SemanticAttributes.EXCEPTION_TYPE, payload.type),
100
99
  toAttribute(SemanticAttributes.EXCEPTION_MESSAGE, payload.value),
101
100
  // toAttribute(SemanticAttributes.EXCEPTION_STACKTRACE, undefined),
102
101
  toAttribute('faro.error.stacktrace', payload.stacktrace),
103
102
  toAttribute('faro.error.context', payload.context),
104
- ].filter(isAttribute),
105
- traceId: (_a = payload.trace) === null || _a === void 0 ? void 0 : _a.trace_id,
106
- spanId: (_b = payload.trace) === null || _b === void 0 ? void 0 : _b.span_id,
107
- };
103
+ ].filter(isAttribute), traceId: (_a = payload.trace) === null || _a === void 0 ? void 0 : _a.trace_id, spanId: (_b = payload.trace) === null || _b === void 0 ? void 0 : _b.span_id });
108
104
  }
109
105
  function toMeasurementLogRecord(transportItem) {
110
106
  var _a, _b;
111
107
  const { meta, payload } = transportItem;
112
108
  const timeUnixNano = toTimeUnixNano(payload.timestamp);
113
109
  const [measurementName, measurementValue] = Object.entries(payload.values).flat();
114
- return {
115
- timeUnixNano,
116
- attributes: [
110
+ const body = getCustomLogBody(transportItem, customOtlpTransform === null || customOtlpTransform === void 0 ? void 0 : customOtlpTransform.createMeasurementLogBody);
111
+ return Object.assign(Object.assign({ timeUnixNano }, (body ? { body } : {})), { attributes: [
117
112
  ...getCommonLogAttributes(meta),
118
113
  toAttribute('measurement.type', payload.type),
119
114
  toAttribute('measurement.name', measurementName),
120
115
  toAttribute('measurement.value', measurementValue),
121
116
  toAttribute('faro.measurement.context', payload.context),
122
- ].filter(isAttribute),
123
- traceId: (_a = payload.trace) === null || _a === void 0 ? void 0 : _a.trace_id,
124
- spanId: (_b = payload.trace) === null || _b === void 0 ? void 0 : _b.span_id,
125
- };
117
+ ].filter(isAttribute), traceId: (_a = payload.trace) === null || _a === void 0 ? void 0 : _a.trace_id, spanId: (_b = payload.trace) === null || _b === void 0 ? void 0 : _b.span_id });
126
118
  }
127
119
  function getCommonLogAttributes(meta) {
128
120
  const { view, page, session, user } = meta;
@@ -184,4 +176,9 @@ function toResource(transportItem) {
184
176
  ].filter(isAttribute),
185
177
  };
186
178
  }
179
+ function getCustomLogBody(transportItem, createCustomLogBody) {
180
+ return typeof createCustomLogBody === 'function'
181
+ ? toAttributeValue(createCustomLogBody(transportItem))
182
+ : undefined;
183
+ }
187
184
  //# sourceMappingURL=transform.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"transform.js","sourceRoot":"","sources":["../../../../src/payload/transform/transform.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IKeyValue } from '@opentelemetry/otlp-transformer';\nimport {\n SemanticAttributes,\n SemanticResourceAttributes,\n TelemetrySdkLanguageValues,\n} from '@opentelemetry/semantic-conventions';\n\nimport {\n EventEvent,\n ExceptionEvent,\n LogEvent,\n LogLevel,\n MeasurementEvent,\n Meta,\n TransportItem,\n TransportItemType,\n VERSION,\n} from '@grafana/faro-core';\nimport type { InternalLogger, TraceEvent } from '@grafana/faro-core';\n\nimport { isAttribute, toAttribute, toAttributeValue } from '../attribute';\n\nimport type {\n LogRecord,\n LogsTransform,\n LogTransportItem,\n Resource,\n ResourceLog,\n ResourceMeta,\n ResourceSpan,\n ScopeLog,\n TraceTransform,\n} from './types';\n\n/**\n * Seems currently to be missing in the semantic-conventions npm package.\n * See: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#todos\n *\n * Attributes are as defined by the Otel docs\n */\nconst SemanticBrowserAttributes = {\n BROWSER_BRANDS: 'browser.brands',\n BROWSER_PLATFORM: 'browser.platform',\n BROWSER_MOBILE: 'browser.mobile',\n BROWSER_USER_AGENT: 'browser.user_agent',\n BROWSER_LANGUAGE: 'browser.language',\n} as const;\n\nexport function getLogTransforms(internalLogger: InternalLogger): LogsTransform {\n function toResourceLog(transportItem: LogTransportItem): ResourceLog {\n const resource = toResource(transportItem);\n\n return {\n resource,\n scopeLogs: [toScopeLog(transportItem)],\n };\n }\n\n function toScopeLog(transportItem: LogTransportItem): ScopeLog {\n return {\n scope: {\n name: '@grafana/faro-web-sdk',\n version: VERSION,\n },\n logRecords: [toLogRecord(transportItem)],\n };\n }\n\n function toLogRecord(transportItem: LogTransportItem): LogRecord {\n const { type } = transportItem;\n\n switch (type) {\n case TransportItemType.LOG:\n return toLogLogRecord(transportItem as TransportItem<LogEvent>);\n case TransportItemType.EXCEPTION:\n return toErrorLogRecord(transportItem as TransportItem<ExceptionEvent>);\n case TransportItemType.EVENT:\n return toEventLogRecord(transportItem as TransportItem<EventEvent>);\n case TransportItemType.MEASUREMENT:\n return toMeasurementLogRecord(transportItem as TransportItem<MeasurementEvent>);\n default:\n internalLogger?.error(`Unknown TransportItemType: ${type}`);\n return {};\n }\n }\n\n function toLogLogRecord(transportItem: TransportItem<LogEvent>): LogRecord {\n const { meta, payload } = transportItem;\n const timeUnixNano = toTimeUnixNano(payload.timestamp);\n const body = toAttributeValue(payload.message) as { stringValue: string; key: string };\n\n function getSeverityProperties(logLevel: LogLevel): { severityNumber: number; severityText: string } {\n switch (logLevel) {\n case LogLevel.TRACE:\n return { severityNumber: 1, severityText: 'TRACE' };\n case LogLevel.DEBUG:\n return { severityNumber: 5, severityText: 'DEBUG' };\n case LogLevel.INFO:\n return { severityNumber: 9, severityText: 'INFO' };\n case LogLevel.LOG:\n return { severityNumber: 10, severityText: 'INFO2' };\n case LogLevel.WARN:\n return { severityNumber: 13, severityText: 'WARN' };\n case LogLevel.ERROR:\n return { severityNumber: 17, severityText: 'ERROR' };\n }\n }\n\n return {\n timeUnixNano,\n ...getSeverityProperties(payload.level),\n body,\n attributes: [...getCommonLogAttributes(meta), toAttribute('faro.log.context', payload.context)].filter(\n isAttribute\n ),\n traceId: payload.trace?.trace_id,\n spanId: payload.trace?.span_id,\n } as const;\n }\n\n function toEventLogRecord(transportItem: TransportItem<EventEvent>): LogRecord {\n const { meta, payload } = transportItem;\n const timeUnixNano = toTimeUnixNano(payload.timestamp);\n const body = toAttributeValue(payload.name) as { stringValue: string; key: string };\n\n return {\n timeUnixNano,\n body,\n attributes: [\n ...getCommonLogAttributes(meta),\n toAttribute('event.name', payload.name), // This is a semantic attribute. But event.name constant is currently missing in sematic-conventions npm package\n toAttribute('event.domain', payload.domain), // This is a semantic attribute. But event.domain constant is currently missing in sematic-conventions npm package\n toAttribute('event.attributes', payload.attributes),\n ].filter(isAttribute),\n traceId: payload.trace?.trace_id,\n spanId: payload.trace?.span_id,\n } as const;\n }\n\n function toErrorLogRecord(transportItem: TransportItem<ExceptionEvent>): LogRecord {\n const { meta, payload } = transportItem;\n const timeUnixNano = toTimeUnixNano(payload.timestamp);\n\n return {\n timeUnixNano,\n attributes: [\n ...getCommonLogAttributes(meta),\n toAttribute(SemanticAttributes.EXCEPTION_TYPE, payload.type),\n toAttribute(SemanticAttributes.EXCEPTION_MESSAGE, payload.value),\n // toAttribute(SemanticAttributes.EXCEPTION_STACKTRACE, undefined),\n toAttribute('faro.error.stacktrace', payload.stacktrace),\n toAttribute('faro.error.context', payload.context),\n ].filter(isAttribute),\n traceId: payload.trace?.trace_id,\n spanId: payload.trace?.span_id,\n } as const;\n }\n\n function toMeasurementLogRecord(transportItem: TransportItem<MeasurementEvent>): LogRecord {\n const { meta, payload } = transportItem;\n const timeUnixNano = toTimeUnixNano(payload.timestamp);\n const [measurementName, measurementValue] = Object.entries(payload.values).flat();\n\n return {\n timeUnixNano,\n attributes: [\n ...getCommonLogAttributes(meta),\n toAttribute('measurement.type', payload.type),\n toAttribute('measurement.name', measurementName),\n toAttribute('measurement.value', measurementValue),\n toAttribute('faro.measurement.context', payload.context),\n ].filter(isAttribute),\n traceId: payload.trace?.trace_id,\n spanId: payload.trace?.span_id,\n } as const;\n }\n\n function getCommonLogAttributes(meta: Meta): IKeyValue[] {\n const { view, page, session, user } = meta;\n\n return [\n toAttribute('view.name', view?.name),\n toAttribute(SemanticAttributes.HTTP_URL, page?.url),\n toAttribute('page.id', page?.id),\n toAttribute('page.attributes', page?.attributes),\n toAttribute('session.id', session?.id),\n toAttribute('session.attributes', session?.attributes),\n toAttribute(SemanticAttributes.ENDUSER_ID, user?.id),\n toAttribute('enduser.name', user?.username),\n toAttribute('enduser.email', user?.email),\n toAttribute('enduser.attributes', user?.attributes),\n ].filter(isAttribute);\n }\n\n function toTimeUnixNano(timestamp: string): number {\n return Date.parse(timestamp) * 1e6;\n }\n\n return {\n toResourceLog,\n toScopeLog,\n toLogRecord,\n };\n}\n\nexport function getTraceTransforms(_internalLogger?: InternalLogger): TraceTransform {\n function toResourceSpan(transportItem: TransportItem<TraceEvent>): ResourceSpan {\n const resource = toResource(transportItem);\n const scopeSpans = transportItem.payload.resourceSpans?.[0]?.scopeSpans;\n\n return {\n resource,\n scopeSpans: scopeSpans ?? [],\n };\n }\n\n return {\n toResourceSpan,\n };\n}\n\nfunction toResource(transportItem: TransportItem): Readonly<Resource> {\n const { browser, sdk, app }: ResourceMeta = transportItem.meta;\n\n return {\n attributes: [\n toAttribute(SemanticBrowserAttributes.BROWSER_MOBILE, browser?.mobile),\n toAttribute(SemanticBrowserAttributes.BROWSER_USER_AGENT, browser?.userAgent),\n toAttribute(SemanticBrowserAttributes.BROWSER_LANGUAGE, browser?.language),\n toAttribute(SemanticBrowserAttributes.BROWSER_BRANDS, browser?.brands),\n toAttribute('browser.os', browser?.os),\n toAttribute('browser.name', browser?.name),\n toAttribute('browser.version', browser?.version),\n\n toAttribute(SemanticResourceAttributes.TELEMETRY_SDK_NAME, sdk?.name),\n toAttribute(SemanticResourceAttributes.TELEMETRY_SDK_VERSION, sdk?.version),\n Boolean(sdk)\n ? toAttribute(SemanticResourceAttributes.TELEMETRY_SDK_LANGUAGE, TelemetrySdkLanguageValues.WEBJS)\n : undefined,\n\n toAttribute(SemanticResourceAttributes.SERVICE_NAME, app?.name),\n toAttribute(SemanticResourceAttributes.SERVICE_VERSION, app?.version),\n toAttribute(SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT, app?.environment),\n ].filter(isAttribute),\n };\n}\n"]}
1
+ {"version":3,"file":"transform.js","sourceRoot":"","sources":["../../../../src/payload/transform/transform.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IKeyValue } from '@opentelemetry/otlp-transformer';\nimport {\n SemanticAttributes,\n SemanticResourceAttributes,\n TelemetrySdkLanguageValues,\n} from '@opentelemetry/semantic-conventions';\n\nimport {\n EventEvent,\n ExceptionEvent,\n LogEvent,\n LogLevel,\n MeasurementEvent,\n Meta,\n TransportItem,\n TransportItemType,\n VERSION,\n} from '@grafana/faro-core';\nimport type { InternalLogger, TraceEvent } from '@grafana/faro-core';\n\nimport type { OtlpHttpTransportOptions } from '../../types';\nimport { isAttribute, toAttribute, toAttributeValue } from '../attribute';\n\nimport type {\n LogRecord,\n LogsTransform,\n LogTransportItem,\n Resource,\n ResourceLog,\n ResourceMeta,\n ResourceSpan,\n ScopeLog,\n StringValueNonNullable,\n TraceTransform,\n} from './types';\n\n/**\n * Seems currently to be missing in the semantic-conventions npm package.\n * See: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/README.md#todos\n *\n * Attributes are as defined by the Otel docs\n */\nconst SemanticBrowserAttributes = {\n BROWSER_BRANDS: 'browser.brands',\n BROWSER_PLATFORM: 'browser.platform',\n BROWSER_MOBILE: 'browser.mobile',\n BROWSER_USER_AGENT: 'browser.user_agent',\n BROWSER_LANGUAGE: 'browser.language',\n} as const;\n\nexport function getLogTransforms(\n internalLogger: InternalLogger,\n customOtlpTransform?: OtlpHttpTransportOptions['otlpTransform']\n): LogsTransform {\n function toResourceLog(transportItem: LogTransportItem): ResourceLog {\n const resource = toResource(transportItem);\n\n return {\n resource,\n scopeLogs: [toScopeLog(transportItem)],\n };\n }\n\n function toScopeLog(transportItem: LogTransportItem): ScopeLog {\n return {\n scope: {\n name: '@grafana/faro-web-sdk',\n version: VERSION,\n },\n logRecords: [toLogRecord(transportItem)],\n };\n }\n\n function toLogRecord(transportItem: LogTransportItem): LogRecord {\n const { type } = transportItem;\n\n switch (type) {\n case TransportItemType.LOG:\n return toLogLogRecord(transportItem as TransportItem<LogEvent>);\n case TransportItemType.EXCEPTION:\n return toErrorLogRecord(transportItem as TransportItem<ExceptionEvent>);\n case TransportItemType.EVENT:\n return toEventLogRecord(transportItem as TransportItem<EventEvent>);\n case TransportItemType.MEASUREMENT:\n return toMeasurementLogRecord(transportItem as TransportItem<MeasurementEvent>);\n default:\n internalLogger?.error(`Unknown TransportItemType: ${type}`);\n return {};\n }\n }\n\n function toLogLogRecord(transportItem: TransportItem<LogEvent>): LogRecord {\n const { meta, payload } = transportItem;\n const timeUnixNano = toTimeUnixNano(payload.timestamp);\n const body = toAttributeValue(payload.message) as StringValueNonNullable;\n\n function getSeverityProperties(logLevel: LogLevel) {\n switch (logLevel) {\n case LogLevel.TRACE:\n return { severityNumber: 1, severityText: 'TRACE' };\n case LogLevel.DEBUG:\n return { severityNumber: 5, severityText: 'DEBUG' };\n case LogLevel.INFO:\n return { severityNumber: 9, severityText: 'INFO' };\n case LogLevel.LOG:\n return { severityNumber: 10, severityText: 'INFO2' };\n case LogLevel.WARN:\n return { severityNumber: 13, severityText: 'WARN' };\n case LogLevel.ERROR:\n return { severityNumber: 17, severityText: 'ERROR' };\n }\n }\n\n return {\n timeUnixNano,\n ...getSeverityProperties(payload.level),\n body,\n attributes: [...getCommonLogAttributes(meta), toAttribute('faro.log.context', payload.context)].filter(\n isAttribute\n ),\n traceId: payload.trace?.trace_id,\n spanId: payload.trace?.span_id,\n } as const;\n }\n\n function toEventLogRecord(transportItem: TransportItem<EventEvent>): LogRecord {\n const { meta, payload } = transportItem;\n const timeUnixNano = toTimeUnixNano(payload.timestamp);\n const body = toAttributeValue(payload.name) as StringValueNonNullable;\n\n return {\n timeUnixNano,\n body,\n attributes: [\n ...getCommonLogAttributes(meta),\n toAttribute('event.name', payload.name), // This is a semantic attribute. But event.name constant is currently missing in sematic-conventions npm package\n toAttribute('event.domain', payload.domain), // This is a semantic attribute. But event.domain constant is currently missing in sematic-conventions npm package\n toAttribute('event.attributes', payload.attributes),\n ].filter(isAttribute),\n traceId: payload.trace?.trace_id,\n spanId: payload.trace?.span_id,\n } as const;\n }\n\n function toErrorLogRecord(transportItem: TransportItem<ExceptionEvent>): LogRecord {\n const { meta, payload } = transportItem;\n const timeUnixNano = toTimeUnixNano(payload.timestamp);\n const body = getCustomLogBody(transportItem, customOtlpTransform?.createErrorLogBody);\n\n return {\n timeUnixNano,\n ...(body ? { body } : {}),\n attributes: [\n ...getCommonLogAttributes(meta),\n toAttribute(SemanticAttributes.EXCEPTION_TYPE, payload.type),\n toAttribute(SemanticAttributes.EXCEPTION_MESSAGE, payload.value),\n // toAttribute(SemanticAttributes.EXCEPTION_STACKTRACE, undefined),\n toAttribute('faro.error.stacktrace', payload.stacktrace),\n toAttribute('faro.error.context', payload.context),\n ].filter(isAttribute),\n traceId: payload.trace?.trace_id,\n spanId: payload.trace?.span_id,\n } as const;\n }\n\n function toMeasurementLogRecord(transportItem: TransportItem<MeasurementEvent>): LogRecord {\n const { meta, payload } = transportItem;\n const timeUnixNano = toTimeUnixNano(payload.timestamp);\n const [measurementName, measurementValue] = Object.entries(payload.values).flat();\n\n const body = getCustomLogBody(transportItem, customOtlpTransform?.createMeasurementLogBody);\n\n return {\n timeUnixNano,\n ...(body ? { body } : {}),\n attributes: [\n ...getCommonLogAttributes(meta),\n toAttribute('measurement.type', payload.type),\n toAttribute('measurement.name', measurementName),\n toAttribute('measurement.value', measurementValue),\n toAttribute('faro.measurement.context', payload.context),\n ].filter(isAttribute),\n traceId: payload.trace?.trace_id,\n spanId: payload.trace?.span_id,\n } as const;\n }\n\n function getCommonLogAttributes(meta: Meta): IKeyValue[] {\n const { view, page, session, user } = meta;\n\n return [\n toAttribute('view.name', view?.name),\n toAttribute(SemanticAttributes.HTTP_URL, page?.url),\n toAttribute('page.id', page?.id),\n toAttribute('page.attributes', page?.attributes),\n toAttribute('session.id', session?.id),\n toAttribute('session.attributes', session?.attributes),\n toAttribute(SemanticAttributes.ENDUSER_ID, user?.id),\n toAttribute('enduser.name', user?.username),\n toAttribute('enduser.email', user?.email),\n toAttribute('enduser.attributes', user?.attributes),\n ].filter(isAttribute);\n }\n\n function toTimeUnixNano(timestamp: string): number {\n return Date.parse(timestamp) * 1e6;\n }\n\n return {\n toResourceLog,\n toScopeLog,\n toLogRecord,\n };\n}\n\nexport function getTraceTransforms(_internalLogger?: InternalLogger): TraceTransform {\n function toResourceSpan(transportItem: TransportItem<TraceEvent>): ResourceSpan {\n const resource = toResource(transportItem);\n const scopeSpans = transportItem.payload.resourceSpans?.[0]?.scopeSpans;\n\n return {\n resource,\n scopeSpans: scopeSpans ?? [],\n };\n }\n\n return {\n toResourceSpan,\n };\n}\n\nfunction toResource(transportItem: TransportItem): Readonly<Resource> {\n const { browser, sdk, app }: ResourceMeta = transportItem.meta;\n\n return {\n attributes: [\n toAttribute(SemanticBrowserAttributes.BROWSER_MOBILE, browser?.mobile),\n toAttribute(SemanticBrowserAttributes.BROWSER_USER_AGENT, browser?.userAgent),\n toAttribute(SemanticBrowserAttributes.BROWSER_LANGUAGE, browser?.language),\n toAttribute(SemanticBrowserAttributes.BROWSER_BRANDS, browser?.brands),\n toAttribute('browser.os', browser?.os),\n toAttribute('browser.name', browser?.name),\n toAttribute('browser.version', browser?.version),\n\n toAttribute(SemanticResourceAttributes.TELEMETRY_SDK_NAME, sdk?.name),\n toAttribute(SemanticResourceAttributes.TELEMETRY_SDK_VERSION, sdk?.version),\n Boolean(sdk)\n ? toAttribute(SemanticResourceAttributes.TELEMETRY_SDK_LANGUAGE, TelemetrySdkLanguageValues.WEBJS)\n : undefined,\n\n toAttribute(SemanticResourceAttributes.SERVICE_NAME, app?.name),\n toAttribute(SemanticResourceAttributes.SERVICE_VERSION, app?.version),\n toAttribute(SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT, app?.environment),\n ].filter(isAttribute),\n };\n}\n\nfunction getCustomLogBody<T>(\n transportItem: T,\n createCustomLogBody?: (item: T) => string\n): StringValueNonNullable | undefined {\n return typeof createCustomLogBody === 'function'\n ? (toAttributeValue(createCustomLogBody(transportItem)) as StringValueNonNullable)\n : undefined;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/payload/transform/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { IKeyValue, IResource, IResourceSpans } from '@opentelemetry/otlp-transformer';\n\nimport type { APIEvent, Meta, TraceEvent, TransportItem } from '@grafana/faro-core';\n\nexport interface Resource extends Partial<Pick<IResource, 'droppedAttributesCount'>> {\n attributes: IKeyValue[];\n}\n\nexport interface LogRecord {\n timeUnixNano?: number;\n severityNumber?: number;\n severityText?: string;\n body?: { stringValue: string };\n attributes?: IKeyValue[];\n traceId?: string;\n spanId?: string;\n}\n\nexport type Scope = {\n name: string;\n version: string;\n};\n\nexport interface ScopeLog {\n scope: Scope;\n logRecords: LogRecord[];\n}\n\nexport interface ScopeSpan {\n scope: Scope;\n logRecords: LogRecord[];\n}\n\nexport interface ResourceLog {\n resource: Resource;\n scopeLogs: ScopeLog[];\n}\n\nexport type ResourceLogs = ResourceLog[];\n\nexport interface ResourceSpan extends Omit<IResourceSpans, 'resource'> {\n resource: Resource;\n}\n\nexport type ResourceSpans = ResourceSpan[];\n\nexport type LogTransportItem = TransportItem<Exclude<APIEvent, 'TraceEvent'>>;\nexport type TraceTransportItem = TransportItem<TraceEvent>;\n\nexport type LogsTransform = {\n toResourceLog: (transportItem: LogTransportItem) => ResourceLog;\n toScopeLog: (transportItem: LogTransportItem) => ScopeLog;\n toLogRecord: (transportItem: LogTransportItem) => LogRecord;\n};\n\nexport type TraceTransform = {\n toResourceSpan: (transportItem: TransportItem<TraceEvent>) => ResourceSpan;\n};\n\nexport type ResourceMeta = Pick<Meta, 'app' | 'browser' | 'sdk'>;\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/payload/transform/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { IKeyValue, IResource, IResourceSpans } from '@opentelemetry/otlp-transformer';\n\nimport type { APIEvent, Meta, TraceEvent, TransportItem } from '@grafana/faro-core';\n\nexport interface Resource extends Partial<Pick<IResource, 'droppedAttributesCount'>> {\n attributes: IKeyValue[];\n}\n\nexport interface LogRecord {\n timeUnixNano?: number;\n severityNumber?: number;\n severityText?: string;\n body?: { stringValue: string };\n attributes?: IKeyValue[];\n traceId?: string;\n spanId?: string;\n}\n\nexport type Scope = {\n name: string;\n version: string;\n};\n\nexport interface ScopeLog {\n scope: Scope;\n logRecords: LogRecord[];\n}\n\nexport interface ScopeSpan {\n scope: Scope;\n logRecords: LogRecord[];\n}\n\nexport interface ResourceLog {\n resource: Resource;\n scopeLogs: ScopeLog[];\n}\n\nexport type ResourceLogs = ResourceLog[];\n\nexport interface ResourceSpan extends Omit<IResourceSpans, 'resource'> {\n resource: Resource;\n}\n\nexport type ResourceSpans = ResourceSpan[];\n\nexport type LogTransportItem = TransportItem<Exclude<APIEvent, 'TraceEvent'>>;\nexport type TraceTransportItem = TransportItem<TraceEvent>;\n\nexport type LogsTransform = {\n toResourceLog: (transportItem: LogTransportItem) => ResourceLog;\n toScopeLog: (transportItem: LogTransportItem) => ScopeLog;\n toLogRecord: (transportItem: LogTransportItem) => LogRecord;\n};\n\nexport type TraceTransform = {\n toResourceSpan: (transportItem: TransportItem<TraceEvent>) => ResourceSpan;\n};\n\nexport type ResourceMeta = Pick<Meta, 'app' | 'browser' | 'sdk'>;\n\nexport type StringValueNonNullable = { stringValue: string };\n"]}
@@ -14,6 +14,8 @@ import { OtelPayload } from './payload';
14
14
  const DEFAULT_BUFFER_SIZE = 30;
15
15
  const DEFAULT_CONCURRENCY = 5; // chrome supports 10 total, firefox 17
16
16
  const DEFAULT_RATE_LIMIT_BACKOFF_MS = 5000;
17
+ const BEACON_BODY_SIZE_LIMIT = 60000;
18
+ const TOO_MANY_REQUESTS = 429;
17
19
  export class OtlpHttpTransport extends BaseTransport {
18
20
  constructor(options) {
19
21
  var _a, _b, _c;
@@ -37,7 +39,10 @@ export class OtlpHttpTransport extends BaseTransport {
37
39
  return true;
38
40
  }
39
41
  send(items) {
40
- const otelPayload = new OtelPayload(this.internalLogger);
42
+ const otelPayload = new OtelPayload({
43
+ internalLogger: this.internalLogger,
44
+ customOtlpTransform: this.options.otlpTransform,
45
+ });
41
46
  items.forEach((item) => otelPayload.addResourceItem(item));
42
47
  this.sendPayload(otelPayload.getPayload());
43
48
  }
@@ -75,9 +80,9 @@ export class OtlpHttpTransport extends BaseTransport {
75
80
  const { requestOptions, apiKey } = this.options;
76
81
  const _a = requestOptions !== null && requestOptions !== void 0 ? requestOptions : {}, { headers } = _a, restOfRequestOptions = __rest(_a, ["headers"]);
77
82
  this.promiseBuffer.add(() => {
78
- return fetch(url, Object.assign({ method: 'POST', headers: Object.assign(Object.assign({ 'Content-Type': 'application/json' }, (headers !== null && headers !== void 0 ? headers : {})), (apiKey ? { 'x-api-key': apiKey } : {})), body, keepalive: true }, (restOfRequestOptions !== null && restOfRequestOptions !== void 0 ? restOfRequestOptions : {})))
83
+ return fetch(url, Object.assign({ method: 'POST', headers: Object.assign(Object.assign({ 'Content-Type': 'application/json' }, (headers !== null && headers !== void 0 ? headers : {})), (apiKey ? { 'x-api-key': apiKey } : {})), body, keepalive: body.length <= BEACON_BODY_SIZE_LIMIT }, (restOfRequestOptions !== null && restOfRequestOptions !== void 0 ? restOfRequestOptions : {})))
79
84
  .then((response) => {
80
- if (response.status === 429) {
85
+ if (response.status === TOO_MANY_REQUESTS) {
81
86
  updateDisabledUntil(this.getRetryAfterDate(response));
82
87
  this.logWarn(`Too many requests, backing off until ${disabledUntil}`);
83
88
  }
@@ -1 +1 @@
1
- {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/transport.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseTransport, createPromiseBuffer, isArray, PromiseBuffer, TransportItem, VERSION } from '@grafana/faro-core';\n\nimport { OtelPayload, OtelTransportPayload } from './payload';\nimport type { OtlpHttpTransportOptions } from './types';\n\nconst DEFAULT_BUFFER_SIZE = 30;\nconst DEFAULT_CONCURRENCY = 5; // chrome supports 10 total, firefox 17\nconst DEFAULT_RATE_LIMIT_BACKOFF_MS = 5000;\n\nexport class OtlpHttpTransport extends BaseTransport {\n readonly name = '@grafana/faro-web-sdk:transport-otlp-http';\n readonly version = VERSION;\n\n private readonly promiseBuffer: PromiseBuffer<Response | void>;\n private readonly rateLimitBackoffMs: number;\n\n private sendingTracesDisabledUntil: Date = new Date();\n private sendingLogsDisabledUntil: Date = new Date();\n\n constructor(private options: OtlpHttpTransportOptions) {\n super();\n this.rateLimitBackoffMs = options.defaultRateLimitBackoffMs ?? DEFAULT_RATE_LIMIT_BACKOFF_MS;\n\n this.promiseBuffer = createPromiseBuffer({\n size: options?.bufferSize ?? DEFAULT_BUFFER_SIZE,\n concurrency: options?.concurrency ?? DEFAULT_CONCURRENCY,\n });\n }\n\n override getIgnoreUrls(): Array<string | RegExp> {\n const { tracesURL = '', logsURL = '' } = this.options;\n return [tracesURL, logsURL].filter(Boolean);\n }\n\n override isBatched(): boolean {\n return true;\n }\n\n send(items: TransportItem[]): void {\n const otelPayload = new OtelPayload(this.internalLogger);\n\n items.forEach((item) => otelPayload.addResourceItem(item));\n this.sendPayload(otelPayload.getPayload());\n }\n\n private sendPayload(payload: OtelTransportPayload): void {\n try {\n const { tracesURL = '', logsURL = '' } = this.options;\n\n for (const [key, value] of Object.entries(payload)) {\n if (!(isArray(value) && value.length > 0)) {\n continue;\n }\n\n let disabledUntil: Date | undefined;\n let updateDisabledUntil = (_: Date) => {};\n let url = '';\n\n switch (key) {\n case 'resourceSpans':\n url = tracesURL;\n disabledUntil = this.sendingTracesDisabledUntil;\n updateDisabledUntil = (retryAfterDate: Date) => {\n this.sendingTracesDisabledUntil = retryAfterDate;\n };\n break;\n case 'resourceLogs':\n url = logsURL;\n disabledUntil = this.sendingLogsDisabledUntil;\n updateDisabledUntil = (retryAfterDate: Date) => {\n this.sendingLogsDisabledUntil = retryAfterDate;\n };\n break;\n }\n\n if (disabledUntil && disabledUntil > new Date(Date.now())) {\n this.logWarn(`Dropping transport item due to too many requests. Backoff until ${disabledUntil}`);\n return undefined;\n }\n\n const body = JSON.stringify({ [key]: value });\n\n const { requestOptions, apiKey } = this.options;\n const { headers, ...restOfRequestOptions } = requestOptions ?? {};\n\n this.promiseBuffer.add(() => {\n return fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(headers ?? {}),\n ...(apiKey ? { 'x-api-key': apiKey } : {}),\n },\n body,\n keepalive: true,\n ...(restOfRequestOptions ?? {}),\n })\n .then((response) => {\n if (response.status === 429) {\n updateDisabledUntil(this.getRetryAfterDate(response));\n this.logWarn(`Too many requests, backing off until ${disabledUntil}`);\n }\n\n return response;\n })\n .catch((error) => {\n this.logError('Failed sending payload to the receiver\\n', JSON.parse(body), error);\n });\n });\n }\n } catch (error) {\n this.logError(error);\n }\n }\n\n private getRetryAfterDate(response: Response): Date {\n const now = Date.now();\n const retryAfterHeader = response.headers.get('Retry-After');\n\n if (retryAfterHeader) {\n const delay = Number(retryAfterHeader);\n\n if (!isNaN(delay)) {\n return new Date(delay * 1000 + now);\n }\n\n const date = Date.parse(retryAfterHeader);\n\n if (!isNaN(date)) {\n return new Date(date);\n }\n }\n\n return new Date(now + this.rateLimitBackoffMs);\n }\n}\n"]}
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/transport.ts"],"names":[],"mappings":"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","sourcesContent":["import { BaseTransport, createPromiseBuffer, isArray, PromiseBuffer, TransportItem, VERSION } from '@grafana/faro-core';\n\nimport { OtelPayload, OtelTransportPayload } from './payload';\nimport type { OtlpHttpTransportOptions } from './types';\n\nconst DEFAULT_BUFFER_SIZE = 30;\nconst DEFAULT_CONCURRENCY = 5; // chrome supports 10 total, firefox 17\nconst DEFAULT_RATE_LIMIT_BACKOFF_MS = 5000;\n\nconst BEACON_BODY_SIZE_LIMIT = 60000;\nconst TOO_MANY_REQUESTS = 429;\n\nexport class OtlpHttpTransport extends BaseTransport {\n readonly name = '@grafana/faro-web-sdk:transport-otlp-http';\n readonly version = VERSION;\n\n private readonly promiseBuffer: PromiseBuffer<Response | void>;\n private readonly rateLimitBackoffMs: number;\n\n private sendingTracesDisabledUntil: Date = new Date();\n private sendingLogsDisabledUntil: Date = new Date();\n\n constructor(private options: OtlpHttpTransportOptions) {\n super();\n this.rateLimitBackoffMs = options.defaultRateLimitBackoffMs ?? DEFAULT_RATE_LIMIT_BACKOFF_MS;\n\n this.promiseBuffer = createPromiseBuffer({\n size: options?.bufferSize ?? DEFAULT_BUFFER_SIZE,\n concurrency: options?.concurrency ?? DEFAULT_CONCURRENCY,\n });\n }\n\n override getIgnoreUrls(): Array<string | RegExp> {\n const { tracesURL = '', logsURL = '' } = this.options;\n return [tracesURL, logsURL].filter(Boolean);\n }\n\n override isBatched(): boolean {\n return true;\n }\n\n send(items: TransportItem[]): void {\n const otelPayload = new OtelPayload({\n internalLogger: this.internalLogger,\n customOtlpTransform: this.options.otlpTransform,\n });\n\n items.forEach((item) => otelPayload.addResourceItem(item));\n this.sendPayload(otelPayload.getPayload());\n }\n\n private sendPayload(payload: OtelTransportPayload): void {\n try {\n const { tracesURL = '', logsURL = '' } = this.options;\n\n for (const [key, value] of Object.entries(payload)) {\n if (!(isArray(value) && value.length > 0)) {\n continue;\n }\n\n let disabledUntil: Date | undefined;\n let updateDisabledUntil = (_: Date) => {};\n let url = '';\n\n switch (key) {\n case 'resourceSpans':\n url = tracesURL;\n disabledUntil = this.sendingTracesDisabledUntil;\n updateDisabledUntil = (retryAfterDate: Date) => {\n this.sendingTracesDisabledUntil = retryAfterDate;\n };\n break;\n case 'resourceLogs':\n url = logsURL;\n disabledUntil = this.sendingLogsDisabledUntil;\n updateDisabledUntil = (retryAfterDate: Date) => {\n this.sendingLogsDisabledUntil = retryAfterDate;\n };\n break;\n }\n\n if (disabledUntil && disabledUntil > new Date(Date.now())) {\n this.logWarn(`Dropping transport item due to too many requests. Backoff until ${disabledUntil}`);\n return undefined;\n }\n\n const body = JSON.stringify({ [key]: value });\n\n const { requestOptions, apiKey } = this.options;\n const { headers, ...restOfRequestOptions } = requestOptions ?? {};\n\n this.promiseBuffer.add(() => {\n return fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(headers ?? {}),\n ...(apiKey ? { 'x-api-key': apiKey } : {}),\n },\n body,\n keepalive: body.length <= BEACON_BODY_SIZE_LIMIT,\n ...(restOfRequestOptions ?? {}),\n })\n .then((response) => {\n if (response.status === TOO_MANY_REQUESTS) {\n updateDisabledUntil(this.getRetryAfterDate(response));\n this.logWarn(`Too many requests, backing off until ${disabledUntil}`);\n }\n\n return response;\n })\n .catch((error) => {\n this.logError('Failed sending payload to the receiver\\n', JSON.parse(body), error);\n });\n });\n }\n } catch (error) {\n this.logError(error);\n }\n }\n\n private getRetryAfterDate(response: Response): Date {\n const now = Date.now();\n const retryAfterHeader = response.headers.get('Retry-After');\n\n if (retryAfterHeader) {\n const delay = Number(retryAfterHeader);\n\n if (!isNaN(delay)) {\n return new Date(delay * 1000 + now);\n }\n\n const date = Date.parse(retryAfterHeader);\n\n if (!isNaN(date)) {\n return new Date(date);\n }\n }\n\n return new Date(now + this.rateLimitBackoffMs);\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"","sourcesContent":["export interface OtlpTransportRequestOptions extends Omit<RequestInit, 'body' | 'headers'> {\n headers?: Record<string, string>;\n}\n\nexport interface OtlpHttpTransportOptions {\n // will be added as `x-api-key` header\n apiKey?: string;\n\n // how many requests to buffer in total\n bufferSize?: number;\n\n // how many requests to execute concurrently\n concurrency?: number;\n\n // if rate limit response does not include a Retry-After header,\n // how many milliseconds to back off before attempting a request.\n // intermediate events will be dropped, not buffered\n defaultRateLimitBackoffMs?: number;\n\n // addition options for global.Fetch\n requestOptions?: OtlpTransportRequestOptions;\n\n // The Otel spec defines separate endpoints per signal\n readonly tracesURL?: string;\n readonly logsURL?: string;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ExceptionEvent, MeasurementEvent, TransportItem } from '@grafana/faro-core';\n\nexport interface OtlpTransportRequestOptions extends Omit<RequestInit, 'body' | 'headers'> {\n headers?: Record<string, string>;\n}\n\nexport interface OtlpHttpTransportOptions {\n // will be added as `x-api-key` header\n apiKey?: string;\n\n // how many requests to buffer in total\n bufferSize?: number;\n\n // how many requests to execute concurrently\n concurrency?: number;\n\n // if rate limit response does not include a Retry-After header,\n // how many milliseconds to back off before attempting a request.\n // intermediate events will be dropped, not buffered\n defaultRateLimitBackoffMs?: number;\n\n // addition options for global.Fetch\n requestOptions?: OtlpTransportRequestOptions;\n\n // The Otel spec defines separate endpoints per signal\n readonly tracesURL?: string;\n readonly logsURL?: string;\n\n // customize aspects about logs transformation\n otlpTransform?: {\n // Body field is optional in Otel Log spec, but can cause issues with Otel Collector components.\n // By default Faro does not send a body for logs of type error and measurement.\n // Users can define a body string by using the following functions.\n createErrorLogBody?: (item: TransportItem<ExceptionEvent>) => string;\n createMeasurementLogBody?: (item: TransportItem<MeasurementEvent>) => string;\n };\n}\n"]}
@@ -1,12 +1,19 @@
1
1
  import { InternalLogger, TransportItem } from '@grafana/faro-core';
2
+ import type { OtlpHttpTransportOptions } from '../types';
2
3
  import type { OtelTransportPayload } from './types';
4
+ type OtelPayloadParams = {
5
+ internalLogger: InternalLogger;
6
+ transportItem?: TransportItem;
7
+ customOtlpTransform?: OtlpHttpTransportOptions['otlpTransform'];
8
+ };
3
9
  export declare class OtelPayload {
4
- private internalLogger;
5
10
  private resourceLogs;
6
11
  private resourceSpans;
7
12
  private getLogTransforms;
8
13
  private getTraceTransforms;
9
- constructor(internalLogger: InternalLogger, transportItem?: TransportItem);
14
+ private internalLogger;
15
+ constructor({ internalLogger, customOtlpTransform, transportItem }: OtelPayloadParams);
10
16
  getPayload(): OtelTransportPayload;
11
17
  addResourceItem(transportItem: TransportItem): void;
12
18
  }
19
+ export {};
@@ -1,2 +1,2 @@
1
1
  export { getLogTransforms, getTraceTransforms } from './transform';
2
- export type { LogRecord, LogTransportItem, ResourceLogs, LogsTransform, Resource, ResourceLog, ResourceSpan, ResourceSpans, Scope, ScopeLog, TraceTransform, } from './types';
2
+ export type { LogRecord, LogTransportItem, ResourceLogs, LogsTransform, Resource, ResourceLog, ResourceSpan, ResourceSpans, Scope, ScopeLog, TraceTransform, StringValueNonNullable, } from './types';
@@ -1,4 +1,5 @@
1
1
  import type { InternalLogger } from '@grafana/faro-core';
2
+ import type { OtlpHttpTransportOptions } from '../../types';
2
3
  import type { LogsTransform, TraceTransform } from './types';
3
- export declare function getLogTransforms(internalLogger: InternalLogger): LogsTransform;
4
+ export declare function getLogTransforms(internalLogger: InternalLogger, customOtlpTransform?: OtlpHttpTransportOptions['otlpTransform']): LogsTransform;
4
5
  export declare function getTraceTransforms(_internalLogger?: InternalLogger): TraceTransform;
@@ -46,3 +46,6 @@ export type TraceTransform = {
46
46
  toResourceSpan: (transportItem: TransportItem<TraceEvent>) => ResourceSpan;
47
47
  };
48
48
  export type ResourceMeta = Pick<Meta, 'app' | 'browser' | 'sdk'>;
49
+ export type StringValueNonNullable = {
50
+ stringValue: string;
51
+ };
@@ -3,7 +3,7 @@ import type { OtlpHttpTransportOptions } from './types';
3
3
  export declare class OtlpHttpTransport extends BaseTransport {
4
4
  private options;
5
5
  readonly name = "@grafana/faro-web-sdk:transport-otlp-http";
6
- readonly version = "1.3.4";
6
+ readonly version = "1.3.6";
7
7
  private readonly promiseBuffer;
8
8
  private readonly rateLimitBackoffMs;
9
9
  private sendingTracesDisabledUntil;
@@ -1,3 +1,4 @@
1
+ import type { ExceptionEvent, MeasurementEvent, TransportItem } from '@grafana/faro-core';
1
2
  export interface OtlpTransportRequestOptions extends Omit<RequestInit, 'body' | 'headers'> {
2
3
  headers?: Record<string, string>;
3
4
  }
@@ -9,4 +10,8 @@ export interface OtlpHttpTransportOptions {
9
10
  requestOptions?: OtlpTransportRequestOptions;
10
11
  readonly tracesURL?: string;
11
12
  readonly logsURL?: string;
13
+ otlpTransform?: {
14
+ createErrorLogBody?: (item: TransportItem<ExceptionEvent>) => string;
15
+ createMeasurementLogBody?: (item: TransportItem<MeasurementEvent>) => string;
16
+ };
12
17
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grafana/faro-transport-otlp-http",
3
- "version": "1.3.4",
3
+ "version": "1.3.6",
4
4
  "description": "Faro transport which converts the Faro data model to the Otlp data model.",
5
5
  "keywords": [
6
6
  "observability",
@@ -50,10 +50,10 @@
50
50
  "quality:circular-deps": "madge --circular ."
51
51
  },
52
52
  "devDependencies": {
53
- "@grafana/faro-core": "^1.3.4"
53
+ "@grafana/faro-core": "^1.3.6"
54
54
  },
55
55
  "publishConfig": {
56
56
  "access": "public"
57
57
  },
58
- "gitHead": "caa46ae232e9bba1fc83604a58553ee5a8d0bb39"
58
+ "gitHead": "95ff610fa16233bbb35484b81ee65daaa5d725c0"
59
59
  }