<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Oct 8, 2013 at 9:44 AM, Thomas Maddox <span dir="ltr"><<a href="mailto:thomas.maddox@rackspace.com" target="_blank">thomas.maddox@rackspace.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">



<div style="font-size:14px;font-family:Calibri,sans-serif;word-wrap:break-word"><div><div class="h5">
<span>
<div>
<div>On 10/7/13 3:49 PM, "Doug Hellmann" <<a href="mailto:doug.hellmann@dreamhost.com" target="_blank">doug.hellmann@dreamhost.com</a>> wrote:</div>
</div>
<div><br>
</div>
<blockquote style="BORDER-LEFT:#b5c4df 5 solid;PADDING:0 0 0 5;MARGIN:0 0 0 5">
<div>
<div>
<div dir="ltr"><br>
<div class="gmail_extra"><br>
<br>
<div class="gmail_quote">On Mon, Oct 7, 2013 at 4:23 PM, Thomas Maddox <span dir="ltr">
<<a href="mailto:thomas.maddox@rackspace.com" target="_blank">thomas.maddox@rackspace.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div style="font-size:14px;font-family:Calibri,sans-serif;word-wrap:break-word">
<div>
<div><span>
<div>
<div>On 10/7/13 1:55 PM, "Doug Hellmann" <<a href="mailto:doug.hellmann@dreamhost.com" target="_blank">doug.hellmann@dreamhost.com</a>> wrote:</div>
</div>
<div><br>
</div>
<blockquote style="BORDER-LEFT:#b5c4df 5 solid;PADDING:0 0 0 5;MARGIN:0 0 0 5">
<div>
<div>
<div dir="ltr"><br>
<div class="gmail_extra"><br>
<br>
<div class="gmail_quote">On Mon, Oct 7, 2013 at 1:44 PM, Thomas Maddox <span dir="ltr">
<<a href="mailto:thomas.maddox@rackspace.com" target="_blank">thomas.maddox@rackspace.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div>
<div>On 10/3/13 4:09 PM, "Thomas Maddox" <<a href="mailto:thomas.maddox@RACKSPACE.COM" target="_blank">thomas.maddox@RACKSPACE.COM</a>> wrote:<br>
<br>
>On 10/3/13 8:53 AM, "Julien Danjou" <<a href="mailto:julien@danjou.info" target="_blank">julien@danjou.info</a>> wrote:<br>
><br>
>>On Thu, Oct 03 2013, Thomas Maddox wrote:<br>
>><br>
>>> Interesting point, Doug and Julien. I'm thinking out loud, but if we<br>
>>>wanted<br>
>>> to use pipeline.yaml, we could have an 'enabled' attribute for each<br>
>>> pipeline?<br>
>><br>
>>That would be an option, for sure. But just removing all of them should<br>
>>also work.<br>
>><br>
>>> I'm curious, does the pipeline dictate whether its resulting<br>
>>> sample is stored, or if no pipeline is configured, will it just store<br>
>>>the<br>
>>> sample according to the plugins in */notifications.py? I will test this<br>
>>>out.<br>
>><br>
>>If there's no pipeline, there's no sample, so nothing's stored.<br>
>><br>
>>> For additional context, the intent of the feature is to allow a<br>
>>>deployer<br>
>>> more flexibility. Like, say we wanted to only enable storing<br>
>>>white-listed<br>
>>> event traits and using trigger pipelines (to come) for notification<br>
>>>based<br>
>>> alerting/monitoring?<br>
>><br>
>>This is already supported by the pipeline as you can list the meters you<br>
>>want or not.<br>
><br>
>I poked around a bunch today; yep, you're right - we can just drop samples<br>
>on the floor by negating all meters in pipeline.yaml. I didn't have much<br>
>luck just removing all pipeline definitions or using a blank one (it<br>
>puked, and anything other than negating all samples felt too hacky to be<br>
>viable with trusted behavior).<br>
><br>
>I had my semantics and understanding of the workflow from the collector to<br>
>the pipeline to the dispatcher all muddled and was set straight today. =]<br>
>I will think on this some more.<br>
><br>
>I was also made aware of some additional Stevedore functionality, like<br>
>NamedExtensionManager, that should allow us to completely enable/disable<br>
>any handlers we don't want to load and the pipelines with just config<br>
>changes, and easily (thanks, Dragon!).<br>
><br>
>I really appreciate the time you all take to help us less experienced<br>
>developers learn on a daily basis! =]<br>
<br>
</div>
</div>
I tried two approaches from this:<br>
<br>
1. Using NamedExtensionManager and passing in an empty list of names, I<br>
get the same RuntimeError[1]<br>
2. Using EnabledExtensionManager (my preference since the use case for<br>
disabling is lesser than enabling) and passing in a black list check, with<br>
which I received the same Runtime error when an empty list of extensions<br>
was the result.<br>
<br>
I was thinking that, with the white-list/black-list capability of [Named,<br>
Enabled]ExtensionManager, it would behave more like an iterator. If the<br>
manager didn't load any Extensions, then it would just no op on operations<br>
on said extensions it owns and the application would carry on as always.<br>
<br>
Is this something that we could change in Stevedore? I wanted to get your<br>
thoughts before opening an issue there, in case this was intended behavior<br>
for some benefit I'm not aware of.<br>
</blockquote>
<div><br>
</div>
<div>The exception is intended to prevent the app from failing silently if it cannot load any plugins for some reason, but </div>
<div>stevedore should throw a different exception for the "could not load any plugins" and "I was told not to use any plugins and then told to do some work" cases.</div>
</div>
</div>
</div>
</div>
</div>
</blockquote>
</span>
<div><br>
</div>
</div>
</div>
<div>Thanks, Doug!</div>
<div><br>
</div>
<div>I poked around a bit more. This is being raised in the map function: <a href="https://github.com/dreamhost/stevedore/blob/master/stevedore/extension.py#L135-L137" target="_blank">https://github.com/dreamhost/stevedore/blob/master/stevedore/extension.py#L135-L137</a>,
 not at load time. I see a separate try/except block for a failure to load, it looks like: <a href="https://github.com/dreamhost/stevedore/blob/master/stevedore/extension.py#L85-L97" target="_blank">https://github.com/dreamhost/stevedore/blob/master/stevedore/extension.py#L85-L97</a>.
 Is that what you're referring to?</div>
