@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
package/README.md CHANGED
@@ -12,6 +12,53 @@ Full support for Azure resource analysis with intelligent detection and flexible
12
12
 
13
13
  AWS support is planned for future releases. The architecture is designed to support multiple CSPs with provider-specific analyzers.
14
14
 
15
+ ## Architecture
16
+
17
+ The SaveMoney tool follows a modular architecture designed for multi-CSP
18
+ support:
19
+
20
+ ```mermaid
21
+ flowchart LR
22
+ subgraph cli["CLI Layer"]
23
+ CMDs[other cmds]
24
+ CLI[savemoney]
25
+ end
26
+ subgraph pkg["Package Layer - @pagopa/dx-savemoney"]
27
+ Config[Config Loader]
28
+ Azure[Azure Analyzer]
29
+ AWS[AWS Analyzer<br/>Coming Soon...]
30
+ end
31
+ subgraph svc["Azure Services"]
32
+ ARM[Azure Resource Manager]
33
+ Monitor[Azure Monitor Metrics]
34
+ Identity[Azure Identity]
35
+ end
36
+ subgraph rsc["Azure Resources"]
37
+ direction LR
38
+ VM[Virtual Machines]
39
+ Disk[Managed Disks]
40
+ NIC[Network Interfaces]
41
+ IP[Public IPs]
42
+ ASP[App Service Plans]
43
+ PE[Private Endpoints]
44
+ SA[Storage Accounts]
45
+ CA[Container Apps]
46
+ SS[Static Web Apps]
47
+ end
48
+ CLI --> Config
49
+ Config --> Azure
50
+ Config -.-> AWS
51
+ Azure --> ARM
52
+ Azure --> Monitor
53
+ Azure --> Identity
54
+ ARM --> rsc
55
+ Monitor --> rsc
56
+ style CLI fill:#0078d4,color:#fff
57
+ style Azure fill:#0078d4,color:#fff
58
+ style AWS fill:#ccc,color:#666
59
+ style Config fill:#107c10,color:#fff
60
+ ```
61
+
15
62
  ## Installation
16
63
 
