根據前篇我們知道,Opentelemetry 在前端實現tracing,是需要覆蓋全局 fetch
、或者全局的 XMLHttpRequest
。本文我們就來實現這兩者,然後透過 call 一個簡單後端 api,從後端打印 request header,看我們有沒有覆蓋成功。
簡單寫一個sdk配置,在初始化的時候就宣告我們自己寫的 instrumentations,在start的時候就讓所有的 instrmentations 也初始化:
export class MockWebSdk {
constructor() {
this.instruments = [
new MockFetchInstrumentation(),
new MockXMLHttpRequestInstrumentation(),
];
}
start() {
this.instruments.forEach((instruments) => {
instruments.init();
});
}
}
然後在 React 的入口文件main.js
中的最上層引入並初始化:
import { MockWebSdk } from './self-otel/sdk.js';
const sdk = new MockWebSdk();
sdk.start();
...
createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
</StrictMode>,
);
跟之前覆蓋 http
很類似,就是先獲取原本的 fetch 方法
const originalFetch = window.fetch;
然後利用window.fetch = callback
來覆蓋全局的fetch。
window.fetch = async (...args) => {
let [resource, config] = args;
// Create a new configuration object if not provided
config = config || {};
// Ensure headers object exists
config.headers = config.headers || {};
}
獲取或新建一個 request config,然後在header 中增加traceparent
屬性,完成 tracing 的第一步。(這邊就簡單把traceparent
的值寫成 '00-fetchTraceId-mockspanId-01'
)
然後再將原本的 fetch 返回
return originalFetch(resource, config)
.then((response) => {
// TODO: exporter logic
return response;
})
.catch((error) => {
throw error;
});
查看console,可以看到我們的 fetch trace header 成功傳到後端服務了:
也是一樣的思路,XMLHttpRequest是一個物件,我們的覆蓋方式就必須是用繼承
const originalXMLHttpRequest = window.XMLHttpRequest;
class MockXMLHttpRequest extends originalXMLHttpRequest {
constructor() {
super(); // Call the original constructor
this._url = ''; // Store the URL of the request
}
}
然後主要就是覆寫send
方法、來新增 header traceparent
屬性 :
send(body) {
// Add a traceparent header before sending the request
this.setRequestHeader(
'traceparent',
'00-xmlTraceId-mockspanId-01',
);
// Call the original send method
super.send(body);
}
而exporter的邏輯,可以監聽load
事件、然後在callback中實現:
this.addEventListener('load', () => {
// TODO: exporter logic
console.log(`Request to ${this._url} completed.`);
});
查看console,可以看到我們的 xml-http -request trace header 也成功傳到後端服務了:
本次demo中,我們詳細介紹了如何在前端實現 OpenTelemetry tracing,通過覆蓋 fetch
和 XMLHttpRequest
兩種常見的網絡請求方式來注入 traceparent
header,從而實現 tracing data。這種方式使我們可以將前端的 tracing context 傳遞到後端,從而實現全鏈路監控。
本文程式碼可以在此 Github repository 中查看。