@pagopa/dx-savemoney 0.1.1 → 0.1.3

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 (36) hide show
  1. package/README.md +58 -9
  2. package/dist/azure/analyzer.d.ts +3 -1
  3. package/dist/azure/analyzer.d.ts.map +1 -1
  4. package/dist/azure/analyzer.js +16 -3
  5. package/dist/azure/analyzer.js.map +1 -1
  6. package/dist/azure/resources/container-app.d.ts +19 -0
  7. package/dist/azure/resources/container-app.d.ts.map +1 -0
  8. package/dist/azure/resources/container-app.js +113 -0
  9. package/dist/azure/resources/container-app.js.map +1 -0
  10. package/dist/azure/resources/index.d.ts +2 -0
  11. package/dist/azure/resources/index.d.ts.map +1 -1
  12. package/dist/azure/resources/index.js +2 -0
  13. package/dist/azure/resources/index.js.map +1 -1
  14. package/dist/azure/resources/public-ip.js +4 -4
  15. package/dist/azure/resources/public-ip.js.map +1 -1
  16. package/dist/azure/resources/static-web-app.d.ts +17 -0
  17. package/dist/azure/resources/static-web-app.d.ts.map +1 -0
  18. package/dist/azure/resources/static-web-app.js +60 -0
  19. package/dist/azure/resources/static-web-app.js.map +1 -0
  20. package/dist/azure/resources/storage.js +4 -4
  21. package/dist/azure/resources/storage.js.map +1 -1
  22. package/dist/azure/resources/vm.js +4 -4
  23. package/dist/azure/resources/vm.js.map +1 -1
  24. package/dist/azure/utils.d.ts +24 -0
  25. package/dist/azure/utils.d.ts.map +1 -1
  26. package/dist/azure/utils.js +72 -20
  27. package/dist/azure/utils.js.map +1 -1
  28. package/package.json +5 -4
  29. package/src/azure/analyzer.ts +31 -0
  30. package/src/azure/resources/container-app.ts +247 -0
  31. package/src/azure/resources/index.ts +2 -0
  32. package/src/azure/resources/public-ip.ts +4 -4
  33. package/src/azure/resources/static-web-app.ts +108 -0
  34. package/src/azure/resources/storage.ts +4 -4
  35. package/src/azure/resources/vm.ts +4 -4
  36. package/src/azure/utils.ts +109 -26
@@ -110,7 +110,7 @@ export async function analyzeVM(
110
110
  monitorClient,
111
111
  resource.id,
112
112
  "Network In Total",
113
- "Total",
113
+ "Average",
114
114
  timespanDays,
115
115
  );
116
116
 
@@ -118,9 +118,9 @@ export async function analyzeVM(
118
118
  // Less than 1% average CPU
119
119
  reason += `Low CPU usage (avg ${cpuUsage.toFixed(2)}%). `;
120
120
  }
