Personal tools

Jul 20, 2010

Aggregate zope munin graphs

Filed Under:

Munin with munin.zope is a handy tool if you want to monitor your Zope instance. But it starts to be annoying when you have too many zeoclients and too many projects on one server. Using munin aggregate functionality you can create nice, human readable graphs reusing your existing data.

With the newest version of munin.zope you have 4 different plugins:

  • ZServer threads
  • ZODB activity
  • Zope cache parameters
  • Zope memory usage

When you start using it in production environment you can end like this:

 

Munin
 

Using aggregation you can end like this:

Munin aggregation

What it does? It takes data from multiple zeoclients (in this case every project from A-E have 4 zeoclients) and renders only total amount per project.
Here is munin.conf which does this trick:

[Server1;projectA]
  address 127.0.0.1
[Server1;projectB]
  address 127.0.0.2
[Server1;projectC]
  address 127.0.0.3
[Server1;projectD]
  address 127.0.0.4
[Server1;projectE]
  address 127.0.0.5

[Server1;Aggregated]
  update no
  total_memory.update no
  total_memory.graph_category Zope
  total_memory.graph_title Aggregated Zope memory
  total_memory.graph_order \
    projectA \
    projectB \
    projectC \
    projectD \
    projectE

  total_memory.projectA.sum \
    projectA:projecta_zopememory_instance_1.VmSize \
    projectA:projecta_zopememory_instance_2.VmSize \
    projectA:projecta_zopememory_instance_3.VmSize \
    projectA:projecta_zopememory_instance_4.VmSize
  total_memory.projectA.label project A

  total_memory.projectB.sum \
    projectB:projectb_zopememory_instance_1.VmSize \
    projectB:projectb_zopememory_instance_2.VmSize \
    projectB:projectb_zopememory_instance_3.VmSize \
    projectB:projectb_zopememory_instance_4.VmSize
  total_memory.projectB.label project B

  total_memory.projectC.sum \
    projectC:projectc_zopememory_instance_1.VmSize \
    projectC:projectc_zopememory_instance_2.VmSize \
    projectC:projectc_zopememory_instance_3.VmSize \
    projectC:projectc_zopememory_instance_4.VmSize
  total_memory.projectC.label project C

  total_memory.projectD.sum \
    projectD:projectd_zopememory_instance_1.VmSize \
    projectD:projectd_zopememory_instance_2.VmSize \
    projectD:projectd_zopememory_instance_3.VmSize \
    projectD:projectd_zopememory_instance_4.VmSize
  total_memory.projectD.label project D

  total_memory.projectE.sum \
    projectE:projecte_zopememory_instance_1.VmSize \
    projectE:projecte_zopememory_instance_2.VmSize \
    projectE:projecte_zopememory_instance_3.VmSize \
    projectE:projecte_zopememory_instance_4.VmSize
  total_memory.projectE.label project E

 

For more information please check:
http://munin-monitoring.org/wiki/aggregate_examples
http://munin-monitoring.org/wiki/PercentGraphHowto
http://munin-monitoring.org/wiki/stack_examples

Jul 19, 2010

Amberjack e Windmill: un matrimonio d'amore

Filed Under:

Il successo di Amberjack e la conferma della sua inclusione nei futuri rilasci di Plone continuano a riempirci di soddisfazione. Per non riposare sugli allori, abbiamo organizzato un matrimonio che promette di generare grandi benefici per tutta la comunità Plone.

Come abbiamo sempre cercato di fare, ci siamo spinti oltre alla semplice creazione di un'opportunità, impegnandoci a supportare chi desidera sfruttarla. Nel caso di Amberjack, ultimamente ci siamo impegnati per agevolare al massimo la creazione interattiva di tutorial, eliminando la necessità di scrivere codice sorgente. Come nel mondo reale, per insegnare un'azione deve bastare saperla eseguire, senza farsi carico di tecnicismi. Ecco perchè abbiamo pensato di integrare in Amberjack un registratore interattivo di tutorial.

Costruire su Amberjack

Abbiamo concepito e realizzato Amberjack, un sistema efficace e intimamente legato a Plone per generare tutorial sul CMS e su qualsiasi prodotto Plone, per consentire, a chi sviluppa nuovi prodotti Plone, di offrire il massimo supporto a coloro che useranno tali prodotti, aumentandone il gradimento e consentendo a tutti di utilizzarli al meglio. Questo livello di supporto si riverbera in positivo sull'intera comunità e sull' immagine pubblica di Plone.

Tuttavia, generare un tutorial Amberjack, fino a ieri, era un'attività piuttosto lenta, che richiedeva una certa dimestichezza con il linguaggio Python e con la programmazione a basso livello. Tali abilità non sono necessariamente presenti in chi, ad esempio negli Enti Pubblici, si occupa di formazione e comunque di supporto agli Utenti. Capita così che prodotti sviluppati all'interno degli Enti, con una partecipazione più o meno limitata delle Aziende, non abbiano ancora beneficiato di Amberjack.

Windmill e Amberjack, un matrimonio di interesse... per tutti!

