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.

Reply via email to