Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | 1x 1x 169x 169x 90x 558x 558x 558x 169x 1x 1x 90x 113x 113x 113x 169x 169x 169x 169x 558x 558x 52x 506x 169x 506x 506x 558x 558x 558x 556x 558x | import { loadCannedMetricsFile, MetricTemplate } from './canned-metrics/canned-metrics-schema'; export type NonEmptyArray<T> = [T, ...T[]]; /** * A single canned service metric * * These are kindly provided to us by the good people of CloudWatch Explorer. */ export interface CannedMetric { /** * Metric namespace */ readonly namespace: string; /** * Metric name */ readonly metricName: string; /** * List of all possible dimension permutations for this metric * * Most metrics will have a single list of strings as their one set of * allowed dimensions, but some metrics are emitted under multiple * combinations of dimensions. */ readonly dimensions: NonEmptyArray<string[]>; /** * Suggested default aggregration statistic * * Not always the most appropriate one to use! These defaults have * been classified by people and they generally just pick "Average" * as the default, even if it doesn't make sense. * * For example: for event-based metrics that only ever emit `1` * (and never `0`) the better statistic would be `Sum`. * * Use your judgement based on the type of metric this is. */ readonly defaultStat: string; } /** * Return the list of canned metrics for the given service */ export function cannedMetricsForService(cloudFormationNamespace: string): CannedMetric[] { // One metricTemplate has a single set of dimensions, but the same metric NAME // may occur in multiple metricTemplates (if it has multiple sets of dimensions) const metricTemplates = cannedMetricsIndex()[cloudFormationNamespace] ?? []; // First construct almost what we need, but with a single dimension per metric const metricsWithDuplicates = flatMap(metricTemplates, metricSet => { const dimensions = metricSet.dimensions.map(d => d.dimensionName); return metricSet.metrics.map(metric => ({ namespace: metricSet.namespace, dimensions, metricName: metric.name, defaultStat: metric.defaultStat, })); }); // Then combine the dimensions for the same metrics into a single list return groupBy(metricsWithDuplicates, m => `${m.namespace}/${m.metricName}`).map(metrics => ({ namespace: metrics[0].namespace, metricName: metrics[0].metricName, defaultStat: metrics[0].defaultStat, dimensions: Array.from(dedupeStringLists(metrics.map(m => m.dimensions))) as any, })); } type CannedMetricsIndex = Record<string, MetricTemplate[]>; let cannedMetricsCache: CannedMetricsIndex | undefined; /** * Load the canned metrics file and process it into an index, grouped by service namespace */ function cannedMetricsIndex() { if (cannedMetricsCache === undefined) { cannedMetricsCache = {}; for (const group of loadCannedMetricsFile()) { for (const metricTemplate of group.metricTemplates) { const [aws, service] = metricTemplate.resourceType.split('::'); const serviceKey = [aws, service].join('::'); (cannedMetricsCache[serviceKey] ?? (cannedMetricsCache[serviceKey] = [])).push(metricTemplate); } } } return cannedMetricsCache; } function flatMap<A, B>(xs: A[], fn: (x: A) => B[]): B[] { return Array.prototype.concat.apply([], xs.map(fn)); } function groupBy<A>(xs: A[], keyFn: (x: A) => string): Array<NonEmptyArray<A>> { const obj: Record<string, NonEmptyArray<A>> = {}; for (const x of xs) { const key = keyFn(x); if (key in obj) { obj[key].push(x); } else { obj[key] = [x]; } } return Object.values(obj); } function* dedupeStringLists(xs: string[][]): IterableIterator<string[]> { const seen = new Set<string>(); for (const x of xs) { x.sort(); const key = `${x.join(',')}`; if (!seen.has(key)) { yield x; } seen.add(key); } } |