</div>
</blockquote>
<div><br>
</div>
<div>The exception is raised when the manager is used, because the manager might have been created as a module or application global object in a place where the traceback wouldn't have been logged properly.</div>
</div>
</div>
</div>
</div>
</div>
</blockquote>
</span>
<div><br>
</div>
</div></div><div>I don't understand. Why wouldn't it have been logged properly when it fails in the _load_plugins(…) method? Due to implementor's code, Stevedore code, or some other reason(s) that I'm missing?</div>
</div></blockquote><div><br></div><div>If the manager is instantiated before logging is configured that log call won't do anything (or might do the wrong thing).</div><div><br></div><div>Stevedore is trying to prevent an app from failing to start if some or all of the extensions don't load, but then complain noisily later when the extensions are actually *used*. The trade-off for protecting against those cases is what you're running into -- sometimes it is OK to not load or invoke any plugins. But stevedore does not know when that is OK, so it is left up to the caller to either catch the exception and ignore it or perform some sort of check explicitly before calling the manager.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="font-size:14px;font-family:Calibri,sans-serif;word-wrap:break-word"><div class="im"><span><blockquote style="BORDER-LEFT:#b5c4df 5 solid;PADDING:0 0 0 5;MARGIN:0 0 0 5">
<div><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="font-size:14px;font-family:Calibri,sans-serif;word-wrap:break-word">
<div><span><blockquote style="BORDER-LEFT:#b5c4df 5 solid;PADDING:0 0 0 5;MARGIN:0 0 0 5"><div><div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">
<div>In this particular case, though, the thing calling the extension manager knows what the pipeline configuration is, and could just skip the call if there are no publishers in the pipeline.</div>
</div>
</div>
</div>
</div>
</div>
</blockquote>
</span>
<div><br>
</div>
</div>
<div>This seems like it'd have the desired end result, but then this logic would have to live in two places for the collector service - both at collector initialization as well as each time a notification is processed. If Stevedore ExtensionManager behaved
 like an iterator map, where extensions = [] and map(func, extensions) just returns None, we would handle the empty case in one place (but silently, indeed). Otherwise, We'd have to check for publishers in the init function and, since that causes no notification
 managers to load,  we also have to check for the existence of notification managers in the callback for each notification. I realize I'm speaking specifically to Ceilometer's collector service, so generally speaking, what I'm suggesting is to fall back to
 how Python handles this naturally, since Stevedore is using a map function as syntactic sugar for an iterator of available extensions; seems the simplest approach to me.</div>
