-
Notifications
You must be signed in to change notification settings - Fork 148
Description
Description
I'm working on an Electron based project and sending the logs with logfire to a proxy via @pydantic/logfire-browser
configured like this:
logfire.configure({
traceUrl,
environment: isDev ? 'development' : 'production',
serviceName: app.getName(),
serviceVersion: app.getVersion(),
instrumentations: [getWebAutoInstrumentations()], // <- from @opentelemetry/auto-instrumentations-web
});
I noticed that at first, logs from development mode (when the app was not packaged yet) did not show in the platform. When diving into the error, I found that it was because XMLHttpRequest
was being used in the @opentelemetry/otlp-exporter-base
but it was not defined (probably because of the electron environment).
This error started happening on production (packaged app) as well, and making a patch that replaced the XMLHttpRequest with regular fetch call was enough to make it work again. I wanted to know if this is a bug or it is intentional and there is something different that is needed to be done on electron projects
Patch:
diff --git a/node_modules/@opentelemetry/otlp-exporter-base/build/src/transport/xhr-transport.js b/node_modules/@opentelemetry/otlp-exporter-base/build/src/transport/xhr-transport.js
index 47dc7bf..eefa3ad 100644
--- a/node_modules/@opentelemetry/otlp-exporter-base/build/src/transport/xhr-transport.js
+++ b/node_modules/@opentelemetry/otlp-exporter-base/build/src/transport/xhr-transport.js
@@ -23,62 +23,58 @@ class XhrTransport {
constructor(_parameters) {
this._parameters = _parameters;
}
- send(data, timeoutMillis) {
- return new Promise(resolve => {
- const xhr = new XMLHttpRequest();
- xhr.timeout = timeoutMillis;
- xhr.open('POST', this._parameters.url);
+ async send(data, timeoutMillis) {
+ try {
+ const controller = new AbortController();
+ const timeoutId = setTimeout(() => controller.abort(), timeoutMillis);
+
const headers = this._parameters.headers();
- Object.entries(headers).forEach(([k, v]) => {
- xhr.setRequestHeader(k, v);
+ const response = await fetch(this._parameters.url, {
+ method: 'POST',
+ headers: headers,
+ body: data,
+ signal: controller.signal
});
- xhr.ontimeout = _ => {
- resolve({
+
+ clearTimeout(timeoutId);
+
+ if (response.status >= 200 && response.status <= 299) {
+ api_1.diag.debug('Fetch request success');
+ return {
+ status: 'success',
+ };
+ } else if ((0, is_export_retryable_1.isExportRetryable)(response.status)) {
+ const retryAfter = response.headers.get('Retry-After');
+ return {
+ status: 'retryable',
+ retryInMillis: (0, is_export_retryable_1.parseRetryAfterToMills)(retryAfter),
+ };
+ } else {
+ return {
status: 'failure',
- error: new Error('XHR request timed out'),
- });
- };
- xhr.onreadystatechange = () => {
- if (xhr.status >= 200 && xhr.status <= 299) {
- api_1.diag.debug('XHR success');
- resolve({
- status: 'success',
- });
- }
- else if (xhr.status && (0, is_export_retryable_1.isExportRetryable)(xhr.status)) {
- resolve({
- status: 'retryable',
- retryInMillis: (0, is_export_retryable_1.parseRetryAfterToMills)(xhr.getResponseHeader('Retry-After')),
- });
- }
- else if (xhr.status !== 0) {
- resolve({
- status: 'failure',
- error: new Error('XHR request failed with non-retryable status'),
- });
- }
- };
- xhr.onabort = () => {
- resolve({
+ error: new Error('Fetch request failed with non-retryable status'),
+ };
+ }
+ } catch (error) {
+ if (error.name === 'AbortError') {
+ return {
status: 'failure',
- error: new Error('XHR request aborted'),
- });
- };
- xhr.onerror = () => {
- resolve({
+ error: new Error('Fetch request timed out'),
+ };
+ } else {
+ return {
status: 'failure',
- error: new Error('XHR request errored'),
- });
- };
- xhr.send(data);
- });
+ error: new Error(`Fetch request failed: ${error.message}`),
+ };
+ }
+ }
}
shutdown() {
// Intentionally left empty, nothing to do.
}
}
/**
- * Creates an exporter transport that uses XHR to send the data
+ * Creates an exporter transport that uses fetch to send the data
* @param parameters applied to each request made by transport
*/
function createXhrTransport(parameters) {
Python, Logfire & OS Versions, related packages (not required)
"@opentelemetry/auto-instrumentations-web": "^0.49.0",
"@pydantic/logfire-browser": "^0.9.0",
"electron": "^37.2.6"