Skip to content

Commit 6974f98

Browse files
authored
Add attachment size audit script for ServiceNow
This script analyzes attachment storage in ServiceNow, identifying the largest attachments and their respective tables. It provides a read-only audit report to help manage storage usage.
1 parent 7e0207d commit 6974f98

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Background Script: Attachment Size Audit
2+
// Purpose: Analyzes your ServiceNow instance's attachment storage to identify which tables and individual files consume the most space.
3+
//Helps you understand storage usage patterns, locate oversized files, and plan cleanup or archival strategies.
4+
//Provides a read-only audit report without modifying any data.
5+
//
6+
// Author: Masthan Sharif Shaik
7+
// Date: October 2025
8+
// Tested on: Zurich, Yokohama
9+
//
10+
// IMPORTANT: Test in non-production environment first
11+
12+
(function attachmentSizeAudit() {
13+
14+
// ================= CONFIGURATION =================
15+
var TOP_N_ATTACHMENTS = 25; // Number of largest attachments to list
16+
var MIN_SIZE_MB = 5; // Only list attachments larger than this (MB)
17+
var USE_COMPRESSED_SIZE = true; // true = use size_compressed, false = use size_bytes
18+
// =================================================
19+
20+
var sizeField = USE_COMPRESSED_SIZE ? "size_compressed" : "size_bytes";
21+
var totalSizeBytes = 0;
22+
23+
gs.info("=== Attachment Size Audit Started ===");
24+
gs.info("Using size field: " + sizeField.toUpperCase());
25+
26+
// ----------------- TOTAL SIZE --------------------
27+
var totalAgg = new GlideAggregate("sys_attachment");
28+
totalAgg.addAggregate("SUM", sizeField);
29+
totalAgg.query();
30+
if (totalAgg.next()) {
31+
totalSizeBytes = totalAgg.getAggregate("SUM", sizeField);
32+
}
33+
34+
gs.info("Total Attachment Storage: " +
35+
formatBytes(totalSizeBytes));
36+
37+
// ------------- SIZE PER TABLE (AGGREGATED) --------------
38+
gs.info("\n=== Storage Usage by Table (Descending) ===");
39+
40+
var tableAgg = new GlideAggregate("sys_attachment");
41+
tableAgg.groupBy("table_name");
42+
tableAgg.addAggregate("SUM", sizeField);
43+
tableAgg.orderByAggregate("SUM", sizeField);
44+
tableAgg.query();
45+
46+
while (tableAgg.next()) {
47+
var table = tableAgg.getValue("table_name") || "<no table>";
48+
var tableSize = tableAgg.getAggregate("SUM", sizeField);
49+
gs.info(table.padEnd(40) + " : " + formatBytes(tableSize));
50+
}
51+
52+
// --------------- TOP N BIGGEST ATTACHMENTS ---------------
53+
gs.info("\n=== Top " + TOP_N_ATTACHMENTS + " Largest Attachments (>" + MIN_SIZE_MB + " MB) ===");
54+
55+
var attGR = new GlideRecord("sys_attachment");
56+
attGR.addQuery(sizeField, ">", MIN_SIZE_MB * 1024 * 1024);
57+
attGR.orderByDesc(sizeField);
58+
attGR.setLimit(TOP_N_ATTACHMENTS);
59+
attGR.query();
60+
61+
while (attGR.next()) {
62+
gs.info(
63+
"[ " + formatBytes(attGR[sizeField]) + " ] " +
64+
attGR.getValue("file_name") +
65+
" | Table: " + attGR.getValue("table_name") +
66+
" | Record: " + attGR.getValue("table_sys_id")
67+
);
68+
}
69+
70+
gs.info("\n=== Attachment Size Audit Complete ===");
71+
72+
// ------------- FORMATTER ----------------
73+
function formatBytes(bytes) {
74+
bytes = parseInt(bytes, 10) || 0;
75+
if (bytes < 1024) return bytes + " B";
76+
var i = Math.floor(Math.log(bytes) / Math.log(1024));
77+
var sizes = ["B", "KB", "MB", "GB", "TB"];
78+
var value = (bytes / Math.pow(1024, i)).toFixed(2);
79+
return value + " " + sizes[i];
80+
}
81+
82+
})();

0 commit comments

Comments
 (0)