Warning, /swf-monitor/docs/SNAPPER_STORAGE.md is written in an unsupported language. File is not indexed.
0001 # Snapper Storage — the Storage view
0002
0003 Production output on the JLab Rucio Storage Elements (RSEs), from
0004 registration until it settles, is recorded in Snapper by the `storage`
0005 component (swf-epicprod
0006 [STORAGE.md](https://github.com/BNLNPPS/swf-epicprod/blob/main/docs/STORAGE.md)):
0007 per disk RSE the inventory by replica state, the copying backlog and
0008 its ages, ghosts, rules, capacity, and cumulative counters of
0009 arrivals, completed transfers and ghosts appeared; per campaign the
0010 disk copies, catalog quality, dataset state and pipeline latencies. This document is the design of the Storage view
0011 over that record: a dedicated focus view showing the data lifecycle
0012 per RSE on one time axis, with the RSE's standing at the cut. It
0013 follows the focus-view mechanism and display laws of the Site,
0014 Errors and Platform views ([SNAPPER.md](SNAPPER.md),
0015 [SNAPPER_ERRORS.md](SNAPPER_ERRORS.md),
0016 [SNAPPER_PLATFORM.md](SNAPPER_PLATFORM.md); snapper-ai
0017 [INTEGRATION.md](https://github.com/BNLNPPS/snapper-ai/blob/main/docs/INTEGRATION.md),
0018 [TIME_HISTORY_UI.md](https://github.com/BNLNPPS/snapper-ai/blob/main/docs/TIME_HISTORY_UI.md)).
0019
0020 The storage component and the Storage view are in production; this
0021 document remains their design of record.
0022
0023 ## The record the view reads
0024
0025 The `storage` component is published by the storage pass after every
0026 run, every four hours, each pass reading only what production changed
0027 (STORAGE.md, The pass). A pass in which nothing moved is affirmed
0028 unchanged, so the component's snaps are the passes that changed
0029 something, at most one per pass. The view derives nothing from the pass's
0030 store or from Rucio: every plotted value is a field of the published
0031 projection (DESIGN.md, invariants 1 and 4). The exception listings
0032 beyond the component's bounded heads live on the Storage exceptions
0033 page, which reads the store (STORAGE.md, Retrieval).
0034
0035 The quantities, by kind, as the projection carries them:
0036
0037 - **Gauges at the pass instant**, per RSE: capacity (used, total,
0038 limit, fill fraction), inventory files and bytes by replica state,
0039 by campaign and by root, dataset placement counts, rule locks by
0040 state, the copying backlog with its age distribution, the ghost
0041 population by state and by campaign. Per campaign: files and bytes,
0042 disk copies, unattached and count-less files, dataset state.
0043 - **Cumulative counters**, monotonic from the census with an
0044 arbitrary origin, per RSE: arrived files and bytes as first copies
0045 and as replicas, transfers completed, ghosts appeared. Per campaign:
0046 arrived files and bytes. Every consumer differences two instants;
0047 the view bins them at render.
0048 - **Interval assessments**, per campaign: the latencies of the
0049 interval's arrivals as count, median and 90th percentile.
0050 - **Exception heads**: the oldest fifty ghosts, stuck rules and
0051 stalled datasets with the exact remainder as overflow counts.
0052 - **Assessment**: per-RSE and per-campaign verdicts against the
0053 SysConfig thresholds and the overall verdict.
0054
0055 The disk RSEs recorded today are ASGC-XRD, BNL-XRD, EIC-CLOUD-LOG,
0056 EIC-XRD, EIC-XRD-LOG, MANITOBA-XRD and XRD6, with the pseudo-RSE `none` holding registered files that have no
0057 replica row. The roots are RECO, FULL and EVGEN. The target campaigns
0058 are the delivery record's: the current and last campaigns and any
0059 campaign producing.
0060
0061 ## The Storage view
0062
0063 A dedicated focus view, `Storage`, on the mechanism the Site, Errors
0064 and Platform views use: its own clean path under the epicprod scope
0065 (`/snapper/epicprod/storage/`), a focus-sized cached series product
0066 over the `storage` and `errors` components' snaps, and its own
0067 detail rendering. It is the data-lifecycle counterpart of the Site
0068 view, which is the job lifecycle per queue, and conforms to it: one
0069 option per RSE with tick boxes, presentation ordered by activity, a
0070 jump list, and the RSE's detail docked beneath its own panels.
0071
0072 **Parameters**, in conformance with the Site and Campaign views:
0073
0074 - focus `rse`: one option per recorded RSE, default all. With several
0075 shown, presentation follows the peak arrival rate over the window,
0076 first copies and replicas together: RSEs ordered by that peak, idle RSEs last in alphabetical
0077 order with their sections closed, and a jump list under the tick row
0078 in the same order with each peak in brackets; open all and close all
0079 fold every section at once.
0080 The log stores and the `none` pseudo-RSE are options like any other
0081 and sort by their own activity.
0082 - **Counting** selector: bytes (default; TB, as Rucio states usage and
0083 limits) or files. The panel title states the unit.
0084 - **Grouping**: a grouping per panel, on the panel's own control row
0085 (snapper-ai INTEGRATION.md, a selector axis declaring `family`), each
0086 offering what that panel's record supports and nothing else. The
0087 copying backlog groups by data tier root (default) or campaign —
0088 never by replica state, everything in it being COPYING. Ghosts group
0089 by Rucio replica state (default) or campaign — never by root, which
0090 the record does not carry; under bytes counting the record holds the
0091 ghost total alone and the panel carries no control. The inventory
0092 groups by replica state (default), root or campaign, all three being
0093 real there. Replica state leads where it is offered: its members are
0094 the operational reading, a growing copying band being uploads that
0095 never finished and unavailable being replicas lost after arrival.
0096 The state is Rucio's own replica state at that RSE, the root is the
0097 DID's first path element, the data tier (RECO, FULL, EVGEN, SIMU),
0098 and the campaign is the campaign family the DID's second path
0099 element names, the target campaigns with every other campaign folded
0100 into `other` as the record folds them. No other panel is grouped.
0101 - **Show** selector: status (the default and the landing, the moving
0102 picture per RSE: arrivals per bin, ghosts appeared per bin, and
0103 usage against the limit, with the campaigns' arrivals after
0104 the RSE sections and the capacity table across RSEs on the card), RSE
0105 capacity alone (each RSE's usage against its limit over time, and
0106 directly beneath the panels the capacity table at the cut instant,
0107 the rows of `rucio account limit list eicprod`; the card carries
0108 nothing else under this reading), ghosts (each RSE's ghost
0109 population, flow and yield, with its capacity), or all panels. The
0110 choice rides the URL, so each reading is a bookmark.
0111 - the window, cut, zoom and curve selection every report page
0112 carries. The clean page lands on the last seven days (the view's
0113 default window; a signed-in user's remembered window takes
0114 precedence), with no floor at the record's first snap: a young
0115 record leaves the left of the window empty rather than shrinking
0116 the window to its span.
0117
0118 **Families per RSE**, panel order following the lifecycle, rates
0119 first, then backlogs, then state. Every family's control row is
0120 docked above its own panel.
0121
0122 1. *Arrivals* — first copies and replicas per bin, stacked, from the
0123 cumulative arrival counters projected to per-interval deltas at
0124 render (the counter-flow mode). Under bytes counting the same from
0125 the byte counters.
0126 2. *Transfers completed* — completed transfers per bin, in files under
0127 either counting, since the record carries no byte count for them.
0128 3. *Copying backlog* — files in the copying state at the pass
0129 instant, stacked by the grouping (campaign or root from the
0130 inventory maps; under the state grouping the panel is the copying
0131 total), with the count over the stuck threshold as an overlay
0132 line. *Copying age* follows as a small panel: the median, 90th
0133 percentile and maximum age in hours.
0134 4. *Ghosts* — the ghost population held at this RSE, stacked by the
0135 grouping: by state and by campaign from the record; the record
0136 carries no ghosts by root, so under the root grouping the panel
0137 shows the total until the pass records it (see Record additions).
0138 Under bytes counting the total only. *Ghosts appeared* follows: the
0139 per-bin flow from its counter. *Ghost yield* follows
0140 that: ghosts appeared over registrations (first copies arrived plus
0141 ghosts appeared) per bin, derived at series time, the upload
0142 failure rate of the RSE read against its arrival rate.
0143 5. *Inventory* — files or bytes by replica state, stacked; under the
0144 campaign and root groupings, the per-campaign or per-root totals
0145 over all states.
0146 6. *Rule locks* — replicating and stuck lock counts, two lines.
0147 7. *Capacity* — the production account's usage at this RSE in TB as
0148 the band, the quantity `rucio account limit list eicprod` prints,
0149 tracked over time; the account's limit as an overlay line where the
0150 catalog reports one, and the RSE-wide usage (every account) as a
0151 second overlay line, unticked by default. Under files counting the
0152 account's file count, with the RSE's file count as the unticked
0153 line. The fill fraction and the quota left are on the card and in
0154 hover, not curves. The record carries the account usage from the
0155 pass of 2026-09-05 afternoon (read as `eicprod` through the agent's
0156 proxy, STORAGE.md RSE tier); before that only the RSE-wide usage.
0157
0158 **Scope-level families**, after the RSE sections, one family per
0159 target campaign where the record is per campaign:
0160
0161 - *Disk copies* — single-copy and two-or-more-copy files, stacked.
0162 - *Catalog quality* — unattached files and files without the event
0163 count the registration contract requires, per campaign.
0164 - *Datasets* — open, partial-anywhere, quiet-open and stalled dataset
0165 counts per campaign.
0166 - *Latency medians* — job end to registration, registration to
0167 availability, first to second copy, in hours, per campaign, plotted
0168 at the pass stamp as the interval's assessment. Kinds the pass has
0169 not yet observed are absent.
0170 - *Arrived* — the campaign's arrival counters as per-bin flows.
0171
0172 **Consequences**: the jobs that failed at storage, as an event-flow
0173 strip beneath the panels with the terminal-state chips of the Errors
0174 view. Two stacked members from the error-state component's entries:
0175 the jobs whose payload exit code is 78, the run script's coded exit
0176 for the output upload-and-register step
0177 ([EPICPROD_OPS.md](https://github.com/BNLNPPS/swf-epicprod/blob/main/docs/EPICPROD_OPS.md)),
0178 whatever component the pilot labelled them with, and the data-management
0179 (`ddm`) component's errors. The exit code is the population-wide
0180 channel of [ERROR_ATTRIBUTION.md](ERROR_ATTRIBUTION.md): the pilot's
0181 own label puts most upload and registration failures under pilot 1305
0182 beside unrelated launch failures, and only the exit code separates
0183 them. Entries recorded before the exit code joined the record
0184 (2026-09-06) carry the `ddm` member alone. The error entries carry no
0185 RSE, so the strip is scope-level, once; the attribution of a failure
0186 to its destination RSE is not recorded and is not shown. The strip's
0187 bins are twice the page's ladder rung, so a sparse week still draws
0188 as bars. The strip plots both measures down the page: the count of
0189 jobs, then the core-hours those jobs held before failing, from the
0190 error record's held field ([SNAPPER_ERRORS.md](SNAPPER_ERRORS.md),
0191 Wasted resources), each with an integrated panel beneath it summing
0192 its bins from the left edge of the window, the two members stacked,
0193 so the window's totals and their split read directly.
0194
0195 State curves hold their last recorded value to the present: the record
0196 is four-hourly and a quiet pass affirms the state unchanged, so the last
0197 pass's gauges are the state until the next pass; flows stay per-bin.
0198 Units on every panel title; house state colors where a state is
0199 drawn (available blue, copying the warning color, unavailable and
0200 bad the failure color); campaign and root members take the
0201 palette. Counter-flow bins come from the window's round ladder on the
0202 ET-midnight grid, as the Site completions panel draws them.
0203
0204 **The cut.** A click is a time cut. For each shown RSE the card
0205 renders the RSE's standing at that instant, docked beneath the RSE's
0206 own panels as the Site view docks its queue slice:
0207
0208 - the interval basis once: the pass that produced the state, its
0209 mode, and the interval it covers;
0210 - the verdict chips for the RSE with the threshold each names, in
0211 the warning color where crossed;
0212 - inventory by replica state, files and bytes, with the change
0213 against the previous snap;
0214 - datasets: total, complete, partial, empty, unavailable;
0215 - the copying backlog: files and bytes, ages, the count over the
0216 threshold;
0217 - ghosts: files and bytes, by state, the oldest age, the mean ghost
0218 size against the mean first copy arrived at the RSE (the size
0219 fingerprint of a large-file timeout), and the reading of the states
0220 (a copying ghost is an upload that never completed, an unavailable
0221 ghost a replica lost after arrival), linking to the Storage
0222 exceptions page filtered to the RSE;
0223 - rule locks by state, the oldest stuck age, rules expiring within
0224 thirty days;
0225 - capacity: the account's usage and files, the RSE-wide usage and
0226 files beside them, the limit, the quota left and the fill fraction
0227 against the account's usage;
0228 - the flow since the window's left edge, differenced from the
0229 counters at the basis snap: first copies, replicas, transfers
0230 completed, ghosts appeared.
0231
0232 After the RSE sections the card renders the scope section once. It
0233 opens with the capacity table across every recorded RSE at the cut
0234 instant, the rows of `rucio account limit list eicprod` with the
0235 record's additions: RSE, type, usage, limit, quota left, fill
0236 percent, files, and the time of the usage record. Then per target
0237 campaign the files and bytes, disk copies, dataset state, latencies and the flow since the window start; then
0238 the exception heads the component carries, ghosts, stuck rules and
0239 stalled datasets, each dataset a link to its DID page, with the
0240 overflow counts and a link to the Storage exceptions page for the
0241 full lists. Every swatch is the curve's color, as on every card.
0242
0243 **Thresholds** — the stuck, stalled and single-copy ages — are the
0244 pass's SysConfig keys (`storage_copying_stuck_hours`,
0245 `storage_stalled_hours`, `storage_single_copy_warn_days`), present at
0246 their defaults; the card marks a crossed threshold in the warning
0247 color and names the key.
0248
0249 ## Retrieval
0250
0251 The view's products ride the Snapper retrieval surface unchanged:
0252 `snapper_series` and the REST series endpoint serve the focus
0253 view's series exactly as the page builds and caches it, and the
0254 component's state at any instant answers through `snapper_state_at`
0255 and `snapper_changes_between`. The exception listings are the
0256 `epicprod_storage` tool and its REST counterpart (STORAGE.md,
0257 Retrieval).
0258
0259 ## Record additions requested from the pass
0260
0261 The view is designed to the projection as published. STORAGE.md
0262 names four quantities the projection does not yet carry (the account
0263 usage per RSE, asked for the same day, is recorded since 2026-09-05);
0264 the families that need them are added when the pass records them:
0265
0266 - ghosts by root per RSE, for the ghost panel under the root grouping;
0267 - ghosts per target campaign, for the catalog-quality family;
0268 - jobs finished per campaign, for the arrival yield family (files
0269 arrived over jobs finished);
0270 - the stage-out map, first copies landed per compute site, for the
0271 stage-out matrix.
0272
0273 ## Implementation notes
0274
0275 - swf-monitor `monitor_app/snapper_providers.py`: curve extraction
0276 from the storage component under the `sto` prefixes (`sto`, a
0277 two-letter code for the quantity and panel kind, the RSE or campaign
0278 as the second segment, the member last; campaign segments carry
0279 hyphens for dots), the labels and colors, the families resolved per
0280 render from the record's RSE and campaign inventories, the Storage
0281 focus view declaration with its two selector axes and the per-option
0282 activity curve, and the storage card. The component card
0283 registration and the focus-view tuple gain the storage entries. The
0284 scope-level campaign families ride a `Campaign totals` option
0285 declared `pin: 'last'` (snapper-ai INTEGRATION.md), so they render
0286 after the ranked RSE sections and never as idle. The small
0287 secondary panels (copying age, ghost flow, rule locks, catalog
0288 quality, datasets, latency) start closed behind their rotators.
0289 - `monitor_app/templates/monitor_app/_snapper_cards.html`: the
0290 `storage` card kind, the RSE sections keyed for docking.
0291 - The focus series cache TTL rule gains the storage key class
0292 (live, 90 s) beside the task and platform classes; the series cache
0293 version bumps with the new curve vocabulary (snapper-ai
0294 `_focus_cache_key`).
0295 - [SNAPPER.md](SNAPPER.md) lists the storage maintainer among the
0296 component maintainers; this document joins the doc index.
0297 - Order of delivery, each stage usable on its own: the curve
0298 extraction, families and focus view, which plot from the first
0299 published snap; the cut card; the consequences strip; the families
0300 awaiting record additions, after the pass records them.
0301
0302 ## Related
0303
0304 - swf-epicprod
0305 [STORAGE.md](https://github.com/BNLNPPS/swf-epicprod/blob/main/docs/STORAGE.md)
0306 — the storage record: the pass, the component, the retrieval
0307 surface, the Storage exceptions page.
0308 - [SNAPPER.md](SNAPPER.md) — Snapper operations in SWF;
0309 [SNAPPER_PLATFORM.md](SNAPPER_PLATFORM.md) and
0310 [SNAPPER_ERRORS.md](SNAPPER_ERRORS.md) — the sibling focus views
0311 and the error-state component whose events the consequences strip
0312 reuses.
0313 - snapper-ai
0314 [DESIGN.md](https://github.com/BNLNPPS/snapper-ai/blob/main/docs/DESIGN.md),
0315 [INTEGRATION.md](https://github.com/BNLNPPS/snapper-ai/blob/main/docs/INTEGRATION.md),
0316 [TIME_HISTORY_UI.md](https://github.com/BNLNPPS/snapper-ai/blob/main/docs/TIME_HISTORY_UI.md)
0317 — the contract, the provider seam, and the display laws.