@mark1russell7/kind 0.12.5 → 0.13.1

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.
@@ -180,8 +180,11 @@ type Stack = "service" | "grpc";
180
180
  * - `latency` delays each packet that Redis sends by `delay`, for the hold (T07). Thus each command
181
181
  * of each replica takes that much longer, but Redis answers it. The heal sets the delay to zero.
182
182
  * - `none` injects nothing: a calibration measures the path itself.
183
+ * - `dns-blackhole` drops each answer of a DNS server in the network namespace of each client pod,
184
+ * for the hold (S2, CoreDNS). CoreDNS still answers, but no answer gets to a client. The heal
185
+ * removes the rules. A client that resolves the name of the Service (`byName`) sees it.
183
186
  */
184
- type TriggerKind = "pod-deletion" | "rolling-update" | "node-drain" | "scale-in" | "crash" | "liveness-restart" | "freeze-process" | "rst" | "blackhole" | "peer-gone-without-close" | "app-stall" | "rollout" | "cpu-throttle" | "authorization-policy" | "idle" | "ztunnel-restart" | "certificate-expiry" | "cannot-serve" | "zone-loss" | "latency";
187
+ type TriggerKind = "pod-deletion" | "rolling-update" | "node-drain" | "scale-in" | "crash" | "liveness-restart" | "freeze-process" | "rst" | "blackhole" | "peer-gone-without-close" | "app-stall" | "rollout" | "cpu-throttle" | "authorization-policy" | "idle" | "ztunnel-restart" | "certificate-expiry" | "cannot-serve" | "zone-loss" | "latency" | "dns-blackhole";
185
188
  /**
186
189
  * A trigger is its kind and the settings of its fault. The parameter `A` is the form of an amount:
187
190
  * a quantity in the format `/2`, a number in the format `/1`.
@@ -366,6 +369,12 @@ interface Workload {
366
369
  * until its first answer comes from its backend. With no value, the rules pick the backend of each session.
367
370
  */
368
371
  readonly onTarget?: number | undefined;
372
+ /**
373
+ * This flag gives each client the name of the Service as its target, not the ClusterIP. Thus each
374
+ * new connection of a client starts with a lookup of the name in the cluster DNS (S2, CoreDNS).
375
+ * With no value, the target is the ClusterIP, and a client does no lookup.
376
+ */
377
+ readonly byName?: boolean | undefined;
369
378
  }
370
379
  /**
371
380
  * A band is a range of times after a reference event of the run. The format `/1` gives each end
@@ -710,11 +719,6 @@ declare const CLIENT = "client";
710
719
  declare const REDIS = "redis";
711
720
  //#endregion
712
721
  //#region src/observe.d.ts
713
- /**
714
- * This module reads a run from its lines. Each time is in milliseconds on CLOCK_MONOTONIC. All the
715
- * containers of the VM share that clock: the clients, the service, the agents, the injector, the
716
- * watcher and the prober.
717
- */
718
722
  /**
719
723
  * A line is one JSON line of a source of a run, with its stamp `t` in milliseconds on
720
724
  * CLOCK_MONOTONIC. It is a request of a client, a record of the service, a line of grpc-go or a probe answer. It is
@@ -1320,16 +1324,23 @@ declare const readRecord: (data: unknown) => KindCellRecord;
1320
1324
  //#region src/stats.d.ts
1321
1325
  /** This fraction, δ_rel, is how far the median of a cell can be outside its band and stay equivalent. */
1322
1326
  declare const RELATIVE = .05;
1323
- /** This function gives the median of sorted values: the middle value, or the mean of the two middle values. */
1327
+ /**
1328
+ * This function gives the median of sorted values: the middle value, or the mean of the two middle values.
1329
+ * It is `median` of @mark1russell7/rigor-statistics, which throws a RangeError for an empty list.
1330
+ */
1324
1331
  declare const middle: (sorted: readonly number[]) => number;
1325
- /** This function gives the value at quantile p of sorted values, by nearest rank: x_(⌈p·n⌉). */
1332
+ /**
1333
+ * This function gives the value at quantile p of sorted values, by nearest rank: x_(⌈p·n⌉). It is
1334
+ * `quantileSorted` of @mark1russell7/rigor-statistics with the method `"nearest-rank"`.
1335
+ */
1326
1336
  declare const quantileOf: (sorted: readonly number[], p: number) => number;
