Commit Graph
2873 Commits
Author SHA1 Message Date
moebiusbandandClaude Opus 5 d0d9d49012 feat(frontend): add display smoothing filter for metric plots
cc-lib's resamplers cannot smooth: validateFrequency bails out when the new
frequency is not coarser than the old one, and every algorithm produces an
output strictly shorter than its input. They consolidate for transport,
which is a separate job from filtering for display, and they only act at all
once a series exceeds the target point count - shorter jobs arrive raw.

Add a centered, NaN-aware moving average in the plot layer, applied after
whatever downsampling the backend performed. It preserves length and index
alignment, so the X array, the visible point count and the zoom-resampling
hook are unaffected. NaN and null samples are skipped, an all-NaN window
stays NaN so gaps keep rendering, and the window shrinks at the series edges
rather than introducing new gaps there.

The window is a user setting in data points, defaulting to 3, and is
orthogonal to the resample algorithm - it stacks on top of average
consolidation rather than replacing it. All series of a stats plot are
smoothed together, since smoothing only some would break the
min <= mid <= max invariant the plot bands rely on. Smoothing is display
only: reported statistics and job footprints come from JobMetric.Statistics
and are untouched. The uPlot cursor readout does show the smoothed value.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-27 12:18:14 +02:00
moebiusbandandClaude Opus 5 93eac532c4 feat: default to average downsampling
Average consolidation makes every plotted point the true arithmetic mean of
its interval, which is what the Ganglia-style plot appearance depends on.
LTTB deliberately keeps extremes instead, so a plot downsampled with it
cannot be read as interval means.

resolveResampleAlgo used to return an empty string when neither the user nor
the config had chosen an algorithm, and cc-lib's GetResampler maps that to
LTTB. Route every fallback through config.ResampleAlgo() and ship "average"
as the generated and example default.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-27 12:17:57 +02:00
moebiusbandandClaude Opus 5 769da61570 fix(frontend): drop dead resample trigger/resolutions config
config.ResampleConfig stopped emitting the trigger and resolutions fields,
but MetricPlot still read them. resampleResolutions and resampleMinimum
were therefore always null, which made the array-based resolution branch in
the setScale hook unreachable and the timestep !== resampleMinimum guard
always true. Keep only the policy-based branch and derive the zoom trigger
straight from targetPoints.

configs/config-large.json still carried the removed minimum-points, trigger
and resolutions keys, which DisallowUnknownFields now rejects, so starting
against it aborted. Replace them with the current keys and add a test that
loads the file, so the example configs cannot drift out of the schema
unnoticed again.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-27 12:17:34 +02:00
moebiusbandandClaude Opus 5 a5c1fdf21f fix: forward resample algorithm to metric store for running jobs
Only archived job data and internal-store node-list data honoured the
selected resample algorithm. For running jobs the algorithm was dropped:
MetricDataRepository.LoadData had no such parameter, so the memory store
fell back to an empty string, which cc-lib's GetResampler maps to LTTB.
The external store client was worse - its APIQueryRequest had no
ResampleAlgo field at all, and LoadNodeListData accepted the parameter
without using it.

Add resampleAlgo to the LoadData interface (mirroring LoadNodeListData),
forward it from metricdispatch, and set it on both stores' requests. The
field is tagged omitempty, so the wire format is unchanged when empty -
verify the deployed cc-metric-store accepts it before relying on it there.

The REST job endpoints pass a non-zero resolution and therefore do
resample, so they now request the configured default instead of an empty
string. Add config.ResampleAlgo() for that, since "" is not a neutral
value at this layer.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-27 12:17:03 +02:00
moebiusbandandClaude Opus 5 d40390061d fix: unify resample policy target-points table
The policy -> target-points mapping existed twice with different values:
internal/config (300/600/1000) fed the resampler's MinimumRequiredPoints
threshold, while internal/metricdispatch (200/500/1000) fed the requested
resolution and the frontend target point count.

Because the threshold was larger than the target, the resampler refused to
downsample series whose length fell between the two numbers, silently
dropping the resolution the backend had asked for. With the medium policy
that covered every series between 500 and 600 points.

Move the table into internal/config as the single source of truth (import
direction rules out the reverse, since metricdispatch already imports
config) and keep the 200/500/1000 values, which already drove the requested
resolution. metricdispatch.TargetPointsForPolicy now delegates to it, so
MinimumRequiredPoints equals the target and resampling happens exactly when
a series exceeds it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-27 12:16:46 +02:00
moebiusbandandClaude Opus 5 fca7b81e3d chore: apply gofumpt formatting
Pre-existing formatting drift picked up by `make fmt`. Whitespace and
comment layout only, no semantic change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-27 10:28:22 +02:00
moebiusbandandClaude Opus 5 4cfbecd818 Merge branch 'feat/565-add-metric-tooltip' into metric-store-tickets
Resolve conflicts in the generated GraphQL code by regenerating it against
the merged schema. cc-lib v2.13.0 adds Tooltip to schema.MetricConfig and
schema.GlobalMetricListItem, so gqlgen now binds the tooltip field directly
and the hand-written globalMetricListItem/metricConfig resolvers introduced
on the tooltip branch are no longer needed.

