@kush_hemant/react-api-monitor 1.0.0

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.
package/package.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "name": "@kush_hemant/react-api-monitor",
3
+ "version": "1.0.0",
4
+ "description": "Automatic API monitoring SDK for React apps",
5
+ "main": "src/index.js",
6
+ "type": "module",
7
+ "keywords": [
8
+ "react",
9
+ "monitoring",
10
+ "api",
11
+ "logging",
12
+ "observability"
13
+ ],
14
+ "author": "Hemant Kushwah",
15
+ "license": "MIT"
16
+ }
@@ -0,0 +1,7 @@
1
+ import { configureSender } from "./sender";
2
+ import { startNetworkMonitoring } from "../network/auto";
3
+
4
+ export function initMonitoring(options) {
5
+ configureSender(options.endpoint);
6
+ startNetworkMonitoring();
7
+ }
@@ -0,0 +1,20 @@
1
+ let endpoint = "";
2
+
3
+ export function configureSender(url) {
4
+ endpoint = url;
5
+ }
6
+
7
+ export function sendLog(data) {
8
+ if (!endpoint) return;
9
+
10
+ navigator.sendBeacon?.(
11
+ endpoint,
12
+ JSON.stringify(data)
13
+ ) ||
14
+ fetch(endpoint, {
15
+ method: "POST",
16
+ headers: { "Content-Type": "application/json" },
17
+ body: JSON.stringify(data),
18
+ keepalive: true,
19
+ }).catch(() => {});
20
+ }
package/src/index.js ADDED
@@ -0,0 +1 @@
1
+ export { initMonitoring } from "./core/init";
File without changes
@@ -0,0 +1,54 @@
1
+ import { sendLog } from "../core/sender";
2
+ import { getMetadata } from "../utils/metadata";
3
+
4
+ export function monitorFetch() {
5
+ const originalFetch = window.fetch;
6
+
7
+ window.fetch = async (input, init = {}) => {
8
+ const start = Date.now();
9
+
10
+ let requestBody = init.body || null;
11
+ let method = init.method || "GET";
12
+
13
+ try {
14
+ const response = await originalFetch(input, init);
15
+
16
+ // Clone response to read body safely
17
+ const clone = response.clone();
18
+ let responseBody = null;
19
+
20
+ try {
21
+ responseBody = await clone.text();
22
+ } catch {}
23
+
24
+ sendLog({
25
+ type: "api_call",
26
+ transport: "fetch",
27
+ url: typeof input === "string" ? input : input.url,
28
+ method,
29
+ statusCode: response.status,
30
+ requestHeaders: init.headers,
31
+ requestBody,
32
+ responseHeaders: Object.fromEntries(
33
+ response.headers.entries()
34
+ ),
35
+ responseBody,
36
+ duration: Date.now() - start,
37
+ ...getMetadata(),
38
+ });
39
+
40
+ return response;
41
+ } catch (err) {
42
+ sendLog({
43
+ type: "api_error",
44
+ transport: "fetch",
45
+ url: input,
46
+ method,
47
+ error: err.message,
48
+ ...getMetadata(),
49
+ });
50
+
51
+ throw err;
52
+ }
53
+ };
54
+ }
@@ -0,0 +1,50 @@
1
+ import { sendLog } from "../core/sender";
2
+ import { getMetadata } from "../utils/metadata";
3
+
4
+ export function monitorXHR() {
5
+ const originalOpen = XMLHttpRequest.prototype.open;
6
+ const originalSend = XMLHttpRequest.prototype.send;
7
+ const originalSetHeader =
8
+ XMLHttpRequest.prototype.setRequestHeader;
9
+
10
+ XMLHttpRequest.prototype.open = function (
11
+ method,
12
+ url,
13
+ ...rest
14
+ ) {
15
+ this._method = method;
16
+ this._url = url;
17
+ this._headers = {};
18
+ return originalOpen.call(this, method, url, ...rest);
19
+ };
20
+
21
+ XMLHttpRequest.prototype.setRequestHeader = function (
22
+ key,
23
+ value
24
+ ) {
25
+ this._headers[key] = value;
26
+ return originalSetHeader.call(this, key, value);
27
+ };
28
+
29
+ XMLHttpRequest.prototype.send = function (body) {
30
+ const start = Date.now();
31
+
32
+ this.addEventListener("loadend", () => {
33
+ sendLog({
34
+ type: "api_call",
35
+ transport: "xhr",
36
+ url: this._url,
37
+ method: this._method,
38
+ statusCode: this.status,
39
+ requestHeaders: this._headers,
40
+ requestBody: body,
41
+ responseHeaders: this.getAllResponseHeaders(),
42
+ responseBody: this.responseText,
43
+ duration: Date.now() - start,
44
+ ...getMetadata(),
45
+ });
46
+ });
47
+
48
+ return originalSend.call(this, body);
49
+ };
50
+ }
@@ -0,0 +1,7 @@
1
+ export function getMetadata() {
2
+ return {
3
+ pageUrl: window.location.href,
4
+ userAgent: navigator.userAgent,
5
+ timestamp: new Date().toISOString(),
6
+ };
7
+ }