</div>
</blockquote>
<div><br>
</div>
<div>If there are no publishers for any pipelines, is there any need to subscribe to the notifications at all?</div>
</div>
</div>
</div>
</div>
</div>
</blockquote>
</span>
<div><br>
</div>
</div><div>Only if we wanted to just store events that come through; no pipeline, just straight to the dispatcher with the coded traits – soon to be configurable.</div></div></blockquote><div><br></div><div>Ah, right, OK.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="font-size:14px;font-family:Calibri,sans-serif;word-wrap:break-word"><div class="im">
<div><br>
</div>
<span>
<blockquote style="BORDER-LEFT:#b5c4df 5 solid;PADDING:0 0 0 5;MARGIN:0 0 0 5">
<div>
<div>
<div dir="ltr">
<div class="gmail_extra">
<div class="gmail_quote">
<div> </div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div style="font-size:14px;font-family:Calibri,sans-serif;word-wrap:break-word">
<div><br>
</div>
<div>Another suggestion (thanks, Dragon!), is we could just subclass the ExtensionManager for a different way of handling the various iterator operations?</div>
</div>
</blockquote>
<div><br>
</div>
<div>You could just loop over the manager, too. It already exposes the extensions as an iterable.</div>
</div>
</div>
</div>
</div>
</div>
</blockquote>
</span>
<div><br>
</div>
</div><div>Yep, good point. I will change it to this for my next patchset. I suppose I was really trying to use the built in functionality for applying a function to all extensions the manager had. =P</div></div></blockquote>
<div><br></div><div>And you still could. Just catch the exception and decide whether it's really an error.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div style="font-size:14px;font-family:Calibri,sans-serif;word-wrap:break-word"><div class="im"><span><blockquote style="BORDER-LEFT:#b5c4df 5 solid;PADDING:0 0 0 5;MARGIN:0 0 0 5"><div><div><div dir="ltr"><div class="gmail_extra">
<div class="gmail_quote">
<div>That mode does not report the error where the app thinks it needs to load some plugins but cannot, so you would have to add an explicit check for that somewhere to replace the one built into stevedore's map() method now.</div>

</div>
</div>
</div>
</div>
</div>
</blockquote>
</span>
<div><br>
</div>
</div><div>Are you referring only to subclassing ExtensionManager here, or doing map(func, manager.extensions) as well? Since we instantiate the manager in the collector init function, we should see a failed load there from the _load_plugins(…) try block.</div>
</div></blockquote><div><br></div><div>Iterating over the extension manager does not check whether there are any extensions loaded. If the manager contains no extensions, the loop just iterates over an empty list.</div><div>
<br></div><div>Doug</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="font-size:14px;font-family:Calibri,sans-serif;word-wrap:break-word">
<div><br>
</div>
<div>Thanks again, man!</div><span class="HOEnZb"><font color="#888888">
<div><br>
</div>
<div>- Thomas</div></font></span><div class="im">
<div><br>
</div>
<span>
<blockquote style="BORDER-LEFT:#b5c4df 5 solid;PADDING:0 0 0 5;MARGIN:0 0 0 5">
<div>
<div>
<div dir="ltr">
<div class="gmail_extra">
<div class="gmail_quote">
<div> </div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div style="font-size:14px;font-family:Calibri,sans-serif;word-wrap:break-word">
<div><br>
</div>
<div>So, now we have several viable options on the table, all of which I believe will work for our needs. More thoughts will definitely be appreciated. =]</div>
<span><font color="#888888">
<div><br>
</div>
<div>- Thomas</div>
</font></span>
<div>
<div><br>
</div>
<span>
<blockquote style="BORDER-LEFT:#b5c4df 5 solid;PADDING:0 0 0 5;MARGIN:0 0 0 5">
<div>
<div>
<div dir="ltr">
<div class="gmail_extra">
<div class="gmail_quote">
<div><br>
</div>
<div>Doug</div>
<div><br>
</div>
<div> <br>
</div>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
-Thomas<br>
<br>
[1]:'RuntimeError: No ceilometer.collector extensions found'<br>
<div><br>
<br>
><br>
>Cheers!<br>
><br>
>-Thomas<br>
><br>
>><br>
>>--<br>
>>Julien Danjou<br>
>>-- Free Software hacker - independent consultant<br>
>>-- <a href="http://julien.danjou.info" target="_blank">http://julien.danjou.info</a><br>
>><br>
><br>
><br>
><br>
</div>
<div>
<div>>_______________________________________________<br>
>OpenStack-dev mailing list<br>
><a href="mailto:OpenStack-dev@lists.openstack.org" target="_blank">OpenStack-dev@lists.openstack.org</a><br>
><a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" target="_blank">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a><br>
><br>
<br>
<br>
<br>
_______________________________________________<br>
OpenStack-dev mailing list<br>
<a href="mailto:OpenStack-dev@lists.openstack.org" target="_blank">OpenStack-dev@lists.openstack.org</a><br>
<a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" target="_blank">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a><br>
</div>
</div>
</blockquote>
</div>
<br>
</div>
</div>
</div>
</div>
</blockquote>
</span>
<div><br>
</div>
<div><br>
</div>
</div>
</div>
<br>
_______________________________________________<br>
OpenStack-dev mailing list<br>
<a href="mailto:OpenStack-dev@lists.openstack.org" target="_blank">OpenStack-dev@lists.openstack.org</a><br>
<a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" target="_blank">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a><br>
<br>
</blockquote>
</div>
<br>
</div>
</div>
</div>
</div>
</blockquote>
</span>
<div><br>
</div>
<div><br>
</div>
</div></div>

<br>_______________________________________________<br>
OpenStack-dev mailing list<br>
<a href="mailto:OpenStack-dev@lists.openstack.org">OpenStack-dev@lists.openstack.org</a><br>
<a href="http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev" target="_blank">http://lists.openstack.org/cgi-bin/mailman/listinfo/openstack-dev</a><br>
<br></blockquote></div><br></div></div>