121
- if (networkIn !== null && networkIn < 1024 * 1024 * 10) {
122
- // Less than 10MB total network in
123
- reason += `Low network traffic. `;
121
+ if (networkIn !== null && networkIn < 1024 * 1024 * 3) {
122
+ // Less than 3MB average per day
123
+ reason += `Low network traffic (${(networkIn / 1024 / 1024).toFixed(2)} MB/day avg). `;
124
124
  }
125
125
 
126
126
  const result = { costRisk, reason, suspectedUnused: reason.length > 0 };
@@ -8,6 +8,100 @@ import { getLogger } from "@logtape/logtape";
8
8
 
9
9
  import type { AnalysisResult } from "../types.js";
10
10
 
11
+ type MetricDataPoint = {
12
+ average?: number;
13
+ count?: number;
14
+ maximum?: number;
15
+ minimum?: number;
16
+ total?: number;
17
+ };
18
+
19
+ /**
20
+ * Aggregates metric data points based on aggregation type.
21
+ *
22
+ * @param dataPoints - Array of metric data points
23
+ * @param aggregation - The aggregation type (e.g., "Average", "Total")
24
+ * @returns The aggregated value or null if unavailable
25
+ */
26
+ export function aggregateDataPoints(
27
+ dataPoints: MetricDataPoint[],
28
+ aggregation: string,
29
+ ): null | number {
30
+ const aggregationLower = aggregation.toLowerCase();
31
+
32
+ // Get all non-null values from the data points
33
+ const values = dataPoints
34
+ .map((dataPoint) => extractAggregatedValue(dataPoint, aggregation))
35
+ .filter((v): v is number => v !== null);
36
+
37
+ if (values.length === 0) {
38
+ return null;
39
+ }
40
+
41
+ if (aggregationLower === "total" || aggregationLower === "count") {
42
+ // Sum all values for Total/Count
43
+ return values.reduce((sum, v) => sum + v, 0);
44
+ }
45
+
46
+ if (aggregationLower === "average") {
47
+ // Calculate the average of all values
48
+ return values.reduce((sum, v) => sum + v, 0) / values.length;
49
+ }
50
+
51
+ if (aggregationLower === "maximum") {
52
+ // Find the maximum value
53
+ return Math.max(...values);
54
+ }
55
+
56
+ if (aggregationLower === "minimum") {
57
+ // Find the minimum value
58
+ return Math.min(...values);
59
+ }
60
+
61
+ return null;
62
+ }
63
+
64
+ /**
65
+ * Extracts the aggregated value from metric data.
66
+ *
67
+ * @param metricData - The metric data point
68
+ * @param aggregation - The aggregation type (e.g., "Average", "Total")
69
+ * @returns The aggregated value or null if unavailable
70
+ */
71
+ export function extractAggregatedValue(
72
+ metricData: MetricDataPoint,
73
+ aggregation: string,
74
+ ): null | number {
75
+ const aggregationLower = aggregation.toLowerCase();
76
+
77
+ if (
78
+ aggregationLower === "average" &&
79
+ typeof metricData.average === "number"
80
+ ) {
81
+ return metricData.average;
82
+ }
83
+ if (aggregationLower === "total" && typeof metricData.total === "number") {
84
+ return metricData.total;
85
+ }
86
+ if (
87
+ aggregationLower === "minimum" &&
88
+ typeof metricData.minimum === "number"
89
+ ) {
90
+ return metricData.minimum;
91
+ }
92
+ if (
93
+ aggregationLower === "maximum" &&
94
+ typeof metricData.maximum === "number"
95
+ ) {
96
+ return metricData.maximum;
97
+ }
98
+ if (aggregationLower === "count" && typeof metricData.count === "number") {
99
+ return metricData.count;
100
+ }
101
+
102
+ return null;
103
+ }
104
+
11
105
  /**
12
106
  * Fetches a specific metric for a resource from Azure Monitor.
13
107
  *
@@ -33,39 +127,28 @@ export async function getMetric(
33
127
  timespan,
34
128
  });
35
129
 
36
- const metricData = result.value[0]?.timeseries?.[0]?.data?.[0];
37
- if (!metricData) {
130
+ if (result.value.length === 0) {
38
131
  return null;
39
132
  }
40
133
 
41
- const aggregationLower = aggregation.toLowerCase();
134
+ const metric = result.value[0];
42
135
 
43
- if (
44
- aggregationLower === "average" &&
45
- typeof metricData.average === "number"
46
- ) {
47
- return metricData.average;
48
- }
49
- if (aggregationLower === "total" && typeof metricData.total === "number") {
50
- return metricData.total;
51
- }
52
- if (
53
- aggregationLower === "minimum" &&
54
- typeof metricData.minimum === "number"
55
- ) {
56
- return metricData.minimum;
57
- }
58
- if (
59
- aggregationLower === "maximum" &&
60
- typeof metricData.maximum === "number"
61
- ) {
62
- return metricData.maximum;
136
+ if (!metric.timeseries || metric.timeseries.length === 0) {
137
+ return null;
63
138
  }
64
- if (aggregationLower === "count" && typeof metricData.count === "number") {
65
- return metricData.count;
139
+
140
+ const timeserie = metric.timeseries[0];
141
+
142
+ if (!timeserie.data || timeserie.data.length === 0) {
143
+ return null;
66
144
  }
67
145
 
68
- return null;
146
+ const aggregatedValue = aggregateDataPoints(
147
+ timeserie.data as MetricDataPoint[],
148
+ aggregation,
149
+ );
150
+
151
+ return aggregatedValue;
69
152
  } catch (error) {
70
153
  const logger = getLogger(["savemoney", "azure", "metrics"]);
71
154
  logger.error(