Adds method tracing helper#670
Conversation
ce9216e to
1527948
Compare
1527948 to
a7f615d
Compare
marcotc
left a comment
There was a problem hiding this comment.
Thank you for this PR @ronan-mch, I really liked your approach to prepend a module for tracing, instead of simply overriding and wrapping the existing method.
It's very cool that the user can declare the methods they want to trace even before they are actually declared.
I left a few comments, but it looks great overall.
|
Also, so much has changed since you last rebased, you might want to update your branch with master too. |
fbd7131 to
bbb811b
Compare
ea01c5e to
30ae527
Compare
30ae527 to
57379d0
Compare
Co-authored-by: Benjamin Quorning <[email protected]>
57379d0 to
d6a145d
Compare
|
@marcotc - is this mergeable? |
|
I'll take a look at this, see if we can merge it. |
@delner - any update on this? |
|
Sorry haven't had the chance yet. Will try to make some time. |
There was a problem hiding this comment.
I think this is a great start for a very useful feature! I have two basic areas where I suggest we might want to change:
- Minimizing the footprint (number of modules) we leave on the classes we patch
- A minor change to the API for user simplicity (remove
self)
Feel free to check out my comments and let me know what you think!
| # | ||
| # class Foo | ||
| # extend Datadog::MethodTracing | ||
| # trace_methods(self, :method1, :method2) |
There was a problem hiding this comment.
Should extending this require you to pass self? Seems redundant. I think it would be better if self was implied here. Might require implementing some kind of helper module via def self.extended.
| methods.each { |m| trace_method(klass, m) } | ||
| end | ||
|
|
||
| def trace_class_methods(klass, *methods) |
There was a problem hiding this comment.
I think it'd be a good idea to add some more robust comments above the def line here for each of these functions, that explain how these functions are used and what they produce.
| end | ||
|
|
||
| def trace_method(klass, method) | ||
| metric = "#{klass}##{method}" |
There was a problem hiding this comment.
Minor, but if this is only used once, would it be simpler to just merge this into line 33? Over declaring the variable? Or there a scope issue where this helps side-step local variables dropping out of scope when defining Module#new?
| end | ||
|
|
||
| def trace_class_methods(klass, *methods) | ||
| methods.each { |m| trace_class_method(klass, m) } |
There was a problem hiding this comment.
This implementation might be problematic when done in bulk if I'm tracing dozens of functions. If I'm understanding it correctly, it would create and prepend a module per function, no?
I think it would be worthwhile making sure all the traced methods end up in one prepended module instead of many.
There are a number of strategies you could employ, but I think the challenge with how the current API is designed is that the user invokes trace_methods and trace_class_methods separately, such that each is an atomic operation which would needfully create a module per invocation.
If you're willing to change the API a little bit, you could consider employing a builder pattern instead, in which you build each in transaction before committing the result. e.g this could look like:
def MyClass
extend Datadog::MethodTracing
datadog_tracing do
trace_methods :foo, :bar
trace_class_methods :baz
end
endThis is just the first idea that came to mind, so there might be a better/simpler way which would still allow us to avoid adding multiple modules. Let me know your thoughts!
|
Closing as I'm no longer working in a company that uses Datadog. |
|
Thanks for the contribution and food for thought! We definitely will reference this PR and discussion in the future, and I wish you well in your new endeavour :) |
|
Thank you! I'm ashamed to admit that I'd forgotten all about this PR until I reviewed my open PRs recently... |
🤣 yeah, definitely can relate on this one! |
This PR adds a new module to
ddtrace.MethodTracingallows developers to quickly add tracing to their classes without muddying up their code with trace blocks.Example usage