1327
1337
  /**
1328
1338
  * This function gives the distribution-free interval of a median: [x_(k), x_(n+1−k)], for the
1329
1339
  * largest k whose two tails each hold 2.5 % or less. For eleven runs, it gives [x_(2), x_(10)],
1330
- * at 98.8 %.
1340
+ * at 98.8 %. It is `medianInterval` of @mark1russell7/rigor-statistics at the level 0.95. An
1341
+ * empty list throws a RangeError.
1331
1342
  */
1332
1343
  declare const medianInterval: (sorted: readonly number[]) => [number, number];
1333
1344
  //#endregion
1334
1345
  export { unitOf as $, scenario as $n, REDIS as $t, TriggerV1 as A, Template as An, recordsOf as At, RunCheck as B, KubeProxyMode as Bn, sliceReadyAt as Bt, KindCellResult as C, PodSettings as Cn, intakeOf as Ct, PredictionV1 as D, Replica as Dn, periodOf as Dt, LoadSample as E, Reference as En, outcomesOf as Et, KIND_NOISE as F, DATAPLANES as Fn, sessionsAt as Ft, factsOf as G, ZONE_LOST as Gn, transitionOf as Gt, checkRun as H, NodeImage as Hn, slicesOf as Ht, KindDecision as I, Dataplane as In, signalOf as It, observationEnd as J, goDuration as Jn, ztunnelReplaced as Jt, judgeKind as K, cidrOverlap as Kn, tunnelsOf as Kt, KindVerdict as L, KUBE_PROXY_MODES as Ln, signalsOf as Lt, upgrade as M, TriggerKind as Mn, restartOf as Mt, upgradeCell as N, WindowPrediction as Nn, restartsAt as Nt, RunCheckV1 as O, ResetReuse as On, podsAt as Ot, Deleted as P, Workload as Pn, rulesOf as Pt, reusesReset as Q, nodeNames as Qn, PORT as Qt, LAST_SLACK as R, KindConfig as Rn, sliceDropOf as Rt, KindCellRecordV1 as S, NonePrediction as Sn, failuresOf as St, KindVerdictV1 as T, RedisDeclaration as Tn, kernelCounts as Tt, cyclesOf as U, ZONE_KEPT as Un, socketsOf as Ut, RunFacts as V, NODE_IMAGES as Vn, sliceReadyOf as Vt, deletionsOf as W, ZONE_LABEL as Wn, stoppingOf as Wt, propagationSource as X, kindConfig as Xn, HEALTH_PORT as Xt, propagationOf as Y, isKubeProxyMode as Yn, CLIENT as Yt, referenceOf as Z, kubeProxyPatch as Zn, LOG_LABEL as Zt, ClusterManifest as _, KindRun as _n, byClients as _t, STAGES as a, overshootBand as an, PodLine as at, FORMAT_V1 as b, MeshFlavor as bn, dropOf as bt, readRecord as c, secondsOf as cn, Request as ct, calibrationOf as d, Band as dn, SliceLine as dt, SERVER as en, scenarioProblems as er, updatesOf as et, cellsTable as f, Cycle as fn, SocketLine as ft, BandV1 as g, KindCell as gn, backendsAt as gt, timeSpread as h, Flap as hn, ZtunnelPodLine as ht, quantileOf as i, drainBand as in, Period as it, judge as j, Trigger as jn, requestsOf as jt, RunFactsV1 as k, Stack as kn, podsOf as kt, Judged as l, showBand as ln, RulesLine as lt, predictionText as m, EdgeProtocol as mn, TunnelLine as mt, medianInterval as n, backlogEnd as nn, HBONE_PORT as nt, kindCellRecordSchema as o, requestBand as on, PropagationSource as ot, medianText as p, Declaration as pn, TCP_STATE as pt, observationAfter as q, cidrRange as qn, ztunnelPodsOf as qt, middle as r, bandOf as rn, Line as rt, kindCellRecordV1Schema as s, seconds as sn, RecordLine as st, RELATIVE as t, CountBand as tn, zoneOf as tr, Endpoint as tt, TimeSpread as u, BacklogTerm as un, Sessions as ut, EnvironmentManifest as v, KubeletProbe as vn, byNode as vt, KindCellV1 as w, Prediction as wn, isTunnelState as wt, KindCellRecord as x, MeshMode as xn, emptyOf as xt, FORMAT as y, Mesh as yn, deletionOf as yt, Propagated as z, KindScenario as zn, sliceEmptyOf as zt };
