Repository navigation
The log said what the spill cost and what the vacuum cost, and the store kept the sentence: two parser families lift bytes and run figures into V130 columns of pg_log_events, and autovacuum health shows per-table run cost beside the catalog (#3602, #3603) - #3664
Merged
Merged
Conversation
…ough the whitespace-stripping JSON helper
This was referenced Sep 18, 2026
erikdarlingdata
added a commit
that referenced
this pull request
Sep 19, 2026
…spliced once Fifty-nine PRs merged to dev today across the coordinator's lanes and the wave-2 worker's; each lane returned its entry to a buffer instead of touching this file, so that fifty-plus PRs did not each rebase the same twenty lines. This is the one splice. Every entry is one line (the archiver's compact() and the pins read them that way); riders fold into their parent's entry (#3599 under #3590, #3619 under #3611, #3623 under #3616, #3640 under #3633; #3617 test-only and #3661 re-cut as #3666 carry none); #3657's entry is in because it MERGED to dev - the twin to main is what is still pending. [Unreleased] gains a `### Added` above `### Fixed` (Keep-a-Changelog order) for the six new capabilities: per-user theme colours (#3606 / #3577 arm B), routed alert families (#3668 / #3598), the PostgreSQL logging audit tool (#3643 / #3607), the service-side wait sampler (#3645 / #3604), and the log-event classifier with its temp-file / autovacuum parser families (#3646 / #3601, #3664 / #3602 #3603). The other forty-eight are honesty fixes to existing surfaces and append to `### Fixed` after the wave-1 bullets, in PR-number order. Thirty-six reference definitions added for the issues the new entries cite and the index did not yet define; the [Unreleased] group is one ascending run again, which moves [#3557] into its slot (the one deleted line). Nothing under ## [3.8.0] or older is touched; the archive script was not run. One editorial touch: the #3585 entry ended in a dangling "Darling" and now reads "Darling only." (the tool exists only in the Darling MCP host). tools/changelog/changelog_archive.py verify: all PASS (1420 bold entries, floor 1,329; 1,358 distinct refs resolve; CRLF throughout; 356,539 bytes under the 750 KiB ceiling). ChangelogIndexAndArchiveTests: 5/5 pass via a net10.0 harness.
erikdarlingdata
added a commit
that referenced
this pull request
Sep 19, 2026
…spliced once (#3672) Fifty-nine PRs merged to dev today across the coordinator's lanes and the wave-2 worker's; each lane returned its entry to a buffer instead of touching this file, so that fifty-plus PRs did not each rebase the same twenty lines. This is the one splice. Every entry is one line (the archiver's compact() and the pins read them that way); riders fold into their parent's entry (#3599 under #3590, #3619 under #3611, #3623 under #3616, #3640 under #3633; #3617 test-only and #3661 re-cut as #3666 carry none); #3657's entry is in because it MERGED to dev - the twin to main is what is still pending. [Unreleased] gains a `### Added` above `### Fixed` (Keep-a-Changelog order) for the six new capabilities: per-user theme colours (#3606 / #3577 arm B), routed alert families (#3668 / #3598), the PostgreSQL logging audit tool (#3643 / #3607), the service-side wait sampler (#3645 / #3604), and the log-event classifier with its temp-file / autovacuum parser families (#3646 / #3601, #3664 / #3602 #3603). The other forty-eight are honesty fixes to existing surfaces and append to `### Fixed` after the wave-1 bullets, in PR-number order. Thirty-six reference definitions added for the issues the new entries cite and the index did not yet define; the [Unreleased] group is one ascending run again, which moves [#3557] into its slot (the one deleted line). Nothing under ## [3.8.0] or older is touched; the archive script was not run. One editorial touch: the #3585 entry ended in a dangling "Darling" and now reads "Darling only." (the tool exists only in the Darling MCP host). tools/changelog/changelog_archive.py verify: all PASS (1420 bold entries, floor 1,329; 1,358 distinct refs resolve; CRLF throughout; 356,539 bytes under the 750 KiB ceiling). ChangelogIndexAndArchiveTests: 5/5 pass via a net10.0 harness.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The log said what the spill cost and what the vacuum cost; the store kept the sentence and threw away the number
#3646 landed the classified log-event pipeline (V129) and stored
log_temp_filesandlog_autovacuum_min_durationlines as recognised-only events: the family was set, the prose was redacted and kept, and nothing was lifted. Sofamily = temp_filereturned "temporary file: path …, size 4294967296" as text, andfamily = autovacuumreturned a fourteen-line report as onemessage— the figures a DBA needs to sum, rank or alert on were inside a string. This PR adds the two parser families the pipeline was built to receive, and the one rung that gives them columns: V130.The mechanism
Two classes implementing
IPgLogFamilyParser, registered inPgLogEventClassifier.DefaultParsersahead ofPgRecognisedFamilyParserexactly as the seam's doc prescribed, so they take their families' lines out of the generic arm. Their numbers travel on the SAME row as thirteen nullable columns (PgLogEventMetrics, passed throughPgLogEvent.From(...)— still the one constructor path, still the one redaction site), not as sibling tables.PgRecognisedFamilyParsernow recognisescheckpointalone;PgLogFamilies.Parsedis five andRecognisedOnlyone. No stored row is relabelled: a V129-eratemp_fileorautovacuumrow keeps its family and has null metrics.PgTempFileEventParser(Per-event temp spill attribution from log_temp_files — counters know a database spilled, not which execution spilled 4 GB at 03:07 #3602) — accepts on^temporary file:(the recogniser Ingest target PostgreSQL logs as telemetry — errors, spills, autovacuum runs, and connection churn are invisible between counter samples #3601 carried), liftssize N→bytes. The path stays inmessage(it names a pgsql_tmp file, not a relation, and is redacted like any message); theSTATEMENT:companion is fingerprinted and never stored — the pipeline's existing rule, unchanged. Two files from one statement (a multi-batch sort, a parallel hash) are two events with one fingerprint, which is the join back topg_stat_statements'temp_blks_*and the per-execution grain the issue asked for.PgAutovacuumEventParser(Autovacuum per-run cost from log_autovacuum_min_duration — the health view says whether it ran, not what it cost #3603) — accepts on the header (automatic [aggressive ]vacuum[ to prevent wraparound] of table "db.schema.table"/automatic analyze of table "…"), splits the relation ONCE on the first dot (database →database_name,schema.table→relation_name), setsis_analyze, then matches each clause independently by keyword so a clause a version does not write leaves its columns null rather than failing the line.elapsed: N.NN s→duration_ms. All parsing isInvariantCulture(PostgreSQL prints through its ownsnprintf; there is no locale in the numbers), pinned under de-DE.The line formats, per version, read from the source (not remembered)
REL_16_STABLE,REL_17_STABLE— identical)REL_18_STABLE)automatic vacuum of table "d.s.t": index scans: N/automatic analyze of table "d.s.t"pages: N removed, N remain, N scanned (P% of total)…, N eagerly scannedappendedtuples: N removed, N remain, N are dead but not yet removablebuffer usage: N hits, N misses, N dirtiedN hits, N reads, N dirtied—missesrenamedreadsbuffer_misses, dirtiedWAL usage: N records, N full page images, N bytes— vacuum only…, N buffers fullappended, and written on analyze lines for the first timesystem usage: CPU: user: N.NN s, system: N.NN s, elapsed: N.NN s(pg_rusage.c, unchanged)duration_mstemporary file: path "%s", size %lu(fd.c, unchanged since 8.3)PostgreSQL 15's one-line autoanalyze (
automatic analyze of table "…" system usage: CPU: …) still yields relation and duration. Not lifted, deliberately:index scans,removable cutoff,relfrozenxid,frozen,visibility map, the per-index lines,I/O timings, the avg read/write rates (derived, and0.000on any sub-second run),full page images,buffers full,delay time.The rung — V130
pg-log-event-metricsNullable, no DEFAULT, no backfill (the V80/V81/V101/V114/V121/V127/V128 shape; catalog-only on a compressed hypertable, segmentby unchanged). Added in two places, the V101 rule: V129's CREATE TABLE text gains the same thirteen columns after
raw_line_hashfor the fresh population —PgSchemaGeneratorTests.EveryPostgresRung_IsIdenticalToTheGeneratedSchemarequires that rung to BE the generator's output, and the generator emits the collector's currentPayloadColumns— and V130's ALTER carries the store that built the seventeen-column table first. No index (the reads still enter throughidx_pg_log_events_time; a(server_id, relation_name, collection_time)index is the same separate rung as V129's family index).StorageVersion 130; the Viewer probe gains sentinel 105 (information_schema.columns … 'pg_log_events' … 'wal_bytes') and thehasPgLogEventMetricstop arm; V129's top-rung claims hand off toPgLogEventMetricsRungTests.Why columns and not the sibling tables #3601 planned
A
pg_temp_filesand apg_autovacuum_runstable would each have needed its own identity column and its own dedupe of the same overlapping tail, its own retention, hypertable, compression policy and CI worker slot, and a join onraw_line_hashfor every read that wanted the event beside its numbers. Thirteen nullable columns cost none of that: the row already has the identity, the dedupe, the fingerprint and the retention, and "everything at 03:07" and "what did the 03:07 spill cost" are one query.familysays which columns can be non-null. What this trades away — per-family retention and per-family indexing — are the separate rungs V129's doc already reserves. Census unchanged: 28 PG collectors, 70 tables / 71 hypertables, 73/84 workers, 152 tools; the README pins did not move.The reads
get_pg_log_eventspublishes the numbers as nested objects present only where the line carried them:temp_file: { bytes, mb }on a spill,autovacuum: { relation_name, kind, duration_ms, pages_*, tuples_*, buffer_*, wal_*, read_mb, written_mb }on a run,nullotherwise — a connection event does not carry thirteen nulls. Inside the run object a null is KEPT and means "this line had no such clause" (an analyze has no pages/tuples; 16/17 print no WAL on an analyze). The description says all of this, names the spill-storm rule as a custom-alert source later, not this tool, and stops saying the two families "gain structured tables in later work".get_pg_autovacuum_healthgainsrecent_runsper table — aggregates over the newest 25 runs in the window (runs_counted,history_capped,vacuum_runs/analyze_runs, total/max/avgduration_ms,total_tuples_removedwithruns_with_tuplesbecause sums skip nulls,total_read_mb/total_written_mb,total_wal_bytes) and the newest 5 runs in the same per-run shape the events read uses (one spelling,AutovacuumRunShape, shared). Read through a newDarlingPgLogEventReader.GetAutovacuumRunsAsync(family = 'autovacuum' AND relation_name = ANY($4::text[]),ROW_NUMBER() … <= $5per relation, same dedupe and chunk bound as the events read). Matched on (database, relation), falling back to relation alone for a V129-era row whose database the log did not name.tables_with_run_historyandrun_history_notesay at the top how much of the page the cost half could speak for and — when none — the three reasons this read cannot tell apart. No new parameter; the history rides the tool's window and page.get_pg_logging_audit's two facets forlog_temp_files/log_autovacuum_min_durationnow say SHIPPED and name the read; the pin that required every consumer to say PLANNED asserts exactly those two flipped (load-bearing edit outside the named files — the pin's own doc said it was meant to go red when a consumer landed).Evidence
timescale/timescaledb:2.28.1-pg18, PostgreSQL 18.4,log_temp_files=0 log_autovacuum_min_duration=0 autovacuum_naptime=2s track_io_timing=on, torn down): a 50k-row table, awork_mem=64kBsort and a hash aggregate, an UPDATE/DELETE for dead tuples,1/0, a unique violation, a lock wait pastdeadlock_timeout. The self-hosted collector's shipped SQL ran on the target's own log, the classifier ran on what came back, the rows went through the collector's COPY into a store migrated to 130, and both tools read them. Classified:autovacuum=54, checkpoint=3, connection=160, error=15, lock_wait=2, temp_file=3. 0 of 54 autovacuum rows missing duration or buffers. Spills:11370496(the sort),892928+122880(the hash agg's fileset pair, ONE fingerprint) —"temp_file": { "bytes": 11370496, "mb": 10.84 }. Thepublic.ordersvacuum:duration_ms 70, pages 0/1702, tuples 10001/40000, buffers 5610/0/4, wal 5475/542577,kind: vacuum; its autoanalyzeduration_ms 60, buffers 1985/1/0, wal 8/2347with pages/tuples null.get_pg_autovacuum_healthon a seeded catalog row for the same table:recent_runs { runs_counted 2, vacuum_runs 1, analyze_runs 1, total_duration_ms 130, total_wal_bytes 544924, … }.DARLING_TEST_PG/DARLING_TEST_PG_LOG_TARGET):PgLogEventMetricsLivePostgresTests(information_schema agrees withPayloadColumnscolumn-for-column after migration; six fixture events through COPY; both reads with the lifted values; per-relation cap;recent_runson the table with runs andnullon the one without), bothPgLogEventsLivePostgresTests(extended:bytes/mbon the spill page, relation/pages/tuples andduration_ms: nullon the autovacuum page, nobyteskey on the lock-wait page),DarlingPgReadSqlParsesLiveTests(the newAutovacuumRunsSqlPREPAREs on 18),DarlingPgAutovacuumVerdictLiveTests— 6/6.Darling.Tests-named harness, WindowsDesktop entry dropped): 737 tests across the touched pin classes —PgLogEventMetricsParserTests(16/17/18 vacuum + analyze fixtures with the real clause texts; wraparound variant; PG15 one-liner; de-DE culture; two spills with a two-line STATEMENT and the literal-never-stored sweep; every Ingest target PostgreSQL logs as telemetry — errors, spills, autovacuum runs, and connection churn are invisible between counter samples #3601 header shape accepted by the structured parser and refused by the recognised arm; the seam's oneFrom; metrics members ↔ columns name-for-name),PgLogEventMetricsRungTests(top rung; thirteen ADD COLUMN, no DEFAULT/NOT NULL/UPDATE/INDEX/VIEW; each column's type rendered by the generator's own mapping and present in BOTH texts in the collector's order; probe ordinal 105 and arm order; census unchanged; runbook + README), the updatedPgLogEventsPipelineTests/PgLogEventsRungTests(handoff),PgSchemaGeneratorTests,DeltaFamilyIntervalCompletionRungTests,DarlingMcpPgLoggingAuditToolsTests,DarlingPgAutovacuumReaderTests,CiClusterWorkerSizingTests,ConsumedTimestampFrameDisciplineTests,McpPageContractTests,McpToolTypeRegistrationTests,ServerPageTabsTests,ViewerPostgresTabsTests,MigrationLadderPins,MigrationDataMovingRungCensusPins,ReadmeDerivedCountPinTests,StoreCopyPhaseTests,StorageCommandTimeoutTests,LiveCleanupConversionRatchetTests,LivePostgresCollectionHygieneTestsand the rest of the PostgreSQL's log is read by a classifier now, not by two regexes: errors, connections and lock waits land in pg_log_events off the same tail and RDS API the deadlock and plan readers use, redacted with the plan parser's own patterns (#3601) #3646 harness — the only failures the threeD:\darling\…Windows-path assertions. Every touched project builds-c Release -p:EnableWindowsTargeting=truewith 0 warnings.What this does NOT do
recent_runsis the evidence the health read's recommendations can consume next; nothing here judges it.read_mb/written_mbassume the default 8 kBblock_size; the block counts beside them are exact.avg read/write rate,full page images,buffers full, the per-index lines and the freeze/cutoff clauses stay inmessageand are not lifted.get_pg_logging_audit(lock waits, connections, checkpoints) still say PLANNED although the pipeline ships them — the pipeline's own follow-up, pinned so the flip is deliberate.Closes #3602
Closes #3603