Project

General

Profile

Actions

Feature #21923

open

DTrace USDT probe Ruby method arguments and return value

Feature #21923: DTrace USDT probe Ruby method arguments and return value

Added by jacobcarlborg (Jacob Carlborg) about 6 hours ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:124869]

Description

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

No data to display

Actions

Also available in: PDF Atom