Also migrate to the cc-lib v2.13.0 metric container types, which changed
from bare maps to structs carrying array-valued metric groups:

  schema.JobData          map -> {Metrics, Groups}
  schema.ScopedJobStats   map -> {Metrics, Groups}
  job.Statistics          map -> schema.JobStatisticsSet{Metrics, Groups}

Callers index .Metrics, return the zero struct instead of nil, and
deepCopy/DecodeJobStats now also carry the Groups payload through.
archive.GetStatistics returns the full JobStatisticsSet so group
statistics survive the round trip.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-27 10:22:22 +02:00
moebiusband e59ee99474 Upgrade cc-lib. Regenerate GraphQL.
Does not compile
2026-08-27 10:08:02 +02:00
moebiusbandandClaude Opus 5 947b784ba8 fix(frontend): show PlotRenderOptions only in user settings
PlotRenderOptions was rendered both in AdminSettings.svelte and in
UserSettings.svelte. Since Config.root.svelte always renders UserSettings,
including for admins, admins saw the identical plot-render cards twice on
/config.

The admin copy was also misleading: every form in the component posts to
/frontend/configuration/, whose handler (RestAPI.updateConfiguration) always
writes per-user config via UserCfgRepo.UpdateConfig — never a global default.
On top of that, the admin-side handleSettingSubmit lacked the colorblind-mode
special case that UserSettings uses to keep PlotColorScheme in sync, so
toggling the option there did not refresh the palette preview.

Removes the component from AdminSettings.svelte along with the message,
displayMessage, handleSettingSubmit and popMessage members that existed only
to feed it. The remaining admin children manage their own messages.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-27 09:05:00 +02:00
moebiusbandandClaude Opus 5 e63cafc877 chore: remove entire.io integration
Reverts 22c442db "Enable entire integration" and drops the accompanying
.gitignore entry:

