@pagopa/dx-savemoney 0.1.2 → 0.1.4
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/README.md +2 -0
- package/dist/azure/analyzer.d.ts.map +1 -1
- package/dist/azure/analyzer.js +6 -1
- package/dist/azure/analyzer.js.map +1 -1
- package/dist/azure/resources/index.d.ts +1 -0
- package/dist/azure/resources/index.d.ts.map +1 -1
- package/dist/azure/resources/index.js +1 -0
- package/dist/azure/resources/index.js.map +1 -1
- package/dist/azure/resources/static-web-app.d.ts +17 -0
- package/dist/azure/resources/static-web-app.d.ts.map +1 -0
- package/dist/azure/resources/static-web-app.js +60 -0
- package/dist/azure/resources/static-web-app.js.map +1 -0
- package/package.json +2 -7
- package/src/azure/analyzer.ts +11 -0
- package/src/azure/resources/index.ts +1 -0
- package/src/azure/resources/static-web-app.ts +108 -0
package/README.md
CHANGED
|
@@ -43,6 +43,7 @@ flowchart LR
|
|
|
43
43
|
PE[Private Endpoints]
|
|
44
44
|
SA[Storage Accounts]
|
|
45
45
|
CA[Container Apps]
|
|
46
|
+
SS[Static Web Apps]
|
|
46
47
|
end
|
|
47
48
|
CLI --> Config
|
|
48
49
|
Config --> Azure
|
|
@@ -95,6 +96,7 @@ The tool analyzes the following Azure resource types with specific detection met
|
|
|
95
96
|
| **Network Interfaces** | API Details | 🟡 Medium | Not attached to VM or Private Endpoint, No public IP assigned |
|
|
96
97
|
| **Private Endpoints** | API Details | 🟡 Medium | No private link connections, Rejected/disconnected connections, No network interfaces |
|
|
97
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) |
|
|
98
100
|
|
|
99
101
|
#### Generic Checks
|
|
100
102
|
|
|
@@ -1 +1 @@
|
|
|
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;
|
|
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"}
|
package/dist/azure/analyzer.js
CHANGED
|
@@ -11,7 +11,7 @@ import { DefaultAzureCredential } from "@azure/identity";
|
|
|
11
11
|
import { getLogger } from "@logtape/logtape";
|
|
12
12
|
import { mergeResults } from "../types.js";
|
|
13
13
|
import { generateReport } from "./report.js";
|
|
14
|
-
import { analyzeAppServicePlan, analyzeContainerApp, 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";
|
|
15
15
|
/**
|
|
16
16
|
* Analyzes resources in multiple Azure subscriptions and generates a report.
|
|
17
17
|
*
|
|
@@ -122,6 +122,11 @@ export async function analyzeResource(resource, monitorClient, computeClient, ne
|
|
|
122
122
|
result = mergeResults(result, aspResult);
|
|
123
123
|
break;
|
|
124
124
|
}
|
|
125
|
+
case "microsoft.web/staticsites": {
|
|
126
|
+
const staticSiteResult = await analyzeStaticSite(resource, monitorClient, timespanDays, verbose);
|
|
127
|
+
result = mergeResults(result, staticSiteResult);
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
125
130
|
default:
|
|
126
131
|
result.reason += "No specific analysis for this resource type. ";
|
|
127
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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"}
|
|
@@ -7,6 +7,7 @@ export { analyzeDisk } from "./disk.js";
|
|
|
7
7
|
export { analyzeNic } from "./nic.js";
|
|
8
8
|
export { analyzePrivateEndpoint } from "./private-endpoint.js";
|
|
9
9
|
export { analyzePublicIp } from "./public-ip.js";
|
|
10
|
+
export { analyzeStaticSite } from "./static-web-app.js";
|
|
10
11
|
export { analyzeStorageAccount } from "./storage.js";
|
|
11
12
|
export { analyzeVM } from "./vm.js";
|
|
12
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,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,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"}
|
|
@@ -7,6 +7,7 @@ export { analyzeDisk } from "./disk.js";
|
|
|
7
7
|
export { analyzeNic } from "./nic.js";
|
|
8
8
|
export { analyzePrivateEndpoint } from "./private-endpoint.js";
|
|
9
9
|
export { analyzePublicIp } from "./public-ip.js";
|
|
10
|
+
export { analyzeStaticSite } from "./static-web-app.js";
|
|
10
11
|
export { analyzeStorageAccount } from "./storage.js";
|
|
11
12
|
export { analyzeVM } from "./vm.js";
|
|
12
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,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,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"}
|
|
@@ -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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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pagopa/dx-savemoney",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Azure resource analyzer for finding unused or cost-inefficient resources.",
|
|
6
6
|
"repository": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"@azure/arm-network": "^34.1.0",
|
|
35
35
|
"@azure/arm-resources": "^7.0.0",
|
|
36
36
|
"@azure/identity": "^4.13.0",
|
|
37
|
-
"@logtape/logtape": "^1.
|
|
37
|
+
"@logtape/logtape": "^1.2.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@tsconfig/node22": "22.0.2",
|
|
@@ -49,13 +49,8 @@
|
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build": "rm -rf dist && tsc",
|
|
51
51
|
"dev": "tsc --watch",
|
|
52
|
-
"lint": "eslint --fix .",
|
|
53
|
-
"lint:check": "eslint .",
|
|
54
52
|
"format": "prettier --write .",
|
|
55
53
|
"format:check": "prettier --check .",
|
|
56
|
-
"test": "vitest run",
|
|
57
|
-
"test:coverage": "vitest run --coverage",
|
|
58
|
-
"test:watch": "vitest run --watch",
|
|
59
54
|
"typecheck": "tsc --noEmit"
|
|
60
55
|
}
|
|
61
56
|
}
|
package/src/azure/analyzer.ts
CHANGED
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
analyzeNic,
|
|
23
23
|
analyzePrivateEndpoint,
|
|
24
24
|
analyzePublicIp,
|
|
25
|
+
analyzeStaticSite,
|
|
25
26
|
analyzeStorageAccount,
|
|
26
27
|
analyzeVM,
|
|
27
28
|
} from "./resources/index.js";
|
|
@@ -216,6 +217,16 @@ export async function analyzeResource(
|
|
|
216
217
|
result = mergeResults(result, aspResult);
|
|
217
218
|
break;
|
|
218
219
|
}
|
|
220
|
+
case "microsoft.web/staticsites": {
|
|
221
|
+
const staticSiteResult = await analyzeStaticSite(
|
|
222
|
+
resource,
|
|
223
|
+
monitorClient,
|
|
224
|
+
timespanDays,
|
|
225
|
+
verbose,
|
|
226
|
+
);
|
|
227
|
+
result = mergeResults(result, staticSiteResult);
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
219
230
|
default:
|
|
220
231
|
result.reason += "No specific analysis for this resource type. ";
|
|
221
232
|
break;
|
|
@@ -8,5 +8,6 @@ export { analyzeDisk } from "./disk.js";
|
|
|
8
8
|
export { analyzeNic } from "./nic.js";
|
|
9
9
|
export { analyzePrivateEndpoint } from "./private-endpoint.js";
|
|
10
10
|
export { analyzePublicIp } from "./public-ip.js";
|
|
11
|
+
export { analyzeStaticSite } from "./static-web-app.js";
|
|
11
12
|
export { analyzeStorageAccount } from "./storage.js";
|
|
12
13
|
export { analyzeVM } from "./vm.js";
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Azure Static Web App analysis
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { MonitorClient } from "@azure/arm-monitor";
|
|
6
|
+
|
|
7
|
+
import * as armResources from "@azure/arm-resources";
|
|
8
|
+
import { getLogger } from "@logtape/logtape";
|
|
9
|
+
|
|
10
|
+
import type { AnalysisResult } from "../../types.js";
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
getMetric,
|
|
14
|
+
verboseLog,
|
|
15
|
+
verboseLogAnalysisResult,
|
|
16
|
+
verboseLogResourceStart,
|
|
17
|
+
} from "../utils.js";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Analyzes an Azure Static Web App for potential cost optimization.
|
|
21
|
+
*
|
|
22
|
+
* @param resource - The Azure resource object
|
|
23
|
+
* @param monitorClient - Azure Monitor client for metrics
|
|
24
|
+
* @param timespanDays - Number of days to analyze metrics
|
|
25
|
+
* @param verbose - Enable verbose logging
|
|
26
|
+
* @returns Analysis result with cost risk and reason
|
|
27
|
+
*/
|
|
28
|
+
export async function analyzeStaticSite(
|
|
29
|
+
resource: armResources.GenericResource,
|
|
30
|
+
monitorClient: MonitorClient,
|
|
31
|
+
timespanDays: number,
|
|
32
|
+
verbose = false,
|
|
33
|
+
): Promise<AnalysisResult> {
|
|
34
|
+
verboseLogResourceStart(
|
|
35
|
+
verbose,
|
|
36
|
+
resource.name || "unknown",
|
|
37
|
+
"Static Web App (Microsoft.Web/staticSites)",
|
|
38
|
+
);
|
|
39
|
+
verboseLog(verbose, "Resource details:", resource);
|
|
40
|
+
|
|
41
|
+
const costRisk: "high" | "low" | "medium" = "low";
|
|
42
|
+
let reason = "";
|
|
43
|
+
|
|
44
|
+
if (!resource.id) {
|
|
45
|
+
return {
|
|
46
|
+
costRisk,
|
|
47
|
+
reason: "Resource ID is missing.",
|
|
48
|
+
suspectedUnused: false,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
verboseLog(verbose, "Checking metrics...");
|
|
54
|
+
|
|
55
|
+
// Check for site hits (requests to the static site)
|
|
56
|
+
// Note: Static Web Apps metrics use Total aggregation, not Average
|
|
57
|
+
// Ref. https://learn.microsoft.com/en-us/azure/azure-monitor/reference/supported-metrics/microsoft-web-staticsites-metrics
|
|
58
|
+
const siteHits = await getMetric(
|
|
59
|
+
monitorClient,
|
|
60
|
+
resource.id,
|
|
61
|
+
"SiteHits",
|
|
62
|
+
"Total",
|
|
63
|
+
timespanDays,
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const bytesSent = await getMetric(
|
|
67
|
+
monitorClient,
|
|
68
|
+
resource.id,
|
|
69
|
+
"BytesSent",
|
|
70
|
+
"Total",
|
|
71
|
+
timespanDays,
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
verboseLog(
|
|
75
|
+
verbose,
|
|
76
|
+
`Site Hits: ${siteHits !== null ? `${siteHits.toFixed(0)} total requests` : "N/A"}`,
|
|
77
|
+
);
|
|
78
|
+
verboseLog(
|
|
79
|
+
verbose,
|
|
80
|
+
`Bytes Sent: ${bytesSent !== null ? `${(bytesSent / 1024 / 1024).toFixed(2)} MB total` : "N/A"}`,
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
// If both metrics are null, it means no data points exist (no traffic at all)
|
|
84
|
+
if (siteHits === null && bytesSent === null) {
|
|
85
|
+
reason += `No traffic data available in ${timespanDays} days. `;
|
|
86
|
+
} else {
|
|
87
|
+
if (siteHits !== null && siteHits < 100) {
|
|
88
|
+
// Less than 100 requests total in the timespan (< ~3.3 requests/day)
|
|
89
|
+
reason += `Very low site traffic (${siteHits.toFixed(0)} requests in ${timespanDays} days). `;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (bytesSent !== null && bytesSent < 1048576) {
|
|
93
|
+
// Less than 1MB total in the timespan (< ~34KB/day)
|
|
94
|
+
reason += `Very low data transfer (${(bytesSent / 1024 / 1024).toFixed(2)} MB in ${timespanDays} days). `;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
} catch (error) {
|
|
98
|
+
const logger = getLogger(["savemoney", "azure"]);
|
|
99
|
+
logger.warn(
|
|
100
|
+
`Failed to get metrics for Static Web App ${resource.name}: ${error instanceof Error ? error.message : error}`,
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const suspectedUnused = reason.length > 0;
|
|
105
|
+
const result = { costRisk, reason: reason.trim(), suspectedUnused };
|
|
106
|
+
verboseLogAnalysisResult(verbose, result);
|
|
107
|
+
return result;
|
|
108
|
+
}
|