Come potrete capire dal video che precede, per non inventare l'acqua calda, siamo ricorsi a Windmill (http://www.getwindmill.com/), prodotto libero ben noto a chi, come noi, pratica il test driven development. Windmill si basa su uno strumento installabile lato Client e integrato con Python, e su una serie di servizi Web  (acceduti via proxy tramite chiamate javascript remote) che centralizzano alcuni dei processi di generazione dei test, ad esempio il loro salvataggio su un file di idoneo formato.

E' così nato collective.amberjack.windmill, prodotto aggiuntivo che installa un'istanza Windmill sul sito Plone, e ne sostituisce alcune delle librerie con versioni specifiche per Amberjack. Ne nasce un "registratore di azioni" che, anzichè essere asservito alla creazione di casi di test, genera un tutorial esemplificativo, completo di ogni fase, dalla login alla logout. Ai formati nativi di Windmill, Python e Javascript, è stata aggiunta la possibilità di salvare queste registrazioni nel formato nativo di Amberjack, rendendo la loro creazione molto più rapida, semplice e immediata.

Prodotti Plone autoesplicativi

Il tutorial può, indifferentemente, essere creato su una istanza Plone locale o direttamente sul sito di produzione, passando l'URL come parametro sulla linea di comando al momento dell'avvio di Windmill. A prescindere dall'istanza Plone utilizzata per la generazione del tutorial, esso può agevolmente essere ricontestualizzato su un server differente grazie al supporto agli URL relativi. Il file zip generato da Windmill viene caricato sul sito di produzione tramite un'apposita funzionalità di upload.

A questo punto, non manca niente: Amberjack e Windmill, sposi felici, annunciano la nascita del loro pargolo, un Plone veramente autoesplicativo, che starà a tutti noi fare crescere nel modo migliore.

Jul 14, 2010

New collective.navigationtoggle release: integration with any theme (I hope)

The new release only fixed a small bug, but also add some better integration with Plone themes. What if fun: a bug inside Sunburst theme was the demonstration that the approach is good!

I already talked about the features of collective.navigationtoggle in previous post, but the new release helped me to be sure of one thing: the unobtrusive approach chosen was good.

The new version also add some refactoring and support for other themes than the classic Plone one. Plone 4 is coming... we must live with this and luckily the products migration has begun.

What is more difficult, after years the default theme is changed (for what I remember, the default theme you all know is with us from Plone 2.0... maybe some changes was done to it at Plone 2.1, but the core never changed). All products that act on Plone UI must check also the new Sunburst theme.

Going back to navigationtoggle, I choosed an approach that was "use existing Plone navigation element to know how to render new ones".

For the new release I only empowered some existings feature, like also generate CSS classes for new element on the navigation.

Why? In Plone 3 navigation main node is like this:

<li class="navTreeItem visualNoMarker">
      <div>
        <a title="..." class="state-... navTreeFolderish" href="...">
            <img width="16" height="16" alt="..." src="...">
            <span>Foo</span>
        </a>
    </div>
   ...
</li>

And Sunburst is like this:

<li class="navTreeItem visualNoMarker">
        <a title="" class="state-... navTreeFolderish contenttype-..." href="...">
            <img height="16" width="16" alt="Folder" src="...">
            <span>Foo</span>
        </a>
   ...
</li>

Apart some node difference (no more containing DIV) the new theme also rely on a contenttype-xxx class.

What is funny (and what make me say "thanks navigationtoggle") is an unwanted behavior of the current Sunburst theme. A bug that double the content type icon: one given from the IMG tag and another ones from CSS, thanks to the new class.

I'm not interested in this bug (Irene says that probably it has been already fixed), but using navigationtoggle with this bugged version of Sunburst... also make the bug applyed to elements navigation nodes generated by our script!

This (uncommonly) is good as respect the original idea: the original theme use doubled icons?! Is not a problem of navigationtoggle, so do it!

Jul 13, 2010

Evil Javascript... use strip() or trim()?

Filed Under:

I hate doing the same error all the time! One time again: how to obtain a cross browser method for Javascript to remove leading and trailing whitespaces inside strings?

Every time I make the same stupid error! So, let's make quickly, a guide for obtaining this behavior.

The trim() function works only on Firefox and maybe other browsers, but not on IE.

In my experience the stript() function instead works better, both on Firefox and IE.

So what is the problem? That every time I forget to use this last one, and I use again trim instead of stript...

There is a solution for my lazy brain? Well... I use very often (AKA "always") jQuery for our projects, so... please Luca... from now just use jQuery.trim().

I feel better! No more error from now...

...

... until next time.

Jul 08, 2010

Scripted CSS Injection (or whatever better name you can find for this technique)

While trying to close a request for one of our customer for obtaining a random image portlet I tested an alternative way to deliver CSS. Using Javascript.

When Web pages load and run things

Let's start with CSS. Browsers load HTML source from the Web. Inside the page you will find resources that are CSS file. Immediately the resource is loaded and the rules inside are applied to your HTML.

Now switch to Javascript resources. For Javascript... it's the same. The Javascript code is executed as soon as it is found in the page...