1335
- //# sourceMappingURL=judge-DiEmspMx.d.ts.map
1346
+ //# sourceMappingURL=judge-CSWVew2-.d.ts.map
@@ -1,4 +1,5 @@
1
1
  import { format, valueIn } from "@mark1russell7/quantity";
2
+ import { median, medianInterval, quantileSorted } from "@mark1russell7/rigor-statistics";
2
3
  import { extentSchema, quantitySchema } from "@mark1russell7/quantity/schema";
3
4
  import { z } from "zod";
4
5
  //#region src/bands.ts
@@ -119,7 +120,36 @@ const SERVER = "lab";
119
120
  const CLIENT = "client";
120
121
  const REDIS = "redis";
121
122
  //#endregion
123
+ //#region src/stats.ts
124
+ /** This fraction, δ_rel, is how far the median of a cell can be outside its band and stay equivalent. */
125
+ const RELATIVE = .05;
126
+ /**
127
+ * This function gives the median of sorted values: the middle value, or the mean of the two middle values.
128
+ * It is `median` of @mark1russell7/rigor-statistics, which throws a RangeError for an empty list.
129
+ */
130
+ const middle = (sorted) => median(sorted);
131
+ /**
132
+ * This function gives the value at quantile p of sorted values, by nearest rank: x_(⌈p·n⌉). It is
133
+ * `quantileSorted` of @mark1russell7/rigor-statistics with the method `"nearest-rank"`.
134
+ */
135
+ const quantileOf = (sorted, p) => quantileSorted(sorted, p, "nearest-rank");
136
+ /**
137
+ * This function gives the distribution-free interval of a median: [x_(k), x_(n+1−k)], for the
138
+ * largest k whose two tails each hold 2.5 % or less. For eleven runs, it gives [x_(2), x_(10)],
139
+ * at 98.8 %. It is `medianInterval` of @mark1russell7/rigor-statistics at the level 0.95. An
140
+ * empty list throws a RangeError.
141
+ */
142
+ const medianInterval$1 = (sorted) => {
143
+ const interval = medianInterval(sorted, .95);
144
+ return [interval.low, interval.high];
145
+ };
146
+ //#endregion
122
147
  //#region src/observe.ts
148
+ /**
149
+ * This module reads a run from its lines. Each time is in milliseconds on CLOCK_MONOTONIC. All the
150
+ * containers of the VM share that clock: the clients, the service, the agents, the injector, the
151
+ * watcher and the prober.
152
+ */
123
153
  /** This port is the HBONE port of ztunnel in each pod of the ambient mesh of Istio 1.31.3: the mesh leg ends there. */
124
154
  const HBONE_PORT = 15008;
125
155
  /** These are the states of a TCP socket of Linux that a tunnel line names (include/net/tcp_states.h of Linux v6.17, lines 12–28). */
@@ -181,10 +211,6 @@ const sessionsAt = (lines, at, target, connections) => {
181
211
  byClient
182
212
  };
183
213
  };
