@pagopa/dx-savemoney 0.2.5 → 0.2.6
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/dist/azure/analyzer.d.ts +31 -16
- package/dist/azure/analyzer.d.ts.map +1 -1
- package/dist/azure/analyzer.js +110 -81
- package/dist/azure/analyzer.js.map +1 -1
- package/dist/azure/analyzers/index.d.ts +6 -0
- package/dist/azure/analyzers/index.d.ts.map +1 -0
- package/dist/azure/analyzers/index.js +5 -0
- package/dist/azure/analyzers/index.js.map +1 -0
- package/dist/azure/analyzers/registry.d.ts +21 -0
- package/dist/azure/analyzers/registry.d.ts.map +1 -0
- package/dist/azure/analyzers/registry.js +69 -0
- package/dist/azure/analyzers/registry.js.map +1 -0
- package/dist/azure/analyzers/types.d.ts +62 -0
- package/dist/azure/analyzers/types.d.ts.map +1 -0
- package/dist/azure/analyzers/types.js +15 -0
- package/dist/azure/analyzers/types.js.map +1 -0
- package/dist/azure/config.d.ts.map +1 -1
- package/dist/azure/config.js +1 -0
- package/dist/azure/config.js.map +1 -1
- package/dist/azure/resources/app-service.d.ts +2 -1
- package/dist/azure/resources/app-service.d.ts.map +1 -1
- package/dist/azure/resources/app-service.js +3 -3
- package/dist/azure/resources/app-service.js.map +1 -1
- package/dist/azure/resources/container-app.d.ts +2 -1
- package/dist/azure/resources/container-app.d.ts.map +1 -1
- package/dist/azure/resources/container-app.js +9 -9
- package/dist/azure/resources/container-app.js.map +1 -1
- package/dist/azure/resources/public-ip.d.ts +2 -1
- package/dist/azure/resources/public-ip.d.ts.map +1 -1
- package/dist/azure/resources/public-ip.js +2 -2
- package/dist/azure/resources/public-ip.js.map +1 -1
- package/dist/azure/resources/static-web-app.d.ts +2 -1
- package/dist/azure/resources/static-web-app.d.ts.map +1 -1
- package/dist/azure/resources/static-web-app.js +3 -3
- package/dist/azure/resources/static-web-app.js.map +1 -1
- package/dist/azure/resources/storage.d.ts +2 -1
- package/dist/azure/resources/storage.d.ts.map +1 -1
- package/dist/azure/resources/storage.js +2 -2
- package/dist/azure/resources/storage.js.map +1 -1
- package/dist/azure/resources/vm.d.ts +2 -1
- package/dist/azure/resources/vm.d.ts.map +1 -1
- package/dist/azure/resources/vm.js +3 -3
- package/dist/azure/resources/vm.js.map +1 -1
- package/dist/azure/types.d.ts +6 -0
- package/dist/azure/types.d.ts.map +1 -1
- package/dist/azure/utils.d.ts +35 -3
- package/dist/azure/utils.d.ts.map +1 -1
- package/dist/azure/utils.js +70 -29
- package/dist/azure/utils.js.map +1 -1
- package/dist/finding.d.ts +114 -0
- package/dist/finding.d.ts.map +1 -0
- package/dist/finding.js +51 -0
- package/dist/finding.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/schema.d.ts +1 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +5 -0
- package/dist/schema.js.map +1 -1
- package/package.json +2 -1
- package/src/__tests__/finding.test.ts +149 -0
- package/src/azure/__tests__/utils.test.ts +164 -2
- package/src/azure/analyzer.ts +140 -165
- package/src/azure/analyzers/index.ts +6 -0
- package/src/azure/analyzers/registry.ts +184 -0
- package/src/azure/analyzers/types.ts +66 -0
- package/src/azure/config.ts +1 -0
- package/src/azure/resources/app-service.ts +4 -0
- package/src/azure/resources/container-app.ts +10 -0
- package/src/azure/resources/public-ip.ts +3 -0
- package/src/azure/resources/static-web-app.ts +4 -0
- package/src/azure/resources/storage.ts +3 -0
- package/src/azure/resources/vm.ts +4 -0
- package/src/azure/types.ts +6 -0
- package/src/azure/utils.ts +110 -39
- package/src/finding.ts +152 -0
- package/src/index.ts +18 -0
- package/src/schema.ts +5 -0
|
@@ -13,7 +13,7 @@ import { getMetric, verboseLog, verboseLogAnalysisResult, verboseLogResourceStar
|
|
|
13
13
|
* @param timespanDays - Number of days to analyze metrics
|
|
14
14
|
* @returns Analysis result with cost risk and reason
|
|
15
15
|
*/
|
|
16
|
-
export async function analyzeAppServicePlan(resource, webSiteClient, monitorClient, timespanDays, thresholds = DEFAULT_THRESHOLDS, verbose = false) {
|
|
16
|
+
export async function analyzeAppServicePlan(resource, webSiteClient, monitorClient, timespanDays, thresholds = DEFAULT_THRESHOLDS, verbose = false, cache) {
|
|
17
17
|
verboseLogResourceStart(verbose, resource.name || "unknown", "App Service Plan (microsoft.web/serverfarms)");
|
|
18
18
|
verboseLog(verbose, "Resource details:", resource);
|
|
19
19
|
const costRisk = "high";
|
|
@@ -38,8 +38,8 @@ export async function analyzeAppServicePlan(resource, webSiteClient, monitorClie
|
|
|
38
38
|
reason += "App Service Plan has no apps deployed. ";
|
|
39
39
|
}
|
|
40
40
|
// Check CPU and Memory metrics
|
|
41
|
-
const cpuPercentage = await getMetric(monitorClient, resource.id, "CpuPercentage", "Average", timespanDays);
|
|
42
|
-
const memoryPercentage = await getMetric(monitorClient, resource.id, "MemoryPercentage", "Average", timespanDays);
|
|
41
|
+
const cpuPercentage = await getMetric(monitorClient, resource.id, "CpuPercentage", "Average", timespanDays, cache);
|
|
42
|
+
const memoryPercentage = await getMetric(monitorClient, resource.id, "MemoryPercentage", "Average", timespanDays, cache);
|
|
43
43
|
if (cpuPercentage !== null &&
|
|
44
44
|
cpuPercentage < thresholds.appService.cpuPercent) {
|
|
45
45
|
reason += `Very low CPU usage (${cpuPercentage.toFixed(2)}%). `;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app-service.js","sourceRoot":"","sources":["../../../src/azure/resources/app-service.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAI7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EACL,SAAS,
|
|
1
|
+
{"version":3,"file":"app-service.js","sourceRoot":"","sources":["../../../src/azure/resources/app-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,6 +5,7 @@ import type { ContainerAppsAPIClient } from "@azure/arm-appcontainers";
|
|
|
5
5
|
import type { MonitorClient } from "@azure/arm-monitor";
|
|
6
6
|
import * as armResources from "@azure/arm-resources";
|
|
7
7
|
import type { AnalysisResult, Thresholds } from "../../types.js";
|
|
8
|
+
import { type MetricsCache } from "../utils.js";
|
|
8
9
|
/**
|
|
9
10
|
* Analyzes an Azure Container App for potential cost optimization.
|
|
10
11
|
*
|
|
@@ -15,5 +16,5 @@ import type { AnalysisResult, Thresholds } from "../../types.js";
|
|
|
15
16
|
* @param verbose - Enable verbose logging
|
|
16
17
|
* @returns Analysis result with cost risk and reason
|
|
17
18
|
*/
|
|
18
|
-
export declare function analyzeContainerApp(resource: armResources.GenericResource, containerAppsClient: ContainerAppsAPIClient, monitorClient: MonitorClient, timespanDays: number, thresholds?: Thresholds, verbose?: boolean): Promise<AnalysisResult>;
|
|
19
|
+
export declare function analyzeContainerApp(resource: armResources.GenericResource, containerAppsClient: ContainerAppsAPIClient, monitorClient: MonitorClient, timespanDays: number, thresholds?: Thresholds, verbose?: boolean, cache?: MetricsCache): Promise<AnalysisResult>;
|
|
19
20
|
//# sourceMappingURL=container-app.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"container-app.d.ts","sourceRoot":"","sources":["../../../src/azure/resources/container-app.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAGrD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"container-app.d.ts","sourceRoot":"","sources":["../../../src/azure/resources/container-app.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAGrD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGjE,OAAO,EAEL,KAAK,YAAY,EAIlB,MAAM,aAAa,CAAC;AAErB;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,YAAY,CAAC,eAAe,EACtC,mBAAmB,EAAE,sBAAsB,EAC3C,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,MAAM,EACpB,UAAU,GAAE,UAA+B,EAC3C,OAAO,UAAQ,EACf,KAAK,CAAC,EAAE,YAAY,GACnB,OAAO,CAAC,cAAc,CAAC,CAwEzB"}
|
|
@@ -14,7 +14,7 @@ import { getMetric, verboseLog, verboseLogAnalysisResult, verboseLogResourceStar
|
|
|
14
14
|
* @param verbose - Enable verbose logging
|
|
15
15
|
* @returns Analysis result with cost risk and reason
|
|
16
16
|
*/
|
|
17
|
-
export async function analyzeContainerApp(resource, containerAppsClient, monitorClient, timespanDays, thresholds = DEFAULT_THRESHOLDS, verbose = false) {
|
|
17
|
+
export async function analyzeContainerApp(resource, containerAppsClient, monitorClient, timespanDays, thresholds = DEFAULT_THRESHOLDS, verbose = false, cache) {
|
|
18
18
|
verboseLogResourceStart(verbose, resource.name || "unknown", "Container App (Microsoft.App/containerApps)");
|
|
19
19
|
verboseLog(verbose, "Resource details:", resource);
|
|
20
20
|
const costRisk = "medium";
|
|
@@ -39,8 +39,8 @@ export async function analyzeContainerApp(resource, containerAppsClient, monitor
|
|
|
39
39
|
template: appDetails.template,
|
|
40
40
|
},
|
|
41
41
|
}, reason, verbose);
|
|
42
|
-
reason = await checkResourceMetrics(resource, monitorClient, timespanDays, thresholds, reason, verbose);
|
|
43
|
-
reason = await checkNetworkMetrics(resource, monitorClient, timespanDays, thresholds, reason, verbose);
|
|
42
|
+
reason = await checkResourceMetrics(resource, monitorClient, timespanDays, thresholds, reason, verbose, cache);
|
|
43
|
+
reason = await checkNetworkMetrics(resource, monitorClient, timespanDays, thresholds, reason, verbose, cache);
|
|
44
44
|
}
|
|
45
45
|
catch (error) {
|
|
46
46
|
const logger = getLogger(["savemoney", "azure"]);
|
|
@@ -55,14 +55,14 @@ export async function analyzeContainerApp(resource, containerAppsClient, monitor
|
|
|
55
55
|
/**
|
|
56
56
|
* Checks network traffic metrics for a Container App.
|
|
57
57
|
*/
|
|
58
|
-
async function checkNetworkMetrics(resource, monitorClient, timespanDays, thresholds, reason, verbose) {
|
|
58
|
+
async function checkNetworkMetrics(resource, monitorClient, timespanDays, thresholds, reason, verbose, cache) {
|
|
59
59
|
let newReason = reason;
|
|
60
60
|
if (!resource.id) {
|
|
61
61
|
return newReason;
|
|
62
62
|
}
|
|
63
63
|
verboseLog(verbose, "Checking network metrics...");
|
|
64
|
-
const networkIn = await getMetric(monitorClient, resource.id, "RxBytes", "Average", timespanDays);
|
|
65
|
-
const networkOut = await getMetric(monitorClient, resource.id, "TxBytes", "Average", timespanDays);
|
|
64
|
+
const networkIn = await getMetric(monitorClient, resource.id, "RxBytes", "Average", timespanDays, cache);
|
|
65
|
+
const networkOut = await getMetric(monitorClient, resource.id, "TxBytes", "Average", timespanDays, cache);
|
|
66
66
|
verboseLog(verbose, `Network In: ${networkIn !== null ? `${(networkIn / 1048576).toFixed(2)} MB/day avg` : "N/A"}`);
|
|
67
67
|
verboseLog(verbose, `Network Out: ${networkOut !== null ? `${(networkOut / 1048576).toFixed(2)} MB/day avg` : "N/A"}`);
|
|
68
68
|
if (networkIn !== null &&
|
|
@@ -75,14 +75,14 @@ async function checkNetworkMetrics(resource, monitorClient, timespanDays, thresh
|
|
|
75
75
|
/**
|
|
76
76
|
* Checks resource usage metrics for a Container App.
|
|
77
77
|
*/
|
|
78
|
-
async function checkResourceMetrics(resource, monitorClient, timespanDays, thresholds, reason, verbose) {
|
|
78
|
+
async function checkResourceMetrics(resource, monitorClient, timespanDays, thresholds, reason, verbose, cache) {
|
|
79
79
|
let newReason = reason;
|
|
80
80
|
if (!resource.id) {
|
|
81
81
|
return newReason;
|
|
82
82
|
}
|
|
83
83
|
verboseLog(verbose, "Checking resource usage metrics...");
|
|
84
|
-
const cpuUsage = await getMetric(monitorClient, resource.id, "UsageNanoCores", "Average", timespanDays);
|
|
85
|
-
const memoryUsage = await getMetric(monitorClient, resource.id, "WorkingSetBytes", "Average", timespanDays);
|
|
84
|
+
const cpuUsage = await getMetric(monitorClient, resource.id, "UsageNanoCores", "Average", timespanDays, cache);
|
|
85
|
+
const memoryUsage = await getMetric(monitorClient, resource.id, "WorkingSetBytes", "Average", timespanDays, cache);
|
|
86
86
|
verboseLog(verbose, `CPU Usage: ${cpuUsage !== null ? `${(cpuUsage / 1000000000).toFixed(4)} cores` : "N/A"}`);
|
|
87
87
|
verboseLog(verbose, `Memory Usage: ${memoryUsage !== null ? `${(memoryUsage / 1048576).toFixed(2)} MB` : "N/A"}`);
|
|
88
88
|
if (cpuUsage !== null && cpuUsage < thresholds.containerApp.cpuNanoCores) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"container-app.js","sourceRoot":"","sources":["../../../src/azure/resources/container-app.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAI7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EACL,SAAS,
|
|
1
|
+
{"version":3,"file":"container-app.js","sourceRoot":"","sources":["../../../src/azure/resources/container-app.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,6 +5,7 @@ import type { MonitorClient } from "@azure/arm-monitor";
|
|
|
5
5
|
import type { NetworkManagementClient } from "@azure/arm-network";
|
|
6
6
|
import * as armResources from "@azure/arm-resources";
|
|
7
7
|
import type { AnalysisResult, Thresholds } from "../../types.js";
|
|
8
|
+
import { type MetricsCache } from "../utils.js";
|
|
8
9
|
/**
|
|
9
10
|
* Analyzes an Azure Public IP for potential cost optimization.
|
|
10
11
|
*
|
|
@@ -14,5 +15,5 @@ import type { AnalysisResult, Thresholds } from "../../types.js";
|
|
|
14
15
|
* @param timespanDays - Number of days to analyze metrics
|
|
15
16
|
* @returns Analysis result with cost risk and reason
|
|
16
17
|
*/
|
|
17
|
-
export declare function analyzePublicIp(resource: armResources.GenericResource, networkClient: NetworkManagementClient, monitorClient: MonitorClient, timespanDays: number, thresholds?: Thresholds, verbose?: boolean): Promise<AnalysisResult>;
|
|
18
|
+
export declare function analyzePublicIp(resource: armResources.GenericResource, networkClient: NetworkManagementClient, monitorClient: MonitorClient, timespanDays: number, thresholds?: Thresholds, verbose?: boolean, cache?: MetricsCache): Promise<AnalysisResult>;
|
|
18
19
|
//# sourceMappingURL=public-ip.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-ip.d.ts","sourceRoot":"","sources":["../../../src/azure/resources/public-ip.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAElE,OAAO,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAGrD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"public-ip.d.ts","sourceRoot":"","sources":["../../../src/azure/resources/public-ip.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAElE,OAAO,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAGrD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGjE,OAAO,EAEL,KAAK,YAAY,EAIlB,MAAM,aAAa,CAAC;AAErB;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,YAAY,CAAC,eAAe,EACtC,aAAa,EAAE,uBAAuB,EACtC,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,MAAM,EACpB,UAAU,GAAE,UAA+B,EAC3C,OAAO,UAAQ,EACf,KAAK,CAAC,EAAE,YAAY,GACnB,OAAO,CAAC,cAAc,CAAC,CAuEzB"}
|
|
@@ -13,7 +13,7 @@ import { getMetric, verboseLog, verboseLogAnalysisResult, verboseLogResourceStar
|
|
|
13
13
|
* @param timespanDays - Number of days to analyze metrics
|
|
14
14
|
* @returns Analysis result with cost risk and reason
|
|
15
15
|
*/
|
|
16
|
-
export async function analyzePublicIp(resource, networkClient, monitorClient, timespanDays, thresholds = DEFAULT_THRESHOLDS, verbose = false) {
|
|
16
|
+
export async function analyzePublicIp(resource, networkClient, monitorClient, timespanDays, thresholds = DEFAULT_THRESHOLDS, verbose = false, cache) {
|
|
17
17
|
verboseLogResourceStart(verbose, resource.name || "unknown", "Public IP (microsoft.network/publicipaddresses)");
|
|
18
18
|
verboseLog(verbose, "Resource details:", resource);
|
|
19
19
|
const costRisk = "medium";
|
|
@@ -43,7 +43,7 @@ export async function analyzePublicIp(resource, networkClient, monitorClient, ti
|
|
|
43
43
|
reason += "Static IP not in use. ";
|
|
44
44
|
}
|
|
45
45
|
// Check network metrics for low usage
|
|
46
|
-
const bytesInDDoS = await getMetric(monitorClient, resource.id, "BytesInDDoS", "Average", timespanDays);
|
|
46
|
+
const bytesInDDoS = await getMetric(monitorClient, resource.id, "BytesInDDoS", "Average", timespanDays, cache);
|
|
47
47
|
if (bytesInDDoS !== null && bytesInDDoS < thresholds.publicIp.bytesInDDoS) {
|
|
48
48
|
reason += `Very low network traffic (${(bytesInDDoS / 1024 / 1024).toFixed(2)} MB/day avg). `;
|
|
49
49
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-ip.js","sourceRoot":"","sources":["../../../src/azure/resources/public-ip.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAI7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EACL,SAAS,
|
|
1
|
+
{"version":3,"file":"public-ip.js","sourceRoot":"","sources":["../../../src/azure/resources/public-ip.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import type { MonitorClient } from "@azure/arm-monitor";
|
|
5
5
|
import * as armResources from "@azure/arm-resources";
|
|
6
6
|
import type { AnalysisResult, Thresholds } from "../../types.js";
|
|
7
|
+
import { type MetricsCache } from "../utils.js";
|
|
7
8
|
/**
|
|
8
9
|
* Analyzes an Azure Static Web App for potential cost optimization.
|
|
9
10
|
*
|
|
@@ -13,5 +14,5 @@ import type { AnalysisResult, Thresholds } from "../../types.js";
|
|
|
13
14
|
* @param verbose - Enable verbose logging
|
|
14
15
|
* @returns Analysis result with cost risk and reason
|
|
15
16
|
*/
|
|
16
|
-
export declare function analyzeStaticSite(resource: armResources.GenericResource, monitorClient: MonitorClient, timespanDays: number, thresholds?: Thresholds, verbose?: boolean): Promise<AnalysisResult>;
|
|
17
|
+
export declare function analyzeStaticSite(resource: armResources.GenericResource, monitorClient: MonitorClient, timespanDays: number, thresholds?: Thresholds, verbose?: boolean, cache?: MetricsCache): Promise<AnalysisResult>;
|
|
17
18
|
//# sourceMappingURL=static-web-app.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"static-web-app.d.ts","sourceRoot":"","sources":["../../../src/azure/resources/static-web-app.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAGrD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"static-web-app.d.ts","sourceRoot":"","sources":["../../../src/azure/resources/static-web-app.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAGrD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGjE,OAAO,EAEL,KAAK,YAAY,EAIlB,MAAM,aAAa,CAAC;AAErB;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,YAAY,CAAC,eAAe,EACtC,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,MAAM,EACpB,UAAU,GAAE,UAA+B,EAC3C,OAAO,UAAQ,EACf,KAAK,CAAC,EAAE,YAAY,GACnB,OAAO,CAAC,cAAc,CAAC,CA2EzB"}
|
|
@@ -13,7 +13,7 @@ import { getMetric, verboseLog, verboseLogAnalysisResult, verboseLogResourceStar
|
|
|
13
13
|
* @param verbose - Enable verbose logging
|
|
14
14
|
* @returns Analysis result with cost risk and reason
|
|
15
15
|
*/
|
|
16
|
-
export async function analyzeStaticSite(resource, monitorClient, timespanDays, thresholds = DEFAULT_THRESHOLDS, verbose = false) {
|
|
16
|
+
export async function analyzeStaticSite(resource, monitorClient, timespanDays, thresholds = DEFAULT_THRESHOLDS, verbose = false, cache) {
|
|
17
17
|
verboseLogResourceStart(verbose, resource.name || "unknown", "Static Web App (Microsoft.Web/staticSites)");
|
|
18
18
|
verboseLog(verbose, "Resource details:", resource);
|
|
19
19
|
const costRisk = "low";
|
|
@@ -30,8 +30,8 @@ export async function analyzeStaticSite(resource, monitorClient, timespanDays, t
|
|
|
30
30
|
// Check for site hits (requests to the static site)
|
|
31
31
|
// Note: Static Web Apps metrics use Total aggregation, not Average
|
|
32
32
|
// Ref. https://learn.microsoft.com/en-us/azure/azure-monitor/reference/supported-metrics/microsoft-web-staticsites-metrics
|
|
33
|
-
const siteHits = await getMetric(monitorClient, resource.id, "SiteHits", "Total", timespanDays);
|
|
34
|
-
const bytesSent = await getMetric(monitorClient, resource.id, "BytesSent", "Total", timespanDays);
|
|
33
|
+
const siteHits = await getMetric(monitorClient, resource.id, "SiteHits", "Total", timespanDays, cache);
|
|
34
|
+
const bytesSent = await getMetric(monitorClient, resource.id, "BytesSent", "Total", timespanDays, cache);
|
|
35
35
|
verboseLog(verbose, `Site Hits: ${siteHits !== null ? `${siteHits.toFixed(0)} total requests` : "N/A"}`);
|
|
36
36
|
verboseLog(verbose, `Bytes Sent: ${bytesSent !== null ? `${(bytesSent / 1024 / 1024).toFixed(2)} MB total` : "N/A"}`);
|
|
37
37
|
// If both metrics are null, it means no data points exist (no traffic at all)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"static-web-app.js","sourceRoot":"","sources":["../../../src/azure/resources/static-web-app.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAI7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EACL,SAAS,
|
|
1
|
+
{"version":3,"file":"static-web-app.js","sourceRoot":"","sources":["../../../src/azure/resources/static-web-app.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import type { MonitorClient } from "@azure/arm-monitor";
|
|
5
5
|
import * as armResources from "@azure/arm-resources";
|
|
6
6
|
import type { AnalysisResult, Thresholds } from "../../types.js";
|
|
7
|
+
import { type MetricsCache } from "../utils.js";
|
|
7
8
|
/**
|
|
8
9
|
* Analyzes an Azure Storage Account for potential cost optimization.
|
|
9
10
|
*
|
|
@@ -12,5 +13,5 @@ import type { AnalysisResult, Thresholds } from "../../types.js";
|
|
|
12
13
|
* @param timespanDays - Number of days to analyze metrics
|
|
13
14
|
* @returns Analysis result with cost risk and reason
|
|
14
15
|
*/
|
|
15
|
-
export declare function analyzeStorageAccount(resource: armResources.GenericResource, monitorClient: MonitorClient, timespanDays: number, thresholds?: Thresholds, verbose?: boolean): Promise<AnalysisResult>;
|
|
16
|
+
export declare function analyzeStorageAccount(resource: armResources.GenericResource, monitorClient: MonitorClient, timespanDays: number, thresholds?: Thresholds, verbose?: boolean, cache?: MetricsCache): Promise<AnalysisResult>;
|
|
16
17
|
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/azure/resources/storage.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAErD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/azure/resources/storage.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAErD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGjE,OAAO,EAEL,KAAK,YAAY,EAIlB,MAAM,aAAa,CAAC;AAErB;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,YAAY,CAAC,eAAe,EACtC,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,MAAM,EACpB,UAAU,GAAE,UAA+B,EAC3C,OAAO,UAAQ,EACf,KAAK,CAAC,EAAE,YAAY,GACnB,OAAO,CAAC,cAAc,CAAC,CAuCzB"}
|
|
@@ -11,7 +11,7 @@ import { getMetric, verboseLog, verboseLogAnalysisResult, verboseLogResourceStar
|
|
|
11
11
|
* @param timespanDays - Number of days to analyze metrics
|
|
12
12
|
* @returns Analysis result with cost risk and reason
|
|
13
13
|
*/
|
|
14
|
-
export async function analyzeStorageAccount(resource, monitorClient, timespanDays, thresholds = DEFAULT_THRESHOLDS, verbose = false) {
|
|
14
|
+
export async function analyzeStorageAccount(resource, monitorClient, timespanDays, thresholds = DEFAULT_THRESHOLDS, verbose = false, cache) {
|
|
15
15
|
verboseLogResourceStart(verbose, resource.name || "unknown", "Storage Account (microsoft.storage/storageaccounts)");
|
|
16
16
|
verboseLog(verbose, "Resource details:", resource);
|
|
17
17
|
const costRisk = "medium";
|
|
@@ -22,7 +22,7 @@ export async function analyzeStorageAccount(resource, monitorClient, timespanDay
|
|
|
22
22
|
suspectedUnused: false,
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
|
-
const transactions = await getMetric(monitorClient, resource.id, "Transactions", "Average", timespanDays);
|
|
25
|
+
const transactions = await getMetric(monitorClient, resource.id, "Transactions", "Average", timespanDays, cache);
|
|
26
26
|
if (transactions !== null &&
|
|
27
27
|
transactions < thresholds.storage.transactionsPerDay) {
|
|
28
28
|
const result = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/azure/resources/storage.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EACL,SAAS,
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/azure/resources/storage.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EACL,SAAS,EAET,UAAU,EACV,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AAErB;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,QAAsC,EACtC,aAA4B,EAC5B,YAAoB,EACpB,aAAyB,kBAAkB,EAC3C,OAAO,GAAG,KAAK,EACf,KAAoB;IAEpB,uBAAuB,CACrB,OAAO,EACP,QAAQ,CAAC,IAAI,IAAI,SAAS,EAC1B,qDAAqD,CACtD,CAAC;IACF,UAAU,CAAC,OAAO,EAAE,mBAAmB,EAAE,QAAQ,CAAC,CAAC;IAEnD,MAAM,QAAQ,GAA8B,QAAQ,CAAC;IACrD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,OAAO;YACL,QAAQ;YACR,MAAM,EAAE,yBAAyB;YACjC,eAAe,EAAE,KAAK;SACvB,CAAC;IACJ,CAAC;IACD,MAAM,YAAY,GAAG,MAAM,SAAS,CAClC,aAAa,EACb,QAAQ,CAAC,EAAE,EACX,cAAc,EACd,SAAS,EACT,YAAY,EACZ,KAAK,CACN,CAAC;IACF,IACE,YAAY,KAAK,IAAI;QACrB,YAAY,GAAG,UAAU,CAAC,OAAO,CAAC,kBAAkB,EACpD,CAAC;QACD,MAAM,MAAM,GAAG;YACb,QAAQ;YACR,MAAM,EAAE,+BAA+B,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa;YAC3E,eAAe,EAAE,IAAI;SACtB,CAAC;QACF,wBAAwB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC1C,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,MAAM,MAAM,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC;IAChE,wBAAwB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1C,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -5,6 +5,7 @@ import type { ComputeManagementClient } from "@azure/arm-compute";
|
|
|
5
5
|
import type { MonitorClient } from "@azure/arm-monitor";
|
|
6
6
|
import * as armResources from "@azure/arm-resources";
|
|
7
7
|
import type { AnalysisResult, Thresholds } from "../../types.js";
|
|
8
|
+
import { type MetricsCache } from "../utils.js";
|
|
8
9
|
/**
|
|
9
10
|
* Analyzes an Azure Virtual Machine for potential cost optimization.
|
|
10
11
|
*
|
|
@@ -15,5 +16,5 @@ import type { AnalysisResult, Thresholds } from "../../types.js";
|
|
|
15
16
|
* @param verbose - Whether verbose logging is enabled
|
|
16
17
|
* @returns Analysis result with cost risk and reason
|
|
17
18
|
*/
|
|
18
|
-
export declare function analyzeVM(resource: armResources.GenericResource, monitorClient: MonitorClient, computeClient: ComputeManagementClient, timespanDays: number, thresholds?: Thresholds, verbose?: boolean): Promise<AnalysisResult>;
|
|
19
|
+
export declare function analyzeVM(resource: armResources.GenericResource, monitorClient: MonitorClient, computeClient: ComputeManagementClient, timespanDays: number, thresholds?: Thresholds, verbose?: boolean, cache?: MetricsCache): Promise<AnalysisResult>;
|
|
19
20
|
//# sourceMappingURL=vm.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vm.d.ts","sourceRoot":"","sources":["../../../src/azure/resources/vm.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAGrD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"vm.d.ts","sourceRoot":"","sources":["../../../src/azure/resources/vm.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,OAAO,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAGrD,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGjE,OAAO,EAEL,KAAK,YAAY,EAIlB,MAAM,aAAa,CAAC;AAErB;;;;;;;;;GASG;AACH,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,YAAY,CAAC,eAAe,EACtC,aAAa,EAAE,aAAa,EAC5B,aAAa,EAAE,uBAAuB,EACtC,YAAY,EAAE,MAAM,EACpB,UAAU,GAAE,UAA+B,EAC3C,OAAO,UAAQ,EACf,KAAK,CAAC,EAAE,YAAY,GACnB,OAAO,CAAC,cAAc,CAAC,CA6FzB"}
|
|
@@ -14,7 +14,7 @@ import { getMetric, verboseLog, verboseLogAnalysisResult, verboseLogResourceStar
|
|
|
14
14
|
* @param verbose - Whether verbose logging is enabled
|
|
15
15
|
* @returns Analysis result with cost risk and reason
|
|
16
16
|
*/
|
|
17
|
-
export async function analyzeVM(resource, monitorClient, computeClient, timespanDays, thresholds = DEFAULT_THRESHOLDS, verbose = false) {
|
|
17
|
+
export async function analyzeVM(resource, monitorClient, computeClient, timespanDays, thresholds = DEFAULT_THRESHOLDS, verbose = false, cache) {
|
|
18
18
|
verboseLogResourceStart(verbose, resource.name || "unknown", "Virtual Machine (microsoft.compute/virtualmachines)");
|
|
19
19
|
verboseLog(verbose, "Resource details:", resource);
|
|
20
20
|
const costRisk = "high";
|
|
@@ -61,8 +61,8 @@ export async function analyzeVM(resource, monitorClient, computeClient, timespan
|
|
|
61
61
|
// Continue with metric analysis if instance view fails
|
|
62
62
|
}
|
|
63
63
|
// Check metrics for low utilization
|
|
64
|
-
const cpuUsage = await getMetric(monitorClient, resource.id, "Percentage CPU", "Average", timespanDays);
|
|
65
|
-
const networkIn = await getMetric(monitorClient, resource.id, "Network In Total", "Average", timespanDays);
|
|
64
|
+
const cpuUsage = await getMetric(monitorClient, resource.id, "Percentage CPU", "Average", timespanDays, cache);
|
|
65
|
+
const networkIn = await getMetric(monitorClient, resource.id, "Network In Total", "Average", timespanDays, cache);
|
|
66
66
|
if (cpuUsage !== null && cpuUsage < thresholds.vm.cpuPercent) {
|
|
67
67
|
reason += `Low CPU usage (avg ${cpuUsage.toFixed(2)}%). `;
|
|
68
68
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vm.js","sourceRoot":"","sources":["../../../src/azure/resources/vm.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAI7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EACL,SAAS,
|
|
1
|
+
{"version":3,"file":"vm.js","sourceRoot":"","sources":["../../../src/azure/resources/vm.ts"],"names":[],"mappings":"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"}
|
package/dist/azure/types.d.ts
CHANGED
|
@@ -7,6 +7,12 @@ import type { AnalysisResult, BaseConfig, CostRisk, Thresholds } from "../types.
|
|
|
7
7
|
* Azure configuration extending base config
|
|
8
8
|
*/
|
|
9
9
|
export type AzureConfig = BaseConfig & {
|
|
10
|
+
/**
|
|
11
|
+
* Maximum number of resources analyzed in parallel within a single
|
|
12
|
+
* subscription. Defaults to 8 when not provided. Set to 1 for a fully
|
|
13
|
+
* sequential run (useful for debugging or to be gentler on quotas).
|
|
14
|
+
*/
|
|
15
|
+
concurrency?: number;
|
|
10
16
|
/**
|
|
11
17
|
* Only analyze resources that match ALL the given tag key-value pairs.
|
|
12
18
|
* If omitted, all resources are analyzed.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/azure/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAE1D,OAAO,KAAK,EACV,cAAc,EACd,UAAU,EACV,QAAQ,EACR,UAAU,EACX,MAAM,aAAa,CAAC;AAErB;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG;IACrC;;;OAGG;IACH,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B;;OAEG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC,QAAQ,EAAE,cAAc,CAAC;IACzB,QAAQ,EAAE,YAAY,CAAC,eAAe,CAAC;CACxC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,OAAO,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/azure/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAE1D,OAAO,KAAK,EACV,cAAc,EACd,UAAU,EACV,QAAQ,EACR,UAAU,EACX,MAAM,aAAa,CAAC;AAErB;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG;IACrC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B;;OAEG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC,QAAQ,EAAE,cAAc,CAAC;IACzB,QAAQ,EAAE,YAAY,CAAC,eAAe,CAAC;CACxC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,OAAO,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC"}
|
package/dist/azure/utils.d.ts
CHANGED
|
@@ -4,6 +4,17 @@
|
|
|
4
4
|
import type { MonitorClient } from "@azure/arm-monitor";
|
|
5
5
|
import type * as armResources from "@azure/arm-resources";
|
|
6
6
|
import type { AnalysisResult } from "../types.js";
|
|
7
|
+
/** Per-run in-memory cache for Azure Monitor metric responses. */
|
|
8
|
+
export type MetricsCache = Map<string, Promise<null | number>>;
|
|
9
|
+
/**
|
|
10
|
+
* Minimal interface required by `getMetric` — only the `metrics.list` shape.
|
|
11
|
+
* Using a structural type instead of the full `MonitorClient` keeps tests
|
|
12
|
+
* strongly typed without unsafe casts and lets non-Azure callers supply a
|
|
13
|
+
* compatible mock.
|
|
14
|
+
*/
|
|
15
|
+
export type MonitorClientLike = {
|
|
16
|
+
metrics: Pick<MonitorClient["metrics"], "list">;
|
|
17
|
+
};
|
|
7
18
|
type MetricDataPoint = {
|
|
8
19
|
average?: number;
|
|
9
20
|
count?: number;
|
|
@@ -28,16 +39,30 @@ export declare function aggregateDataPoints(dataPoints: MetricDataPoint[], aggre
|
|
|
28
39
|
*/
|
|
29
40
|
export declare function extractAggregatedValue(metricData: MetricDataPoint, aggregation: string): null | number;
|
|
30
41
|
/**
|
|
31
|
-
*
|
|
42
|
+
* @internal — exposed for tests only.
|
|
43
|
+
*/
|
|
44
|
+
export declare function _metricsCacheSize(): number;
|
|
45
|
+
/**
|
|
46
|
+
* Fetches a specific metric for a resource from Azure Monitor, with an
|
|
47
|
+
* in-memory cache to deduplicate concurrent and repeated lookups within
|
|
48
|
+
* the same run.
|
|
32
49
|
*
|
|
33
|
-
*
|
|
50
|
+
* Concurrent callers for the same `(resourceId, metricName, aggregation,
|
|
51
|
+
* timespanDays)` tuple share the same underlying request.
|
|
52
|
+
*
|
|
53
|
+
* Pass an explicit `cache` (created per run in the orchestrator) to keep
|
|
54
|
+
* concurrent analysis runs isolated from each other. When omitted, the
|
|
55
|
+
* module-scoped fallback cache is used — safe for sequential runs.
|
|
56
|
+
*
|
|
57
|
+
* @param monitorClient - Azure Monitor client (or compatible mock)
|
|
34
58
|
* @param resourceId - The Azure resource ID
|
|
35
59
|
* @param metricName - The name of the metric to fetch (e.g., "Percentage CPU")
|
|
36
60
|
* @param aggregation - The aggregation type (e.g., "Average", "Total")
|
|
37
61
|
* @param timespanDays - Number of days to look back for metrics
|
|
62
|
+
* @param cache - Optional run-scoped cache; falls back to the module-scoped one
|
|
38
63
|
* @returns The metric value or null if unavailable
|
|
39
64
|
*/
|
|
40
|
-
export declare function getMetric(monitorClient:
|
|
65
|
+
export declare function getMetric(monitorClient: MonitorClientLike, resourceId: string, metricName: string, aggregation: string, timespanDays: number, cache?: MetricsCache): Promise<null | number>;
|
|
41
66
|
/**
|
|
42
67
|
* Returns true if the resource matches ALL specified tag key-value pairs.
|
|
43
68
|
* If filterTags is empty or undefined, always returns true (no filtering).
|
|
@@ -46,6 +71,13 @@ export declare function getMetric(monitorClient: MonitorClient, resourceId: stri
|
|
|
46
71
|
* @param filterTags - Map of required tag key→value pairs
|
|
47
72
|
*/
|
|
48
73
|
export declare function matchesTags(resource: armResources.GenericResource, filterTags: Map<string, string> | undefined): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Clears the module-scoped fallback metrics cache.
|
|
76
|
+
*
|
|
77
|
+
* Only needed when `getMetric` is called without an explicit `cache`
|
|
78
|
+
* argument. Prefer passing a run-scoped `MetricsCache` instead.
|
|
79
|
+
*/
|
|
80
|
+
export declare function resetMetricsCache(): void;
|
|
49
81
|
/**
|
|
50
82
|
* Logs a verbose message, optionally with an object.
|
|
51
83
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/azure/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAI1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,KAAK,eAAe,GAAG;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,eAAe,EAAE,EAC7B,WAAW,EAAE,MAAM,GAClB,IAAI,GAAG,MAAM,CAiCf;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,eAAe,EAC3B,WAAW,EAAE,MAAM,GAClB,IAAI,GAAG,MAAM,CA6Bf;AAED
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/azure/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAI1D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,kEAAkE;AAClE,MAAM,MAAM,YAAY,GAAG,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC;CACjD,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,eAAe,EAAE,EAC7B,WAAW,EAAE,MAAM,GAClB,IAAI,GAAG,MAAM,CAiCf;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,eAAe,EAC3B,WAAW,EAAE,MAAM,GAClB,IAAI,GAAG,MAAM,CA6Bf;AASD;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,SAAS,CAC7B,aAAa,EAAE,iBAAiB,EAChC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,KAAK,GAAE,YAA2B,GACjC,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CAexB;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,YAAY,CAAC,eAAe,EACtC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,GAC1C,OAAO,CAQT;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,OAAO,QAUjB;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,cAAc,QAYvB;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,QASrB"}
|
package/dist/azure/utils.js
CHANGED
|
@@ -66,42 +66,46 @@ export function extractAggregatedValue(metricData, aggregation) {
|
|
|
66
66
|
return null;
|
|
67
67
|
}
|
|
68
68
|
/**
|
|
69
|
-
*
|
|
69
|
+
* Module-scoped fallback cache. Used when callers of `getMetric` do not
|
|
70
|
+
* supply a run-scoped cache. Prefer passing an explicit `MetricsCache`
|
|
71
|
+
* instance through `AnalyzerContext` so concurrent runs stay isolated.
|
|
72
|
+
*/
|
|
73
|
+
const metricsCache = new Map();
|
|
74
|
+
/**
|
|
75
|
+
* @internal — exposed for tests only.
|
|
76
|
+
*/
|
|
77
|
+
export function _metricsCacheSize() {
|
|
78
|
+
return metricsCache.size;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Fetches a specific metric for a resource from Azure Monitor, with an
|
|
82
|
+
* in-memory cache to deduplicate concurrent and repeated lookups within
|
|
83
|
+
* the same run.
|
|
84
|
+
*
|
|
85
|
+
* Concurrent callers for the same `(resourceId, metricName, aggregation,
|
|
86
|
+
* timespanDays)` tuple share the same underlying request.
|
|
70
87
|
*
|
|
71
|
-
*
|
|
88
|
+
* Pass an explicit `cache` (created per run in the orchestrator) to keep
|
|
89
|
+
* concurrent analysis runs isolated from each other. When omitted, the
|
|
90
|
+
* module-scoped fallback cache is used — safe for sequential runs.
|
|
91
|
+
*
|
|
92
|
+
* @param monitorClient - Azure Monitor client (or compatible mock)
|
|
72
93
|
* @param resourceId - The Azure resource ID
|
|
73
94
|
* @param metricName - The name of the metric to fetch (e.g., "Percentage CPU")
|
|
74
95
|
* @param aggregation - The aggregation type (e.g., "Average", "Total")
|
|
75
96
|
* @param timespanDays - Number of days to look back for metrics
|
|
97
|
+
* @param cache - Optional run-scoped cache; falls back to the module-scoped one
|
|
76
98
|
* @returns The metric value or null if unavailable
|
|
77
99
|
*/
|
|
78
|
-
export async function getMetric(monitorClient, resourceId, metricName, aggregation, timespanDays) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
return null;
|
|
88
|
-
}
|
|
89
|
-
const metric = result.value[0];
|
|
90
|
-
if (!metric.timeseries || metric.timeseries.length === 0) {
|
|
91
|
-
return null;
|
|
92
|
-
}
|
|
93
|
-
const timeserie = metric.timeseries[0];
|
|
94
|
-
if (!timeserie.data || timeserie.data.length === 0) {
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
const aggregatedValue = aggregateDataPoints(timeserie.data, aggregation);
|
|
98
|
-
return aggregatedValue;
|
|
99
|
-
}
|
|
100
|
-
catch (error) {
|
|
101
|
-
const logger = getLogger(["savemoney", "azure", "metrics"]);
|
|
102
|
-
logger.error(`Failed to fetch metric ${metricName} for resource ${resourceId}: ${error instanceof Error ? error.message : String(error)}`);
|
|
103
|
-
return null;
|
|
104
|
-
}
|
|
100
|
+
export async function getMetric(monitorClient, resourceId, metricName, aggregation, timespanDays, cache = metricsCache) {
|
|
101
|
+
const key = `${resourceId}|${metricName}|${aggregation}|${timespanDays}`;
|
|
102
|
+
const cached = cache.get(key);
|
|
103
|
+
if (cached !== undefined) {
|
|
104
|
+
return cached;
|
|
105
|
+
}
|
|
106
|
+
const promise = fetchMetric(monitorClient, resourceId, metricName, aggregation, timespanDays);
|
|
107
|
+
cache.set(key, promise);
|
|
108
|
+
return promise;
|
|
105
109
|
}
|
|
106
110
|
/**
|
|
107
111
|
* Returns true if the resource matches ALL specified tag key-value pairs.
|
|
@@ -117,6 +121,15 @@ export function matchesTags(resource, filterTags) {
|
|
|
117
121
|
const resourceTags = resource.tags ?? {};
|
|
118
122
|
return [...filterTags.entries()].every(([key, value]) => resourceTags[key] === value);
|
|
119
123
|
}
|
|
124
|
+
/**
|
|
125
|
+
* Clears the module-scoped fallback metrics cache.
|
|
126
|
+
*
|
|
127
|
+
* Only needed when `getMetric` is called without an explicit `cache`
|
|
128
|
+
* argument. Prefer passing a run-scoped `MetricsCache` instead.
|
|
129
|
+
*/
|
|
130
|
+
export function resetMetricsCache() {
|
|
131
|
+
metricsCache.clear();
|
|
132
|
+
}
|
|
120
133
|
/**
|
|
121
134
|
* Logs a verbose message, optionally with an object.
|
|
122
135
|
*
|
|
@@ -167,4 +180,32 @@ export function verboseLogResourceStart(verbose, resourceName, resourceType) {
|
|
|
167
180
|
logger.debug("=".repeat(80));
|
|
168
181
|
}
|
|
169
182
|
}
|
|
183
|
+
async function fetchMetric(monitorClient, resourceId, metricName, aggregation, timespanDays) {
|
|
184
|
+
try {
|
|
185
|
+
const timespan = `P${timespanDays}D`;
|
|
186
|
+
const result = await monitorClient.metrics.list(resourceId, {
|
|
187
|
+
aggregation,
|
|
188
|
+
metricnames: metricName,
|
|
189
|
+
timespan,
|
|
190
|
+
});
|
|
191
|
+
if (result.value.length === 0) {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
const metric = result.value[0];
|
|
195
|
+
if (!metric.timeseries || metric.timeseries.length === 0) {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
const timeserie = metric.timeseries[0];
|
|
199
|
+
if (!timeserie.data || timeserie.data.length === 0) {
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
const aggregatedValue = aggregateDataPoints(timeserie.data, aggregation);
|
|
203
|
+
return aggregatedValue;
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
const logger = getLogger(["savemoney", "azure", "metrics"]);
|
|
207
|
+
logger.error(`Failed to fetch metric ${metricName} for resource ${resourceId}: ${error instanceof Error ? error.message : String(error)}`);
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
170
211
|
//# sourceMappingURL=utils.js.map
|