17
64
  ```bash
@@ -39,15 +86,17 @@ yarn add @pagopa/dx-savemoney
39
86
 
40
87
  The tool analyzes the following Azure resource types with specific detection methods and risk levels:
41
88
 
42
- | Resource Type | Detection Method | Cost Risk | What's Checked |
43
- | :---------------------- | :---------------------- | :-------: | :-------------------------------------------------------------------------------------- |
44
- | **Virtual Machines** | Instance View + Metrics | 🔴 High | Deallocated/stopped state, Low CPU usage (<1%), Low network traffic (<10MB) |
45
- | **App Service Plans** | API Details + Metrics | 🔴 High | No apps deployed, Very low CPU (<5%), Very low memory (<10%), Oversized Premium tier |
46
- | **Managed Disks** | API Details | 🟡 Medium | Unattached state, No `managedBy` property |
47
- | **Public IP Addresses** | API Details + Metrics | 🟡 Medium | Not associated with any resource, Static IP not in use, Very low network traffic (<1MB) |
48
- | **Network Interfaces** | API Details | 🟡 Medium | Not attached to VM or Private Endpoint, No public IP assigned |
49
- | **Private Endpoints** | API Details | 🟡 Medium | No private link connections, Rejected/disconnected connections, No network interfaces |
50
- | **Storage Accounts** | Metrics | 🟡 Medium | Very low transaction count (<100 in timespan) |
89
+ | Resource Type | Detection Method | Cost Risk | What's Checked |
90
+ | :---------------------- | :---------------------- | :-------: | :------------------------------------------------------------------------------------------------------------------ |
91
+ | **Virtual Machines** | Instance View + Metrics | 🔴 High | Deallocated/stopped state, Low CPU usage (<1%), Low network traffic (<3MB per days) |
92
+ | **App Service Plans** | API Details + Metrics | 🔴 High | No apps deployed, Very low CPU (<5%), Very low memory (<10%), Oversized Premium tier |
93
+ | **Container Apps** | API Details + Metrics | 🟡 Medium | Not running state, Zero replicas configured, Low CPU (<0.001 cores), Low memory (<10MB), Low network traffic (<1MB) |
94
+ | **Managed Disks** | API Details | 🟡 Medium | Unattached state, No `managedBy` property |
95
+ | **Public IP Addresses** | API Details + Metrics | 🟡 Medium | Not associated with any resource, Static IP not in use, Very low network traffic (<~340KB per day) |
96
+ | **Network Interfaces** | API Details | 🟡 Medium | Not attached to VM or Private Endpoint, No public IP assigned |
97
+ | **Private Endpoints** | API Details | 🟡 Medium | No private link connections, Rejected/disconnected connections, No network interfaces |
98
+ | **Storage Accounts** | Metrics | 🟡 Medium | Very low transaction count (<10 per days in timespan) |
99
+ | **Static Web Apps** | Metrics | 🟢 Low | No traffic data available, Very low site hits (<100 requests in 30 days), Very low data transfer (<1MB in 30 days) |
51
100
 
52
101
  #### Generic Checks
53
102
 
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Azure resource analyzer - Main orchestration logic
3
3
  */
4
+ import { ContainerAppsAPIClient } from "@azure/arm-appcontainers";
4
5
  import { WebSiteManagementClient } from "@azure/arm-appservice";
5
6
  import { ComputeManagementClient } from "@azure/arm-compute";
6
7
  import { MonitorClient } from "@azure/arm-monitor";
@@ -23,10 +24,11 @@ export declare function analyzeAzureResources(config: AzureConfig, format: "deta
23
24
  * @param computeClient - Azure Compute client
24
25
  * @param networkClient - Azure Network client
25
26
  * @param webSiteClient - Azure Web Site client
27
+ * @param containerAppsClient - Azure Container Apps client
26
28
  * @param preferredLocation - Preferred Azure location
27
29
  * @param timespanDays - Number of days to analyze metrics
28
30
  * @param verbose - Whether verbose logging is enabled
29
31
  * @returns Analysis result with cost risk and reason
30
32
  */
31
- export declare function analyzeResource(resource: armResources.GenericResource, monitorClient: MonitorClient, computeClient: ComputeManagementClient, networkClient: NetworkManagementClient, webSiteClient: WebSiteManagementClient, preferredLocation: string, timespanDays: number, verbose?: boolean): Promise<AnalysisResult>;
33
+ export declare function analyzeResource(resource: armResources.GenericResource, monitorClient: MonitorClient, computeClient: ComputeManagementClient, networkClient: NetworkManagementClient, webSiteClient: WebSiteManagementClient, containerAppsClient: ContainerAppsAPIClient, preferredLocation: string, timespanDays: number, verbose?: boolean): Promise<AnalysisResult>;
32
34
  //# sourceMappingURL=analyzer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../../src/azure/analyzer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAIrD,OAAO,KAAK,EAAE,WAAW,EAA+B,MAAM,YAAY,CAAC;AAE3E,OAAO,EAAE,KAAK,cAAc,EAAgB,MAAM,aAAa,CAAC;AAYhE;;;;;GAKG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,eAAe,GAAG,MAAM,GAAG,OAAO,iBA8D3C;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,YAAY,CAAC,eAAe,EACtC,aAAa,EAAE,aAAa,EAC5B,aAAa,EAAE,uBAAuB,EACtC,aAAa,EAAE,uBAAuB,EACtC,aAAa,EAAE,uBAAuB,EACtC,iBAAiB,EAAE,MAAM,EACzB,YAAY,EAAE,MAAM,EACpB,OAAO,UAAQ,GACd,OAAO,CAAC,cAAc,CAAC,CA4FzB"}
1
+ {"version":3,"file":"analyzer.d.ts","sourceRoot":"","sources":["../../src/azure/analyzer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,KAAK,YAAY,MAAM,sBAAsB,CAAC;AAIrD,OAAO,KAAK,EAAE,WAAW,EAA+B,MAAM,YAAY,CAAC;AAE3E,OAAO,EAAE,KAAK,cAAc,EAAgB,MAAM,aAAa,CAAC;AAchE;;;;;GAKG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,eAAe,GAAG,MAAM,GAAG,OAAO,iBAmE3C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,YAAY,CAAC,eAAe,EACtC,aAAa,EAAE,aAAa,EAC5B,aAAa,EAAE,uBAAuB,EACtC,aAAa,EAAE,uBAAuB,EACtC,aAAa,EAAE,uBAAuB,EACtC,mBAAmB,EAAE,sBAAsB,EAC3C,iBAAiB,EAAE,MAAM,EACzB,YAAY,EAAE,MAAM,EACpB,OAAO,UAAQ,GACd,OAAO,CAAC,cAAc,CAAC,CAiHzB"}
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Azure resource analyzer - Main orchestration logic
3
3
  */
4
+ import { ContainerAppsAPIClient } from "@azure/arm-appcontainers";
4
5
  import { WebSiteManagementClient } from "@azure/arm-appservice";
5
6
  import { ComputeManagementClient } from "@azure/arm-compute";
6
7
  import { MonitorClient } from "@azure/arm-monitor";
@@ -10,7 +11,7 @@ import { DefaultAzureCredential } from "@azure/identity";
10
11
  import { getLogger } from "@logtape/logtape";
11
12
  import { mergeResults } from "../types.js";
12
13
  import { generateReport } from "./report.js";
13
- import { analyzeAppServicePlan, analyzeDisk, analyzeNic, analyzePrivateEndpoint, analyzePublicIp, analyzeStorageAccount, analyzeVM, } from "./resources/index.js";
14
+ import { analyzeAppServicePlan, analyzeContainerApp, analyzeDisk, analyzeNic, analyzePrivateEndpoint, analyzePublicIp, analyzeStaticSite, analyzeStorageAccount, analyzeVM, } from "./resources/index.js";
14
15
  /**
15
16
  * Analyzes resources in multiple Azure subscriptions and generates a report.
16
17
  *
@@ -28,9 +29,10 @@ export async function analyzeAzureResources(config, format) {
28
29
  const computeClient = new ComputeManagementClient(credential, subscriptionId.trim());
29
30
  const networkClient = new NetworkManagementClient(credential, subscriptionId.trim());
30
31
  const webSiteClient = new WebSiteManagementClient(credential, subscriptionId.trim());
32
+ const containerAppsClient = new ContainerAppsAPIClient(credential, subscriptionId.trim());
31
33
  // Use the async iterator to avoid memory explosion for large environments
32
34
  for await (const resource of resourceClient.resources.list()) {
33
- const { costRisk, reason, suspectedUnused } = await analyzeResource(resource, monitorClient, computeClient, networkClient, webSiteClient, config.preferredLocation, config.timespanDays, config.verbose || false);
35
+ const { costRisk, reason, suspectedUnused } = await analyzeResource(resource, monitorClient, computeClient, networkClient, webSiteClient, containerAppsClient, config.preferredLocation, config.timespanDays, config.verbose || false);
34
36
  if (suspectedUnused) {
35
37
  allReports.push({
36
38
  analysis: {
@@ -60,12 +62,13 @@ export async function analyzeAzureResources(config, format) {
60
62
  * @param computeClient - Azure Compute client
61
63
  * @param networkClient - Azure Network client
62
64
  * @param webSiteClient - Azure Web Site client
65
+ * @param containerAppsClient - Azure Container Apps client
63
66
  * @param preferredLocation - Preferred Azure location
64
67
  * @param timespanDays - Number of days to analyze metrics
65
68
  * @param verbose - Whether verbose logging is enabled
66
69
  * @returns Analysis result with cost risk and reason
67
70
  */
68
- export async function analyzeResource(resource, monitorClient, computeClient, networkClient, webSiteClient, preferredLocation, timespanDays, verbose = false) {
71
+ export async function analyzeResource(resource, monitorClient, computeClient, networkClient, webSiteClient, containerAppsClient, preferredLocation, timespanDays, verbose = false) {
69
72
  const type = resource.type?.toLowerCase() || "";
70
73
  let result = {
71
74
  costRisk: "low",
@@ -79,6 +82,11 @@ export async function analyzeResource(resource, monitorClient, computeClient, ne
79
82
  }
80
83
  // Route to type-specific analysis hooks
81
84
  switch (type) {
85
+ case "microsoft.app/containerapps": {
86
+ const containerAppResult = await analyzeContainerApp(resource, containerAppsClient, monitorClient, timespanDays, verbose);
87
+ result = mergeResults(result, containerAppResult);
88
+ break;
89
+ }
82
90
  case "microsoft.compute/disks": {
83
91
  const diskResult = await analyzeDisk(resource, computeClient, verbose);
84
92
  result = mergeResults(result, diskResult);
@@ -114,6 +122,11 @@ export async function analyzeResource(resource, monitorClient, computeClient, ne
114
122
  result = mergeResults(result, aspResult);
115
123
  break;
116
124
  }
125
+ case "microsoft.web/staticsites": {
126
+ const staticSiteResult = await analyzeStaticSite(resource, monitorClient, timespanDays, verbose);
127
+ result = mergeResults(result, staticSiteResult);
128
+ break;
129
+ }
117
130
  default:
118
131
  result.reason += "No specific analysis for this resource type. ";
119
132
  break;
@@ -1 +1 @@
1
- {"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../../src/azure/analyzer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"analyzer.js","sourceRoot":"","sources":["../../src/azure/analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Azure Container App analysis
3
+ */
4
+ import type { ContainerAppsAPIClient } from "@azure/arm-appcontainers";
5
+ import type { MonitorClient } from "@azure/arm-monitor";
6
+ import * as armResources from "@azure/arm-resources";
7
+ import type { AnalysisResult } from "../../types.js";
8
+ /**
9
+ * Analyzes an Azure Container App for potential cost optimization.
10
+ *
11
+ * @param resource - The Azure resource object
12
+ * @param containerAppsClient - Azure Container Apps client for details
13
+ * @param monitorClient - Azure Monitor client for metrics
14
+ * @param timespanDays - Number of days to analyze metrics
15
+ * @param verbose - Enable verbose logging
16
+ * @returns Analysis result with cost risk and reason
17
+ */
18
+ export declare function analyzeContainerApp(resource: armResources.GenericResource, containerAppsClient: ContainerAppsAPIClient, monitorClient: MonitorClient, timespanDays: number, verbose?: boolean): Promise<AnalysisResult>;
19
+ //# sourceMappingURL=container-app.d.ts.map
@@ -0,0 +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,MAAM,gBAAgB,CAAC;AASrD;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,YAAY,CAAC,eAAe,EACtC,mBAAmB,EAAE,sBAAsB,EAC3C,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,MAAM,EACpB,OAAO,UAAQ,GACd,OAAO,CAAC,cAAc,CAAC,CAoEzB"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Azure Container App analysis
3
+ */
4
+ import { getLogger } from "@logtape/logtape";
5
+ import { getMetric, verboseLog, verboseLogAnalysisResult, verboseLogResourceStart, } from "../utils.js";
6
+ /**
7
+ * Analyzes an Azure Container App for potential cost optimization.
8
+ *
9
+ * @param resource - The Azure resource object
10
+ * @param containerAppsClient - Azure Container Apps client for details
11
+ * @param monitorClient - Azure Monitor client for metrics
12
+ * @param timespanDays - Number of days to analyze metrics
13
+ * @param verbose - Enable verbose logging
14
+ * @returns Analysis result with cost risk and reason
15
+ */
16
+ export async function analyzeContainerApp(resource, containerAppsClient, monitorClient, timespanDays, verbose = false) {
17
+ verboseLogResourceStart(verbose, resource.name || "unknown", "Container App (Microsoft.App/containerApps)");
18
+ verboseLog(verbose, "Resource details:", resource);
19
+ const costRisk = "medium";
20
+ let reason = "";
21
+ if (!resource.id) {
22
+ return {
23
+ costRisk,
24
+ reason: "Resource ID is missing.",
25
+ suspectedUnused: false,
26
+ };
27
+ }
28
+ const resourceParts = resource.id.split("/");
29
+ const resourceGroupName = resourceParts[4];
30
+ const containerAppName = resourceParts[8];
31
+ try {
32
+ const appDetails = await containerAppsClient.containerApps.get(resourceGroupName, containerAppName);
33
+ verboseLog(verbose, "Container App API details:", appDetails);
34
+ reason = checkRunningStatus({
35
+ properties: {
36
+ provisioningState: appDetails.provisioningState,
37
+ runningStatus: appDetails.runningStatus,
38
+ template: appDetails.template,
39
+ },
40
+ }, reason, verbose);
41
+ reason = await checkResourceMetrics(resource, monitorClient, timespanDays, reason, verbose);
42
+ reason = await checkNetworkMetrics(resource, monitorClient, timespanDays, reason, verbose);
43
+ }
44
+ catch (error) {
45
+ const logger = getLogger(["savemoney", "azure"]);
46
+ logger.warn(`Failed to get Container App details for ${containerAppName}: ${error instanceof Error ? error.message : error}`);
47
+ reason += "Could not retrieve detailed Container App information. ";
48
+ }
49
+ const suspectedUnused = reason.length > 0;
50
+ const result = { costRisk, reason: reason.trim(), suspectedUnused };
51
+ verboseLogAnalysisResult(verbose, result);
52
+ return result;
53
+ }
54
+ /**
55
+ * Checks network traffic metrics for a Container App.
56
+ */
57
+ async function checkNetworkMetrics(resource, monitorClient, timespanDays, reason, verbose) {
58
+ let newReason = reason;
59
+ if (!resource.id) {
60
+ return newReason;
61
+ }
62
+ verboseLog(verbose, "Checking network metrics...");
63
+ const networkIn = await getMetric(monitorClient, resource.id, "RxBytes", "Average", timespanDays);
64
+ const networkOut = await getMetric(monitorClient, resource.id, "TxBytes", "Average", timespanDays);
65
+ verboseLog(verbose, `Network In: ${networkIn !== null ? `${(networkIn / 1048576).toFixed(2)} MB/day avg` : "N/A"}`);
66
+ verboseLog(verbose, `Network Out: ${networkOut !== null ? `${(networkOut / 1048576).toFixed(2)} MB/day avg` : "N/A"}`);
67
+ if (networkIn !== null &&
68
+ networkOut !== null &&
69
+ networkIn + networkOut < 34000) {
70
+ newReason += `Very low network traffic (${((networkIn + networkOut) / 1048576).toFixed(2)} MB/day avg). `;
71
+ }
72
+ return newReason;
73
+ }
74
+ /**
75
+ * Checks resource usage metrics for a Container App.
76
+ */
77
+ async function checkResourceMetrics(resource, monitorClient, timespanDays, reason, verbose) {
78
+ let newReason = reason;
79
+ if (!resource.id) {
80
+ return newReason;
81
+ }
82
+ verboseLog(verbose, "Checking resource usage metrics...");
83
+ const cpuUsage = await getMetric(monitorClient, resource.id, "UsageNanoCores", "Average", timespanDays);
84
+ const memoryUsage = await getMetric(monitorClient, resource.id, "WorkingSetBytes", "Average", timespanDays);
85
+ verboseLog(verbose, `CPU Usage: ${cpuUsage !== null ? `${(cpuUsage / 1000000000).toFixed(4)} cores` : "N/A"}`);
86
+ verboseLog(verbose, `Memory Usage: ${memoryUsage !== null ? `${(memoryUsage / 1048576).toFixed(2)} MB` : "N/A"}`);
87
+ if (cpuUsage !== null && cpuUsage < 1000000) {
88
+ newReason += `Very low CPU usage (${(cpuUsage / 1000000000).toFixed(4)} cores). `;
89
+ }
90
+ if (memoryUsage !== null && memoryUsage < 10485760) {
91
+ newReason += `Very low memory usage (${(memoryUsage / 1048576).toFixed(2)} MB). `;
92
+ }
93
+ return newReason;
94
+ }
95
+ /**
96
+ * Checks the running status of a Container App.
97
+ */
98
+ function checkRunningStatus(appDetails, reason, verbose) {
99
+ let newReason = reason;
100
+ const { provisioningState, runningStatus, template } = appDetails.properties || {};
101
+ verboseLog(verbose, `Min Replicas: ${template?.scale?.minReplicas ?? "N/A"}`);
102
+ verboseLog(verbose, `Max Replicas: ${template?.scale?.maxReplicas ?? "N/A"}`);
103
+ if (provisioningState === "Succeeded" && runningStatus !== "Running") {
104
+ newReason += "Container App is not running. ";
105
+ }
106
+ const minReplicas = template?.scale?.minReplicas;
107
+ const maxReplicas = template?.scale?.maxReplicas;
108
+ if (minReplicas === 0 && maxReplicas === 0) {
109
+ newReason += "Container App has 0 replicas configured. ";
110
+ }
111
+ return newReason;
112
+ }
113
+ //# sourceMappingURL=container-app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container-app.js","sourceRoot":"","sources":["../../../src/azure/resources/container-app.ts"],"names":[],"mappings":"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"}
@@ -2,10 +2,12 @@
2
2
  * Azure resource-specific analysis functions
3
3
  */
4
4
  export { analyzeAppServicePlan } from "./app-service.js";
5
+ export { analyzeContainerApp } from "./container-app.js";
5
6
  export { analyzeDisk } from "./disk.js";
6
7
  export { analyzeNic } from "./nic.js";
7
8
  export { analyzePrivateEndpoint } from "./private-endpoint.js";
8
9
  export { analyzePublicIp } from "./public-ip.js";
10
+ export { analyzeStaticSite } from "./static-web-app.js";
9
11
  export { analyzeStorageAccount } from "./storage.js";
10
12
  export { analyzeVM } from "./vm.js";
11
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/azure/resources/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/azure/resources/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC"}
@@ -2,10 +2,12 @@
2
2
  * Azure resource-specific analysis functions
3
3
  */
4
4
  export { analyzeAppServicePlan } from "./app-service.js";
5
+ export { analyzeContainerApp } from "./container-app.js";
5
6
  export { analyzeDisk } from "./disk.js";
6
7
  export { analyzeNic } from "./nic.js";
7
8
  export { analyzePrivateEndpoint } from "./private-endpoint.js";
8
9
  export { analyzePublicIp } from "./public-ip.js";
10
+ export { analyzeStaticSite } from "./static-web-app.js";
9
11
  export { analyzeStorageAccount } from "./storage.js";
10
12
  export { analyzeVM } from "./vm.js";
11
13
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/azure/resources/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/azure/resources/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC"}
@@ -42,10 +42,10 @@ export async function analyzePublicIp(resource, networkClient, monitorClient, ti
42
42
  reason += "Static IP not in use. ";
43
43
  }
44
44
  // Check network metrics for low usage
45
- const bytesInDDoS = await getMetric(monitorClient, resource.id, "BytesInDDoS", "Total", timespanDays);
46
- if (bytesInDDoS !== null && bytesInDDoS < 1000000) {
47
- // Less than 1MB total in 30 days
48
- reason += `Very low network traffic (${(bytesInDDoS / 1024 / 1024).toFixed(2)} MB). `;
45
+ const bytesInDDoS = await getMetric(monitorClient, resource.id, "BytesInDDoS", "Average", timespanDays);
46
+ if (bytesInDDoS !== null && bytesInDDoS < 340000) {
47
+ // Less than ~340KB average per day
48
+ reason += `Very low network traffic (${(bytesInDDoS / 1024 / 1024).toFixed(2)} MB/day avg). `;
49
49
  }
50
50
  }
51
51
  catch (error) {
@@ -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,EACL,SAAS,EACT,UAAU,EACV,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AAErB;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,QAAsC,EACtC,aAAsC,EACtC,aAA4B,EAC5B,YAAoB,EACpB,OAAO,GAAG,KAAK;IAEf,uBAAuB,CACrB,OAAO,EACP,QAAQ,CAAC,IAAI,IAAI,SAAS,EAC1B,iDAAiD,CAClD,CAAC;IACF,UAAU,CAAC,OAAO,EAAE,mBAAmB,EAAE,QAAQ,CAAC,CAAC;IAEnD,MAAM,QAAQ,GAA8B,QAAQ,CAAC;IACrD,IAAI,MAAM,GAAG,EAAE,CAAC;IAEhB,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,OAAO;YACL,QAAQ;YACR,MAAM,EAAE,yBAAyB;YACjC,eAAe,EAAE,KAAK;SACvB,CAAC;IACJ,CAAC;IAED,6DAA6D;IAC7D,MAAM,aAAa,GAAG,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7C,MAAM,iBAAiB,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IAC3C,MAAM,YAAY,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IAEtC,IAAI,CAAC;QACH,qCAAqC;QACrC,MAAM,eAAe,GAAG,MAAM,aAAa,CAAC,iBAAiB,CAAC,GAAG,CAC/D,iBAAiB,EACjB,YAAY,CACb,CAAC;QAEF,UAAU,CAAC,OAAO,EAAE,wBAAwB,EAAE,eAAe,CAAC,CAAC;QAE/D,yDAAyD;QACzD,IAAI,CAAC,eAAe,CAAC,eAAe,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,CAAC;YACpE,MAAM,IAAI,8CAA8C,CAAC;QAC3D,CAAC;QAED,iDAAiD;QACjD,IACE,eAAe,CAAC,wBAAwB,KAAK,QAAQ;YACrD,CAAC,eAAe,CAAC,eAAe,EAChC,CAAC;YACD,MAAM,IAAI,wBAAwB,CAAC;QACrC,CAAC;QAED,sCAAsC;QACtC,MAAM,WAAW,GAAG,MAAM,SAAS,CACjC,aAAa,EACb,QAAQ,CAAC,EAAE,EACX,aAAa,EACb,OAAO,EACP,YAAY,CACb,CAAC;QAEF,IAAI,WAAW,KAAK,IAAI,IAAI,WAAW,GAAG,OAAO,EAAE,CAAC;YAClD,iCAAiC;YACjC,MAAM,IAAI,6BAA6B,CAAC,WAAW,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC;QACxF,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;QACjD,MAAM,CAAC,IAAI,CACT,uCAAuC,YAAY,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,CACzG,CAAC;QACF,MAAM,IAAI,qDAAqD,CAAC;IAClE,CAAC;IAED,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,eAAe,EAAE,CAAC;IACpE,wBAAwB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1C,OAAO,MAAM,CAAC;AAChB,CAAC"}
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,EACL,SAAS,EACT,UAAU,EACV,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AAErB;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,QAAsC,EACtC,aAAsC,EACtC,aAA4B,EAC5B,YAAoB,EACpB,OAAO,GAAG,KAAK;IAEf,uBAAuB,CACrB,OAAO,EACP,QAAQ,CAAC,IAAI,IAAI,SAAS,EAC1B,iDAAiD,CAClD,CAAC;IACF,UAAU,CAAC,OAAO,EAAE,mBAAmB,EAAE,QAAQ,CAAC,CAAC;IAEnD,MAAM,QAAQ,GAA8B,QAAQ,CAAC;IACrD,IAAI,MAAM,GAAG,EAAE,CAAC;IAEhB,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,OAAO;YACL,QAAQ;YACR,MAAM,EAAE,yBAAyB;YACjC,eAAe,EAAE,KAAK;SACvB,CAAC;IACJ,CAAC;IAED,6DAA6D;IAC7D,MAAM,aAAa,GAAG,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7C,MAAM,iBAAiB,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IAC3C,MAAM,YAAY,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IAEtC,IAAI,CAAC;QACH,qCAAqC;QACrC,MAAM,eAAe,GAAG,MAAM,aAAa,CAAC,iBAAiB,CAAC,GAAG,CAC/D,iBAAiB,EACjB,YAAY,CACb,CAAC;QAEF,UAAU,CAAC,OAAO,EAAE,wBAAwB,EAAE,eAAe,CAAC,CAAC;QAE/D,yDAAyD;QACzD,IAAI,CAAC,eAAe,CAAC,eAAe,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,CAAC;YACpE,MAAM,IAAI,8CAA8C,CAAC;QAC3D,CAAC;QAED,iDAAiD;QACjD,IACE,eAAe,CAAC,wBAAwB,KAAK,QAAQ;YACrD,CAAC,eAAe,CAAC,eAAe,EAChC,CAAC;YACD,MAAM,IAAI,wBAAwB,CAAC;QACrC,CAAC;QAED,sCAAsC;QACtC,MAAM,WAAW,GAAG,MAAM,SAAS,CACjC,aAAa,EACb,QAAQ,CAAC,EAAE,EACX,aAAa,EACb,SAAS,EACT,YAAY,CACb,CAAC;QAEF,IAAI,WAAW,KAAK,IAAI,IAAI,WAAW,GAAG,MAAM,EAAE,CAAC;YACjD,mCAAmC;YACnC,MAAM,IAAI,6BAA6B,CAAC,WAAW,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC;QAChG,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;QACjD,MAAM,CAAC,IAAI,CACT,uCAAuC,YAAY,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,CACzG,CAAC;QACF,MAAM,IAAI,qDAAqD,CAAC;IAClE,CAAC;IAED,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,eAAe,EAAE,CAAC;IACpE,wBAAwB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1C,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Azure Static Web App analysis
3
+ */
4
+ import type { MonitorClient } from "@azure/arm-monitor";
5
+ import * as armResources from "@azure/arm-resources";
6
+ import type { AnalysisResult } from "../../types.js";
7
+ /**
8
+ * Analyzes an Azure Static Web App for potential cost optimization.
9
+ *
10
+ * @param resource - The Azure resource object
11
+ * @param monitorClient - Azure Monitor client for metrics
12
+ * @param timespanDays - Number of days to analyze metrics
13
+ * @param verbose - Enable verbose logging
14
+ * @returns Analysis result with cost risk and reason
15
+ */
16
+ export declare function analyzeStaticSite(resource: armResources.GenericResource, monitorClient: MonitorClient, timespanDays: number, verbose?: boolean): Promise<AnalysisResult>;
17
+ //# sourceMappingURL=static-web-app.d.ts.map
@@ -0,0 +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,MAAM,gBAAgB,CAAC;AASrD;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,YAAY,CAAC,eAAe,EACtC,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,MAAM,EACpB,OAAO,UAAQ,GACd,OAAO,CAAC,cAAc,CAAC,CA2EzB"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Azure Static Web App analysis
3
+ */
4
+ import { getLogger } from "@logtape/logtape";
5
+ import { getMetric, verboseLog, verboseLogAnalysisResult, verboseLogResourceStart, } from "../utils.js";
6
+ /**
7
+ * Analyzes an Azure Static Web App for potential cost optimization.
8
+ *
9
+ * @param resource - The Azure resource object
10
+ * @param monitorClient - Azure Monitor client for metrics
11
+ * @param timespanDays - Number of days to analyze metrics
12
+ * @param verbose - Enable verbose logging
13
+ * @returns Analysis result with cost risk and reason
14
+ */
15
+ export async function analyzeStaticSite(resource, monitorClient, timespanDays, verbose = false) {
16
+ verboseLogResourceStart(verbose, resource.name || "unknown", "Static Web App (Microsoft.Web/staticSites)");
17
+ verboseLog(verbose, "Resource details:", resource);
18
+ const costRisk = "low";
19
+ let reason = "";
20
+ if (!resource.id) {
21
+ return {
22
+ costRisk,
23
+ reason: "Resource ID is missing.",
24
+ suspectedUnused: false,
25
+ };
26
+ }
27
+ try {
28
+ verboseLog(verbose, "Checking metrics...");
29
+ // Check for site hits (requests to the static site)
30
+ // Note: Static Web Apps metrics use Total aggregation, not Average
31
+ // Ref. https://learn.microsoft.com/en-us/azure/azure-monitor/reference/supported-metrics/microsoft-web-staticsites-metrics
32
+ const siteHits = await getMetric(monitorClient, resource.id, "SiteHits", "Total", timespanDays);
33
+ const bytesSent = await getMetric(monitorClient, resource.id, "BytesSent", "Total", timespanDays);
34
+ verboseLog(verbose, `Site Hits: ${siteHits !== null ? `${siteHits.toFixed(0)} total requests` : "N/A"}`);
35
+ verboseLog(verbose, `Bytes Sent: ${bytesSent !== null ? `${(bytesSent / 1024 / 1024).toFixed(2)} MB total` : "N/A"}`);
36
+ // If both metrics are null, it means no data points exist (no traffic at all)
37
+ if (siteHits === null && bytesSent === null) {
38
+ reason += `No traffic data available in ${timespanDays} days. `;
39
+ }
40
+ else {
41
+ if (siteHits !== null && siteHits < 100) {
42
+ // Less than 100 requests total in the timespan (< ~3.3 requests/day)
43
+ reason += `Very low site traffic (${siteHits.toFixed(0)} requests in ${timespanDays} days). `;
44
+ }
45
+ if (bytesSent !== null && bytesSent < 1048576) {
46
+ // Less than 1MB total in the timespan (< ~34KB/day)
47
+ reason += `Very low data transfer (${(bytesSent / 1024 / 1024).toFixed(2)} MB in ${timespanDays} days). `;
48
+ }
49
+ }
50
+ }
51
+ catch (error) {
52
+ const logger = getLogger(["savemoney", "azure"]);
53
+ logger.warn(`Failed to get metrics for Static Web App ${resource.name}: ${error instanceof Error ? error.message : error}`);
54
+ }
55
+ const suspectedUnused = reason.length > 0;
56
+ const result = { costRisk, reason: reason.trim(), suspectedUnused };
57
+ verboseLogAnalysisResult(verbose, result);
58
+ return result;
59
+ }
60
+ //# sourceMappingURL=static-web-app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static-web-app.js","sourceRoot":"","sources":["../../../src/azure/resources/static-web-app.ts"],"names":[],"mappings":"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"}
@@ -21,12 +21,12 @@ export async function analyzeStorageAccount(resource, monitorClient, timespanDay
21
21
  suspectedUnused: false,
22
22
  };
23
23
  }
24
- const transactions = await getMetric(monitorClient, resource.id, "Transactions", "Total", timespanDays);
25
- if (transactions !== null && transactions < 100) {
26
- // Very low transactions
24
+ const transactions = await getMetric(monitorClient, resource.id, "Transactions", "Average", timespanDays);
25
+ if (transactions !== null && transactions < 10) {
26
+ // Less than 10 transactions per day on average
27
27
  const result = {
28
28
  costRisk,
29
- reason: `Very low transaction count (${transactions}). `,
29
+ reason: `Very low transaction count (${transactions.toFixed(2)} avg/day). `,
30
30
  suspectedUnused: true,
31
31
  };
32
32
  verboseLogAnalysisResult(verbose, result);
@@ -1 +1 @@
1
- {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/azure/resources/storage.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,OAAO,EACL,SAAS,EACT,UAAU,EACV,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AAErB;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,QAAsC,EACtC,aAA4B,EAC5B,YAAoB,EACpB,OAAO,GAAG,KAAK;IAEf,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,OAAO,EACP,YAAY,CACb,CAAC;IACF,IAAI,YAAY,KAAK,IAAI,IAAI,YAAY,GAAG,GAAG,EAAE,CAAC;QAChD,wBAAwB;QACxB,MAAM,MAAM,GAAG;YACb,QAAQ;YACR,MAAM,EAAE,+BAA+B,YAAY,KAAK;YACxD,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"}
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/azure/resources/storage.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,OAAO,EACL,SAAS,EACT,UAAU,EACV,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AAErB;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,QAAsC,EACtC,aAA4B,EAC5B,YAAoB,EACpB,OAAO,GAAG,KAAK;IAEf,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,CACb,CAAC;IACF,IAAI,YAAY,KAAK,IAAI,IAAI,YAAY,GAAG,EAAE,EAAE,CAAC;QAC/C,+CAA+C;QAC/C,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"}
@@ -61,14 +61,14 @@ export async function analyzeVM(resource, monitorClient, computeClient, timespan
61
61
  }
62
62
  // Check metrics for low utilization
63
63
  const cpuUsage = await getMetric(monitorClient, resource.id, "Percentage CPU", "Average", timespanDays);
64
- const networkIn = await getMetric(monitorClient, resource.id, "Network In Total", "Total", timespanDays);
64
+ const networkIn = await getMetric(monitorClient, resource.id, "Network In Total", "Average", timespanDays);
65
65
  if (cpuUsage !== null && cpuUsage < 1) {
66
66
  // Less than 1% average CPU
67
67
  reason += `Low CPU usage (avg ${cpuUsage.toFixed(2)}%). `;
68
68
  }
69
- if (networkIn !== null && networkIn < 1024 * 1024 * 10) {
70
- // Less than 10MB total network in
71
- reason += `Low network traffic. `;
69
+ if (networkIn !== null && networkIn < 1024 * 1024 * 3) {
70
+ // Less than 3MB average per day
71
+ reason += `Low network traffic (${(networkIn / 1024 / 1024).toFixed(2)} MB/day avg). `;
72
72
  }
73
73
  const result = { costRisk, reason, suspectedUnused: reason.length > 0 };
74
74
  verboseLogAnalysisResult(verbose, result);
@@ -1 +1 @@
1
- {"version":3,"file":"vm.js","sourceRoot":"","sources":["../../../src/azure/resources/vm.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"vm.js","sourceRoot":"","sources":["../../../src/azure/resources/vm.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,29 @@
3
3
  */
4
4
  import type { MonitorClient } from "@azure/arm-monitor";
5
5
  import type { AnalysisResult } from "../types.js";
6
+ type MetricDataPoint = {
7
+ average?: number;
8
+ count?: number;
9
+ maximum?: number;
10
+ minimum?: number;
11
+ total?: number;
12
+ };
13
+ /**
14
+ * Aggregates metric data points based on aggregation type.
15
+ *
16
+ * @param dataPoints - Array of metric data points
17
+ * @param aggregation - The aggregation type (e.g., "Average", "Total")
18
+ * @returns The aggregated value or null if unavailable
19
+ */
20
+ export declare function aggregateDataPoints(dataPoints: MetricDataPoint[], aggregation: string): null | number;
21
+ /**
22
+ * Extracts the aggregated value from metric data.
23
+ *
24
+ * @param metricData - The metric data point
25
+ * @param aggregation - The aggregation type (e.g., "Average", "Total")
26
+ * @returns The aggregated value or null if unavailable
27
+ */
28
+ export declare function extractAggregatedValue(metricData: MetricDataPoint, aggregation: string): null | number;
6
29
  /**
7
30
  * Fetches a specific metric for a resource from Azure Monitor.
8
31
  *
@@ -37,4 +60,5 @@ export declare function verboseLogAnalysisResult(verbose: boolean, result: Analy
37
60
  * @param resourceType - Type of the resource
38
61
  */
39
62
  export declare function verboseLogResourceStart(verbose: boolean, resourceName: string, resourceType: string): void;
63
+ export {};
40
64
  //# sourceMappingURL=utils.d.ts.map