Skip to content

Commit 6cac971

Browse files
authored
Pull request to add 'Attachment Size Audit' Background Script to the Code Snippets Repository (#2482)
* Add README for Attachment Size Audit script This README provides an overview of the Attachment Size Audit script, including its functionality, configuration, prerequisites, and use cases. * 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 93891d6 commit 6cac971

File tree

2 files changed

+187
-0
lines changed

2 files changed

+187
-0
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# Attachment Size Audit
2+
3+
A ServiceNow background script that analyzes your instance's attachment storage and identifies which tables consume the most space and locate oversized files.
4+
5+
## Overview
6+
7+
This read-only script scans all attachments in your instance and provides:
8+
- Total storage used across all attachments
9+
- Storage breakdown by source table (kb_knowledge, sc_task, incident, etc.)
10+
- List of the 25 largest individual attachments
11+
12+
The script does not modify or delete any data—it only reads and reports findings.
13+
14+
## How It Works
15+
16+
The script runs through three main steps:
17+
18+
1. **Calculate Total Storage** - Sums all attachment sizes to give your total storage footprint
19+
2. **Break Down by Table** - Groups attachments by source table to identify which applications consume the most storage
20+
3. **Find Largest Files** - Identifies individual attachments larger than your threshold and lists them in descending order
21+
22+
## Configuration
23+
24+
Before running, adjust these variables at the top of the script:
25+
26+
- `TOP_N_ATTACHMENTS` (default: 25) - Number of largest files to display
27+
- `MIN_SIZE_MB` (default: 5) - Only show attachments larger than this size in MB
28+
- `USE_COMPRESSED_SIZE` (default: true) - Use actual disk size (true) or logical file size (false)
29+
30+
## Prerequisites
31+
32+
- Admin role to execute background scripts
33+
- Global scope (or scoped app with sys_attachment visibility)
34+
- Read access to sys_attachment table
35+
- Access to System Logs to view results
36+
37+
## How to Run
38+
39+
1. Navigate to **System Definition → Scripts - Background**
40+
2. Click **New** and paste the script
41+
3. Optionally adjust configuration variables
42+
4. Click **Execute**
43+
5. View results in **System Diagnostics → System Log** (search for "Attachment Size Audit")
44+
45+
## Sample Output
46+
47+
```
48+
=== Attachment Size Audit Started ===
49+
Using size field: SIZE_COMPRESSED
50+
51+
Total Attachment Storage: 415.28 MB
52+
53+
=== Storage Usage by Table (Descending) ===
54+
invisible.sys_store_app : 175.29 MB
55+
sys_upgrade_manifest : 49.39 MB
56+
ZZ_YYsn_wn_media : 33.50 MB
57+
ZZ_YYdb_image : 28.99 MB
58+
sys_sg_mobile_builder_config : 25.36 MB
59+
ZZ_YYhelp_content : 21.00 MB
60+
incident : 1.18 MB
61+
kb_knowledge : 75.54 KB
62+
63+
=== Top 25 Largest Attachments (>5 MB) ===
64+
[ 68.47 MB ] sncencZZYY.fd254d9443a161100967247e6bb8f200_3_1_3.zip | Table: invisible.sys_store_app | Record: fd254d9443a161100967247e6bb8f200
65+
[ 24.72 MB ] upgrade_manifest.csv | Table: sys_upgrade_manifest | Record: d5ee366b47203210ca05a464116d4328
66+
[ 24.66 MB ] upgrade_manifest.csv | Table: sys_upgrade_manifest | Record: 9ee610ffe17a22108bb2327e625886d0
67+
[ 17.77 MB ] image | Table: ZZ_YYhelp_content | Record: 19d642e347203210ca05a464116d4369
68+
[ 11.63 MB ] sncencZZYY.a77e3ede4df92010f87774ecf02d44f3_28_1_1.zip | Table: invisible.sys_store_app | Record: a77e3ede4df92010f87774ecf02d44f3
69+
70+
=== Attachment Size Audit Complete ===
71+
```
72+
73+
## Use Cases
74+
75+
- **Storage Planning** - Understand current attachment storage and plan for capacity growth
76+
- **Cost Optimization** - Identify storage hotspots for cloud instances to reduce costs
77+
- **Performance Issues** - Find large attachment tables that may be slowing queries
78+
- **Cleanup Strategy** - Identify which tables and files should be targeted for archival or deletion
79+
- **Pre-Upgrade Preparation** - Run before major upgrades to identify optimization opportunities
80+
81+
## Future Enhancement Opportunities
82+
83+
- **Generate Cleanup Script** - Create a companion script to delete old or orphaned attachments with DRY_RUN mode
84+
- **Orphaned Attachment Detection** - Identify attachments where parent records have been deleted
85+
- **File Age Analysis** - Track attachments older than 30/90/365 days to support retention policies
86+
- **File Type Breakdown** - Categorize attachments by extension (PDF, DOCX, MP4, etc.)
87+
- **Email Notifications** - Send automated summaries to storage admins with key metrics
88+
- **Dashboard Widget** - Create PA widget to visualize storage trends over time
89+
- **Scheduled Reporting** - Set up as scheduled job to track growth monthly
90+
- **Duplicate Detection** - Find duplicate attachments on same records for cleanup opportunities
91+
92+
## Safety & Performance
93+
94+
- **Read-only operation** - No data is modified or deleted
95+
- **No infinite loops** - Explicit limits on record processing
96+
- **Timeout prevention** - Efficient aggregate queries for large datasets
97+
- **Sub Pro Testing** - Test in sub-production environments first
98+
99+
100+
## Authors
101+
Masthan Sharif Shaik ( <a href="https://www.linkedin.com/in/nowsharif/" target="_blank">LinkedIn</a> , <a href="https://www.servicenow.com/community/user/viewprofilepage/user-id/668622" target="_blank">SN Community</a> )
102+
103+
## Version History:
104+
* 0.1
105+
* Initial Release
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)