...but for this reason, when we need to act using Javascript on an already loaded DOM, we rely onto Javascript events.

We read immediately the code, but the execution is postponed later, when the page is fully loaded.

As the use of jQuery became standard for those tasks (especially in Plone) we always use something like this:

jq(document).ready(function() {
    // do something
});

When this lead to problems

Although we have really no choice, there are some cases where this "postpone things" is not perfect: when we need to apply (using Javascript) CSS classes on page elements at page load time.

But we can't avoid making those actions when page is loaded.

If we don't rely on onload event, we have no ready DOM to traverse. So we can't load and change a DOM node if the page is not fully loaded (even if we put the Javascript script after the HTML that define the node).

<html>
<body>
    <div id="foo">Hello world</div>
    <script type="text/javascript">
    <!--
        var foo = document.getElementById("foo");
        alert(foo.innerHTML);
    // -->
    </script>
</body>
</html>

The code above is bad, even if you are using or not jQuery... So we really need to wait for the moment when DOM is ready. You can't act of the page DOM before it is fully loaded.

However: what is the problem applying CSS style when the DOM is loaded?

The nasty effect can be a visual flip.

The page in the browser show the DOM node with the original CSS style, then after some time (that can be not so brief sometimes if the page is full of elements and heavy scripts) the Javascript engine run your code, and the node is changed: your new CSS class or your new scripted style is applied.

<html>
<head>
    <style type="text/css">
    #foo {
        background-color: red;
    }
    </style>
    <script type="text/javascript">
    <!--
        window.onload = function() {
            ... MANY OTHER EXPENSIVE OPERATIONS
            var foo = document.getElementById("foo");
            alert(foo.innerHTML);
        }
    // -->
    </script>
</head>
<body>
    <div id="foo">Hello world</div>
    ... A LOT OF MANY AND MANY HTML NODES
    <script type="text/javscript">
    <!--
        var foo = document.getElementById("foo");
        alert(foo.innerHTML);
    // -->
    </script>
</body>
</html>

A practical example

A customer ask us to develop a Plone portlet that:

  • show some random images when the page is load
  • works behind a reverse proxy (Varnish)
  • works with Javascript disabled (accessibility and graceful degradation)

Step 1

Varnish is caching all our resource, images and also HTML for every page. We can't (and don't want) change this.
How to cache everything but some little images inside a portlet?

The idea is to use Javascript  for performing AJAX request for this portlet and obtain a structure of data. The cache of this kind of request can be avoided easily.

Step 2

So we are able to load an HTML for the portlet without images then, when the DOM is ready, we can populate the portlet waiting for the AJAX call to the server. For some time the visitor see and empty portlet that magically begin load images. The effect is pleasant (at least... it's not annoying).

But we can't!
The portlet must work also with disabled Javascript... So we must load random images also when the page is loaded.

NB: if the visitor use a browser with Javascript disabled, we can only give him some random pre-loaded images, but we can't prevent Varnish cache of the whole page. Reloading the same page will show him the same images for some minutes. This is acceptable for us (and for the customer!).

Step 3

The final result is to load the first "static" images in the portlet itself, then use Javascript as described at step 1: changing those images with new ones obtained from AJAX call.

This lead to the ugly visual flip effect I talked above.

I can't explain why (this is not my work), but see an empty section that is filled after a little delay is not ugly... instead seeing a set of images that suddenly change to other is... bothersome!

Step 4?

Ok, so we can simply load static images hidden by some CSS class, then using Javascript we can show them only after the AJAX call and...
Opss!

But in this way we don't see any image when Javascript is disabled!

Ok... step 4 aborted.

Scripted CSS Injection

The perfect world is the one where the step 4 is performed, but only with Javascript enabled.

I need a CSS that is loaded early like all other CSS in the page (so its style is applied immediately to the page) but only when Javascript is enabled.

I found a way to do this, but surfing the web I was not able to find other example like this one. So I called this approach Scripted CSS Injection (SCI)... maybe someone can point me to other original name or example?

However... how this works? Simply generating the additional CSS... with Javascript!
For this we use the standard window.write Javascript API. The window.write command is used commonly to write HTML inside windows (is more common to use it in popup windows for generating the contained HTML from scratch).

The additional Javascript is load in the page head section and it doesn't wait for DOM load. The one in our product is only one line:

document.write('<style type="text/css">.hideFlag img {display: none}</style>');

As I said at the beginning, Javascript is interpreted as CSS, so immediately when found in the page.
The browser will add to HTML the style node immediatly.

What is nice of SCI approach is obvious: a browser with no Javascript support can't add the CSS rule to the page!

Fairytale gone well

This technique finally lead us to a portlet that:

  • will show cached images if without Javascript support, but images are still random (chosen server side and changed with some delay)
  • will show random (and not cachable) images client side if Javascript is enabled
  • No ugly visual flip effects. With Javascript enabled static images are loaded hidden, then new dynamic ones are taken from the server and show. Thanks to SCI approach.

For more info, check the code of auslfe.portlet.multimedia.

Document Actions