ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:124869] [Ruby Feature#21923] DTrace USDT probe Ruby method arguments and return value
@ 2026-02-23 12:43 jacobcarlborg (Jacob Carlborg) via ruby-core
  0 siblings, 0 replies; only message in thread
From: jacobcarlborg (Jacob Carlborg) via ruby-core @ 2026-02-23 12:43 UTC (permalink / raw)
  To: ruby-core; +Cc: jacobcarlborg (Jacob Carlborg)

Issue #21923 has been reported by jacobcarlborg (Jacob Carlborg).

----------------------------------------
Feature #21923: DTrace USDT probe Ruby method arguments and return value
https://bugs.ruby-lang.org/issues/21923

* Author: jacobcarlborg (Jacob Carlborg)
* Status: Open
----------------------------------------
I'm interested in improving the DTrace USDT probes in Ruby. I would like to expose the Ruby method arguments and return value to the DTrace probes `(c)method-entry` and `(c)method-return`. This would be done by adding a fifth argument to the DTrace probes. For `method-entry` this would be the Ruby arguments the Ruby method is called with and for `method-return` it would be the Ruby return value the Ruby method returned.

My idea is to serialize the arguments as a JSON array and pass that as a C string, containing the JSON data, to the USDT probes. On the DTrace side, there's a `json` function available that can be used to extract parts of the JSON structure using a simple query string, example: `json(copyinstr(arg4), "success.foo.bar[1].baz")`. Because the serialization can fail, the top level JSON member would be `success` or `error` indicating if the serialization was successful or not. Using JSON to pass data to a DTrace USDT probe has precedence in the form of a Rust crate [1], created by one of the original DTrace authors, that uses the same approach. I have a proof of concept implementing this.

I would like to get some feedback on how to best implement this. I think the main challenge is how to implement this without any side effects. Ruby already has support for serializing to JSON, but that is implemented in a separate gem, using a C extension. The challenges I see are:

* There shouldn't be any side effects when enabling DTrace probes, therefore directly using the gem is not a good alternative. It needs to load a dynamic library and new constants will become available to the Ruby code, if this gem is used.

* The JSON serialization for DTrace needs to live in the Ruby VM and not in a separate gem. The question is then: should the JSON serialization for the gem and the DTrace probes be shared? Alternatively there could be an implementation of JSON serialization, for the gem, and a DTrace probe argument serialization, that happens to use JSON, but would be an implementation detail.

* If the JSON serialization should be shared between DTrace probes and the gem, is there a mechanism to share code between the Ruby VM and a gem without publicly exposing it, i.e. to C extensions? Or would there need to be an official JSON API that other C extensions could use?

* The current JSON implementation relies on exceptions. For DTrace, it would be better not to rely on exceptions. But I guess it would be possible to catch all exceptions.

* The current JSON implementation will, except for the `JSON` class, expose some additional constants which should not happen when using DTrace. This will introduce side effects. This should be possible to handle by slightly modifying the implementation.


* The current JSON serialization supports customizing the serialization by implementing the `to_json`/`as_json` methods. If serializing DTrace arguments with support for the `to_json`/`as_json` methods, the advantage is that this is already implemented by some third-party libraries. The disadvantage is that it could cause side effects.

* When DTrace probes are enabled and serializing the DTrace probe arguments and some Ruby methods are called, it would be best if those weren't traced. Can a global variable be used to check if the Ruby VM already is currently serializing DTrace probe arguments? Or is an atomic or thread-local variable necessary? Or is there a better alternative to do this?

[1] https://github.com/oxidecomputer/usdt




-- 
https://bugs.ruby-lang.org/
______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-02-23 12:43 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-23 12:43 [ruby-core:124869] [Ruby Feature#21923] DTrace USDT probe Ruby method arguments and return value jacobcarlborg (Jacob Carlborg) via ruby-core

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).