feat: JFR events for open, HTTP range, segment decode/encode, chunk filtering and writer back-pressure

Ouverte
#601 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

Personne n'a encore pris cette issue.

Évaluation

Difficulté
4/5
Temps estimé
3-5 jours
Accessibilité débutants
55/100
Type d'issue
Fonctionnalité
Clarté
Clairement spécifiée
Activité
Active
Stack technique
java

Piste de recherche

Start by reading the reader and writer entry points named in the issue: VortexReader.open, VortexHttpReader.open, SerializedArrayDecoder.decode, ScanIterator, and VortexWriter. Add the JFR event classes and wire them into those paths as specified, then use the named tests to check event fields, filtering counts, and back-pressure duration. Done when the event tests pass and the reference guide, how-to guide, changelog, and module map are updated.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

enhancement

Goal

Emit JDK Flight Recorder events from the reader and writer, so a JFR recording shows where a read or write spends its time (file open/mapping, HTTP range fetches, per-segment decode/encode, chunk pruning, writer back-pressure) with no extra dependency and near-zero cost when recording is off.

Events

New package core/src/main/java/io/github/dfa1/vortex/core/jfr/ (with package-info.java). Each event is a public class extending jdk.jfr.Event, annotated @Name("io.github.dfa1.vortex.X"), @Label, @Category({"Vortex", …}), @Description and @StackTrace(false). Public fields get /// docs (doclint is all); byte sizes get @DataAmount.

Class Category Fields
FileOpenedEvent I/O source, fileSize, formatVersion, segmentCount
FileMappingEvent I/O file, size
HttpRangeEvent I/O source, offset (-1 = tail), length, status (0 = no response)
SegmentDecodedEvent Decode encoding, rowCount, segmentSize
ChunkFilterEvent Filter totalChunks, chunksPruned, chunksWithoutMatch, chunksReturned, rowsReturned
SegmentEncodedEvent Encode encoding, bufferCount, encodedSize
SegmentWaitEvent Pipeline segmentsInFlight

Reader wiring

Pattern: event.begin(), set fields, commit().

  • VortexReader.open(path, registry, layoutRegistry): FileOpened spans the whole open and is committed after parse; FileMapping wraps channel.map. A failed open emits no FileOpened.
  • VortexHttpReader.open(uri, registry, layoutRegistry, client): FileOpened begins before fetchTail and is committed after the reader is built.
    • New private sendRange(req, client, uri, offset, length) wraps client.send in try/finally and always commits HttpRange, with status = 0 on failure. fetchTail calls it with offset -1 and TAIL_SIZE.bytes(); fetchRange with from and to - from + 1.
    • New package-private static String describe(URI) returning scheme://host[:port] + raw path. It drops user info, query and fragment, because presigned URLs carry credentials. Used for every source field.
  • SerializedArrayDecoder.decode: begin at the top; after registry.decode(ctx) set encoding = node.encodingId().id(), rowCount, segmentSize = segLen, then commit. Covers both readers.
  • ScanIterator:
    • New counters chunksPruned, chunksWithoutMatch, chunksReturned.
    • In hasNext(), split canPruneChunk(...) || !selectMatchingRows(...) into two branches that each count, chunkIndex++; continue.
    • Increment chunksReturned in next().
    • close() calls emitChunkFilterEvent(), a no-op when filter == null || chunks == null.

Writer wiring (VortexWriter)

  • encodeSegment: begin at the top; before returning, if (event.shouldCommit()) fill encoding from result.rootNode().encodingId().id(), bufferCount, encodedSize, then commit. Failures emit nothing.
  • drainSegments: replace pending.poll().join() with a static awaitHead(head, pending.size() + 1). It joins directly if head.isDone(); otherwise begins a SegmentWaitEvent, joins in a try, commits in the finally.
  • No change to the writer's default behavior. (The default executor runs tasks on the caller, so SegmentWait never appears there.)

Tests

Given/When/Then throughout. For events committed on other threads, assert presence and field values, never exact counts.

  • core/src/test/.../core/testing/JfrRecorderTest.java: abstract base; a RecordingStream with setReuse(false) starts in @BeforeEach; offers awaitEvents() and events(name).
  • reader VortexReaderJfrTest (fixture primitives.vortex): FileOpened and FileMapping fields; a too-small file emits no FileOpened.
  • reader VortexHttpReaderJfrTest (mocked HttpClient): tail HttpRange (offset -1, status 206); source has no credentials or query; status 0 when send throws IOException.
  • writer JfrEventsTest (uses LegacyZoneMaps.OPTIONS, same package):
    • SegmentEncoded present with non-negative sizes (a vortex.sequence segment has 0 buffers).
    • Default executor: no SegmentWait.
    • Executor sleeping 200 ms before each task: SegmentWait duration > 50 ms and segmentsInFlight > 0.
    • Chunks 1..50, 51..100, 101..150 with eq(id, 75) → totals 3/2/0/1 and 1 row.
    • Single chunk {1, 100} with eq(id, 50) → 1/0/1/0 and 0 rows.
    • Unfiltered scan emits no ChunkFilter.

Docs (same commit)

  • docs/reference.md: "JFR events" section (event table) + TOC entry.
  • docs/how-to.md: "Find where a read or write spends its time (JFR)".
  • CHANGELOG.md: ## [Unreleased] → Added.
  • AGENTS.md: core.jfr line in the module map.

Verify

  • ./mvnw test -pl core,reader,writer -am
  • ./mvnw verify -DskipTests (Javadoc lint + checkstyle)
Langage dominant
Java
Étoiles
3
Forks
2
Merge moyen
14 h 59 min
PR mergées (30 j)
137

Préparer son environnement

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de dfa1/vortex-java

Toutes les issues de dfa1/vortex-java

Issues similaires

Plus d'issues Java

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.