nano resources_fr.properties
toolb.non.empty=Opprimer lignes blanches
toolb.non.empty=Supprimer lignes vides
nano resources_fr.properties
toolb.non.empty=Opprimer lignes blanches
toolb.non.empty=Supprimer lignes vides
Maintenant que votre pivot est affiché, vous avez peut-être envie de l’exporter sous Excel pour retravailler les données.
Pour cela vous utilisez le bouton bien connu :
Sauf qu’au lieu de récupérer l’export vous êtes confronté à une erreur du style :
mai 25, 2005 12:26:18 PM org.apache.catalina.core.ApplicationContext log SEVERE: StandardWrapper.Throwable java.lang.NoClassDefFoundError: org/apache/fop/configuration/Configuration at com.tonbeller.jpivot.print.PrintServlet.init(PrintServlet.java:71) at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1173) at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:809) ../.. Caused by: java.lang.ClassNotFoundException: org.apache.fop.configuration.Configuration at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1645) at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1491) ... 14 more
cd biserver-ce/tomcat/webapps/pentaho/WEB-INF/lib/ wget https://mirrors.ibiblio.org/pub/mirrors/maven/fop/jars/fop-0.20.5.jar
Bon,
je suis pas très fier de ce que j’ai fait mais je vous relate mes erreurs et comment je suis arrivé à les résoudre pour vous éviter de faire pareil…
J’installe Mysql sur mon nouveau serveur dédié, monstre de calcul (8 cpu « machin » bridge) et d’espace disque ( 1To). Je configure ma base de données au format Innodb ( le format qui permet les contraintes externes, etc.); je configure les capacités de mémoire, l’espace disque temporaire;
bref, je crois avoir tout passé en revue…
Puis j’alimente ma base avec des données provenant de réseaux sociaux – autant dire que la volumétrie est importante.
Au bout de quelques semaines, je m’aperçoit que le fichier ibdata qui est dans le répertoire de données grossit mais ne rétrécit jamais , y compris lorsque je supprime des tables de plusieurs centaines de GigaOctets.
Finalement j’atteins la taille limite de mon disque et là je suis mal surtout que je dois produire des rapports d’analyse pour avant hier.
C’est là que je m’aperçoit que par défaut à l’installation, MySQL et configuré pour gérer toutes les tables et leurs index dans un seul et même fichier – le fameux « ibdata » et que ce fichier est voué a grossir – jamais à réduire !
Il aurait fallu utiliser l’option « innodb_file_per_table » dans le fichier de configuration (my.cnf) pour que chaque table utilise son propre fichier de stockage des données et d’index.
Ok, je l’ai pas fait; mais alors comment faire pour rattraper ma bourde ?
Oui, je dirais qu’il faut y aller « à la barbare » c’est à dire faire une réinstallation des bases!
Première chose, faire une sauvegarde complète des bases :
mysqldump -R -q -p --all-databases > 20120402_mysql_all.sql
Ensuite, arrêter MySQL et supprimer tous les fichiers du répertoire des bases de données( moi, je fais un move sur un support de sauvegarde):
service mysql stop mv /home/mysql/* /home/backup/mysql_old_dir
Redémarrer Mysql :
service mysql start
Enfin, restaurer les tables :
mysql -u root < 20120402_mysql_all.sql
N’hésitez pas à commenter ce post si vous avez été dans le même cas !
Ma bête de course est en train de pleurer à cause d’un manque d’espace disque…
Mais que se passe-t’il donc?
Bon ok, lorsque j’ai fait l’installation d’Ubuntu 64 bits, j’ai paramétré la partition racine à 9 Gb, ce qui est un peu limite.
En utilisant Baobab, le programme de visualisation d’espace disque , je me suis aperçu que le fautif était MongoDB et plus précisément son système de journalisation:
Voici donc le moyen pour éviter de consommer de l’espace disque inutilement :
sudo service mongodb stop
# Enable journaling, https://www.mongodb.org/display/DOCS/Journaling
journal=false
sudo service mongodb stop
Et voilà, votre partition ne va pas être inutilement remplie!
Un autre moyen est de déplacer le répertoire des données de /var/lib/mongodb vers une autre partition (exemple /home/mongodb) Pour cela éditer le fichier /etc/mongodb.conf et modifiez la ligne suivante :
# Where to store the data. dbpath=/var/lib/mongodb
en
# Where to store the data. dbpath=/home/mongodb
puis déplacer les fichiers qui étaient initialement dans /var/lib/mongodb vers le répertoire cible :
sudo cp -rv /var/lib/mongodb /home/mongodb/
Si vous aussi vous avez eu le même problème et que ce post vous a aidé, vous pouvez laisser un commentaire !
Bon, tout est dans le titre… mais, quand même, ça nécessite quelques explications et surtout des solutions de contournement.
Si vous venez, comme moi, du domaine décisionnel « non libre » ( Microsoft Essbase, etc.) , vous avez sûrement l’habitude d’utiliser les clefs de membres des dimensions pour les sélectionner directement dans les requêtes MDX.
Ok on fait un récap:
Lorsque vous faites une requête MDX, vous pouvez sélectionner un membre de dimension soit par sa valeur affichée ( en général le nom du membre), soit par la clef utilisée par le moteur OLAP. En général, la clef utilisée et une clef numérique donc plus facile à manipuler.
Un exemple, vite !!
Ok, disons que vous voulez mettre en perspective les ventes deux de vos produits phares :
La requête MDX ressemblerait à peu près à ça :
SELECT {[ProductHierarchy].[casseroles en métal argenté(c)], [ProductHierarchy].[poêles dorées à l'or fin(TM)]} on ROWS, {[Measures].[sales]} ON COLUMNS FROM [Commercial]
Jusque là tout va bien, sauf que en fait la même requête doit servir pour deux pays différents. Et pour chaque pays, le nom des produits est différent.
Plus précisément, en Angleterre les deux produits s’appellent respectivement : [silver metal pan(c)] et [gilded with fine gold pans(TM)]
Et là on a un problème: la requête précédemment crée ne fonctionne plus telle quelle à condition que les dénominations soient remplacées par leur traduction respective!
Du coup, en Angleterre la requête qui fonctionne est celle là :
SELECT {[ProductHierarchy].[silver metal pan(c)], [ProductHierarchy].[gilded with fine gold pans(TM)]} on ROWS,
{[Measures].[sales]} ON COLUMNS
FROM [Commercial]
Alors, comment faire pour que la requête MDX fonctionne correctement quelque soit le pays (et donc les traductions) ?
C’est là qu’en tant que super spécialiste de votre moteur OLAP préféré, vous allez utiliser les fonctions différentiation par la clef .
Dans notre exemple la casserole en argent a un N° d’identifiant numérique égal à 112 et la poêle en or fin le N° 113, quelque soit les langages.
On utilise le caractère & ( « et commercial » ou « ampersand » en anglais) pour utiliser la clef à la place du nom.
La requête devient alors :
SELECT {[ProductHierarchy].&[112], [ProductHierarchy].&[113]} on ROWS,
{[Measures].[sales]} ON COLUMNS
FROM [Commercial]
Ok, on met tout ça en pratique.
On crée donc la dimension ProductHierarchy dans le cube Mondrian à partir d’une table de dimension dénommée DimProduct avec deux champs ProductKey ( notre clef) et ProductName:
Le fait d’avoir rempli la propriété « column » avec le nom du champ « ProductKey » va permettre un certain nombre de choses, dont l’optimisation des requêtes SQL qui sont effectuées par le moteur de Mondrian, mais aussi la possibilité de faire notre requête sur la base de la clef ProductKey.
Vous exécutez la requête et là, patatras voilà ce que l’interpréteur de requête de Mondrian nous dit :
Mondrian Error:MDX object ‘[ProductHierarchy.New Hierarchy 0].&[113]’ not found in cube ‘Commercial’
La raison en est simple, Julian Hyde (le créateur de Mondrian ) n’a tout simplement pas prévu cette fonction dans son moteur.
Voici la preuve: un ticket a été référencé dans le gestionnaire d’incident de Mondrian sous la description :Member key treated as member name in WHERE
Arggh, voilà donc une mauvaise surprise ! Pour enfoncer le clou, ce bug a été ouvert en 2009…
Vous pourriez me dire: « tu n’as qu’à mettre le champ ProductName dans la propriété ‘column’ et on en parle plus ! ».
Oui, en effet ça marche mais :
On va donc utiliser une fonctionnalité qui ,elle, a été implémentée: les propriétés en conjonction avec les filtres.
Dans un premier temps on va créer une propriété basée sur le champ « ProductKey »:
Et enfin on va utiliser un filtre , basé sur cette propriété
SELECT {Filter([ProductHierarchy].[Product].Members,
([ProductHierarchy].CurrentMember.Properties(« key »)=113)
OR
([ProductHierarchy].CurrentMember.Properties(« key »)=111))
} ON ROWS,
{[Measures].[sales]} ON COLUMNS
FROM [Commercial]
Là -enfin-, vous pouvez utilisez cette requête, quelque soit les traductions des produits utilisées.
Si vous avez déjà été dans cette situation n’hésitez pas à commenter cet article ou à demander des précisions !
J’ai été assez désappointé par la dernière version de PDI ( Pentaho data integration) délivrée par Matt Casters en version 4.3 GA.
En effet, spoon, qui est l’interface de création des ETL, se charge en plus de 3 minutes montre en main !!!
Inacceptable dans ce monde speedé!!
Moi qui pensait que PDI était le seul truc de bien dans pentaho ( avec peut-être Mondrian) et bien j’en suis resté baba…
Et là je me suis aperçu que je n’étais pas le seul dans cette situation. Ce qui est assez déprimant c’est que le bug recensé n’est pas attribué, donc ne risque pas d’être résolu. Heureusement, Matt Casters himself , nous donne le work-around:
Miracle, spoon prend 40 secondes à charger ( ce qui est encore trop long, mais bon…) !
Par contre, du coup, toutes les fonctionnalités agiles de PDI ne sont plus disponibles (mais comme c’est du pipeau, c’est pas bien grave)
Bon par contre, Matt nous dit dans le forum qu’il travaille à la résolution de ce bug alors que le ticket en cours n’est pas attribué.
Hou, le menteur!!
Dans l’article précédent (Veewee : La creation d’une boite Vagrant), nous avons vu comment créer une machine virtuelle prête pour Vagrant.
Considérons que nous avons avons ajouter la box à l’environnement Vagrant avec la commande :
vagrant box add 'myubuntubox' 'pathto/myubuntubox.box'
vagrant init 'myubuntubox' vagrant up vagrant ssh
Dans le cas de Chef, on trouve de nombreuses recettes sur Github permettant d’installer à peu près tout, avec par exemple le repository officiel d’Opscode (https://github.com/opscode-cookbooks).
Afin de simplifier, un peu la vie de ceux qui veulent se lancer, j’ai préparer un petit projet qui vous permet de vous lancer : https://github.com/gpsnail/VagrantBox
Suivez les instructions du README pour commencer.
N’hésitez à me faire part de vos commentaires.
Le problème est très vite arrivé quand on veut déployer de nouveaux rapports sur plusieurs serveurs différents de façon automatique.
imaginons que ayez un nouveau rapport de type CDE ( kesako ?)que vous avez fabriqué sur votre serveur local.
Vous avez copié les fichiers physiques du rapports sur le serveur de production grâce à un script shell par exemple.
Si vous vous connectez sur votre console utilisateur (https://monserveur:8080/pentaho/Home), vous ne voyez pas le nouveau rapport !!
L’explication est simple, tant que vous n’avez pas rafraîchi la solution , les nouveaux fichiers ne sont pas pris en compte par le moteur Pentaho.
Sous le capot, Pentaho utilise un indexage des fichiers qu’il enregistre dans la base de données ( tables PRO_FILES et PRO_ACLS_LIST dans la base de données hibernate).
Tant que l’on a pas commandé à pentaho de rafraîchir le repository, les nouveaux objets qui ont été copiés n’ont pas été enregistrés dans l’index pentaho.
Comment on peut piloter ce rafraîchissement, par exemple par script shell ?
La seule façon que j’ai trouvé est de créer une page jsp que je vais installer dans le contexte d’exécution de pentaho.
Je vais l’appeler RefreshRepository.jsp et voici le code :
<%@ page language= »java »
import= »org.pentaho.platform.engine.core.system.PentahoSystem,
org.pentaho.platform.api.engine.IPentahoSession,
org.pentaho.platform.web.jsp.messages.Messages,
org.pentaho.platform.api.engine.IUITemplater,
org.pentaho.platform.web.http.WebTemplateHelper,
org.pentaho.platform.util.messages.LocaleHelper,
org.pentaho.platform.api.repository.ISolutionRepository,
org.pentaho.platform.repository.solution.dbbased.DbBasedSolutionRepository,
org.pentaho.platform.web.http.PentahoHttpSessionHelper » %>
<%
response.setCharacterEncoding(LocaleHelper.getSystemEncoding());
IPentahoSession userSession = PentahoHttpSessionHelper.getPentahoSession( request );
String content = « »;
ISolutionRepository solutionRepository = PentahoSystem.get(ISolutionRepository.class, userSession);
solutionRepository.reloadSolutionRepository(userSession, userSession.getLoggingLevel());
content = « OK refresh »;
%>
<%= content %>
biserver-ce/tomcat/webapps/pentaho/jsp/
Une fois fait, je peux maintenant piloter le refresh en faisant :
https://monserveur:8080/pentaho/RefreshRepository?userid=totologin&password=XXXX
Du coup je peux piloter le refresh par script Shell :
wget –quiet -O – « https://monserveur:8080/pentaho/RefreshRepository?userid=totologin&password=XXXX »
Il y a quelques temps j’ai dû ouvrir à des personnes externes un site de gestion d’incidents ( trac). Il se trouve que nous gérons les clients comme des contacts dans notre système openldap.
En gros un client a type a comme structure dans ldap :
dn: cn=jean Filemonpul,ou=clients,ou=Users,dc=masociete,dc=com
cn: jean Filemonpul
givenname: jeanfil
mail: jean.filemonpul@parlespieds.com
mobile: +33473000011
objectclass: inetOrgPerson
objectclass: extensibleObject
objectclass: person
objectclass: mailAccount
objectclass: top
ou: client
sn: filmonpul
uid: jfil
userpassword: {MD5}9×2+54ef34zeLOL4OneqsqsrSUgXUlsdsg==se
Par opposition, un utilisateur interne a cette structure:
dn: cn=pikki@masociete.com,ou=Users,dc=masociete,dc=com
cn: pikki@masociete.com
givenname: pikki
mail: pikki@masociete.com
mailbox: /home/vmail/masociete.com/pikki
mailenable: OK
mailuserquota: 1048576
mobile: +336XXXXXXXX
objectclass: inetOrgPerson
objectclass: extensibleObject
objectclass: person
objectclass: mailAccount
objectclass: top
ou: masociete
sn: pikki
uid: pikki
userpassword: {MD5}q09j+fqgfg4645refgzereza33454==
ldapsearch -W -x -D « cn=moimeme,dc=masociete,dc=com »
'(|(ou=masociete)(ou=client))'
qui veut dire: << cherche toutes les entrées du ldap ayant comme "ou" soit "masociete", soit "client" >> .Nickel, il me renvoie bien des entrées. Du coup, je me dis, je vais mettre ça dans mon fichier de config apache :
Require ldap-filter (|(ou=client) (ou=masociete))
katastrof, en rechargeant apache( service apache2 reload) , impossible de se connecter ni en tant que client , ni en tant qu’utilisateur.
Voici mon fichier de configuration:
ServerAdmin admin-system@masociete.com
ServerName tickets.masociete.com
DocumentRoot /var/www/tickets
Options FollowSymLinks MultiViews
AllowOverride AuthConfig
Options +SymLinksIfOwnerMatch
AllowOverride All
Order allow,deny
Allow from all
ErrorLog /var/log/apache2/trac/error.log
LogLevel warn
CustomLog /var/log/apache2/trac/access.log combined
ServerSignature On
#set up Trac handling
SetHandler mod_python
PythonHandler trac.web.modpython_frontend
PythonOption TracEnv /var/www/tickets
PythonOption TracUriRoot /
PythonPath « sys.path + [‘/var/www/tickets’] »
AuthType Basic
AuthName « LDAP auth »
AuthBasicProvider ldap
AuthLDAPUrl ldap://127.0.0.1/ou=Users,dc=masociete,dc=com?uid?sub
AuthLDAPBindDN « cn=rechercheuser,dc=masociete,dc=com »
AuthLDAPBindPassword XXXXXXX
Require ldap-filter |(ou=client) (ou=masociete)
Comme je l’abordais dans mon précédent article, l’utilisation de Vagrant pour le développement a été pour moi un gros plus et une superbe découverte.
Mais, vous allez me dire comment créer sa propre Box en effet, il est pas évident de faire confiance à celle que l’on peut trouver sur internet surtout dans le cadre d’une équipe de projet.
C’est à ce titre, que je conseille l’utilisation de Veewee (https://github.com/jedi4ever/veewee) qui permet de créer toutes sortes de Box et qui est surtout d’une simplicité d’utilisation déconcertante.
Le pré-requis pour l’utilisation de veewee est une plate-forme ruby 1.9.2 et la dernière version de VirtualBox (https://www.virtualbox.org), là, il faut impérativement installer RVM sur la machine qui va vous servir à créer votre box et cela afin d’avoir la meilleur version possible de ruby à savoir la 1.9.2p290.
Une fois, les pré-requis en place, la meilleure façon de procéder est de cloner veewee à partir de Github, le procédure d’installation est très bien faite : https://github.com/jedi4ever/veewee/blob/master/doc/installation.md
Ensuite, il y a juste à utiliser veewee (il faut se positionner à la racine du répertoire veewee) et voici la procédure à suivre pour créer une boite directement sans trop de changement :
Ce processus crée une nouvelle définition de boîte dans le répertoire veewee/definitions. Vous pouvez si vous vous en sentez le courage modifier les fichiers mais à titre d’exemple nous le ferons pas. La prochaine étape est de créer la Box :
Cette étape prend pas mal de temps à cause essentiellement des téléchargements d’images ISO nécessaire à l’installation. Vous pourrez suivre de manière simple la procédure.
Une fois, cette étape terminée, vous aurez une boite en place :
Une fois, la box créée, vous pourrez l’exporter dans une fichier « .box » à distribuer à l’ensemble de votre équipe de développement avec la commande suivante :
Nous venons de voir comment créer une Box vide, cependant, maintenant le problème se pose de la mise en place celle-ci dans un environnement réel avec les outils nécessaires comme mysql, postgres, php .etc.. Nous allons pour cela utiliser le système de « Provision » permettant à partir d’un script de mettre en place l’environnement et de l’utiliser ensuite au quotidien. Nous aborderons cela dans un prochain article en attendant, je ne saurait que trop vous conseiller de tester.