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

Aberta
#601 1 comentário 0 reações 0 responsáveis Ver no GitHub

Mantenedores costumam responder em até 1 dia

Ninguém assumiu esta issue ainda.

Avaliação

Dificuldade
4/5
Tempo estimado
3-5 dias
Facilidade para iniciantes
55/100
Tipo de issue
Funcionalidade
Clareza
Claramente especificada
Status de atividade
Ativa
Stack de tecnologia
java

Direção de pesquisa

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.

Escrita pelo modelo de indexação a partir do texto da issue.

Descrição

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)
Linguagem predominante
Java
Estrelas
3
Forks
2
Merge médio
9h 47min
PRs com merge (30d)
128

Preparar o ambiente

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de dfa1/vortex-java

Todas as issues de dfa1/vortex-java

Issues semelhantes

Mais issues de Java

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.