@exabugs/dynamodb-client 1.11.4 → 1.12.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/CHANGELOG.md +8 -0
- package/dist/integrations/react-admin/components/CloudWatchLog/CloudWatchLogButton.d.ts +14 -0
- package/dist/integrations/react-admin/components/CloudWatchLog/CloudWatchLogButton.d.ts.map +1 -0
- package/dist/integrations/react-admin/components/CloudWatchLog/CloudWatchLogButton.js +17 -0
- package/dist/integrations/react-admin/components/CloudWatchLog/CloudWatchLogButton.js.map +1 -0
- package/dist/integrations/react-admin/components/CloudWatchLog/cloudWatchLogUrl.d.ts +32 -0
- package/dist/integrations/react-admin/components/CloudWatchLog/cloudWatchLogUrl.d.ts.map +1 -0
- package/dist/integrations/react-admin/components/CloudWatchLog/cloudWatchLogUrl.js +63 -0
- package/dist/integrations/react-admin/components/CloudWatchLog/cloudWatchLogUrl.js.map +1 -0
- package/dist/integrations/react-admin/components/CloudWatchLog/index.d.ts +5 -0
- package/dist/integrations/react-admin/components/CloudWatchLog/index.d.ts.map +1 -0
- package/dist/integrations/react-admin/components/CloudWatchLog/index.js +3 -0
- package/dist/integrations/react-admin/components/CloudWatchLog/index.js.map +1 -0
- package/dist/integrations/react-admin/components/index.d.ts +3 -1
- package/dist/integrations/react-admin/components/index.d.ts.map +1 -1
- package/dist/integrations/react-admin/components/index.js +2 -1
- package/dist/integrations/react-admin/components/index.js.map +1 -1
- package/dist/integrations/react-admin/index.d.ts +2 -0
- package/dist/integrations/react-admin/index.d.ts.map +1 -1
- package/dist/integrations/react-admin/index.js +1 -0
- package/dist/integrations/react-admin/index.js.map +1 -1
- package/dist/notify/alerts.d.ts +145 -0
- package/dist/notify/alerts.d.ts.map +1 -0
- package/dist/notify/alerts.js +152 -0
- package/dist/notify/alerts.js.map +1 -0
- package/dist/notify/format.d.ts.map +1 -1
- package/dist/notify/format.js +2 -0
- package/dist/notify/format.js.map +1 -1
- package/dist/notify/handler.d.ts +63 -0
- package/dist/notify/handler.d.ts.map +1 -1
- package/dist/notify/handler.js +205 -3
- package/dist/notify/handler.js.map +1 -1
- package/dist/notify/index.d.ts +5 -2
- package/dist/notify/index.d.ts.map +1 -1
- package/dist/notify/index.js +2 -1
- package/dist/notify/index.js.map +1 -1
- package/dist/notify/normalize.d.ts +12 -1
- package/dist/notify/normalize.d.ts.map +1 -1
- package/dist/notify/normalize.js +73 -14
- package/dist/notify/normalize.js.map +1 -1
- package/dist/notify/store.d.ts +17 -3
- package/dist/notify/store.d.ts.map +1 -1
- package/dist/notify/store.js +87 -0
- package/dist/notify/store.js.map +1 -1
- package/dist/notify/types.d.ts +47 -0
- package/dist/notify/types.d.ts.map +1 -1
- package/dist/server/handler.cjs +3 -3
- package/dist/server/media-handler.cjs +2 -2
- package/dist/server/media-process-handler-dlq.cjs +2 -2
- package/dist/server/media-process-handler.cjs +2 -2
- package/dist/sharp-layer.zip +0 -0
- package/docs/NOTIFY.md +81 -1
- package/package.json +1 -1
package/dist/notify/handler.d.ts
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 通知ハンドラ(Lambda)。入力 → Notice → 同じバッチの重複をまとめる → 重複抑制 → 流量制限 → チャネルへ配信。
|
|
3
|
+
*
|
|
4
|
+
* - 重複抑制: 先に確保 → 送信 → どのチャネルにも届かなかった分は確保を解放(次の発生で、窓を待たずに通知できる)
|
|
5
|
+
* - 流量制限: チャネルごとに、窓の中の件数の上限。超えたら「省略」の 1 通だけ送る
|
|
6
|
+
* - 全チャネルが失敗したら例外を投げる(Lambda の失敗先に流す)。一部の失敗は `failedChannels` に入る
|
|
7
|
+
* - アラームの状態変化(`ALARM:` で始まる event)は、変化したときにしか届かないので、抑制しない
|
|
8
|
+
* - dry-run は記録(store)に触れない
|
|
9
|
+
* - このハンドラのロググループは購読しないこと(ループになる)
|
|
10
|
+
* - alerts(任意。recorder を渡したときだけ): 重複抑制の前に、全グループ(抑制されるものも)を記録する。
|
|
11
|
+
* 記録の失敗・時間切れは通知を止めない(その通知は URL なしで送る)
|
|
12
|
+
* - alerts のループ: Records の失敗ログ(`Request failed` など)は resource を持たないので、target での除外は
|
|
13
|
+
* 効かない。Records のロググループを skipRecordLogGroups に入れる。加えて、記録の失敗・時間切れが続いたら、
|
|
14
|
+
* このコンテナでは一定時間、記録しない(遮断。通知は従来どおり送る)
|
|
15
|
+
*/
|
|
16
|
+
import { type AlertRecorder } from './alerts.js';
|
|
1
17
|
import type { AdminDirectory, Channel, Notice, NoticeLevel, NoticeStore, NotifyLogger } from './types.js';
|
|
2
18
|
export interface NotifyHandlerOptions {
|
|
3
19
|
app: string;
|
|
@@ -19,6 +35,40 @@ export interface NotifyHandlerOptions {
|
|
|
19
35
|
failOnAnyChannelError?: boolean;
|
|
20
36
|
now?: () => Date;
|
|
21
37
|
logger?: NotifyLogger;
|
|
38
|
+
/** alerts の記録(任意)。無ければ記録しない */
|
|
39
|
+
recorder?: AlertRecorder;
|
|
40
|
+
/**
|
|
41
|
+
* 管理画面のベース URL(例: https://admin.example.com)。記録に成功した通知の本文に
|
|
42
|
+
* `詳細: <adminBaseUrl>/alerts/<id>/show` を足す。無ければ本文は変わらない
|
|
43
|
+
*/
|
|
44
|
+
adminBaseUrl?: string;
|
|
45
|
+
/** ログ参照のリージョン(既定 AWS_REGION)。ログの購読は同じリージョンから届く */
|
|
46
|
+
region?: string;
|
|
47
|
+
/**
|
|
48
|
+
* 記録の上限(既定: 3000 ミリ秒、50 件(記録の単位 = alertKey の数)、並列 5)。
|
|
49
|
+
* 有限の正の整数でない値は既定値にする
|
|
50
|
+
*/
|
|
51
|
+
recordLimits?: {
|
|
52
|
+
timeoutMs?: number;
|
|
53
|
+
maxAlerts?: number;
|
|
54
|
+
concurrency?: number;
|
|
55
|
+
};
|
|
56
|
+
/** 記録しない event(既定: ['HEARTBEAT']。定期の生存確認) */
|
|
57
|
+
skipRecordEvents?: string[];
|
|
58
|
+
/**
|
|
59
|
+
* 記録しないロググループ(購読ペイロードの logGroup。完全一致、または末尾 `*` の前方一致)。
|
|
60
|
+
* Records(alerts の書き込み先)のロググループを入れる(記録の失敗ログ → 通知 → 記録、のループを防ぐ)。
|
|
61
|
+
* 通知は従来どおり送る
|
|
62
|
+
*/
|
|
63
|
+
skipRecordLogGroups?: string[];
|
|
64
|
+
/**
|
|
65
|
+
* 記録の遮断(既定: 失敗・時間切れが 3 回続いたら 60000 ミリ秒)。遮断中は記録せず、URL なしで通知する。
|
|
66
|
+
* 状態はコンテナ(ハンドラ)ごと。遮断が明けた後の最初の失敗で、また遮断する。成功で解除する
|
|
67
|
+
*/
|
|
68
|
+
recordBreaker?: {
|
|
69
|
+
failures?: number;
|
|
70
|
+
cooldownMs?: number;
|
|
71
|
+
};
|
|
22
72
|
}
|
|
23
73
|
export interface NotifyResult {
|
|
24
74
|
/** 正規化した通知の数(同じバッチの重複をまとめる前) */
|
|
@@ -37,6 +87,19 @@ export interface NotifyResult {
|
|
|
37
87
|
recipients: string[];
|
|
38
88
|
notices: Notice[];
|
|
39
89
|
}>;
|
|
90
|
+
/**
|
|
91
|
+
* alerts に記録した数。通知の件数ではなく、記録の単位(alertKey)の数
|
|
92
|
+
* (recorder があり、dry-run でないときだけ)
|
|
93
|
+
*/
|
|
94
|
+
recorded?: number;
|
|
95
|
+
/**
|
|
96
|
+
* 記録できなかった数(上限超過・時間切れ・失敗・遮断)。通知の件数ではなく、記録の単位(alertKey)の数。
|
|
97
|
+
* 記録しない設定(skipRecordEvents・skipRecordLogGroups・target が alerts)の分は含まない
|
|
98
|
+
* (recorder があり、dry-run でないときだけ)
|
|
99
|
+
*/
|
|
100
|
+
unrecorded?: number;
|
|
101
|
+
/** 記録を遮断していた(この呼び出しでは記録しなかった、または途中で遮断した)。遮断したときだけ true */
|
|
102
|
+
recordSuspended?: boolean;
|
|
40
103
|
}
|
|
41
104
|
export declare function createNotifyHandler(options: NotifyHandlerOptions): (event: unknown) => Promise<NotifyResult>;
|
|
42
105
|
//# sourceMappingURL=handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/notify/handler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/notify/handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAyC,KAAK,aAAa,EAAc,MAAM,aAAa,CAAC;AAIpG,OAAO,KAAK,EACV,cAAc,EACd,OAAO,EACP,MAAM,EACN,WAAW,EACX,WAAW,EACX,YAAY,EACb,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,KAAK,EAAE,WAAW,CAAC;IACnB,+BAA+B;IAC/B,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IAC/C,IAAI,CAAC,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,6BAA6B;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uCAAuC;IACvC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,+CAA+C;IAC/C,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,YAAY,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAChF,6CAA6C;IAC7C,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B;;;OAGG;IACH,aAAa,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5D;AAED,MAAM,WAAW,YAAY;IAC3B,gCAAgC;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,sBAAsB;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe;IACf,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,qBAAqB;IACrB,IAAI,CAAC,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAC3E;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,0DAA0D;IAC1D,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAuBD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,IA4KjD,OAAO,OAAO,KAAG,OAAO,CAAC,YAAY,CAAC,CAmJrD"}
|
package/dist/notify/handler.js
CHANGED
|
@@ -7,17 +7,58 @@
|
|
|
7
7
|
* - アラームの状態変化(`ALARM:` で始まる event)は、変化したときにしか届かないので、抑制しない
|
|
8
8
|
* - dry-run は記録(store)に触れない
|
|
9
9
|
* - このハンドラのロググループは購読しないこと(ループになる)
|
|
10
|
+
* - alerts(任意。recorder を渡したときだけ): 重複抑制の前に、全グループ(抑制されるものも)を記録する。
|
|
11
|
+
* 記録の失敗・時間切れは通知を止めない(その通知は URL なしで送る)
|
|
12
|
+
* - alerts のループ: Records の失敗ログ(`Request failed` など)は resource を持たないので、target での除外は
|
|
13
|
+
* 効かない。Records のロググループを skipRecordLogGroups に入れる。加えて、記録の失敗・時間切れが続いたら、
|
|
14
|
+
* このコンテナでは一定時間、記録しない(遮断。通知は従来どおり送る)
|
|
10
15
|
*/
|
|
16
|
+
import { ALERTS_RESOURCE, alertKeyOf } from './alerts.js';
|
|
11
17
|
import { consoleNotifyLogger } from './logger.js';
|
|
12
|
-
import {
|
|
18
|
+
import { normalizeWithLogs } from './normalize.js';
|
|
13
19
|
import { DEFAULT_RATE, DEFAULT_WINDOWS, fingerprintOf } from './policy.js';
|
|
20
|
+
const RANK = { fatal: 3, error: 2, warn: 1, ok: 0 };
|
|
14
21
|
export function createNotifyHandler(options) {
|
|
15
22
|
const now = options.now ?? (() => new Date());
|
|
16
23
|
const logger = options.logger ?? consoleNotifyLogger;
|
|
17
24
|
const windows = { ...DEFAULT_WINDOWS, ...options.windows };
|
|
18
25
|
const rate = options.rate ?? DEFAULT_RATE;
|
|
19
26
|
const adminCacheSec = options.adminCacheSec ?? 300;
|
|
20
|
-
const ctx = {
|
|
27
|
+
const ctx = {
|
|
28
|
+
app: options.app,
|
|
29
|
+
env: options.env,
|
|
30
|
+
now,
|
|
31
|
+
region: options.region ?? process.env.AWS_REGION,
|
|
32
|
+
};
|
|
33
|
+
const limits = {
|
|
34
|
+
timeoutMs: positiveInt(options.recordLimits?.timeoutMs, 3000),
|
|
35
|
+
maxAlerts: positiveInt(options.recordLimits?.maxAlerts, 50),
|
|
36
|
+
concurrency: positiveInt(options.recordLimits?.concurrency, 5),
|
|
37
|
+
};
|
|
38
|
+
const breakerOpts = {
|
|
39
|
+
failures: positiveInt(options.recordBreaker?.failures, 3),
|
|
40
|
+
cooldownMs: positiveInt(options.recordBreaker?.cooldownMs, 60_000),
|
|
41
|
+
};
|
|
42
|
+
const skipRecord = new Set(options.skipRecordEvents ?? ['HEARTBEAT']);
|
|
43
|
+
const skipGroup = logGroupMatcher(options.skipRecordLogGroups ?? []);
|
|
44
|
+
const baseUrl = adminBaseUrlOf(options.adminBaseUrl, logger);
|
|
45
|
+
/** 記録の遮断の状態(このハンドラ = コンテナの中だけ)。時刻は now から */
|
|
46
|
+
const breaker = { failures: 0, openUntil: 0 };
|
|
47
|
+
const breakerOpen = () => now().getTime() < breaker.openUntil;
|
|
48
|
+
const onRecordFailure = () => {
|
|
49
|
+
breaker.failures += 1;
|
|
50
|
+
if (breaker.failures >= breakerOpts.failures && !breakerOpen()) {
|
|
51
|
+
breaker.openUntil = now().getTime() + breakerOpts.cooldownMs;
|
|
52
|
+
logger.warn('alerts の記録の失敗が続いたため、しばらく記録を止めます(通知は送ります)', {
|
|
53
|
+
failures: breaker.failures,
|
|
54
|
+
cooldownMs: breakerOpts.cooldownMs,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const onRecordSuccess = () => {
|
|
59
|
+
breaker.failures = 0;
|
|
60
|
+
breaker.openUntil = 0;
|
|
61
|
+
};
|
|
21
62
|
if (!options.admins && options.channels.some((c) => c.needsRecipients)) {
|
|
22
63
|
throw new Error('宛先が必要なチャネルがあるのに、admins が指定されていません');
|
|
23
64
|
}
|
|
@@ -47,8 +88,113 @@ export function createNotifyHandler(options) {
|
|
|
47
88
|
}
|
|
48
89
|
return [...map.values()];
|
|
49
90
|
};
|
|
91
|
+
/** 記録の単位にまとめる(記録しないもの: 記録先自身の通知、生存確認、記録しないロググループ) */
|
|
92
|
+
const units = (items) => {
|
|
93
|
+
const map = new Map();
|
|
94
|
+
for (const { notice: n, log, logGroup } of items) {
|
|
95
|
+
if (n.target === ALERTS_RESOURCE || skipRecord.has(n.event))
|
|
96
|
+
continue;
|
|
97
|
+
if (logGroup !== undefined && skipGroup(logGroup))
|
|
98
|
+
continue;
|
|
99
|
+
const key = alertKeyOf(n);
|
|
100
|
+
const at = log
|
|
101
|
+
? { occurredAt: n.occurredAt, log }
|
|
102
|
+
: { occurredAt: n.occurredAt };
|
|
103
|
+
const u = map.get(key);
|
|
104
|
+
if (u) {
|
|
105
|
+
u.count += 1;
|
|
106
|
+
u.notice = n;
|
|
107
|
+
u.last = at;
|
|
108
|
+
u.rank = Math.max(u.rank, RANK[n.level]);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
map.set(key, { key, notice: n, count: 1, first: at, last: at, rank: RANK[n.level] });
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return [...map.values()];
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* 記録する。例外を外へ出さない。上限(件数・時間)を超えた分と失敗した分は、記録できなかった数に入る。
|
|
118
|
+
* 時間切れで打ち切っても、送信中の HTTP は止まらない(後で書かれることがある。URL は付けない)
|
|
119
|
+
*/
|
|
120
|
+
const recordAll = async (recorder, all) => {
|
|
121
|
+
const ids = new Map();
|
|
122
|
+
if (all.length === 0)
|
|
123
|
+
return { ids, unrecorded: 0, suspended: false };
|
|
124
|
+
if (breakerOpen()) {
|
|
125
|
+
// 遮断中: 記録しない(ログは出さない。遮断したときに 1 回出している)
|
|
126
|
+
return { ids, unrecorded: all.length, suspended: true };
|
|
127
|
+
}
|
|
128
|
+
// 重いもの(error / fatal)を優先する。同じ重さは発生順
|
|
129
|
+
const targets = [...all].sort((a, b) => b.rank - a.rank).slice(0, limits.maxAlerts);
|
|
130
|
+
let next = 0;
|
|
131
|
+
let timedOut = false;
|
|
132
|
+
let suspended = false;
|
|
133
|
+
/** 始めて、まだ終わっていない記録の数(時間切れのとき、失敗として数える) */
|
|
134
|
+
let pending = 0;
|
|
135
|
+
const worker = async () => {
|
|
136
|
+
while (!timedOut && next < targets.length) {
|
|
137
|
+
// 途中で遮断したら、残りは記録しない(失敗のたびに Records のエラーログを増やさない)
|
|
138
|
+
if (breakerOpen()) {
|
|
139
|
+
suspended = true;
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const u = targets[next++];
|
|
143
|
+
pending += 1;
|
|
144
|
+
try {
|
|
145
|
+
const r = await recorder.record({
|
|
146
|
+
notice: u.notice,
|
|
147
|
+
count: u.count,
|
|
148
|
+
first: u.first,
|
|
149
|
+
last: u.last,
|
|
150
|
+
});
|
|
151
|
+
if (!timedOut) {
|
|
152
|
+
pending -= 1;
|
|
153
|
+
ids.set(u.key, r.id);
|
|
154
|
+
onRecordSuccess();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
catch (e) {
|
|
158
|
+
if (!timedOut) {
|
|
159
|
+
pending -= 1;
|
|
160
|
+
onRecordFailure();
|
|
161
|
+
}
|
|
162
|
+
logger.error('alerts の記録に失敗しました', {
|
|
163
|
+
event: u.notice.event,
|
|
164
|
+
error: e instanceof Error ? e.message : String(e),
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
let timer;
|
|
170
|
+
const deadline = new Promise((resolve) => {
|
|
171
|
+
timer = setTimeout(() => {
|
|
172
|
+
timedOut = true;
|
|
173
|
+
resolve();
|
|
174
|
+
}, limits.timeoutMs);
|
|
175
|
+
});
|
|
176
|
+
const workers = Array.from({ length: Math.min(limits.concurrency, targets.length) }, worker);
|
|
177
|
+
await Promise.race([Promise.all(workers), deadline]);
|
|
178
|
+
clearTimeout(timer);
|
|
179
|
+
// 時間切れで打ち切った記録は、失敗として数える(遅い・止まった Records も遮断の対象)
|
|
180
|
+
for (; pending > 0; pending--)
|
|
181
|
+
onRecordFailure();
|
|
182
|
+
if (breakerOpen() && ids.size < targets.length)
|
|
183
|
+
suspended = true;
|
|
184
|
+
const unrecorded = all.length - ids.size;
|
|
185
|
+
if (unrecorded > 0) {
|
|
186
|
+
logger.warn('alerts に記録できなかった通知があります(URL なしで通知します)', {
|
|
187
|
+
unrecorded,
|
|
188
|
+
timedOut,
|
|
189
|
+
suspended,
|
|
190
|
+
overLimit: Math.max(0, all.length - targets.length),
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
return { ids, unrecorded, suspended };
|
|
194
|
+
};
|
|
50
195
|
return async (event) => {
|
|
51
|
-
const
|
|
196
|
+
const normalized = normalizeWithLogs(event, ctx);
|
|
197
|
+
const notices = normalized.map((x) => x.notice);
|
|
52
198
|
const result = {
|
|
53
199
|
received: notices.length,
|
|
54
200
|
sent: 0,
|
|
@@ -60,6 +206,29 @@ export function createNotifyHandler(options) {
|
|
|
60
206
|
const groups = group(notices);
|
|
61
207
|
const candidates = [];
|
|
62
208
|
const delivered = new Set();
|
|
209
|
+
// alerts の記録: 重複抑制(claim)の前に、抑制されるものも含めて。dry-run では触れない
|
|
210
|
+
if (options.recorder && !options.dryRun) {
|
|
211
|
+
try {
|
|
212
|
+
const { ids, unrecorded, suspended } = await recordAll(options.recorder, units(normalized));
|
|
213
|
+
result.recorded = ids.size;
|
|
214
|
+
result.unrecorded = unrecorded;
|
|
215
|
+
if (suspended)
|
|
216
|
+
result.recordSuspended = true;
|
|
217
|
+
if (baseUrl) {
|
|
218
|
+
for (const g of groups) {
|
|
219
|
+
const id = ids.get(alertKeyOf(g.notice));
|
|
220
|
+
if (id)
|
|
221
|
+
g.notice = { ...g.notice, detailUrl: `${baseUrl}/alerts/${id}/show` };
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
catch (e) {
|
|
226
|
+
// recordAll は例外を出さないが、念のため(記録の不具合で通知を止めない)
|
|
227
|
+
logger.error('alerts の記録に失敗しました', {
|
|
228
|
+
error: e instanceof Error ? e.message : String(e),
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
}
|
|
63
232
|
try {
|
|
64
233
|
for (const g of groups) {
|
|
65
234
|
const windowSec = windowOf(g.notice);
|
|
@@ -172,4 +341,37 @@ export function createNotifyHandler(options) {
|
|
|
172
341
|
}
|
|
173
342
|
}
|
|
174
343
|
}
|
|
344
|
+
/** 有限の正の整数(小数は切り捨て)。そうでなければ既定値 */
|
|
345
|
+
function positiveInt(v, fallback) {
|
|
346
|
+
if (typeof v !== 'number' || !Number.isFinite(v))
|
|
347
|
+
return fallback;
|
|
348
|
+
const n = Math.floor(v);
|
|
349
|
+
return n >= 1 ? n : fallback;
|
|
350
|
+
}
|
|
351
|
+
/** 管理画面のベース URL。http(s) でなければ使わない(記録はする。URL を付けない)。末尾の `/` は除く */
|
|
352
|
+
function adminBaseUrlOf(v, logger) {
|
|
353
|
+
if (v === undefined)
|
|
354
|
+
return undefined;
|
|
355
|
+
if (typeof v !== 'string' || !/^https?:\/\/[^\s/]+\S*$/i.test(v)) {
|
|
356
|
+
logger.warn('adminBaseUrl が http(s) の URL ではないので、通知に詳細の URL を付けません', {
|
|
357
|
+
adminBaseUrl: typeof v === 'string' ? v.slice(0, 200) : typeof v,
|
|
358
|
+
});
|
|
359
|
+
return undefined;
|
|
360
|
+
}
|
|
361
|
+
return v.replace(/\/+$/, '');
|
|
362
|
+
}
|
|
363
|
+
/** ロググループ名の照合(完全一致、または末尾 `*` の前方一致) */
|
|
364
|
+
function logGroupMatcher(patterns) {
|
|
365
|
+
const exact = new Set();
|
|
366
|
+
const prefixes = [];
|
|
367
|
+
for (const p of patterns) {
|
|
368
|
+
if (typeof p !== 'string' || p === '')
|
|
369
|
+
continue;
|
|
370
|
+
if (p.endsWith('*'))
|
|
371
|
+
prefixes.push(p.slice(0, -1));
|
|
372
|
+
else
|
|
373
|
+
exact.add(p);
|
|
374
|
+
}
|
|
375
|
+
return (g) => exact.has(g) || prefixes.some((p) => g.startsWith(p));
|
|
376
|
+
}
|
|
175
377
|
//# sourceMappingURL=handler.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/notify/handler.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/notify/handler.ts"],"names":[],"mappings":"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"}
|
package/dist/notify/index.d.ts
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* ログ(warn 以上)・CloudWatch アラーム・直接呼び出しを Notice にそろえ、重複抑制のうえ、
|
|
5
5
|
* Slack・メールなどのチャネルへ配信する部品。配線(購読フィルタ・Lambda・Terraform)は各アプリが行う。
|
|
6
6
|
*/
|
|
7
|
+
export { ALERTS_RESOURCE, ALERT_RETENTION_DAYS, alertKeyOf, cleanupAlerts, createAlertRecorder, } from './alerts.js';
|
|
8
|
+
export type { AlertInput, AlertOccurrence, AlertRecord, AlertRecorder, AlertRecorderOptions, AlertsCleanupCollection, AlertsCollection, CleanupAlertsOptions, CleanupAlertsResult, } from './alerts.js';
|
|
7
9
|
export { createEmailChannel, sesSender } from './channels/email.js';
|
|
8
10
|
export type { EmailMessage, EmailOptions, EmailSender, SesSendInput } from './channels/email.js';
|
|
9
11
|
export { createSlackChannel } from './channels/slack.js';
|
|
@@ -11,8 +13,9 @@ export type { SlackOptions } from './channels/slack.js';
|
|
|
11
13
|
export { createNotifyHandler } from './handler.js';
|
|
12
14
|
export type { NotifyHandlerOptions, NotifyResult } from './handler.js';
|
|
13
15
|
export { consoleNotifyLogger, logFatal } from './logger.js';
|
|
14
|
-
export { noticeFromLogLine, normalize } from './normalize.js';
|
|
16
|
+
export { noticeFromLogLine, normalize, normalizeWithLogs } from './normalize.js';
|
|
17
|
+
export type { NormalizedNotice } from './normalize.js';
|
|
15
18
|
export { DEFAULT_RATE, DEFAULT_WINDOWS, fingerprintOf } from './policy.js';
|
|
16
19
|
export { DynamoNoticeStore, MemoryNoticeStore } from './store.js';
|
|
17
|
-
export type { AdminDirectory, Channel, ClaimResult, Notice, NoticeLevel, NoticeStore, NotifyLogger, } from './types.js';
|
|
20
|
+
export type { AdminDirectory, AlertIndex, AlertTouchInput, AlertTouchResult, Channel, LogRef, ClaimResult, Notice, NoticeLevel, NoticeStore, NotifyLogger, } from './types.js';
|
|
18
21
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/notify/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACpE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACjG,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/notify/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,UAAU,EACV,aAAa,EACb,mBAAmB,GACpB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,UAAU,EACV,eAAe,EACf,WAAW,EACX,aAAa,EACb,oBAAoB,EACpB,uBAAuB,EACvB,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACpE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACjG,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACjF,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAClE,YAAY,EACV,cAAc,EACd,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,OAAO,EACP,MAAM,EACN,WAAW,EACX,MAAM,EACN,WAAW,EACX,WAAW,EACX,YAAY,GACb,MAAM,YAAY,CAAC"}
|
package/dist/notify/index.js
CHANGED
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
* ログ(warn 以上)・CloudWatch アラーム・直接呼び出しを Notice にそろえ、重複抑制のうえ、
|
|
5
5
|
* Slack・メールなどのチャネルへ配信する部品。配線(購読フィルタ・Lambda・Terraform)は各アプリが行う。
|
|
6
6
|
*/
|
|
7
|
+
export { ALERTS_RESOURCE, ALERT_RETENTION_DAYS, alertKeyOf, cleanupAlerts, createAlertRecorder, } from './alerts.js';
|
|
7
8
|
export { createEmailChannel, sesSender } from './channels/email.js';
|
|
8
9
|
export { createSlackChannel } from './channels/slack.js';
|
|
9
10
|
export { createNotifyHandler } from './handler.js';
|
|
10
11
|
export { consoleNotifyLogger, logFatal } from './logger.js';
|
|
11
|
-
export { noticeFromLogLine, normalize } from './normalize.js';
|
|
12
|
+
export { noticeFromLogLine, normalize, normalizeWithLogs } from './normalize.js';
|
|
12
13
|
export { DEFAULT_RATE, DEFAULT_WINDOWS, fingerprintOf } from './policy.js';
|
|
13
14
|
export { DynamoNoticeStore, MemoryNoticeStore } from './store.js';
|
|
14
15
|
//# sourceMappingURL=index.js.map
|
package/dist/notify/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/notify/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/notify/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,UAAU,EACV,aAAa,EACb,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAYrB,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAEpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEjF,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -1,11 +1,22 @@
|
|
|
1
|
-
import type { Notice } from './types.js';
|
|
1
|
+
import type { LogRef, Notice } from './types.js';
|
|
2
2
|
export interface NormalizeContext {
|
|
3
3
|
app: string;
|
|
4
4
|
env: string;
|
|
5
5
|
now: () => Date;
|
|
6
|
+
/** ログ参照(LogRef)のリージョン。無ければログ参照を作らない */
|
|
7
|
+
region?: string;
|
|
8
|
+
}
|
|
9
|
+
/** 正規化した通知と、その元のログの所在(ログの購読から来たときだけ) */
|
|
10
|
+
export interface NormalizedNotice {
|
|
11
|
+
notice: Notice;
|
|
12
|
+
log?: LogRef;
|
|
13
|
+
/** 購読ペイロードのロググループ(ログの購読から来たときだけ。region が無くても入る) */
|
|
14
|
+
logGroup?: string;
|
|
6
15
|
}
|
|
7
16
|
/** ログ 1 行 → Notice(通知対象でなければ undefined) */
|
|
8
17
|
export declare function noticeFromLogLine(line: string, ctx: NormalizeContext, at?: number): Notice | undefined;
|
|
9
18
|
/** どの入力かを判別して Notice[] にする。未知の入力は空配列 */
|
|
10
19
|
export declare function normalize(event: unknown, ctx: NormalizeContext): Notice[];
|
|
20
|
+
/** normalize と同じ。ログの購読から来た通知には、ログの所在(LogRef)を添える */
|
|
21
|
+
export declare function normalizeWithLogs(event: unknown, ctx: NormalizeContext): NormalizedNotice[];
|
|
11
22
|
//# sourceMappingURL=normalize.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/notify/normalize.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,MAAM,EAAe,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/notify/normalize.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAe,MAAM,YAAY,CAAC;AAE9D,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,IAAI,CAAC;IAChB,uCAAuC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wCAAwC;AACxC,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AA2JD,2CAA2C;AAC3C,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,gBAAgB,EACrB,EAAE,CAAC,EAAE,MAAM,GACV,MAAM,GAAG,SAAS,CAEpB;AA+KD,wCAAwC;AACxC,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,gBAAgB,GAAG,MAAM,EAAE,CAEzE;AAED,oDAAoD;AACpD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,gBAAgB,GAAG,gBAAgB,EAAE,CAc3F"}
|
package/dist/notify/normalize.js
CHANGED
|
@@ -25,7 +25,15 @@ const LAMBDA_FAILURE_LINE = /^(?:\S+\s+[0-9a-fA-F-]{8,}\s+|RequestId: \S+\s+(?:E
|
|
|
25
25
|
const REPORT_FAILURE = /^REPORT RequestId:[\s\S]*\bStatus: (timeout|error|failure)\b/;
|
|
26
26
|
const LAMBDA_FAILURE_LABEL = /^(Invoke Error|Unhandled Promise Rejection|Uncaught Exception)\b/;
|
|
27
27
|
/** `時刻<TAB>RequestId<TAB>LEVEL<TAB>本文`(テキスト形式)。本文と外側の level を分ける */
|
|
28
|
-
const TEXT_PREFIX = /^\S+\t(
|
|
28
|
+
const TEXT_PREFIX = /^\S+\t([0-9a-fA-F-]{8,}|undefined)\t(TRACE|DEBUG|INFO|WARN|ERROR|FATAL)\t([\s\S]*)$/;
|
|
29
|
+
/**
|
|
30
|
+
* 実行基盤の行(`RequestId: …`、`START / END / REPORT RequestId: …`)の RequestId。
|
|
31
|
+
* 行頭だけを見る(アプリの JSON の message の中の `RequestId:` は拾わない)
|
|
32
|
+
*/
|
|
33
|
+
const REQUEST_ID_IN_TEXT = /^(?:(?:START|END|REPORT) )?RequestId: ([0-9a-fA-F-]{8,})/;
|
|
34
|
+
/** RequestId として受け付ける形(ログ参照に入れる。長さと文字を制限する) */
|
|
35
|
+
const REQUEST_ID = /^[0-9A-Za-z-]{8,64}$/;
|
|
36
|
+
const requestIdOf = (v) => typeof v === 'string' && v !== 'undefined' && REQUEST_ID.test(v) ? v : undefined;
|
|
29
37
|
function asObj(text) {
|
|
30
38
|
const t = text.trim();
|
|
31
39
|
if (!t.startsWith('{'))
|
|
@@ -41,12 +49,21 @@ function asObj(text) {
|
|
|
41
49
|
const str = (v) => (typeof v === 'string' ? v : undefined);
|
|
42
50
|
const isAppLog = (o) => typeof o.level === 'string' || typeof o.event === 'string';
|
|
43
51
|
function parseLine(line) {
|
|
52
|
+
const p = parseLineBody(line);
|
|
53
|
+
// Lambda の RequestId だけを使う(テキスト形式の接頭辞 → JSON 形式の外側 → `RequestId:` 行)。
|
|
54
|
+
// 接頭辞の無いアプリの JSON 行の requestId は使わない(Lambda のものとは限らない)
|
|
55
|
+
const requestId = requestIdOf(TEXT_PREFIX.exec(line)?.[1]) ??
|
|
56
|
+
p.requestId ??
|
|
57
|
+
requestIdOf(REQUEST_ID_IN_TEXT.exec(line)?.[1]);
|
|
58
|
+
return requestId ? { ...p, requestId } : p;
|
|
59
|
+
}
|
|
60
|
+
function parseLineBody(line) {
|
|
44
61
|
let body = line;
|
|
45
62
|
let outerLevel;
|
|
46
63
|
const m = TEXT_PREFIX.exec(line);
|
|
47
64
|
if (m) {
|
|
48
|
-
outerLevel = m[
|
|
49
|
-
body = m[
|
|
65
|
+
outerLevel = m[2];
|
|
66
|
+
body = m[3];
|
|
50
67
|
}
|
|
51
68
|
// Invoke Error など: `ラベル<TAB>{json}`
|
|
52
69
|
const tab = body.indexOf('\t{');
|
|
@@ -71,12 +88,13 @@ function parseLine(line) {
|
|
|
71
88
|
/^(TRACE|DEBUG|INFO|WARN|ERROR|FATAL)$/.test(outer.level) &&
|
|
72
89
|
!('event' in outer);
|
|
73
90
|
if (lambdaWrapped) {
|
|
91
|
+
const requestId = requestIdOf(outer.requestId);
|
|
74
92
|
const level = str(outer.level);
|
|
75
93
|
const msg = outer.message;
|
|
76
94
|
// アプリの JSON 文字列が message に入っている
|
|
77
95
|
const inner = typeof msg === 'string' ? asObj(msg) : undefined;
|
|
78
96
|
if (inner && isAppLog(inner))
|
|
79
|
-
return { app: inner, text: '', outerLevel: level };
|
|
97
|
+
return { app: inner, text: '', outerLevel: level, requestId };
|
|
80
98
|
// エラーのオブジェクト(Invoke Error など)
|
|
81
99
|
const errObj = typeof msg === 'object' && msg !== null ? msg : undefined;
|
|
82
100
|
const withType = typeof outer.errorType === 'string'
|
|
@@ -85,10 +103,15 @@ function parseLine(line) {
|
|
|
85
103
|
? errObj
|
|
86
104
|
: undefined;
|
|
87
105
|
if (withType) {
|
|
88
|
-
return {
|
|
106
|
+
return {
|
|
107
|
+
runtime: withType,
|
|
108
|
+
text: typeof msg === 'string' ? msg : '',
|
|
109
|
+
outerLevel: level,
|
|
110
|
+
requestId,
|
|
111
|
+
};
|
|
89
112
|
}
|
|
90
113
|
const text = typeof msg === 'string' ? msg : errObj ? JSON.stringify(errObj) : '';
|
|
91
|
-
return { text, outerLevel: level };
|
|
114
|
+
return { text, outerLevel: level, requestId };
|
|
92
115
|
}
|
|
93
116
|
return { app: outer, text: '', outerLevel };
|
|
94
117
|
}
|
|
@@ -106,9 +129,19 @@ function failure(message, ctx, occurredAt, target) {
|
|
|
106
129
|
}
|
|
107
130
|
/** ログ 1 行 → Notice(通知対象でなければ undefined) */
|
|
108
131
|
export function noticeFromLogLine(line, ctx, at) {
|
|
132
|
+
return parseLogLine(line, ctx, at)?.notice;
|
|
133
|
+
}
|
|
134
|
+
/** ログ 1 行 → Notice と RequestId(ログから取れたとき) */
|
|
135
|
+
function parseLogLine(line, ctx, at) {
|
|
136
|
+
const p = parseLine(line);
|
|
137
|
+
const notice = noticeFromParsed(p, ctx, at);
|
|
138
|
+
if (!notice)
|
|
139
|
+
return undefined;
|
|
140
|
+
return { notice, requestId: p.requestId };
|
|
141
|
+
}
|
|
142
|
+
function noticeFromParsed(p, ctx, at) {
|
|
109
143
|
const t = at !== undefined && Number.isFinite(at) ? new Date(at) : ctx.now();
|
|
110
144
|
const occurredAt = (Number.isNaN(t.getTime()) ? ctx.now() : t).toISOString();
|
|
111
|
-
const p = parseLine(line);
|
|
112
145
|
const outer = p.outerLevel ? levelOf(p.outerLevel) : undefined;
|
|
113
146
|
if (p.platformStatus && /^(timeout|error|failure)$/.test(p.platformStatus)) {
|
|
114
147
|
return failure(`Lambda の実行が失敗しました(status: ${p.platformStatus})`, ctx, occurredAt);
|
|
@@ -168,17 +201,36 @@ export function noticeFromLogLine(line, ctx, at) {
|
|
|
168
201
|
}
|
|
169
202
|
return undefined;
|
|
170
203
|
}
|
|
204
|
+
/** ロググループ・ストリーム名(CloudWatch の上限 512 文字。制御文字を含むものは使わない) */
|
|
205
|
+
const LOG_NAME = /^[^\u0000-\u001f\u007f]{1,512}$/;
|
|
206
|
+
const logName = (v) => typeof v === 'string' && LOG_NAME.test(v) ? v : undefined;
|
|
171
207
|
function fromLogs(event, ctx) {
|
|
172
208
|
const payload = JSON.parse(gunzipSync(Buffer.from(event.awslogs.data, 'base64')).toString('utf8'));
|
|
209
|
+
const logGroup = logName(payload.logGroup);
|
|
210
|
+
const logStream = logName(payload.logStream);
|
|
173
211
|
const out = [];
|
|
174
212
|
for (const e of payload.logEvents ?? []) {
|
|
175
213
|
// 1 行の失敗で、同じバッチの他の行を失わない
|
|
176
214
|
try {
|
|
177
215
|
if (typeof e?.message !== 'string')
|
|
178
216
|
continue;
|
|
179
|
-
const
|
|
180
|
-
if (
|
|
181
|
-
|
|
217
|
+
const r = parseLogLine(e.message, ctx, e.timestamp);
|
|
218
|
+
if (!r)
|
|
219
|
+
continue;
|
|
220
|
+
const log = ctx.region && logGroup && logStream
|
|
221
|
+
? {
|
|
222
|
+
region: ctx.region,
|
|
223
|
+
logGroup,
|
|
224
|
+
logStream,
|
|
225
|
+
timestamp: Date.parse(r.notice.occurredAt),
|
|
226
|
+
...(r.requestId ? { requestId: r.requestId } : {}),
|
|
227
|
+
}
|
|
228
|
+
: undefined;
|
|
229
|
+
out.push({
|
|
230
|
+
notice: r.notice,
|
|
231
|
+
...(log ? { log } : {}),
|
|
232
|
+
...(logGroup ? { logGroup } : {}),
|
|
233
|
+
});
|
|
182
234
|
}
|
|
183
235
|
catch {
|
|
184
236
|
continue;
|
|
@@ -230,16 +282,23 @@ function fromDirect(event, ctx) {
|
|
|
230
282
|
}
|
|
231
283
|
/** どの入力かを判別して Notice[] にする。未知の入力は空配列 */
|
|
232
284
|
export function normalize(event, ctx) {
|
|
285
|
+
return normalizeWithLogs(event, ctx).map((x) => x.notice);
|
|
286
|
+
}
|
|
287
|
+
/** normalize と同じ。ログの購読から来た通知には、ログの所在(LogRef)を添える */
|
|
288
|
+
export function normalizeWithLogs(event, ctx) {
|
|
233
289
|
if (typeof event !== 'object' || event === null)
|
|
234
290
|
return [];
|
|
235
291
|
const e = event;
|
|
236
292
|
if (typeof e.awslogs?.data === 'string') {
|
|
237
293
|
return fromLogs(e, ctx);
|
|
238
294
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
295
|
+
const wrap = (ns) => ns.map((notice) => ({ notice }));
|
|
296
|
+
if (e['detail-type'] === 'CloudWatch Alarm State Change') {
|
|
297
|
+
return wrap(fromAlarm(e, ctx));
|
|
298
|
+
}
|
|
299
|
+
if (typeof e.notice === 'object' && e.notice !== null) {
|
|
300
|
+
return wrap(fromDirect(e, ctx));
|
|
301
|
+
}
|
|
243
302
|
return [];
|
|
244
303
|
}
|
|
245
304
|
//# sourceMappingURL=normalize.js.map
|