Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[network-plugin] Feat: Capture network events #1105

Open
wants to merge 43 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
7c5f909
record xhr
jlalmes Jan 31, 2023
ada77af
use performance
jlalmes Feb 1, 2023
2b23db5
emit less events & isInitial flag
jlalmes Feb 1, 2023
dafbdd4
stub xhr & fetch observers
jlalmes Feb 1, 2023
6e9377a
stub req headers & body
jlalmes Feb 1, 2023
27f4360
small type refactor
jlalmes Feb 1, 2023
7fa75b5
add NavigationTiming
jlalmes Feb 1, 2023
52c58b3
rename props
jlalmes Feb 1, 2023
05a45df
implement fetch
jlalmes Feb 1, 2023
863717d
use stringify
jlalmes Feb 1, 2023
e693366
refactor options
jlalmes Feb 1, 2023
78b338f
add requestMethod
jlalmes Feb 1, 2023
d656ac7
rename replay prop
jlalmes Feb 1, 2023
1d77b6c
add ignoreRequestFn
jlalmes Feb 1, 2023
f3d85e2
rn initiatorTypes
jlalmes Feb 1, 2023
a503ca4
fix build and rename prop
jlalmes Feb 1, 2023
ca21bab
bug fix
jlalmes Feb 1, 2023
70395af
move win.perf check up
jlalmes Feb 1, 2023
0e08bc7
better last perf entry
jlalmes Feb 1, 2023
9d33b47
implement xhr
jlalmes Feb 1, 2023
a174964
better xhr events implementation
jlalmes Feb 1, 2023
7f9ba0d
skip empty request callbacks
jlalmes Feb 1, 2023
ad966bc
by url
jlalmes Feb 1, 2023
0ae1f06
linting
jlalmes Feb 1, 2023
147aba6
fix xhr
jlalmes Feb 2, 2023
ec4010f
better getRequestPerformanceEntry
jlalmes Feb 2, 2023
c5a1d14
dont filter xhr & fetch from initial
jlalmes Feb 2, 2023
6566294
fix xhr
jlalmes Feb 2, 2023
dcf3721
add responseStatus
jlalmes Feb 2, 2023
a131e37
docs
jlalmes Feb 2, 2023
dba49bf
formatting
jlalmes Feb 2, 2023
15ecfcf
slim NetworkRequest
jlalmes Feb 4, 2023
fc5b77a
update docs
jlalmes Feb 4, 2023
a0c721b
startTime & endTime
jlalmes Feb 7, 2023
d7db138
fix: warning from rollup
jlalmes Feb 7, 2023
8fdec47
moved findLast util
jlalmes Feb 7, 2023
0f30b29
any body
jlalmes Feb 7, 2023
8c41efd
better patch
jlalmes Feb 7, 2023
cae71f7
content-type body filtering
jlalmes Feb 7, 2023
d860433
update docs
jlalmes Feb 7, 2023
0278113
better body typing
jlalmes Feb 8, 2023
6804e4b
better recordBody
jlalmes Feb 8, 2023
8863576
Update docs/recipes/network.md
jlalmes Feb 20, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions docs/recipes/network.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# network recorder and replayer

Starting from v2.0.0, we add the plugin to record network output.
This feature aims to provide developers with more information about the bug scene. There are some options for recording and replaying network output.

### Enable recording network

You can enable using default option like this:

```js
rrweb.record({
emit: function emit(event) {
events.push(event);
},
// to use default record option
plugins: [rrweb.getRecordNetworkPlugin()],
});
```

You can also customize the behavior of logger like this:

```js
rrweb.record({
emit: function emit(event) {
fetch('https://api.my-server.com/events', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
events: [event],
}),
});
},
// customized record options
plugins: [
rrweb.getRecordConsolePlugin({
jlalmes marked this conversation as resolved.
Show resolved Hide resolved
initiatorTypes: ['fetch', 'xmlhttprequest'],
// block recording event for request to upload events to server
ignoreRequestFn: (request) => {
if (request.url === 'https://api.my-server.com/events') {
return true;
}
return false;
},
recordHeaders: true,
recordBody: true,
recordInitialRequests: false,
}),
],
});
```

**alert**: If you are uploading events to a server, you should always use `ignoreRequestFn` to block recording events for these requests or else you will cause a nasty loop.

All options are described below:
| key | default | description |
| ---------------- | --------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| initiatorTypes | `['fetch','xmlhttprequest','img',...]` | Default value contains names of all [initiator types](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/initiatorType). You can override it by setting the types you need. |
| ignoreRequestFn | `() => false` | Block recording events for specific requests |
| recordHeaders | `false` | Record the request & response headers for `fetch` and `xmlhttprequest` requests |
| recordBody | `false` | Record the request & response bodies for `fetch` and `xmlhttprequest` requests |
| recordInitialRequests | `false` | Record an event for all requests prior to rrweb.record() being called |

## replay network

It is up to you to decide how to best replay your network events using the `onNetworkData` callback.

```js
const replayer = new rrweb.Replayer(events, {
plugins: [
rrweb.getReplayNetworkPlugin({
onNetworkData: ({ requests }) => {
for (const request of requests) {
const url = request.url;
const method = request.method;
const status = request.status;
console.log(`${method} ${url} ${status}`);
}
},
}),
],
});
replayer.play();
```

Description of replay option is as follows:

| key | default | description |
| ------------- | ----------- | ------------------------------------------------------------------------------------------ |
| onNetworkData | `undefined` | You could use this interface to replay the network requests in a simulated browser console |

## technical implementation

This implementation records [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) and [`XMLHttpRequest`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) by patching their object & methods. We record document navigation using [`PerformanceNavigationTiming`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceNavigationTiming) and we use [`PerformanceResourceTiming`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming) for recording everything else (script, img, link etc.) via [`PerformanceObserver`](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceObserver) API.

For more information please see [[network-plugin] Feat: Capture network events #1105](https://github.com/rrweb-io/rrweb/pull/1105) PR.
2 changes: 2 additions & 0 deletions packages/rrweb/src/entries/all.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ export * from '../index';
export * from '../packer';
export * from '../plugins/console/record';
export * from '../plugins/console/replay';
export * from '../plugins/network/record';
export * from '../plugins/network/replay';
19 changes: 2 additions & 17 deletions packages/rrweb/src/plugins/console/record/index.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,7 @@
import type { listenerHandler, RecordPlugin, IWindow } from '@rrweb/types';
import { patch } from '../../../utils';
import { ErrorStackParser, StackFrame } from './error-stack-parser';
import { stringify } from './stringify';

export type StringifyOptions = {
// limit of string length
stringLengthLimit?: number;
/**
* limit of number of keys in an object
* if an object contains more keys than this limit, we would call its toString function directly
*/
numOfKeysLimit: number;
/**
* limit number of depth in an object
* if an object is too deep, toString process may cause browser OOM
*/
depthOfLimit: number;
};
import { ErrorStackParser, StackFrame } from '../../utils/error-stack-parser';
import { stringify, StringifyOptions } from '../../utils/stringify';

type LogRecordOptions = {
level?: LogLevel[];
Expand Down
Loading