kayvee 3.16.0 → 3.18.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/.eslintrc.js +124 -0
- package/.github/workflows/notify-ci-status.yml +20 -0
- package/.nvmrc +1 -1
- package/.prettierrc.json +1 -0
- package/Makefile +20 -4
- package/build/lib/kayvee.js +13 -17
- package/build/lib/logger/logger.js +84 -76
- package/build/lib/middleware.js +62 -89
- package/build/lib/router/index.js +61 -63
- package/build/package.json +16 -8
- package/build/test/context_logger.js +36 -44
- package/build/test/kayvee.js +16 -16
- package/build/test/logger_test.js +113 -102
- package/build/test/middleware.js +90 -235
- package/build/test/router.js +238 -94
- package/lib/kayvee.ts +19 -7
- package/lib/logger/logger.ts +101 -47
- package/lib/middleware.ts +31 -31
- package/lib/router/index.ts +18 -13
- package/package.json +16 -8
- package/test/context_logger.ts +7 -7
- package/test/kayvee.ts +16 -7
- package/test/logger_test.ts +24 -27
- package/test/middleware.ts +88 -222
- package/test/router.ts +247 -176
- package/tsconfig.json +1 -1
- package/.eslintrc.yml +0 -47
- package/tsd.json +0 -15
- package/tslint.json +0 -134
- package/typings/globals/es6-shim/index.d.ts +0 -666
- package/typings/globals/es6-shim/typings.json +0 -8
- package/typings/index.d.ts +0 -1
- package/typings/mocha/mocha.d.ts +0 -236
- package/typings/node/node.d.ts +0 -2340
- package/typings/tsd.d.ts +0 -2
- package/typings.json +0 -5
package/build/test/router.js
CHANGED
|
@@ -1,11 +1,59 @@
|
|
|
1
1
|
var assert = require("assert");
|
|
2
2
|
var router = require("../lib/router");
|
|
3
|
-
describe("router.Router",
|
|
4
|
-
describe("constructor",
|
|
5
|
-
it("parses well formatted configs",
|
|
3
|
+
describe("router.Router", () => {
|
|
4
|
+
describe("constructor", () => {
|
|
5
|
+
it("parses well formatted configs", () => {
|
|
6
6
|
process.env.SCHOOL = "Hogwarts";
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
const conf = `
|
|
8
|
+
routes:
|
|
9
|
+
rule-one:
|
|
10
|
+
matchers:
|
|
11
|
+
title: ["authorize-app"]
|
|
12
|
+
output:
|
|
13
|
+
type: "notifications"
|
|
14
|
+
channel: "%{foo.bar}"
|
|
15
|
+
icon: ":rocket:"
|
|
16
|
+
message: "authorized %{foo.bar} in \${SCHOOL}"
|
|
17
|
+
user: "@fishman"
|
|
18
|
+
rule-two:
|
|
19
|
+
matchers:
|
|
20
|
+
foo.bar: ["multiple", "matches"]
|
|
21
|
+
baz: ["whatever"]
|
|
22
|
+
output:
|
|
23
|
+
type: "alerts"
|
|
24
|
+
series: "other-series"
|
|
25
|
+
dimensions: ["baz"]
|
|
26
|
+
stat_type: "gauge"
|
|
27
|
+
rule-three:
|
|
28
|
+
matchers:
|
|
29
|
+
foo.bar: ["multiple", "matches"]
|
|
30
|
+
baz: ["whatever"]
|
|
31
|
+
output:
|
|
32
|
+
type: "alerts"
|
|
33
|
+
series: "other-series"
|
|
34
|
+
dimensions: ["baz"]
|
|
35
|
+
stat_type: "gauge"
|
|
36
|
+
value_field: "hello"
|
|
37
|
+
rule-four:
|
|
38
|
+
matchers:
|
|
39
|
+
foo.bar: ["multiple", "matches"]
|
|
40
|
+
baz: ["whatever"]
|
|
41
|
+
output:
|
|
42
|
+
type: "alerts"
|
|
43
|
+
series: "other-series"
|
|
44
|
+
dimensions: []
|
|
45
|
+
stat_type: "gauge"
|
|
46
|
+
rule-five:
|
|
47
|
+
matchers:
|
|
48
|
+
foo.bar: [true]
|
|
49
|
+
baz: [false]
|
|
50
|
+
output:
|
|
51
|
+
type: "alerts"
|
|
52
|
+
series: "other-series"
|
|
53
|
+
dimensions: []
|
|
54
|
+
stat_type: "gauge"
|
|
55
|
+
`;
|
|
56
|
+
const expected = [
|
|
9
57
|
new router.Rule("rule-one", { title: ["authorize-app"] }, {
|
|
10
58
|
type: "notifications",
|
|
11
59
|
channel: "%{foo.bar}",
|
|
@@ -42,115 +90,211 @@ describe("router.Router", function () {
|
|
|
42
90
|
value_field: "value",
|
|
43
91
|
}),
|
|
44
92
|
];
|
|
45
|
-
|
|
93
|
+
const actual = new router.Router();
|
|
46
94
|
actual._loadConfigString(conf);
|
|
47
95
|
assert.deepEqual(actual.rules, expected);
|
|
48
96
|
});
|
|
49
|
-
it("rejects specials in matchers",
|
|
50
|
-
|
|
97
|
+
it("rejects specials in matchers", () => {
|
|
98
|
+
const confTmpl = (v) => `
|
|
99
|
+
routes:
|
|
100
|
+
non-string-values:
|
|
101
|
+
matchers:
|
|
102
|
+
no-numbers: [${v}]
|
|
103
|
+
output:
|
|
104
|
+
type: "analytics"
|
|
105
|
+
series: "fun"
|
|
106
|
+
`;
|
|
51
107
|
// Make sure the template works
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
assert.doesNotThrow(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
assert.throws(
|
|
58
|
-
};
|
|
59
|
-
for (var _i = 0, _a = ["5", "[]", "{}"]; _i < _a.length; _i++) {
|
|
60
|
-
var invalidVal = _a[_i];
|
|
61
|
-
_loop_1(invalidVal);
|
|
108
|
+
const conf = confTmpl('"valid"');
|
|
109
|
+
const actual = new router.Router();
|
|
110
|
+
assert.doesNotThrow(() => actual._loadConfigString(conf));
|
|
111
|
+
for (const invalidVal of ["5", "[]", "{}"]) {
|
|
112
|
+
const invalidConf = confTmpl(invalidVal);
|
|
113
|
+
assert.throws(() => actual._loadConfigString(invalidConf));
|
|
62
114
|
}
|
|
63
|
-
assert.throws(
|
|
115
|
+
assert.throws(() => actual._loadConfigString(confTmpl('""')));
|
|
64
116
|
return;
|
|
65
117
|
});
|
|
66
|
-
it("rejects duplicates in matchers",
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
118
|
+
it("rejects duplicates in matchers", () => {
|
|
119
|
+
const confTmpl = (v) => `
|
|
120
|
+
routes:
|
|
121
|
+
sloppy:
|
|
122
|
+
matchers:
|
|
123
|
+
title: [${v}]
|
|
124
|
+
output:
|
|
125
|
+
type: "analytics"
|
|
126
|
+
series: "fun"
|
|
127
|
+
`;
|
|
128
|
+
const actual = new router.Router();
|
|
129
|
+
const validConf = confTmpl('"non-repeated", "name"');
|
|
130
|
+
assert.doesNotThrow(() => actual._loadConfigString(validConf));
|
|
131
|
+
const invalidConf = confTmpl('"repeated", "repeated", "name"');
|
|
132
|
+
assert.throws(() => actual._loadConfigString(invalidConf));
|
|
73
133
|
});
|
|
74
|
-
it("requires correct types in outputs",
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
134
|
+
it("requires correct types in outputs", () => {
|
|
135
|
+
const confTmpl = (series, dimensions) => `
|
|
136
|
+
routes:
|
|
137
|
+
wrong:
|
|
138
|
+
matchers:
|
|
139
|
+
title: ["test"]
|
|
140
|
+
output:
|
|
141
|
+
type: "alerts"
|
|
142
|
+
series: ${series}
|
|
143
|
+
dimensions: ${dimensions}
|
|
144
|
+
value_field: "hihi"
|
|
145
|
+
stat_type: "gauge"
|
|
146
|
+
`;
|
|
147
|
+
const actual = new router.Router();
|
|
148
|
+
const validConf = confTmpl('"my-series"', '["dim1", "dim2"]');
|
|
149
|
+
assert.doesNotThrow(() => actual._loadConfigString(validConf));
|
|
150
|
+
const invalidConf0 = confTmpl('["my-series"]', '["dim1", "dim2"]');
|
|
151
|
+
assert.throws(() => actual._loadConfigString(invalidConf0));
|
|
152
|
+
const invalidConf1 = confTmpl('"my-series"', '"dim1"');
|
|
153
|
+
assert.throws(() => actual._loadConfigString(invalidConf1));
|
|
83
154
|
});
|
|
84
|
-
it("requires all keys in outputs",
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
155
|
+
it("requires all keys in outputs", () => {
|
|
156
|
+
const confTmpl = (v) => `
|
|
157
|
+
routes:
|
|
158
|
+
wrong:
|
|
159
|
+
matchers:
|
|
160
|
+
title: ["test"]
|
|
161
|
+
output:
|
|
162
|
+
type: "alerts"${v}
|
|
163
|
+
dimensions: ["dim1", "dim2"]
|
|
164
|
+
stat_type: "gauge"
|
|
165
|
+
`;
|
|
166
|
+
const actual = new router.Router();
|
|
167
|
+
const validConf = confTmpl(`
|
|
168
|
+
series: "whatever"`);
|
|
169
|
+
assert.doesNotThrow(() => actual._loadConfigString(validConf));
|
|
170
|
+
const invalidConf = confTmpl("");
|
|
171
|
+
assert.throws(() => actual._loadConfigString(invalidConf));
|
|
91
172
|
});
|
|
92
|
-
it("doesn't allow extra keys",
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
173
|
+
it("doesn't allow extra keys", () => {
|
|
174
|
+
const confTmpl = (v) => `
|
|
175
|
+
routes:
|
|
176
|
+
wrong:
|
|
177
|
+
matchers:
|
|
178
|
+
title: ["test"]
|
|
179
|
+
output:
|
|
180
|
+
type: "metrics"${v}
|
|
181
|
+
dimensions: ["dim1", "dim2"]
|
|
182
|
+
`;
|
|
183
|
+
const actual = new router.Router();
|
|
184
|
+
const validConf = confTmpl(`
|
|
185
|
+
series: "whatever"`);
|
|
186
|
+
assert.doesNotThrow(() => actual._loadConfigString(validConf));
|
|
187
|
+
const invalidConf = confTmpl(`
|
|
188
|
+
series: "whatever"
|
|
189
|
+
something-else: "hi there"`);
|
|
190
|
+
assert.throws(() => actual._loadConfigString(invalidConf));
|
|
99
191
|
});
|
|
100
|
-
it("errors on type-os",
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
config =
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
assert.throws(
|
|
113
|
-
config =
|
|
114
|
-
|
|
192
|
+
it("errors on type-os", () => {
|
|
193
|
+
const actual = new router.Router();
|
|
194
|
+
let config;
|
|
195
|
+
config = `
|
|
196
|
+
route: # Should be routes (plural)
|
|
197
|
+
string-values:
|
|
198
|
+
matchers:
|
|
199
|
+
errors: [ "type-o" ]
|
|
200
|
+
output:
|
|
201
|
+
type: "analytics"
|
|
202
|
+
series: "fun"
|
|
203
|
+
`;
|
|
204
|
+
assert.throws(() => actual._loadConfigString(config));
|
|
205
|
+
config = `
|
|
206
|
+
routes:
|
|
207
|
+
string-values:
|
|
208
|
+
matcher: # Should be matchers (plural)
|
|
209
|
+
errors: [ "type-o" ]
|
|
210
|
+
output:
|
|
211
|
+
type: "analytics"
|
|
212
|
+
series: "fun"
|
|
213
|
+
`;
|
|
214
|
+
assert.throws(() => actual._loadConfigString(config));
|
|
215
|
+
config = `
|
|
216
|
+
routes:
|
|
217
|
+
string-values:
|
|
218
|
+
matchers:
|
|
219
|
+
errors: [ "type-o" ]
|
|
220
|
+
outputs: # Should be output (signular)
|
|
221
|
+
type: "analytics"
|
|
222
|
+
series: "fun"
|
|
223
|
+
`;
|
|
224
|
+
assert.throws(() => actual._loadConfigString(config));
|
|
225
|
+
config = `
|
|
226
|
+
routes:
|
|
227
|
+
$invalid-string-values: # Invalid rule name
|
|
228
|
+
matchers:
|
|
229
|
+
errors: [ "type-o" ]
|
|
230
|
+
output:
|
|
231
|
+
type: "analytics"
|
|
232
|
+
series: "fun"
|
|
233
|
+
`;
|
|
234
|
+
assert.throws(() => actual._loadConfigString(config));
|
|
235
|
+
config = `
|
|
236
|
+
routes:
|
|
237
|
+
string-values:
|
|
238
|
+
matchers:
|
|
239
|
+
errors: [ "type-o" ]
|
|
240
|
+
output:
|
|
241
|
+
type: "analytic" # Should be analytics (plural)p
|
|
242
|
+
series: "fun"
|
|
243
|
+
`;
|
|
244
|
+
assert.throws(() => actual._loadConfigString(config));
|
|
245
|
+
config = `
|
|
246
|
+
routes:
|
|
247
|
+
string-values:
|
|
248
|
+
matchers:
|
|
249
|
+
errors: [ "*", "type-o" ] # A wildcard cannot exist with other matchers
|
|
250
|
+
output:
|
|
251
|
+
type: "analytics"
|
|
252
|
+
series: "fun"
|
|
253
|
+
`;
|
|
254
|
+
assert.throws(() => actual._loadConfigString(config));
|
|
115
255
|
});
|
|
116
256
|
});
|
|
117
|
-
describe("route",
|
|
118
|
-
it("matches one or more rule and returns appropriate outputs",
|
|
119
|
-
|
|
257
|
+
describe("route", () => {
|
|
258
|
+
it("matches one or more rule and returns appropriate outputs", () => {
|
|
259
|
+
const r = new router.Router([
|
|
120
260
|
new router.Rule("rule-one", { title: ["hello", "hi"], foo: ["bar", "baz"] }, { channel: "#-%{foo}-", dimensions: ["-%{foo}-"] }),
|
|
121
261
|
new router.Rule("rule-two", { "bing.bong": ["buzz"] }, { series: "x" }),
|
|
122
262
|
]);
|
|
123
|
-
|
|
263
|
+
const msg0 = {
|
|
124
264
|
title: "hi",
|
|
125
265
|
foo: "bar",
|
|
126
266
|
};
|
|
127
|
-
|
|
267
|
+
const expected0 = [
|
|
268
|
+
{
|
|
128
269
|
rule: "rule-one",
|
|
129
270
|
channel: "#-bar-",
|
|
130
271
|
dimensions: ["-bar-"],
|
|
131
|
-
}
|
|
132
|
-
|
|
272
|
+
},
|
|
273
|
+
];
|
|
274
|
+
const actual0 = r.route(msg0).routes;
|
|
133
275
|
assert.deepEqual(expected0, actual0);
|
|
134
|
-
|
|
276
|
+
const msg1 = {
|
|
135
277
|
title: "hi",
|
|
136
278
|
bing: {
|
|
137
279
|
bong: "buzz",
|
|
138
280
|
},
|
|
139
281
|
};
|
|
140
|
-
|
|
282
|
+
const expected1 = [
|
|
283
|
+
{
|
|
141
284
|
rule: "rule-two",
|
|
142
285
|
series: "x",
|
|
143
|
-
}
|
|
144
|
-
|
|
286
|
+
},
|
|
287
|
+
];
|
|
288
|
+
const actual1 = r.route(msg1).routes;
|
|
145
289
|
assert.deepEqual(expected1, actual1);
|
|
146
|
-
|
|
290
|
+
const msg2 = {
|
|
147
291
|
title: "hello",
|
|
148
292
|
foo: "baz",
|
|
149
293
|
bing: {
|
|
150
294
|
bong: "buzz",
|
|
151
295
|
},
|
|
152
296
|
};
|
|
153
|
-
|
|
297
|
+
const expected2 = [
|
|
154
298
|
{
|
|
155
299
|
rule: "rule-one",
|
|
156
300
|
channel: "#-baz-",
|
|
@@ -161,15 +305,15 @@ describe("router.Router", function () {
|
|
|
161
305
|
series: "x",
|
|
162
306
|
},
|
|
163
307
|
];
|
|
164
|
-
|
|
308
|
+
const actual2 = r.route(msg2).routes;
|
|
165
309
|
assert.deepEqual(expected2, actual2);
|
|
166
310
|
});
|
|
167
311
|
});
|
|
168
312
|
});
|
|
169
|
-
describe("router.Rule",
|
|
170
|
-
describe("matches",
|
|
171
|
-
it("works on simple cases",
|
|
172
|
-
|
|
313
|
+
describe("router.Rule", () => {
|
|
314
|
+
describe("matches", () => {
|
|
315
|
+
it("works on simple cases", () => {
|
|
316
|
+
const r = new router.Rule("test-rule", { title: ["hello", "hi"], foo: ["bar"] }, {});
|
|
173
317
|
assert(r.matches({
|
|
174
318
|
title: "hello",
|
|
175
319
|
foo: "bar",
|
|
@@ -190,8 +334,8 @@ describe("router.Rule", function () {
|
|
|
190
334
|
"missing-stuff": "indeed",
|
|
191
335
|
}));
|
|
192
336
|
});
|
|
193
|
-
it("works on nested messages",
|
|
194
|
-
|
|
337
|
+
it("works on nested messages", () => {
|
|
338
|
+
const r = new router.Rule("test-rule", { "foo.bar": ["hello", "hi"] }, {});
|
|
195
339
|
assert(r.matches({
|
|
196
340
|
title: "greeting",
|
|
197
341
|
foo: {
|
|
@@ -227,8 +371,8 @@ describe("router.Rule", function () {
|
|
|
227
371
|
foo: "hi",
|
|
228
372
|
}));
|
|
229
373
|
});
|
|
230
|
-
it("wild card matching",
|
|
231
|
-
|
|
374
|
+
it("wild card matching", () => {
|
|
375
|
+
const r = new router.Rule("test-rule", { any: ["*"] }, {});
|
|
232
376
|
assert(r.matches({
|
|
233
377
|
any: false,
|
|
234
378
|
}));
|
|
@@ -259,8 +403,8 @@ describe("router.Rule", function () {
|
|
|
259
403
|
},
|
|
260
404
|
}));
|
|
261
405
|
});
|
|
262
|
-
it("bool matching",
|
|
263
|
-
|
|
406
|
+
it("bool matching", () => {
|
|
407
|
+
const r = new router.Rule("test-rule", { bull: [true] }, {});
|
|
264
408
|
assert(r.matches({
|
|
265
409
|
bull: true,
|
|
266
410
|
}));
|
|
@@ -282,25 +426,25 @@ describe("router.Rule", function () {
|
|
|
282
426
|
}));
|
|
283
427
|
});
|
|
284
428
|
});
|
|
285
|
-
describe("outputFor",
|
|
286
|
-
it("substitutes kv entries",
|
|
287
|
-
|
|
429
|
+
describe("outputFor", () => {
|
|
430
|
+
it("substitutes kv entries", () => {
|
|
431
|
+
const r = new router.Rule("myrule", {}, {
|
|
288
432
|
channel: "#-%{foo}-",
|
|
289
433
|
dimensions: ["-%{foo}-", "-%{bar.baz}-"],
|
|
290
434
|
});
|
|
291
|
-
|
|
435
|
+
const msg = {
|
|
292
436
|
title: "greeting",
|
|
293
437
|
foo: "partner",
|
|
294
438
|
bar: {
|
|
295
439
|
baz: "nest egg",
|
|
296
440
|
},
|
|
297
441
|
};
|
|
298
|
-
|
|
442
|
+
const expected = {
|
|
299
443
|
rule: "myrule",
|
|
300
444
|
channel: "#-partner-",
|
|
301
445
|
dimensions: ["-partner-", "-nest egg-"],
|
|
302
446
|
};
|
|
303
|
-
|
|
447
|
+
const actual = r.outputFor(msg);
|
|
304
448
|
assert.deepEqual(expected, actual);
|
|
305
449
|
});
|
|
306
450
|
});
|
package/lib/kayvee.ts
CHANGED
|
@@ -20,12 +20,24 @@ function replaceErrors(key, value) {
|
|
|
20
20
|
function format(data) {
|
|
21
21
|
if (deploy_env || workflow_id || pod_id || pod_shortname || pod_account || pod_region) {
|
|
22
22
|
const extras: any = {};
|
|
23
|
-
if (deploy_env) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
if (deploy_env) {
|
|
24
|
+
extras.deploy_env = deploy_env;
|
|
25
|
+
}
|
|
26
|
+
if (workflow_id) {
|
|
27
|
+
extras.wf_id = workflow_id;
|
|
28
|
+
}
|
|
29
|
+
if (pod_id) {
|
|
30
|
+
extras["pod-id"] = pod_id;
|
|
31
|
+
}
|
|
32
|
+
if (pod_shortname) {
|
|
33
|
+
extras["pod-shortname"] = pod_shortname;
|
|
34
|
+
}
|
|
35
|
+
if (pod_region) {
|
|
36
|
+
extras["pod-region"] = pod_region;
|
|
37
|
+
}
|
|
38
|
+
if (pod_account) {
|
|
39
|
+
extras["pod-account"] = pod_account;
|
|
40
|
+
}
|
|
29
41
|
|
|
30
42
|
return JSON.stringify(_.extend(extras, data), replaceErrors);
|
|
31
43
|
}
|
|
@@ -38,7 +50,7 @@ function formatLog(source = "", level = "", title = "", data = {}) {
|
|
|
38
50
|
if (!_.isObject(data)) {
|
|
39
51
|
info = {};
|
|
40
52
|
}
|
|
41
|
-
const reserved = {source, level, title};
|
|
53
|
+
const reserved = { source, level, title };
|
|
42
54
|
|
|
43
55
|
// reserved keys overwrite other keys in data
|
|
44
56
|
return format(_.extend({}, info, reserved));
|