On 25/02/11 18:29, Markus Roberts wrote:
>
> There's also a 3rd thing I didn't started working on: allow the code to
> set probes dynamically (instead of statistically adding them by
> modifying puppet code). I don't know if ruby versatility can allow this,
> but I'd love to be able to instance_eval { ... add probes around a
> method ... } to a given live puppet instance/class fully dynamically
> (that would be completely crazy).
>
>
> This is in fact fairly easy to do, though you're right that it's
> completely crazy. :)
>
> Suppose we have an array x and we want to do something with it's length
> (negate it here, but presumably we'd be doing something more useful like
> recording it or something):
>
> irb(main)> x = [1,2,3]
> => [1,2,3]
> irb(main)> unless x.respond_to? :brice_wrapped_length
> irb(main)> class <<x
> irb(main)> alias brice_wrapped_length length
> irb(main)> def length
> irb(main)> -brice_wrapped_length
> irb(main)> end
> irb(main)> end
> irb(main)> end
> => nil
> irb(main)> x.length
> => -3
> irb(main)> x << :foo
> => [1, 2, 3, :foo]
> irb(main)> x.length
> => -4
>
> Note that this only affects the one object; other arrays aren't touched:
>
> irb(main)> y = [:a,:b]
> [:a,:b]
> irb(main)> y.length
> 2
>
> The unless part is important to prevent instrumenting the same object
> twice, which will cause it to hang (and eventually stack overflow). To
> remove the instrumentation, just reverse everything (if instead of
> unless, alias the other way, and then remove brice_wrapped_length).
Thanks for the example. This is quite interesting and opens the door to
a lot of strange things :)
I was thinking about allowing the user to describe probes by specifying
a puppet class and a method through an indirection to control probes
(like in "Puppet::Indirector::Indirection.find"), then I'd do something
(completely untested):
method = "find"
klass_name = "Puppet::Indirector::Indirection"
require klass_name.split('::').map { |n| n.downcase }.join('/')
klass = klass_name.split('::').inject(Puppet) { |p,c| p.const_get(c) }
klass.class_eval do
alias "instr_#{method}" method
define_method(method, *args) do
# here call to instrumentation
send("instr_#{method}", args)
ensure
# here wrap up instrumentation
end
end
Then I hope, somewhere else, someone calling Puppet::Something.find
(provided Something uses the indirector of course), then it would call
my programmatic redifinition of "find"...
This will be a funny week-end if that proves to work :)
> For production use (which I'm describing, not advocating) you'd want to
> take care that exceptions were properly handled, etc. I almost always
> wind up using ensure clauses when I do this--or rather, I would use them
> if I did do this, which I'm not actually admitting to.
:)
--
Brice Figureau
My Blog: http://www.masterzen.fr/
--
You received this message because you are subscribed to the Google Groups
"Puppet Developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/puppet-dev?hl=en.