@lwmacct/260529-promclient 0.13.260628 → 0.14.260628

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.
Files changed (2) hide show
  1. package/README.md +312 -0
  2. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,312 @@
1
+ # @lwmacct/260529-promclient
2
+
3
+ Small Prometheus-compatible HTTP API client with PromQL helpers and response transforms.
4
+
5
+ 这是一个轻量 TypeScript 共享库,用于在业务项目中访问 Prometheus 兼容 HTTP API。它封装了 instant query、range query、批量查询、PromQL label selector 构造、时间步长计算,以及常见响应数据转换。
6
+
7
+ ## 特性
8
+
9
+ - 调用 `/api/v1/query` 和 `/api/v1/query_range`
10
+ - 支持批量查询,可并行或串行执行
11
+ - URL 较短时使用 `GET`,超过阈值后自动切换为 `POST`
12
+ - 支持全局 headers、单次请求 headers、动态 headers 和 `AbortSignal`
13
+ - 提供 Prometheus API 响应的 TypeScript 类型
14
+ - 提供 PromQL selector / label matcher 转义工具
15
+ - 提供 vector、matrix、scalar、string 响应转换工具
16
+ - 无运行时依赖
17
+
18
+ ## 安装
19
+
20
+ ```bash
21
+ npm install @lwmacct/260529-promclient
22
+ ```
23
+
24
+ 运行环境需要提供 `fetch`。如果当前环境没有全局 `fetch`,可以通过 `fetcher` 传入兼容实现。
25
+
26
+ ## 快速开始
27
+
28
+ ```ts
29
+ import { PromClient, getVectorItems, selector } from "@lwmacct/260529-promclient";
30
+
31
+ const client = new PromClient({
32
+ baseUrl: "https://prometheus.example.com",
33
+ headers: {
34
+ Authorization: `Bearer ${process.env.PROM_TOKEN}`,
35
+ },
36
+ });
37
+
38
+ const query = selector("up", [
39
+ { name: "job", operator: "=", value: "api" },
40
+ ]);
41
+
42
+ const response = await client.query(query);
43
+ const items = getVectorItems(response);
44
+
45
+ for (const item of items) {
46
+ console.log(item.metric.instance, Number(item.value[1]));
47
+ }
48
+ ```
49
+
50
+ ## Client
51
+
52
+ ### 创建客户端
53
+
54
+ ```ts
55
+ import { PromClient } from "@lwmacct/260529-promclient";
56
+
57
+ const client = new PromClient({
58
+ baseUrl: "http://localhost:9090",
59
+ });
60
+ ```
61
+
62
+ 可用选项:
63
+
64
+ | 选项 | 类型 | 说明 |
65
+ | --- | --- | --- |
66
+ | `baseUrl` | `string` | Prometheus 服务地址,必填 |
67
+ | `fetcher` | `typeof fetch` | 自定义 fetch 实现 |
68
+ | `headers` | `HeadersInit \| (() => HeadersInit \| Promise<HeadersInit>)` | 全局请求头,支持动态返回 |
69
+ | `maxGetUrlLength` | `number` | GET URL 最大长度,默认 `2000` |
70
+
71
+ ### Instant Query
72
+
73
+ ```ts
74
+ const response = await client.query("up", {
75
+ time: new Date(),
76
+ timeout: "10s",
77
+ limit: 100,
78
+ });
79
+ ```
80
+
81
+ `query` 返回 `PromSuccessResponse<PromInstantData>`。`PromInstantData` 可能是 `vector`、`scalar` 或 `string`。
82
+
83
+ ### Range Query
84
+
85
+ ```ts
86
+ const response = await client.queryRange("rate(http_requests_total[5m])", {
87
+ start: Date.now() / 1000 - 3600,
88
+ end: Date.now() / 1000,
89
+ step: "1m",
90
+ timeout: "10s",
91
+ });
92
+ ```
93
+
94
+ `queryRange` 返回 `PromSuccessResponse<PromMatrixData>`。
95
+
96
+ 时间参数支持:
97
+
98
+ - `Date`
99
+ - Unix 秒时间戳
100
+ - Prometheus 可接受的字符串时间
101
+
102
+ ### Batch Query
103
+
104
+ ```ts
105
+ const responses = await client.batch([
106
+ { query: "up" },
107
+ {
108
+ type: "queryRange",
109
+ query: "rate(http_requests_total[5m])",
110
+ options: {
111
+ start: Date.now() / 1000 - 3600,
112
+ end: Date.now() / 1000,
113
+ step: "1m",
114
+ },
115
+ },
116
+ ]);
117
+ ```
118
+
119
+ 默认并行执行。需要串行执行时:
120
+
121
+ ```ts
122
+ const responses = await client.batch(requests, { parallel: false });
123
+ ```
124
+
125
+ ## PromQL 工具
126
+
127
+ ### Label Matcher
128
+
129
+ ```ts
130
+ import { labelMatcher, regexLabelMatcher, selector } from "@lwmacct/260529-promclient";
131
+
132
+ labelMatcher("job", "=", "api");
133
+ // job="api"
134
+
135
+ regexLabelMatcher("instance", ["10.0.0.1:9100", "10.0.0.2:9100"]);
136
+ // instance=~"10\\.0\\.0\\.1:9100|10\\.0\\.0\\.2:9100"
137
+
138
+ selector("node_cpu_seconds_total", [
139
+ { name: "mode", operator: "!=", value: "idle" },
140
+ { name: "job", operator: "=", value: "node" },
141
+ ]);
142
+ // node_cpu_seconds_total{mode!="idle",job="node"}
143
+ ```
144
+
145
+ ### 转义函数
146
+
147
+ ```ts
148
+ import { escapeLabelValue, escapeRegex, regexList } from "@lwmacct/260529-promclient";
149
+ ```
150
+
151
+ - `escapeLabelValue`:转义 PromQL label value 中的反斜线、双引号和换行
152
+ - `escapeRegex`:转义正则特殊字符
153
+ - `regexList`:把字符串数组转换成安全的正则 alternation
154
+
155
+ ## 时间工具
156
+
157
+ ```ts
158
+ import { getAdaptiveStep, serializeTime } from "@lwmacct/260529-promclient";
159
+
160
+ const step = getAdaptiveStep(24 * 60 * 60, 600);
161
+ // "5m"
162
+
163
+ const time = serializeTime(new Date());
164
+ // Unix 秒字符串
165
+ ```
166
+
167
+ `getAdaptiveStep(seconds, maxPoints)` 会根据查询时间范围和最大点数,从内置 step 列表中选择合适的 Prometheus step。
168
+
169
+ 内置 step 包括:
170
+
171
+ ```ts
172
+ ["1m", "5m", "10m", "15m", "30m", "1h", "2h", "3h", "4h", "6h", "12h", "1d"]
173
+ ```
174
+
175
+ ## 响应转换
176
+
177
+ Prometheus 的 sample value 是字符串。转换工具会在需要时解析为 number,并过滤 `NaN`。
178
+
179
+ ### Instant Response
180
+
181
+ ```ts
182
+ import {
183
+ getVectorItems,
184
+ getScalarValue,
185
+ getScalarNumber,
186
+ mapVector,
187
+ mapVectorByLabel,
188
+ } from "@lwmacct/260529-promclient";
189
+ ```
190
+
191
+ 常用函数:
192
+
193
+ | 函数 | 说明 |
194
+ | --- | --- |
195
+ | `getVectorItems(response)` | 从 instant response 中取出 vector items,非 vector 时返回空数组 |
196
+ | `getScalarValue(response)` | 从 scalar/string response 中取出原始字符串值 |
197
+ | `getScalarNumber(response, defaultValue?)` | 从 scalar response 中解析数字 |
198
+ | `mapVectorByLabel(response, labelName, parser?)` | 按指定 label 聚合 vector 数值 |
199
+ | `mapVector(response, mapper)` | 自定义映射 vector items |
200
+
201
+ ### Range Response
202
+
203
+ ```ts
204
+ import {
205
+ mapMatrixItemToSeries,
206
+ mapMatrixToSeries,
207
+ mapMatrixByLabel,
208
+ } from "@lwmacct/260529-promclient";
209
+ ```
210
+
211
+ 常用函数:
212
+
213
+ | 函数 | 说明 |
214
+ | --- | --- |
215
+ | `mapMatrixItemToSeries(item, parser?)` | 把单条 matrix series 转为 `[timestampMs, value]` 数组 |
216
+ | `mapMatrixToSeries(response, parser?, filter?)` | 把 matrix response 展平为按时间升序排列的点数组 |
217
+ | `mapMatrixByLabel(response, labelName, parser?)` | 按指定 label 输出多条时间序列 |
218
+
219
+ 示例:
220
+
221
+ ```ts
222
+ const response = await client.queryRange("rate(http_requests_total[5m])", {
223
+ start: Date.now() / 1000 - 3600,
224
+ end: Date.now() / 1000,
225
+ step: "1m",
226
+ });
227
+
228
+ const seriesByInstance = mapMatrixByLabel(response, "instance");
229
+ ```
230
+
231
+ ## 类型守卫和基础工具
232
+
233
+ ```ts
234
+ import {
235
+ hasResults,
236
+ isMatrixData,
237
+ isScalarData,
238
+ isStringData,
239
+ isSuccessResponse,
240
+ isVectorData,
241
+ safeParseFloat,
242
+ toMilliseconds,
243
+ } from "@lwmacct/260529-promclient";
244
+ ```
245
+
246
+ 这些工具适合在业务侧处理 Prometheus 原始响应时做类型缩窄和基础转换。
247
+
248
+ ## 错误处理
249
+
250
+ 客户端会区分三类错误:
251
+
252
+ | 错误 | 触发条件 |
253
+ | --- | --- |
254
+ | `PromHttpError` | HTTP 状态码非 2xx |
255
+ | `PromApiError` | Prometheus API 返回 `status: "error"` |
256
+ | `PromParseError` | 响应 JSON 解析失败,或响应状态不符合预期 |
257
+
258
+ ```ts
259
+ import {
260
+ PromApiError,
261
+ PromHttpError,
262
+ PromParseError,
263
+ } from "@lwmacct/260529-promclient";
264
+
265
+ try {
266
+ await client.query("up");
267
+ } catch (error) {
268
+ if (error instanceof PromHttpError) {
269
+ console.error(error.status, error.statusText, error.url);
270
+ } else if (error instanceof PromApiError) {
271
+ console.error(error.errorType, error.response.error);
272
+ } else if (error instanceof PromParseError) {
273
+ console.error(error.message);
274
+ }
275
+ }
276
+ ```
277
+
278
+ ## 子路径导入
279
+
280
+ 包提供以下导出入口:
281
+
282
+ ```ts
283
+ import { PromClient } from "@lwmacct/260529-promclient/client";
284
+ import { PromHttpError } from "@lwmacct/260529-promclient/errors";
285
+ import { selector } from "@lwmacct/260529-promclient/promql";
286
+ import { getAdaptiveStep } from "@lwmacct/260529-promclient/time";
287
+ import { mapMatrixByLabel } from "@lwmacct/260529-promclient/transform";
288
+ ```
289
+
290
+ 完整入口 `@lwmacct/260529-promclient` 会导出所有公共 API。
291
+
292
+ ## 开发
293
+
294
+ ```bash
295
+ npm install
296
+ npm run typecheck
297
+ npm run build
298
+ ```
299
+
300
+ 当前仓库没有测试脚本,发布前至少需要通过类型检查和构建。
301
+
302
+ ## 发布
303
+
304
+ 仓库在推送 `v*` tag 时通过 GitHub Actions 发布 npm 包和 GitHub Release asset。
305
+
306
+ ```bash
307
+ npm run typecheck
308
+ npm run build
309
+ task git:tag:next
310
+ ```
311
+
312
+ `task git:tag:next` 来自远程 Taskfile,会创建并推送下一个版本标签。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lwmacct/260529-promclient",
3
- "version": "0.13.260628",
3
+ "version": "0.14.260628",
4
4
  "private": false,
5
5
  "description": "Small Prometheus-compatible HTTP API client with PromQL helpers and response transforms.",
6
6
  "type": "module",