184
- const medianOf = (sorted) => {
185
- const middle = Math.floor(sorted.length / 2);
186
- return sorted.length % 2 === 1 ? sorted[middle] : (sorted[middle - 1] + sorted[middle]) / 2;
187
- };
188
214
  /**
189
215
  * This function gives the measured period of the clients from their request lines that start from
190
216
  * `from` to `to`. The timer of a client is late by a different amount at each tick. Thus the median
@@ -210,12 +236,12 @@ const periodOf = (lines, from, to) => {
210
236
  const intervals = mine.slice(1).map((t, at) => t - mine[at]);
211
237
  span += mine.at(-1) - mine[0];
212
238
  all.push(...intervals);
213
- byClient[client] = medianOf(intervals.sort((a, b) => a - b));
239
+ byClient[client] = middle(intervals.sort((a, b) => a - b));
214
240
  }
215
241
  if (all.length === 0) return null;
216
242
  all.sort((a, b) => a - b);
217
243
  return {
218
- median: medianOf(all),
244
+ median: middle(all),
219
245
  mean: span / all.length,
220
246
  low: all[0],
221
247
  high: all.at(-1),
@@ -324,38 +350,6 @@ const restartsAt = (lines, at) => {
324
350
  return out;
325
351
  };
326
352
  //#endregion
327
- //#region src/stats.ts
328
- /** This fraction, δ_rel, is how far the median of a cell can be outside its band and stay equivalent. */
329
- const RELATIVE = .05;
330
- /** This function gives the median of sorted values: the middle value, or the mean of the two middle values. */
331
- const middle = (sorted) => {
332
- const half = Math.floor(sorted.length / 2);
333
- return sorted.length % 2 === 1 ? sorted[half] : (sorted[half - 1] + sorted[half]) / 2;
334
- };
335
- /** This function gives the value at quantile p of sorted values, by nearest rank: x_(⌈p·n⌉). */
336
- const quantileOf = (sorted, p) => sorted[Math.min(sorted.length, Math.max(1, Math.ceil(p * sorted.length))) - 1];
337
- /** This function gives P(X ≤ j) for X ~ Binomial(n, 1/2), exactly. */
338
- const below = (n, j) => {
339
- let term = 1;
340
- let sum = 0;
341
- for (let i = 0; i <= j; i += 1) {
342
- sum += term;
343
- term = term * (n - i) / (i + 1);
344
- }
345
- return sum / 2 ** n;
346
- };
347
- /**
348
- * This function gives the distribution-free interval of a median: [x_(k), x_(n+1−k)], for the
349
- * largest k whose two tails each hold 2.5 % or less. For eleven runs, it gives [x_(2), x_(10)],
350
- * at 98.8 %.
351
- */
352
- const medianInterval = (sorted) => {
353
- const n = sorted.length;
354
- let k = 0;
355
- while (k + 1 <= n / 2 && below(n, k) <= .025) k += 1;
356
- return k === 0 ? [sorted[0], sorted[n - 1]] : [sorted[k - 1], sorted[n - k]];
357
- };
358
- //#endregion
359
353
  //#region src/verdict.ts
