feat(timestamp-stack): add routing timestamp instrumentation - #1
Draft
YuanYuYuan wants to merge 20 commits into
Draft
feat(timestamp-stack): add routing timestamp instrumentation#1YuanYuYuan wants to merge 20 commits into
YuanYuYuan wants to merge 20 commits into
Conversation
|
PR missing one of the required labels: {'bug', 'ci', 'new feature', 'dependencies', 'api-sync', 'breaking-change', 'documentation', 'enhancement', 'internal'} |
9 tasks
YuanYuYuan
force-pushed
the
feat/routing-timestamps
branch
from
June 2, 2026 08:31
ccd8d94 to
133921d
Compare
|
PR missing one of the required labels: {'bug', 'documentation', 'ci', 'api-sync', 'dependencies', 'internal', 'breaking-change', 'enhancement', 'new feature'} |
|
PR missing one of the required labels: {'ci', 'api-sync', 'breaking-change', 'bug', 'documentation', 'enhancement', 'dependencies', 'internal', 'new feature'} |
* Add scripts and CI workflows to build debian package * fix: remove arch-specific glibc version from deb description * fix: add argument validation and include dist-info in deb package * fix: guard against multiple wheels matching glob in build-debian job * fix: use array for dist-info lookup and enable nullglob for wheel glob * fix: keep RECORD in dist-info and derive versioned libc6 dep from wheel filename * fix: add INSTALLER marker and quote version in workflow * fix: use eclipse-zenoh/ci debian publication workflow * fix: zip deb artifact before upload for publish-crates-debian compatibility
…-zenoh#735) Co-authored-by: eclipse-zenoh-bot <eclipse-zenoh-bot@users.noreply.github.com>
…-zenoh#737) Co-authored-by: eclipse-zenoh-bot <eclipse-zenoh-bot@users.noreply.github.com>
* Add TimestampStack API * Add timestamp stack callback to Session API * Update zenoh git ref * Fix formatting * Fix clippy warning * Apply review comments * Add missing @Property to stubs * Apply upstream API changes * Fix file formatting
…lipse-zenoh#738) This reverts commit 28c33ab.
- src/timestamp_stack.rs: InterceptionPoint, TsStackContext, TimestampInstrumentation, TimestampStackRecord, TimestampStack, py_to_session_ts_callback - src/lib.rs: module registered, types exported - src/sample.rs, query.rs: timestamp_stack() getters on Sample, Reply, ReplyError - src/session.rs, pubsub.rs: timestamp_instrumentation / timestamp_callback kwargs - zenoh/__init__.pyi: stubs for all new types and kwargs - examples/z_timestamp_instrumentation.py: end-to-end usage example - tests/test_timestamp_stack.py: 10 integration tests
Temporary: will be reverted to upstream eclipse-zenoh/zenoh before the final PR once the Rust core PR is merged.
…strumentationTimestamp enum
…eplies inherit query stack
PublisherBuilder has no timestamp_instrumentation setter. Pass it per-put via publisher.put(timestamp_instrumentation=...) instead.
- session.delete, publisher.delete: add timestamp_instrumentation kwarg - Querier.get: add timestamp_instrumentation kwarg - Query: expose timestamp_stack getter - AdvancedPublisher.put/delete: wire timestamp_instrumentation - lib.rs: export TimestampInstrumentationBuilder - timestamp_stack.rs: add #[getter] to point and is_custom so Python accesses them as properties (r.point, r.is_custom) not methods
- __init__.pyi: add class bodies for InterceptionPoint, TsStackContext, TimestampInstrumentationBuilder, TimestampInstrumentation, TimestampStackRecord, TimestampStack, SessionTimestampCallback alias - __init__.pyi: add timestamp_stack property to Sample, ReplyError, Query, Reply - __init__.pyi: add timestamp_instrumentation to Publisher.delete, Session.delete, and all 3 Querier.get overloads - ext.pyi: add timestamp_instrumentation to AdvancedPublisher.put/delete; import TimestampInstrumentation - example: fix declare_publisher incorrectly passing timestamp_instrumentation (no setter on PublisherBuilder); move instrumentation to pub.put calls - tests: add 4 new tests covering delete instrumentation, Query.timestamp_stack, and Querier.get instrumentation
Addresses OlivierHecart review comment on eclipse-zenoh/zenoh#2620: the name TsStackContext ties the callback context to the timestamp-stack implementation. TimestampContext is more generic and less coupled to the wire extension name. The interception_point field is retained — it is necessary for callbacks that want to stamp different values at Send vs Route vs Receive.
YuanYuYuan
force-pushed
the
feat/routing-timestamps
branch
from
June 23, 2026 07:56
ea470cc to
8414c42
Compare
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.
Summary
Python bindings for opt-in timestamp instrumentation for measuring end-to-end message latency in Zenoh. Messages carry a
TsStackwire extension that accumulatesInterceptionrecords at Send, Route, and Receive points along a message's path.Entirely
feature = "unstable"-gated. Zero overhead on uninstrumented messages.Sister PRs
API Design
All new types are importable directly from
zenoh:Configuring instrumentation
Returns a
TimestampInstrumentationobject. RaisesZErrorif all flags areFalse.Session-level custom clock
Registered once at
zenoh.opentime; applied to every instrumented message on that session:Returning
b""(empty bytes) skips stamping at that point. When no callback is registered, Zenoh uses a lazily-initialized UHLC clock.Attaching instrumentation
timestamp_instrumentation=is accepted as a keyword argument on all write operations:Note:
timestamp_instrumentationis not available onsession.declare_publisher. The RustPublisherBuilderhas no setter for it — instrumentation is always specified per operation.Pass
Noneto suppress instrumentation on a specific call even when a session default would otherwise apply.Reading timestamps
sample.timestamp_stackisNonewhen the message was not instrumented:Records are in wire order: Send first, Receive last, one or more Route records in between (one per routing hop).
The same
.timestamp_stackproperty is available onReplyError,Reply, andQuery:InterceptionPoint
UNKNOWNexists for forward compatibility — the Rust enum is#[non_exhaustive].Changes
New module:
src/timestamp_stack.rsInterceptionPoint— Send / Route / Receive / Unknown with forward-compatibility catch-all;.pointand.is_customexposed as#[getter]propertiesTsStackContext— context passed to a custom clock callback (zid,whatami,interception_point)TimestampInstrumentation— keyword-only constructor,is_instrumented(point)queryTimestampStackRecord—.point,.is_custom,.timestamp(),.as_timestamp()TimestampStack—.instrumentation,.recordspy_to_session_ts_callback— bridges a Python callable toArc<dyn Fn(TsStackContext) -> Vec<u8> + Send + Sync>Query.timestamp_stackgettersrc/session.rsupdatedSession.put()—timestamp_instrumentation=kwargSession.delete()—timestamp_instrumentation=kwargSession.get()—timestamp_instrumentation=kwargSession.open()—timestamp_callback=kwargsrc/query.rsupdatedQuery.reply()—timestamp_instrumentation=kwargQuery.reply_err()—timestamp_instrumentation=kwargsrc/pubsub.rsupdatedPublisher.put()—timestamp_instrumentation=kwarg (per-put override)Publisher.delete()—timestamp_instrumentation=kwarg (per-delete override)src/ext.rsupdatedAdvancedPublisher.put()—timestamp_instrumentation=kwargAdvancedPublisher.delete()—timestamp_instrumentation=kwargzenoh/__init__.pyiandzenoh/ext.pyistubs updatedFull class bodies for
InterceptionPoint,TsStackContext,TimestampInstrumentationBuilder,TimestampInstrumentation,TimestampStackRecord,TimestampStack, andSessionTimestampCallback. Alltimestamp_instrumentation=kwargs typed across every write operation.timestamp_stackproperty typed onSample,ReplyError,Reply, andQuery.Tests and examples
tests/test_timestamp_stack.py— 14 integration tests covering put/subscribe, publisher per-put/delete override, session delete, querier get, query/reply paths, custom callback,ReplyErrorpropagation, andQuery.timestamp_stackexamples/z_timestamp_instrumentation.py— three scenarios: put/subscribe, publisher with per-put override, and session-level custom callbackBreaking Changes
None. All new APIs are behind
unstablefeature.