@blueking/open-telemetry 0.0.1 → 0.0.4
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 +5 -3
- package/playground/App.vue +0 -148
- package/playground/bk-ot.ts +0 -110
- package/playground/components/DemoLogPanel.vue +0 -89
- package/playground/composables/use-demo-log.ts +0 -39
- package/playground/index.html +0 -13
- package/playground/main.ts +0 -36
- package/playground/mock/index.ts +0 -43
- package/playground/pages/BlankScreenDemo.vue +0 -97
- package/playground/pages/BusinessDemo.vue +0 -74
- package/playground/pages/CustomPluginDemo.vue +0 -104
- package/playground/pages/ErrorDemo.vue +0 -75
- package/playground/pages/Home.vue +0 -133
- package/playground/pages/HttpDemo.vue +0 -120
- package/playground/pages/LongTaskDemo.vue +0 -66
- package/playground/pages/WebSocketDemo.vue +0 -100
- package/playground/router/index.ts +0 -92
- package/playground/style.css +0 -180
- package/src/browser.ts +0 -44
- package/src/core/config.ts +0 -327
- package/src/core/plugin.ts +0 -97
- package/src/core/processor.ts +0 -74
- package/src/core/route-observer.ts +0 -128
- package/src/core/sampling.ts +0 -64
- package/src/core/sdk.ts +0 -327
- package/src/core/url.ts +0 -66
- package/src/index.ts +0 -55
- package/src/plugins/blank-screen.ts +0 -170
- package/src/plugins/common.ts +0 -131
- package/src/plugins/csp-violation.ts +0 -74
- package/src/plugins/device.ts +0 -91
- package/src/plugins/error.ts +0 -211
- package/src/plugins/http-body.ts +0 -437
- package/src/plugins/long-task.ts +0 -99
- package/src/plugins/page-view.ts +0 -83
- package/src/plugins/route-timing.ts +0 -89
- package/src/plugins/session.ts +0 -127
- package/src/plugins/web-vitals.ts +0 -159
- package/src/plugins/websocket.ts +0 -179
- package/tsconfig.app.json +0 -27
- package/tsconfig.dts.json +0 -13
- package/tsconfig.json +0 -7
- package/tsconfig.node.json +0 -26
- package/vite.config.ts +0 -70
package/playground/style.css
DELETED
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* 全局基础样式:仅约束布局与排版,组件内细节样式靠 scoped 文件管理
|
|
3
|
-
* 主题色统一通过 CSS 变量驱动,避免重复硬编码
|
|
4
|
-
*/
|
|
5
|
-
:root {
|
|
6
|
-
--color-bg: #f5f7fa;
|
|
7
|
-
--color-surface: #fff;
|
|
8
|
-
--color-border: #e2e8f0;
|
|
9
|
-
--color-text-primary: #1f2937;
|
|
10
|
-
--color-text-secondary: #4b5563;
|
|
11
|
-
--color-text-muted: #94a3b8;
|
|
12
|
-
--color-primary: #3b82f6;
|
|
13
|
-
--color-primary-hover: #2563eb;
|
|
14
|
-
--color-success: #10b981;
|
|
15
|
-
--color-warning: #f59e0b;
|
|
16
|
-
--color-danger: #ef4444;
|
|
17
|
-
--color-code-bg: #0f172a;
|
|
18
|
-
--color-code-text: #e2e8f0;
|
|
19
|
-
--space-xs: 4px;
|
|
20
|
-
--space-sm: 8px;
|
|
21
|
-
--space-md: 16px;
|
|
22
|
-
--space-lg: 24px;
|
|
23
|
-
--space-xl: 32px;
|
|
24
|
-
--radius-sm: 4px;
|
|
25
|
-
--radius-md: 8px;
|
|
26
|
-
--radius-lg: 12px;
|
|
27
|
-
--shadow-sm: 0 1px 2px rgb(15 23 42 / 6%);
|
|
28
|
-
--shadow-md: 0 4px 12px rgb(15 23 42 / 8%);
|
|
29
|
-
--font-sans:
|
|
30
|
-
-apple-system, blinkmacsystemfont, 'Segoe UI', roboto, 'Helvetica Neue', arial, 'PingFang SC', 'Hiragino Sans GB',
|
|
31
|
-
'Microsoft YaHei', sans-serif;
|
|
32
|
-
--font-mono: 'SFMono-Regular', menlo, monaco, consolas, 'Liberation Mono', 'Courier New', monospace;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
* {
|
|
36
|
-
box-sizing: border-box;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
html,
|
|
40
|
-
body,
|
|
41
|
-
#app {
|
|
42
|
-
height: 100%;
|
|
43
|
-
padding: 0;
|
|
44
|
-
margin: 0;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
body {
|
|
48
|
-
font-family: var(--font-sans);
|
|
49
|
-
font-size: 14px;
|
|
50
|
-
line-height: 1.6;
|
|
51
|
-
color: var(--color-text-primary);
|
|
52
|
-
background: var(--color-bg);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
a {
|
|
56
|
-
color: var(--color-primary);
|
|
57
|
-
text-decoration: none;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
a:hover {
|
|
61
|
-
color: var(--color-primary-hover);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
button {
|
|
65
|
-
font-family: inherit;
|
|
66
|
-
font-size: 14px;
|
|
67
|
-
cursor: pointer;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
code,
|
|
71
|
-
pre {
|
|
72
|
-
font-family: var(--font-mono);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/* 通用内容块:每个 demo 页面共用 */
|
|
76
|
-
.demo-page {
|
|
77
|
-
display: flex;
|
|
78
|
-
flex-direction: column;
|
|
79
|
-
gap: var(--space-lg);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
.demo-page__title {
|
|
83
|
-
margin: 0;
|
|
84
|
-
font-size: 22px;
|
|
85
|
-
font-weight: 600;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
.demo-page__desc {
|
|
89
|
-
margin: 0;
|
|
90
|
-
color: var(--color-text-secondary);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
.demo-card {
|
|
94
|
-
padding: var(--space-lg);
|
|
95
|
-
background: var(--color-surface);
|
|
96
|
-
border: 1px solid var(--color-border);
|
|
97
|
-
border-radius: var(--radius-md);
|
|
98
|
-
box-shadow: var(--shadow-sm);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
.demo-card__title {
|
|
102
|
-
margin: 0 0 var(--space-sm);
|
|
103
|
-
font-size: 16px;
|
|
104
|
-
font-weight: 600;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
.demo-card__hint {
|
|
108
|
-
margin: 0 0 var(--space-md);
|
|
109
|
-
color: var(--color-text-secondary);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
.demo-actions {
|
|
113
|
-
display: flex;
|
|
114
|
-
flex-wrap: wrap;
|
|
115
|
-
gap: var(--space-sm);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
.demo-btn {
|
|
119
|
-
padding: 8px 16px;
|
|
120
|
-
color: #fff;
|
|
121
|
-
background: var(--color-primary);
|
|
122
|
-
border: none;
|
|
123
|
-
border-radius: var(--radius-sm);
|
|
124
|
-
transition: background-color 0.15s ease-in-out;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
.demo-btn:hover {
|
|
128
|
-
background: var(--color-primary-hover);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
.demo-btn--success {
|
|
132
|
-
background: var(--color-success);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
.demo-btn--warning {
|
|
136
|
-
background: var(--color-warning);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
.demo-btn--danger {
|
|
140
|
-
background: var(--color-danger);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
.demo-btn--ghost {
|
|
144
|
-
color: var(--color-text-primary);
|
|
145
|
-
background: transparent;
|
|
146
|
-
border: 1px solid var(--color-border);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
.demo-btn--ghost:hover {
|
|
150
|
-
background: var(--color-bg);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
.demo-log {
|
|
154
|
-
max-height: 240px;
|
|
155
|
-
padding: var(--space-md);
|
|
156
|
-
overflow: auto;
|
|
157
|
-
font-size: 12px;
|
|
158
|
-
color: var(--color-code-text);
|
|
159
|
-
background: var(--color-code-bg);
|
|
160
|
-
border-radius: var(--radius-sm);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
.demo-log__line {
|
|
164
|
-
margin: 0;
|
|
165
|
-
word-break: break-all;
|
|
166
|
-
white-space: pre-wrap;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
.demo-log__line + .demo-log__line {
|
|
170
|
-
margin-top: 4px;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
.demo-snippet {
|
|
174
|
-
padding: var(--space-md);
|
|
175
|
-
overflow: auto;
|
|
176
|
-
font-size: 12px;
|
|
177
|
-
color: var(--color-code-text);
|
|
178
|
-
background: var(--color-code-bg);
|
|
179
|
-
border-radius: var(--radius-sm);
|
|
180
|
-
}
|
package/src/browser.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Tencent is pleased to support the open source community by making
|
|
3
|
-
* 蓝鲸智云PaaS平台 (BlueKing PaaS) available.
|
|
4
|
-
*
|
|
5
|
-
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
|
|
6
|
-
*
|
|
7
|
-
* 蓝鲸智云PaaS平台 (BlueKing PaaS) is licensed under the MIT License.
|
|
8
|
-
*
|
|
9
|
-
* License for 蓝鲸智云PaaS平台 (BlueKing PaaS):
|
|
10
|
-
*
|
|
11
|
-
* ---------------------------------------------------
|
|
12
|
-
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
|
13
|
-
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
|
14
|
-
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
|
|
15
|
-
* to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
16
|
-
*
|
|
17
|
-
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
|
|
18
|
-
* the Software.
|
|
19
|
-
*
|
|
20
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
21
|
-
* THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
23
|
-
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
24
|
-
* IN THE SOFTWARE.
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
import { createPlugin } from './core/plugin';
|
|
28
|
-
import { createBkOT, initBkOT } from './core/sdk';
|
|
29
|
-
|
|
30
|
-
export * from './index';
|
|
31
|
-
|
|
32
|
-
const BkOpenTelemetry = {
|
|
33
|
-
createBkOT,
|
|
34
|
-
createPlugin,
|
|
35
|
-
initBkOT,
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
if (typeof window !== 'undefined') {
|
|
39
|
-
Object.assign(window, {
|
|
40
|
-
BkOpenTelemetry,
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export { BkOpenTelemetry };
|
package/src/core/config.ts
DELETED
|
@@ -1,327 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Tencent is pleased to support the open source community by making
|
|
3
|
-
* 蓝鲸智云PaaS平台 (BlueKing PaaS) available.
|
|
4
|
-
*
|
|
5
|
-
* Copyright (C) 2017-2025 Tencent. All rights reserved.
|
|
6
|
-
*
|
|
7
|
-
* 蓝鲸智云PaaS平台 (BlueKing PaaS) is licensed under the MIT License.
|
|
8
|
-
*
|
|
9
|
-
* License for 蓝鲸智云PaaS平台 (BlueKing PaaS):
|
|
10
|
-
*
|
|
11
|
-
* ---------------------------------------------------
|
|
12
|
-
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
|
13
|
-
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
|
14
|
-
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
|
|
15
|
-
* to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
16
|
-
*
|
|
17
|
-
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
|
|
18
|
-
* the Software.
|
|
19
|
-
*
|
|
20
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
21
|
-
* THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
23
|
-
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
24
|
-
* IN THE SOFTWARE.
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
import type { BkOTPlugin } from './plugin';
|
|
28
|
-
import type { Attributes } from '@opentelemetry/api';
|
|
29
|
-
|
|
30
|
-
export interface BkOTAttributesConfig {
|
|
31
|
-
custom?: () => Attributes;
|
|
32
|
-
error?: () => Attributes;
|
|
33
|
-
metric?: () => Attributes;
|
|
34
|
-
page?: () => Attributes;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export type BkOTAttributeValue = boolean | number | string;
|
|
38
|
-
|
|
39
|
-
export interface BkOTBatchConfig {
|
|
40
|
-
exportTimeoutMillis?: number;
|
|
41
|
-
maxExportBatchSize?: number;
|
|
42
|
-
maxQueueSize?: number;
|
|
43
|
-
scheduledDelayMillis?: number;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export interface BkOTConfig {
|
|
47
|
-
attributes?: BkOTAttributesConfig;
|
|
48
|
-
autoStart?: boolean;
|
|
49
|
-
debug?: boolean;
|
|
50
|
-
enabled?: boolean;
|
|
51
|
-
endpoint?: string;
|
|
52
|
-
environment?: string;
|
|
53
|
-
headers?: Record<string, string>;
|
|
54
|
-
plugins?: BkOTPlugin[];
|
|
55
|
-
redact?: BkOTRedactConfig;
|
|
56
|
-
rum?: BkOTRumConfig;
|
|
57
|
-
sampleRate?: number;
|
|
58
|
-
spanBatch?: BkOTBatchConfig;
|
|
59
|
-
token?: string;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export interface BkOTCustomEventPayload {
|
|
63
|
-
attributes?: Attributes;
|
|
64
|
-
error?: Error;
|
|
65
|
-
name: string;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export interface BkOTHttpBodyConfig {
|
|
69
|
-
maxBodySize?: number;
|
|
70
|
-
redact?: (payload: BkOTHttpBodyRedactPayload) => string;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export interface BkOTHttpBodyRedactPayload {
|
|
74
|
-
body: string;
|
|
75
|
-
contentType?: string;
|
|
76
|
-
method: string;
|
|
77
|
-
status?: number;
|
|
78
|
-
truncated: boolean;
|
|
79
|
-
type: 'request' | 'response';
|
|
80
|
-
url: string;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export interface BkOTInstrumentationsConfig {
|
|
84
|
-
documentLoad?: boolean;
|
|
85
|
-
fetch?: boolean;
|
|
86
|
-
userInteraction?: boolean | { eventNames?: string[] };
|
|
87
|
-
xhr?: boolean;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export interface BkOTRedactConfig {
|
|
91
|
-
// 用于隐私脱敏:在所有 RUM 自定义插件 emit 之前过滤一次属性
|
|
92
|
-
attributes?: (attributes: Attributes) => Attributes;
|
|
93
|
-
// 用于隐私脱敏:所有上报到 attribute 的 URL 在写入前会经过此函数
|
|
94
|
-
url?: (url: string) => string;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export interface BkOTRumConfig extends BkOTInstrumentationsConfig {
|
|
98
|
-
cspViolation?: boolean;
|
|
99
|
-
device?: boolean | { storageKey?: string };
|
|
100
|
-
httpBody?: BkOTHttpBodyConfig | boolean;
|
|
101
|
-
pageView?: boolean;
|
|
102
|
-
routeTiming?: boolean;
|
|
103
|
-
websocket?: boolean;
|
|
104
|
-
webVitals?: boolean;
|
|
105
|
-
blankScreen?:
|
|
106
|
-
| {
|
|
107
|
-
checkDelay?: number;
|
|
108
|
-
// 自定义"页面已渲染"忽略选择器,命中即认为是 loading 占位、非空白
|
|
109
|
-
ignoreSelectors?: string[];
|
|
110
|
-
rootSelector?: string;
|
|
111
|
-
threshold?: number;
|
|
112
|
-
}
|
|
113
|
-
| boolean;
|
|
114
|
-
error?:
|
|
115
|
-
| {
|
|
116
|
-
// 同 hash 错误窗口内最多上报多少条,默认 5
|
|
117
|
-
maxPerWindow?: number;
|
|
118
|
-
// 节流窗口长度(ms),默认 60_000
|
|
119
|
-
windowMs?: number;
|
|
120
|
-
}
|
|
121
|
-
| boolean;
|
|
122
|
-
longTask?:
|
|
123
|
-
| {
|
|
124
|
-
// 任务时长阈值(ms),低于该值的 longtask 不上报,默认 50
|
|
125
|
-
threshold?: number;
|
|
126
|
-
}
|
|
127
|
-
| boolean;
|
|
128
|
-
session?:
|
|
129
|
-
| {
|
|
130
|
-
// 不活跃多久后视为新会话,默认 30 分钟
|
|
131
|
-
inactivityMs?: number;
|
|
132
|
-
storageKey?: string;
|
|
133
|
-
}
|
|
134
|
-
| boolean;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export interface NormalizedBkOTConfig extends Omit<
|
|
138
|
-
BkOTConfig,
|
|
139
|
-
'attributes' | 'autoStart' | 'debug' | 'enabled' | 'endpoint' | 'environment' | 'plugins' | 'redact' | 'token'
|
|
140
|
-
> {
|
|
141
|
-
autoStart: boolean;
|
|
142
|
-
debug: boolean;
|
|
143
|
-
enabled: boolean;
|
|
144
|
-
endpoint: string;
|
|
145
|
-
environment: string;
|
|
146
|
-
logs: SignalExporterConfig;
|
|
147
|
-
metricIntervalMillis: number;
|
|
148
|
-
metrics: SignalExporterConfig;
|
|
149
|
-
plugins: BkOTPlugin[];
|
|
150
|
-
resourceAttributes: Attributes;
|
|
151
|
-
sampleRate: number;
|
|
152
|
-
traces: SignalExporterConfig;
|
|
153
|
-
getCustomAttributes: () => Attributes;
|
|
154
|
-
getErrorAttributes: () => Attributes;
|
|
155
|
-
getMetricAttributes: () => Attributes;
|
|
156
|
-
getPageAttributes: () => Attributes;
|
|
157
|
-
redactAttributes: (attributes: Attributes) => Attributes;
|
|
158
|
-
redactUrl: (url: string) => string;
|
|
159
|
-
instrumentations: Required<Pick<BkOTInstrumentationsConfig, 'documentLoad' | 'fetch' | 'xhr'>> & {
|
|
160
|
-
userInteraction: BkOTInstrumentationsConfig['userInteraction'];
|
|
161
|
-
};
|
|
162
|
-
rum: Omit<Required<BkOTRumConfig>, 'documentLoad' | 'fetch' | 'httpBody' | 'userInteraction' | 'xhr'> & {
|
|
163
|
-
httpBody: false | Required<BkOTHttpBodyConfig>;
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
export interface SignalExporterConfig {
|
|
168
|
-
concurrencyLimit?: number;
|
|
169
|
-
endpoint: string;
|
|
170
|
-
headers?: Record<string, string>;
|
|
171
|
-
timeoutMillis?: number;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
const DEFAULT_OTLP_ENDPOINT = 'http://localhost:4318'; // 默认上报到本机 OTLP collector
|
|
175
|
-
const DEFAULT_METRIC_INTERVAL_MILLIS = 10 * 1000; // 10s 上报一次
|
|
176
|
-
|
|
177
|
-
const trimTrailingSlash = (value: string) => value.replace(/\/+$/, '');
|
|
178
|
-
|
|
179
|
-
const resolveSignalEndpoint = (endpoint: string | undefined, signalPath: 'logs' | 'metrics' | 'traces') => {
|
|
180
|
-
const normalized = trimTrailingSlash(endpoint || DEFAULT_OTLP_ENDPOINT);
|
|
181
|
-
if (normalized.endsWith(`/v1/${signalPath}`)) {
|
|
182
|
-
return normalized;
|
|
183
|
-
}
|
|
184
|
-
if (normalized.endsWith('/v1')) {
|
|
185
|
-
return `${normalized}/${signalPath}`;
|
|
186
|
-
}
|
|
187
|
-
return `${normalized}/v1/${signalPath}`;
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
const resolveSignalConfig = (base: BkOTConfig, signalPath: 'logs' | 'metrics' | 'traces'): SignalExporterConfig => {
|
|
191
|
-
// token 只负责提供默认鉴权头;headers 保持显式配置优先,便于特殊场景覆盖。
|
|
192
|
-
const mergedHeaders =
|
|
193
|
-
base.token || base.headers
|
|
194
|
-
? {
|
|
195
|
-
...(base.token ? { Authorization: `Bearer ${base.token}` } : {}),
|
|
196
|
-
...(base.headers ?? {}),
|
|
197
|
-
}
|
|
198
|
-
: undefined;
|
|
199
|
-
|
|
200
|
-
return {
|
|
201
|
-
endpoint: resolveSignalEndpoint(base.endpoint, signalPath),
|
|
202
|
-
headers: mergedHeaders,
|
|
203
|
-
};
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
const clampSampleRate = (sampleRate?: number) => {
|
|
207
|
-
if (typeof sampleRate !== 'number' || !Number.isFinite(sampleRate)) {
|
|
208
|
-
return 1;
|
|
209
|
-
}
|
|
210
|
-
return Math.max(0, Math.min(1, sampleRate));
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
const positiveNumber = (value: number | undefined, fallback: number) =>
|
|
214
|
-
typeof value === 'number' && Number.isFinite(value) && value > 0 ? value : fallback;
|
|
215
|
-
|
|
216
|
-
const nonNegativeNumber = (value: number | undefined, fallback: number) =>
|
|
217
|
-
typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : fallback;
|
|
218
|
-
|
|
219
|
-
const boundedRatio = (value: number | undefined, fallback: number) => {
|
|
220
|
-
if (typeof value !== 'number' || !Number.isFinite(value)) {
|
|
221
|
-
return fallback;
|
|
222
|
-
}
|
|
223
|
-
return Math.max(0, Math.min(1, value));
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
const identityRedactHttpBody = (payload: BkOTHttpBodyRedactPayload) => payload.body;
|
|
227
|
-
|
|
228
|
-
const normalizeHttpBodyConfig = (httpBody: BkOTRumConfig['httpBody']): false | Required<BkOTHttpBodyConfig> => {
|
|
229
|
-
if (!httpBody) {
|
|
230
|
-
return false;
|
|
231
|
-
}
|
|
232
|
-
if (typeof httpBody === 'boolean') {
|
|
233
|
-
return {
|
|
234
|
-
maxBodySize: 10 * 1024,
|
|
235
|
-
redact: identityRedactHttpBody,
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
return {
|
|
239
|
-
maxBodySize: positiveNumber(httpBody.maxBodySize, 10 * 1024),
|
|
240
|
-
redact: httpBody.redact ?? identityRedactHttpBody,
|
|
241
|
-
};
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
const normalizeRumConfig = (rum: BkOTConfig['rum']): NormalizedBkOTConfig['rum'] => ({
|
|
245
|
-
device: rum?.device ?? true,
|
|
246
|
-
httpBody: normalizeHttpBodyConfig(rum?.httpBody),
|
|
247
|
-
session:
|
|
248
|
-
typeof rum?.session === 'object'
|
|
249
|
-
? {
|
|
250
|
-
...rum.session,
|
|
251
|
-
inactivityMs: positiveNumber(rum.session.inactivityMs, 30 * 60 * 1000),
|
|
252
|
-
}
|
|
253
|
-
: (rum?.session ?? true),
|
|
254
|
-
pageView: rum?.pageView ?? true,
|
|
255
|
-
error:
|
|
256
|
-
typeof rum?.error === 'object'
|
|
257
|
-
? {
|
|
258
|
-
...rum.error,
|
|
259
|
-
maxPerWindow: positiveNumber(rum.error.maxPerWindow, 5),
|
|
260
|
-
windowMs: positiveNumber(rum.error.windowMs, 60_000),
|
|
261
|
-
}
|
|
262
|
-
: (rum?.error ?? true),
|
|
263
|
-
webVitals: rum?.webVitals ?? true,
|
|
264
|
-
blankScreen:
|
|
265
|
-
typeof rum?.blankScreen === 'object'
|
|
266
|
-
? {
|
|
267
|
-
...rum.blankScreen,
|
|
268
|
-
checkDelay: nonNegativeNumber(rum.blankScreen.checkDelay, 3000),
|
|
269
|
-
threshold: boundedRatio(rum.blankScreen.threshold, 0.8),
|
|
270
|
-
}
|
|
271
|
-
: (rum?.blankScreen ?? true),
|
|
272
|
-
websocket: rum?.websocket ?? true,
|
|
273
|
-
longTask:
|
|
274
|
-
typeof rum?.longTask === 'object'
|
|
275
|
-
? {
|
|
276
|
-
...rum.longTask,
|
|
277
|
-
threshold: nonNegativeNumber(rum.longTask.threshold, 50),
|
|
278
|
-
}
|
|
279
|
-
: (rum?.longTask ?? false),
|
|
280
|
-
cspViolation: rum?.cspViolation ?? false,
|
|
281
|
-
routeTiming: rum?.routeTiming ?? false,
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
const identityRedactAttributes = (attributes: Attributes) => attributes;
|
|
285
|
-
const identityRedactUrl = (url: string) => url;
|
|
286
|
-
|
|
287
|
-
export const normalizeConfig = (config: BkOTConfig): NormalizedBkOTConfig => {
|
|
288
|
-
const resourceAttributes: Attributes = {
|
|
289
|
-
'deployment.environment.name': config.environment ?? 'production',
|
|
290
|
-
'rum.provider': 'blueking',
|
|
291
|
-
'telemetry.sdk.language': 'webjs',
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
return {
|
|
295
|
-
...config,
|
|
296
|
-
debug: config.debug ?? false,
|
|
297
|
-
enabled: config.enabled ?? true,
|
|
298
|
-
environment: config.environment ?? 'production',
|
|
299
|
-
endpoint: trimTrailingSlash(config.endpoint || DEFAULT_OTLP_ENDPOINT),
|
|
300
|
-
traces: resolveSignalConfig(config, 'traces'),
|
|
301
|
-
metrics: resolveSignalConfig(config, 'metrics'),
|
|
302
|
-
logs: resolveSignalConfig(config, 'logs'),
|
|
303
|
-
sampleRate: clampSampleRate(config.sampleRate),
|
|
304
|
-
resourceAttributes,
|
|
305
|
-
metricIntervalMillis: DEFAULT_METRIC_INTERVAL_MILLIS,
|
|
306
|
-
instrumentations: {
|
|
307
|
-
documentLoad: config.rum?.documentLoad ?? true,
|
|
308
|
-
fetch: config.rum?.fetch ?? true,
|
|
309
|
-
xhr: config.rum?.xhr ?? true,
|
|
310
|
-
userInteraction: config.rum?.userInteraction ?? true,
|
|
311
|
-
},
|
|
312
|
-
rum: normalizeRumConfig(config.rum),
|
|
313
|
-
plugins: config.plugins ?? [],
|
|
314
|
-
autoStart: config.autoStart ?? true,
|
|
315
|
-
getPageAttributes:
|
|
316
|
-
config.attributes?.page ??
|
|
317
|
-
(() => ({
|
|
318
|
-
'rum.page.host': typeof window === 'undefined' ? '' : window.location.host,
|
|
319
|
-
'rum.page.path': typeof window === 'undefined' ? '' : window.location.pathname,
|
|
320
|
-
})),
|
|
321
|
-
getMetricAttributes: config.attributes?.metric ?? (() => ({})),
|
|
322
|
-
getErrorAttributes: config.attributes?.error ?? (() => ({})),
|
|
323
|
-
getCustomAttributes: config.attributes?.custom ?? (() => ({})),
|
|
324
|
-
redactAttributes: config.redact?.attributes ?? identityRedactAttributes,
|
|
325
|
-
redactUrl: config.redact?.url ?? identityRedactUrl,
|
|
326
|
-
};
|
|
327
|
-
};
|
package/src/core/plugin.ts
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Tencent is pleased to support the open source community by making
|
|
3
|
-
* 蓝鲸智云PaaS平台 (BlueKing PaaS) available.
|
|
4
|
-
*
|
|
5
|
-
* Copyright (C) 2017-2025 Tencent. All rights reserved.
|
|
6
|
-
*
|
|
7
|
-
* 蓝鲸智云PaaS平台 (BlueKing PaaS) is licensed under the MIT License.
|
|
8
|
-
*
|
|
9
|
-
* License for 蓝鲸智云PaaS平台 (BlueKing PaaS):
|
|
10
|
-
*
|
|
11
|
-
* ---------------------------------------------------
|
|
12
|
-
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
|
13
|
-
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
|
14
|
-
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
|
|
15
|
-
* to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
16
|
-
*
|
|
17
|
-
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
|
|
18
|
-
* the Software.
|
|
19
|
-
*
|
|
20
|
-
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
|
21
|
-
* THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
-
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
23
|
-
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
24
|
-
* IN THE SOFTWARE.
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
import type { NormalizedBkOTConfig } from './config';
|
|
28
|
-
import type { Attributes, Meter, Span, Tracer } from '@opentelemetry/api';
|
|
29
|
-
import type { Logger, LogRecord } from '@opentelemetry/api-logs';
|
|
30
|
-
|
|
31
|
-
export interface BkOTPlugin {
|
|
32
|
-
enabled?: ((config: NormalizedBkOTConfig) => boolean) | boolean;
|
|
33
|
-
name: string;
|
|
34
|
-
flush?: () => Promise<void> | void;
|
|
35
|
-
init: (context: BkOTRuntimeContext) => Promise<void> | void;
|
|
36
|
-
shutdown?: () => Promise<void> | void;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export interface BkOTRuntimeContext {
|
|
40
|
-
config: NormalizedBkOTConfig;
|
|
41
|
-
logger: Logger;
|
|
42
|
-
meter: Meter;
|
|
43
|
-
tracer: Tracer;
|
|
44
|
-
/** 对外提供的属性脱敏入口,所有插件在 emit 前都应过一次 */
|
|
45
|
-
applyRedact: (attributes: Attributes) => Attributes;
|
|
46
|
-
/** 包装 logger.emit,自动应用 redact 与 runtime attributes */
|
|
47
|
-
emitLog: (record: LogRecord) => void;
|
|
48
|
-
getRuntimeAttributes: () => Attributes;
|
|
49
|
-
setRuntimeAttributes: (attributes: Attributes) => void;
|
|
50
|
-
startSpan: (name: string, attributes?: Attributes) => Span;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export const isPluginEnabled = (plugin: BkOTPlugin, config: NormalizedBkOTConfig) => {
|
|
54
|
-
if (typeof plugin.enabled === 'function') {
|
|
55
|
-
return plugin.enabled(config);
|
|
56
|
-
}
|
|
57
|
-
return plugin.enabled !== false;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
export const createPlugin = (plugin: BkOTPlugin) => plugin;
|
|
61
|
-
|
|
62
|
-
export class PluginManager {
|
|
63
|
-
private readonly plugins: BkOTPlugin[];
|
|
64
|
-
private startedPlugins: BkOTPlugin[] = [];
|
|
65
|
-
|
|
66
|
-
public constructor(plugins: BkOTPlugin[]) {
|
|
67
|
-
this.plugins = plugins;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
public async flush() {
|
|
71
|
-
// 并行 flush,避免单个慢插件拖累整体
|
|
72
|
-
await Promise.all(this.startedPlugins.map(plugin => Promise.resolve().then(() => plugin.flush?.())));
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
public async shutdown() {
|
|
76
|
-
const plugins = [...this.startedPlugins].reverse();
|
|
77
|
-
for (const plugin of plugins) {
|
|
78
|
-
await plugin.shutdown?.();
|
|
79
|
-
}
|
|
80
|
-
this.startedPlugins = [];
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
public async start(context: BkOTRuntimeContext) {
|
|
84
|
-
try {
|
|
85
|
-
for (const plugin of this.plugins) {
|
|
86
|
-
if (!isPluginEnabled(plugin, context.config)) {
|
|
87
|
-
continue;
|
|
88
|
-
}
|
|
89
|
-
await plugin.init(context);
|
|
90
|
-
this.startedPlugins.push(plugin);
|
|
91
|
-
}
|
|
92
|
-
} catch (error) {
|
|
93
|
-
await this.shutdown();
|
|
94
|
-
throw error;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|