@zhongxiaobing/monitor-react 0.1.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/README.md +53 -0
- package/dist/index.d.mts +151 -0
- package/dist/index.d.ts +151 -0
- package/dist/index.js +764 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +737 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# @zhongxiaobing/monitor-react React 接入
|
|
2
|
+
|
|
3
|
+
## 极简接入
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import React from 'react'
|
|
7
|
+
import ReactDOM from 'react-dom/client'
|
|
8
|
+
import { BrowserRouter } from 'react-router-dom'
|
|
9
|
+
import { createReactMonitor } from '@zhongxiaobing/monitor-react'
|
|
10
|
+
import App from './App'
|
|
11
|
+
|
|
12
|
+
const { MonitorRoot, monitor } = createReactMonitor({
|
|
13
|
+
appId: 'my-react-app',
|
|
14
|
+
appName: 'My React App',
|
|
15
|
+
env: 'prod',
|
|
16
|
+
dsn: '/api/collect'
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
20
|
+
<React.StrictMode>
|
|
21
|
+
<BrowserRouter>
|
|
22
|
+
<MonitorRoot fallback={<div>Something went wrong.</div>}>
|
|
23
|
+
<App />
|
|
24
|
+
</MonitorRoot>
|
|
25
|
+
</BrowserRouter>
|
|
26
|
+
</React.StrictMode>
|
|
27
|
+
)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
默认行为:
|
|
31
|
+
- 自动启用 error、network、blankScreen 三个默认插件
|
|
32
|
+
- 自动挂载 React ErrorBoundary
|
|
33
|
+
- 可通过 `monitor.captureException(...)` 手动上报异常
|
|
34
|
+
|
|
35
|
+
## 可选配置
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
const { MonitorRoot } = createReactMonitor({
|
|
39
|
+
appId: 'my-react-app',
|
|
40
|
+
env: 'prod',
|
|
41
|
+
dsn: '/api/collect',
|
|
42
|
+
fallback: <div>Something went wrong.</div>,
|
|
43
|
+
blankScreen: {
|
|
44
|
+
detectOnRouteChange: true,
|
|
45
|
+
delayMs: 3000,
|
|
46
|
+
routeChangeDelayMs: 1500
|
|
47
|
+
},
|
|
48
|
+
disableDefaultPlugins: ['blankScreen'],
|
|
49
|
+
beforeSend(event) {
|
|
50
|
+
return event
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
```
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import React, { ReactNode, ComponentType, Component, ErrorInfo } from 'react';
|
|
2
|
+
|
|
3
|
+
type MonitorEventType = 'exception' | 'resource_error' | 'http_error' | 'blank_screen';
|
|
4
|
+
interface Breadcrumb {
|
|
5
|
+
type: string;
|
|
6
|
+
category?: string;
|
|
7
|
+
message?: string;
|
|
8
|
+
timestamp: number;
|
|
9
|
+
data?: Record<string, unknown>;
|
|
10
|
+
}
|
|
11
|
+
interface BaseEvent {
|
|
12
|
+
eventId: string;
|
|
13
|
+
eventType: MonitorEventType;
|
|
14
|
+
appId: string;
|
|
15
|
+
appName?: string;
|
|
16
|
+
env: string;
|
|
17
|
+
release?: string;
|
|
18
|
+
url: string;
|
|
19
|
+
pathname: string;
|
|
20
|
+
title: string;
|
|
21
|
+
timestamp: number;
|
|
22
|
+
userAgent: string;
|
|
23
|
+
userId?: string;
|
|
24
|
+
deviceId?: string;
|
|
25
|
+
breadcrumbs?: Breadcrumb[];
|
|
26
|
+
tags?: Record<string, string>;
|
|
27
|
+
extra?: Record<string, unknown>;
|
|
28
|
+
}
|
|
29
|
+
interface ExceptionEvent extends BaseEvent {
|
|
30
|
+
eventType: 'exception';
|
|
31
|
+
error: {
|
|
32
|
+
name?: string;
|
|
33
|
+
message: string;
|
|
34
|
+
stack?: string;
|
|
35
|
+
source?: string;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
interface HttpErrorEvent extends BaseEvent {
|
|
39
|
+
eventType: 'http_error';
|
|
40
|
+
request: {
|
|
41
|
+
url: string;
|
|
42
|
+
method: string;
|
|
43
|
+
status?: number;
|
|
44
|
+
duration?: number;
|
|
45
|
+
success: boolean;
|
|
46
|
+
source?: 'fetch' | 'xhr';
|
|
47
|
+
};
|
|
48
|
+
response?: {
|
|
49
|
+
code?: string | number;
|
|
50
|
+
message?: string;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
interface BlankScreenEvent extends BaseEvent {
|
|
54
|
+
eventType: 'blank_screen';
|
|
55
|
+
blankScreen: {
|
|
56
|
+
score: number;
|
|
57
|
+
rootSelector?: string;
|
|
58
|
+
domSummary?: string[];
|
|
59
|
+
readyState?: string;
|
|
60
|
+
trigger?: 'initial' | 'route_change' | 'manual';
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
type MonitorEvent = ExceptionEvent | HttpErrorEvent | BlankScreenEvent;
|
|
64
|
+
|
|
65
|
+
interface MonitorApi {
|
|
66
|
+
emit(event: MonitorEvent): void;
|
|
67
|
+
captureException(error: unknown, extra?: Record<string, unknown>): void;
|
|
68
|
+
}
|
|
69
|
+
interface PluginSetupContext {
|
|
70
|
+
api: MonitorApi;
|
|
71
|
+
options: MonitorInitOptions;
|
|
72
|
+
}
|
|
73
|
+
interface MonitorPlugin {
|
|
74
|
+
name: string;
|
|
75
|
+
setup(context: PluginSetupContext): void | (() => void);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
interface MonitorInitOptions {
|
|
79
|
+
appId: string;
|
|
80
|
+
appName?: string;
|
|
81
|
+
env: string;
|
|
82
|
+
release?: string;
|
|
83
|
+
dsn: string;
|
|
84
|
+
sampleRate?: number;
|
|
85
|
+
plugins?: MonitorPlugin[];
|
|
86
|
+
beforeSend?: (event: MonitorEvent) => MonitorEvent | null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
interface BlankScreenPluginOptions {
|
|
90
|
+
rootSelector?: string;
|
|
91
|
+
delayMs?: number;
|
|
92
|
+
scoreThreshold?: number;
|
|
93
|
+
samplePoints?: Array<[number, number]>;
|
|
94
|
+
ignoreSelectors?: string[];
|
|
95
|
+
detectOnRouteChange?: boolean;
|
|
96
|
+
routeChangeDelayMs?: number;
|
|
97
|
+
dedupeWindowMs?: number;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
interface ErrorPluginOptions {
|
|
101
|
+
captureOnError?: boolean;
|
|
102
|
+
captureUnhandledRejection?: boolean;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
interface NetworkPluginOptions {
|
|
106
|
+
timeoutMs?: number;
|
|
107
|
+
capture5xx?: boolean;
|
|
108
|
+
captureTimeout?: boolean;
|
|
109
|
+
captureNetworkError?: boolean;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
type DefaultReactMonitorPluginName = 'error' | 'network' | 'blankScreen';
|
|
113
|
+
interface CreateReactMonitorOptions extends Omit<MonitorInitOptions, 'plugins'> {
|
|
114
|
+
plugins?: MonitorPlugin[];
|
|
115
|
+
disableDefaultPlugins?: DefaultReactMonitorPluginName[];
|
|
116
|
+
error?: ErrorPluginOptions;
|
|
117
|
+
network?: NetworkPluginOptions;
|
|
118
|
+
blankScreen?: BlankScreenPluginOptions;
|
|
119
|
+
fallback?: ReactNode;
|
|
120
|
+
}
|
|
121
|
+
interface MonitorRootProps {
|
|
122
|
+
children: ReactNode;
|
|
123
|
+
fallback?: ReactNode;
|
|
124
|
+
}
|
|
125
|
+
interface ReactMonitorInstance {
|
|
126
|
+
monitor: MonitorApi;
|
|
127
|
+
MonitorRoot: (props: MonitorRootProps) => ReactNode;
|
|
128
|
+
withMonitor: <TProps extends object>(Component: ComponentType<TProps>) => ComponentType<TProps>;
|
|
129
|
+
}
|
|
130
|
+
declare function createReactMonitor(options: CreateReactMonitorOptions): ReactMonitorInstance;
|
|
131
|
+
declare function useMonitor(): MonitorApi;
|
|
132
|
+
|
|
133
|
+
interface MonitorErrorBoundaryProps {
|
|
134
|
+
monitor: MonitorApi;
|
|
135
|
+
fallback?: ReactNode;
|
|
136
|
+
children: ReactNode;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
interface MonitorErrorBoundaryState {
|
|
140
|
+
hasError: boolean;
|
|
141
|
+
}
|
|
142
|
+
declare class MonitorErrorBoundary extends Component<MonitorErrorBoundaryProps, MonitorErrorBoundaryState> {
|
|
143
|
+
state: MonitorErrorBoundaryState;
|
|
144
|
+
static getDerivedStateFromError(): {
|
|
145
|
+
hasError: boolean;
|
|
146
|
+
};
|
|
147
|
+
componentDidCatch(error: Error, info: ErrorInfo): void;
|
|
148
|
+
render(): React.ReactNode;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export { type CreateReactMonitorOptions, type DefaultReactMonitorPluginName, MonitorErrorBoundary, type MonitorErrorBoundaryProps, type MonitorRootProps, type ReactMonitorInstance, createReactMonitor, useMonitor };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import React, { ReactNode, ComponentType, Component, ErrorInfo } from 'react';
|
|
2
|
+
|
|
3
|
+
type MonitorEventType = 'exception' | 'resource_error' | 'http_error' | 'blank_screen';
|
|
4
|
+
interface Breadcrumb {
|
|
5
|
+
type: string;
|
|
6
|
+
category?: string;
|
|
7
|
+
message?: string;
|
|
8
|
+
timestamp: number;
|
|
9
|
+
data?: Record<string, unknown>;
|
|
10
|
+
}
|
|
11
|
+
interface BaseEvent {
|
|
12
|
+
eventId: string;
|
|
13
|
+
eventType: MonitorEventType;
|
|
14
|
+
appId: string;
|
|
15
|
+
appName?: string;
|
|
16
|
+
env: string;
|
|
17
|
+
release?: string;
|
|
18
|
+
url: string;
|
|
19
|
+
pathname: string;
|
|
20
|
+
title: string;
|
|
21
|
+
timestamp: number;
|
|
22
|
+
userAgent: string;
|
|
23
|
+
userId?: string;
|
|
24
|
+
deviceId?: string;
|
|
25
|
+
breadcrumbs?: Breadcrumb[];
|
|
26
|
+
tags?: Record<string, string>;
|
|
27
|
+
extra?: Record<string, unknown>;
|
|
28
|
+
}
|
|
29
|
+
interface ExceptionEvent extends BaseEvent {
|
|
30
|
+
eventType: 'exception';
|
|
31
|
+
error: {
|
|
32
|
+
name?: string;
|
|
33
|
+
message: string;
|
|
34
|
+
stack?: string;
|
|
35
|
+
source?: string;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
interface HttpErrorEvent extends BaseEvent {
|
|
39
|
+
eventType: 'http_error';
|
|
40
|
+
request: {
|
|
41
|
+
url: string;
|
|
42
|
+
method: string;
|
|
43
|
+
status?: number;
|
|
44
|
+
duration?: number;
|
|
45
|
+
success: boolean;
|
|
46
|
+
source?: 'fetch' | 'xhr';
|
|
47
|
+
};
|
|
48
|
+
response?: {
|
|
49
|
+
code?: string | number;
|
|
50
|
+
message?: string;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
interface BlankScreenEvent extends BaseEvent {
|
|
54
|
+
eventType: 'blank_screen';
|
|
55
|
+
blankScreen: {
|
|
56
|
+
score: number;
|
|
57
|
+
rootSelector?: string;
|
|
58
|
+
domSummary?: string[];
|
|
59
|
+
readyState?: string;
|
|
60
|
+
trigger?: 'initial' | 'route_change' | 'manual';
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
type MonitorEvent = ExceptionEvent | HttpErrorEvent | BlankScreenEvent;
|
|
64
|
+
|
|
65
|
+
interface MonitorApi {
|
|
66
|
+
emit(event: MonitorEvent): void;
|
|
67
|
+
captureException(error: unknown, extra?: Record<string, unknown>): void;
|
|
68
|
+
}
|
|
69
|
+
interface PluginSetupContext {
|
|
70
|
+
api: MonitorApi;
|
|
71
|
+
options: MonitorInitOptions;
|
|
72
|
+
}
|
|
73
|
+
interface MonitorPlugin {
|
|
74
|
+
name: string;
|
|
75
|
+
setup(context: PluginSetupContext): void | (() => void);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
interface MonitorInitOptions {
|
|
79
|
+
appId: string;
|
|
80
|
+
appName?: string;
|
|
81
|
+
env: string;
|
|
82
|
+
release?: string;
|
|
83
|
+
dsn: string;
|
|
84
|
+
sampleRate?: number;
|
|
85
|
+
plugins?: MonitorPlugin[];
|
|
86
|
+
beforeSend?: (event: MonitorEvent) => MonitorEvent | null;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
interface BlankScreenPluginOptions {
|
|
90
|
+
rootSelector?: string;
|
|
91
|
+
delayMs?: number;
|
|
92
|
+
scoreThreshold?: number;
|
|
93
|
+
samplePoints?: Array<[number, number]>;
|
|
94
|
+
ignoreSelectors?: string[];
|
|
95
|
+
detectOnRouteChange?: boolean;
|
|
96
|
+
routeChangeDelayMs?: number;
|
|
97
|
+
dedupeWindowMs?: number;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
interface ErrorPluginOptions {
|
|
101
|
+
captureOnError?: boolean;
|
|
102
|
+
captureUnhandledRejection?: boolean;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
interface NetworkPluginOptions {
|
|
106
|
+
timeoutMs?: number;
|
|
107
|
+
capture5xx?: boolean;
|
|
108
|
+
captureTimeout?: boolean;
|
|
109
|
+
captureNetworkError?: boolean;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
type DefaultReactMonitorPluginName = 'error' | 'network' | 'blankScreen';
|
|
113
|
+
interface CreateReactMonitorOptions extends Omit<MonitorInitOptions, 'plugins'> {
|
|
114
|
+
plugins?: MonitorPlugin[];
|
|
115
|
+
disableDefaultPlugins?: DefaultReactMonitorPluginName[];
|
|
116
|
+
error?: ErrorPluginOptions;
|
|
117
|
+
network?: NetworkPluginOptions;
|
|
118
|
+
blankScreen?: BlankScreenPluginOptions;
|
|
119
|
+
fallback?: ReactNode;
|
|
120
|
+
}
|
|
121
|
+
interface MonitorRootProps {
|
|
122
|
+
children: ReactNode;
|
|
123
|
+
fallback?: ReactNode;
|
|
124
|
+
}
|
|
125
|
+
interface ReactMonitorInstance {
|
|
126
|
+
monitor: MonitorApi;
|
|
127
|
+
MonitorRoot: (props: MonitorRootProps) => ReactNode;
|
|
128
|
+
withMonitor: <TProps extends object>(Component: ComponentType<TProps>) => ComponentType<TProps>;
|
|
129
|
+
}
|
|
130
|
+
declare function createReactMonitor(options: CreateReactMonitorOptions): ReactMonitorInstance;
|
|
131
|
+
declare function useMonitor(): MonitorApi;
|
|
132
|
+
|
|
133
|
+
interface MonitorErrorBoundaryProps {
|
|
134
|
+
monitor: MonitorApi;
|
|
135
|
+
fallback?: ReactNode;
|
|
136
|
+
children: ReactNode;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
interface MonitorErrorBoundaryState {
|
|
140
|
+
hasError: boolean;
|
|
141
|
+
}
|
|
142
|
+
declare class MonitorErrorBoundary extends Component<MonitorErrorBoundaryProps, MonitorErrorBoundaryState> {
|
|
143
|
+
state: MonitorErrorBoundaryState;
|
|
144
|
+
static getDerivedStateFromError(): {
|
|
145
|
+
hasError: boolean;
|
|
146
|
+
};
|
|
147
|
+
componentDidCatch(error: Error, info: ErrorInfo): void;
|
|
148
|
+
render(): React.ReactNode;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export { type CreateReactMonitorOptions, type DefaultReactMonitorPluginName, MonitorErrorBoundary, type MonitorErrorBoundaryProps, type MonitorRootProps, type ReactMonitorInstance, createReactMonitor, useMonitor };
|