- .claude/settings.json: removes all seven "entire hooks claude-code ..."
  command hooks (PostToolUse on Task and TodoWrite, PreToolUse on Task,
  SessionEnd, SessionStart, Stop, UserPromptSubmit) and the
  Read(./.entire/metadata/**) deny rule. The file held nothing else, so it
  is deleted rather than left as an empty object.
- .entire/settings.json, .entire/.gitignore: untracked and removed.
- .gitignore: drops the now-pointless .entire entry.

.claude/settings.local.json is untouched; it carries unrelated local
permission settings.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-27 09:04:53 +02:00
moebiusband b0fb86cd4d Merge branch 'feat/74-assign-user-role-based-on-ldap-group' into metric-store-tickets 2026-08-27 08:13:48 +02:00
moebiusband 2d5d8fa20b Add large config example 2026-08-26 21:13:33 +02:00
moebiusband ac47931283 Fix session handling with oidc login route 2026-08-26 21:13:13 +02:00
Christoph Kluge d28849d8d7 fix invisible navbar due to stuck animation with certain browser settings 2026-07-28 17:37:42 +02:00
Christoph Kluge 31f7386671 limit subcluster dropdown render size, add scrollbar 2026-07-28 17:36:58 +02:00
Christoph Kluge 053c44d7b5 add tooltips to metricConfig, rendered in metricSelect, rework availability display 2026-07-28 17:36:29 +02:00
Aditya Ujeniya fddd5bd291 update: new metric store dataNotAligned issue fixed 2026-07-26 22:45:02 +02:00
Aditya Ujeniya bf65b70c02 modify(metricstore): more verbose logging to DataNonAlignedIssue 2026-07-26 20:33:19 +02:00
Aditya Ujeniya 28bd9cea68 refactor(metricstore): document prune serialization; drop dead GetSelectors leftovers 2026-07-22 13:51:49 +02:00
Aditya Ujeniya 633414d666 feat(metricstore): prune empty node levels in retention free path 2026-07-22 13:24:44 +02:00
Aditya Ujeniya 162e835cf1 feat(metricstore): add exclusion-aware free that prunes empty node levels 2026-07-22 11:18:06 +02:00
Aditya Ujeniya 7b8668b8e4 feat: fill in NaN values when buffers dont contain requested data at the start or end of the buffers 2026-07-20 13:35:31 +02:00
Aditya UjeniyaandClaude Opus 4.8 f83f8afa86 fix(metricstore): make stats read path non-mutating to avoid data race
recomputeStats() wrote statSum/statSamples/statMin/statMax/statsValid from
inside the stats() fast path, which runs under only a shared RLock via
MemoryStore.Stats -> Level.findBuffers. Two concurrent queries on the same
invalid buffer could both enter the fast path and race on those fields.

Require statsValid in the fast-path guard instead of recomputing inline;
invalid buffers now fall through to the existing point-by-point scan, which
only reads b.data. recomputeStats() is unchanged and still used by
checkpoint loadFile at single-threaded load time.

Updated stats_test.go: overwritten buffers now stay statsValid=false after a
query (documenting non-mutating reads); TestStatsMultiBufferChain and
TestStatsFastPathThenPartialTail now recompute stats after building bare
buffers so the fast-path cache fold is still covered; added
TestStatsConcurrentQueriesNoRace (race-clean under -race for both valid and
post-overwrite buffers) and TestStatsGappedChain (real inter-buffer gap
correctly excluded from Samples/Min/Max/Avg).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 11:03:16 +02:00
Aditya Ujeniya e37b2e71a6 feat(metricstore): compute buffer stats eagerly on checkpoint load 2026-07-20 10:49:24 +02:00
Aditya Ujeniya 650db33b22 docs(metricstore): fix misleading comment in stats fast-path test 2026-07-20 10:47:33 +02:00
Aditya UjeniyaandClaude Opus 4.8 9d5268a828 fix(metricstore): guard stats fast path against empty buffer
Add len(b.data) > 0 guard to prevent infinite loop when an empty linked
buffer is reachable. With the guard false, the normal path handles empty
buffers safely via the existing t < b.start || idx >= len(b.data) check.

Add regression test TestStatsFastPathThenPartialTail to pin the boundary:
three-buffer chain where earlier buffers are fully covered (fast path) and
the last buffer is partially covered (normal path).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 10:43:43 +02:00
Aditya UjeniyaandClaude Opus 4.8 9eb6d0e83e feat(metricstore): serve full-buffer stats from cached aggregate
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 10:30:42 +02:00
Aditya Ujeniya b6a9f7ed3c feat(metricstore): add recomputeStats full-scan helper 2026-07-20 10:26:30 +02:00
Aditya Ujeniya 5ff376c742 style(metricstore): gofmt stats_test comment alignment 2026-07-20 10:25:16 +02:00
Aditya Ujeniya 931a2a6e79 feat(metricstore): maintain running buffer stats on write 2026-07-20 10:22:16 +02:00
Aditya UjeniyaandClaude Opus 4.8 aa61ccb88b feat(metricstore): add running-stat fields to buffer
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 10:17:12 +02:00
Aditya Ujeniya c509a0104b change resampling policy points 2026-07-20 09:43:18 +02:00
Aditya Ujeniya 662e86b45d chore: ignore local agent and docs working directories 2026-07-08 15:45:24 +02:00
Aditya UjeniyaandClaude Fable 5 94799aca36 fix: drop unconditional force-free of buffers retained for running jobs
MemoryUsageTracker freed all buffers older than the retention cutoff on
every tick whenever the last retention pass had excluded used nodes,
regardless of memory pressure — discarding the history kept in memory
for long-running jobs. Buffers are now only reclaimed by the existing
emergency path once memory usage exceeds the configured cap. The
now-unused selectorsExcluded state is removed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 15:45:24 +02:00
Aditya UjeniyaandClaude Fable 5 dd2f5968b1 feat: pass NodeProvider to metricstore Init
Setting the provider after Init left the checkpoint restore inside Init
without job information and forced callers to pre-call InitMetrics and
SetNodeProvider in the right order. Init now receives the provider as a
parameter and injects it before the restore, so the ordering is enforced
by the signature. SetNodeProvider remains for callers that do not run
Init (tests, -cleanup-checkpoints).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 15:44:54 +02:00
Aditya UjeniyaandClaude Fable 5 ea2bfbb6aa fix: wire NodeProvider into CLI checkpoint cleanup path
The -cleanup-checkpoints CLI flag called CleanupCheckpoints without
initializing the MemoryStore singleton or setting its NodeProvider,
so it silently fell back to legacy clean-everything behavior and
could delete checkpoints for hosts with running jobs. Inject the job
repository as NodeProvider the same way runServer does, so the CLI
path also skips used hosts. Also update SetNodeProvider's doc comment,
which only mentioned Free but is now also consulted by FromCheckpoint
and CleanupCheckpoints.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 14:31:26 +02:00
Aditya Ujeniya 33a1bd3529 fix: set NodeProvider before metricstore Init so checkpoint load sees it 2026-07-08 14:18:03 +02:00
Aditya Ujeniya 58c71da0b8 feat: skip checkpoint cleanup for nodes with running jobs 2026-07-08 14:13:15 +02:00
Aditya Ujeniya 1e416a6dd0 feat: load full checkpoint history for nodes with running jobs 2026-07-08 14:05:56 +02:00
Aditya UjeniyaandClaude Fable 5 97ab828d60 feat: add isNodeUsed helper for NodeProvider lookups
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 14:01:37 +02:00
moebiusbandandClaude Opus 4.8 3474690adc feat(auth): map OIDC token roles to CC roles via configurable mapping
OIDC roles were translated by a hardcoded switch that only recognised the
literal names user/admin/manager/support (dropping api) and required the
IdP to emit exactly those names.

Add an optional auth.oidc.role-mapping (OIDC role/group claim value -> CC
role) so operators can map their own realm/client role names, including
api. The mapping is the sole source of roles: only mapped names are
honored, unmapped token roles are ignored, and users without any mapped
role receive the base "user" role. Mapping targets are validated once at
startup. Role assignment stays authoritative on every login as before.

Note: deployments relying on the IdP emitting literal CC role names must
now map them explicitly (e.g. "admin": "admin").

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 66451678484b
2026-06-19 11:28:20 +02:00
moebiusbandandClaude Opus 4.8 63a82d022b feat(auth): assign elevated LDAP roles via configurable filters
The LDAP sync only ever granted the base "user" role. Add an optional
auth.ldap.role-filters map (role -> LDAP filter) so accounts matching a
filter are granted that elevated role (admin/support/api/manager).

LDAP is authoritative for the configured roles: sync both adds and removes
them to match group membership, while roles not listed (e.g. a manually
granted manager) are preserved. A managed manager that still has assigned
projects is never stripped. With no role-filters configured behaviour is
identical to before.

Roles are reconciled during periodic sync and at login. Sync evaluates
each filter once over the whole base (one search per role, not per user)
and reconciles existing users via a single ListUsers lookup plus the new
UserRepository.UpdateRoles helper.

Closes #74

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: e38526c3259d
2026-06-19 06:36:55 +02:00
moebiusbandandClaude Opus 4.8 84841a7006 fix(deps): update Go dependencies
Bump gqlgen, aws-sdk-go-v2, go-oidc, go-sqlite3, gqlparser, go-openapi,
golang.org/x/* and other transitive dependencies to their latest patch
and minor releases.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 964ca6774882
2026-06-18 10:29:20 +02:00
moebiusbandandClaude Opus 4.8 6f1c36099b fix(web): adapt metric plots to policy-based resample config
The backend resample config changed from {trigger, resolutions[]} to a
policy/targetPoints model, but several components still spread
resampleConfig.resolutions, throwing "resolutions is not iterable" and
breaking the job list render. Default the initial resolution to null (the
backend resolves it from the configured policy; zoom overrides it) and
drop the now-obsolete resolution selector and admin display fields.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 27516ce259fd
2026-06-18 10:29:12 +02:00
moebiusbandandClaude Opus 4.8 d89f526eb2 feat(config): warn on unrecognized top-level config sections
A setting nested at the wrong level (e.g. "resampling" placed next to
"main" instead of inside it) was silently ignored. Emit a startup warning
for any top-level config section not consumed by the backend so such
misconfigurations surface instead of failing silently.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: 69d1b85c8db3
2026-06-18 10:28:59 +02:00
moebiusband ffbe171327 Merge branch 'main' into feature/526-average-resample 2026-06-18 07:17:41 +02:00
Jan EitzingerandGitHub 1bd3f25371 Merge pull request #562 from ClusterCockpit/feature/517-make-legal-links-configurable
feat(web): make footer legal links configurable
2026-06-17 18:35:25 +02:00
moebiusbandandClaude Opus 4.8 411bc9b317 feat(web): make footer legal links configurable
Add a "main.footer-links" config option so the footer Imprint and
Privacy Policy links can point at internal pages (default) or external
URLs. External http(s) targets open in a new tab; empty/unset values
fall back to the built-in /imprint and /privacy routes, keeping the
existing ./var/*.tmpl override mechanism intact.

Closes #517

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Entire-Checkpoint: c5dca72c848f
2026-06-17 17:29:50 +02:00
Jan EitzingerandGitHub 9d1efcd55d Merge pull request #561 from ClusterCockpit/feature-283-remove-env-support-alt
feat(auth): replace .env/godotenv secret handling with config-based s…
2026-06-17 15:28:40 +02:00
moebiusband 3562bfa3aa Rewording of init README 2026-06-17 15:24:13 +02:00