360
354
  /**
361
355
  * This time is δ for kind: each time of a run lands in its band ± δ. Its parts are the interval of
@@ -1201,7 +1195,7 @@ const judgeKind = (cell, runs) => {
1201
1195
  };
1202
1196
  if (band !== null && values.length > 0) {
1203
1197
  const ends = secondsOf(band);
1204
- const [from, to] = medianInterval(values);
1198
+ const [from, to] = medianInterval$1(values);
1205
1199
  const wide = {
1206
1200
  lo: ends.lo * .95,
1207
1201
  hi: ends.hi * 1.05
@@ -1421,8 +1415,7 @@ const judge = (record) => {
1421
1415
  const timeSpread = (times) => {
1422
1416
  if (times.length === 0) return null;
1423
1417
  const sorted = times.map((each) => valueIn(each, "s")).sort((a, b) => a - b);
1424
- const half = Math.floor(sorted.length / 2);
1425
- const median = sorted.length % 2 === 1 ? sorted[half] : (sorted[half - 1] + sorted[half]) / 2;
1418
+ const median = middle(sorted);
1426
1419
  return {
1427
1420
  count: sorted.length,
1428
1421
  min: seconds(sorted[0]),
@@ -1557,7 +1550,8 @@ const TRIGGERS = [
1557
1550
  "certificate-expiry",
1558
1551
  "cannot-serve",
1559
1552
  "zone-loss",
1560
- "latency"
1553
+ "latency",
1554
+ "dns-blackhole"
1561
1555
  ];
1562
1556
  const KUBE_PROXY = [
1563
1557
  "iptables",
@@ -1857,7 +1851,8 @@ const recordOf = (a, main) => {
1857
1851
  keepalive_time: extent,
1858
1852
  keepalive_timeout: time
1859
1853
  }).optional(),
1860
- onTarget: count.optional()
1854
+ onTarget: count.optional(),
1855
+ byName: z.boolean().optional()
1861
1856
  }),
1862
1857
  prediction,
1863
1858
  calibrates: z.boolean(),
@@ -1976,6 +1971,6 @@ const readRecord = (data) => {
1976
1971
  throw new Error(`a kind cell record has the format ${FORMAT} or ${FORMAT_V1}, not ${String(format)}`);
1977
1972
  };
1978
1973
  //#endregion
1979
- export { restartsAt as $, RELATIVE as A, dropOf as B, observationEnd as C, drainBand as Ct, reusesReset as D, secondsOf as Dt, referenceOf as E, seconds as Et, TCP_STATE as F, kernelCounts as G, failuresOf as H, backendsAt as I, podsAt as J, outcomesOf as K, byClients as L, middle as M, quantileOf as N, unitOf as O, showBand as Ot, HBONE_PORT as P, restartOf as Q, byNode as R, observationAfter as S, bandOf as St, propagationSource as T, requestBand as Tt, intakeOf as U, emptyOf as V, isTunnelState as W, recordsOf as X, podsOf as Y, requestsOf as Z, checkRun as _, LOG_LABEL as _t, calibrationOf as a, sliceEmptyOf as at, factsOf as b, SERVER as bt, predictionText as c, slicesOf as ct, FORMAT_V1 as d, transitionOf as dt, rulesOf as et, judge as f, tunnelsOf as ft, LAST_SLACK as g, HEALTH_PORT as gt, KIND_NOISE as h, CLIENT as ht, readRecord as i, sliceDropOf as it, medianInterval as j, updatesOf as k, timeSpread as l, socketsOf as lt, upgradeCell as m, ztunnelReplaced as mt, kindCellRecordSchema as n, signalOf as nt, cellsTable as o, sliceReadyAt as ot, upgrade as p, ztunnelPodsOf as pt, periodOf as q, kindCellRecordV1Schema as r, signalsOf as rt, medianText as s, sliceReadyOf as st, STAGES as t, sessionsAt as tt, FORMAT as u, stoppingOf as ut, cyclesOf as v, PORT as vt, propagationOf as w, overshootBand as wt, judgeKind as x, backlogEnd as xt, deletionsOf as y, REDIS as yt, deletionOf as z };
1974
+ export { signalsOf as $, HBONE_PORT as A, isTunnelState as B, observationEnd as C, drainBand as Ct, reusesReset as D, secondsOf as Dt, referenceOf as E, seconds as Et, deletionOf as F, podsOf as G, outcomesOf as H, dropOf as I, restartOf as J, recordsOf as K, emptyOf as L, backendsAt as M, byClients as N, unitOf as O, showBand as Ot, byNode as P, signalOf as Q, failuresOf as R, observationAfter as S, bandOf as St, propagationSource as T, requestBand as Tt, periodOf as U, kernelCounts as V, podsAt as W, rulesOf as X, restartsAt as Y, sessionsAt as Z, checkRun as _, LOG_LABEL as _t, calibrationOf as a, socketsOf as at, factsOf as b, SERVER as bt, predictionText as c, tunnelsOf as ct, FORMAT_V1 as d, RELATIVE as dt, sliceDropOf as et, judge as f, medianInterval$1 as ft, LAST_SLACK as g, HEALTH_PORT as gt, KIND_NOISE as h, CLIENT as ht, readRecord as i, slicesOf as it, TCP_STATE as j, updatesOf as k, timeSpread as l, ztunnelPodsOf as lt, upgradeCell as m, quantileOf as mt, kindCellRecordSchema as n, sliceReadyAt as nt, cellsTable as o, stoppingOf as ot, upgrade as p, middle as pt, requestsOf as q, kindCellRecordV1Schema as r, sliceReadyOf as rt, medianText as s, transitionOf as st, STAGES as t, sliceEmptyOf as tt, FORMAT as u, ztunnelReplaced as ut, cyclesOf as v, PORT as vt, propagationOf as w, overshootBand as wt, judgeKind as x, backlogEnd as xt, deletionsOf as y, REDIS as yt, intakeOf as z };
1980
1975
 
1981
- //# sourceMappingURL=judge-B6cyI41-.js.map
1976
+ //# sourceMappingURL=judge-DA754h1o.js.map