diff --git a/VERSIONS_HOTLINE/55142 b/VERSIONS_HOTLINE/55142
new file mode 100644
index 0000000000000000000000000000000000000000..581480c3b3c0bee4a1691d2c7427cb99d6fd0331
--- /dev/null
+++ b/VERSIONS_HOTLINE/55142
@@ -0,0 +1 @@
+ - ticket #55142 : ajout de mécanismes d'analyse du déroulement du moissonnage des ressources numériques
\ No newline at end of file
diff --git a/application/modules/admin/controllers/HarvestController.php b/application/modules/admin/controllers/HarvestController.php
index 217841aa3b4df02193745f57bcb7d7a3b7614810..3d25ef73c97b0d4203cf9f34d612d83db115a2af 100644
--- a/application/modules/admin/controllers/HarvestController.php
+++ b/application/modules/admin/controllers/HarvestController.php
@@ -231,10 +231,8 @@ class Admin_HarvestController extends ZendAfi_Controller_Action {
       return;
     }
 
-    $logger = new Zend_Log();
-    $logger->addWriter(new Zend_Log_Writer_Stream('php://output'));
+    $logger = new Class_Cata_LogVolatile();
 
-    ob_start();
     $logger->info('Début du moissonnage');
 
     $service->setLogger($logger);
@@ -243,7 +241,7 @@ class Admin_HarvestController extends ZendAfi_Controller_Action {
 
     $logger->info('Fin du moissonnage');
 
-    $this->view->log = ob_get_clean();
+    $this->view->log = implode('<br>', $logger->getLines());;
   }
 
 
diff --git a/cosmogramme/cosmozend/application/modules/cosmo/controllers/LogsController.php b/cosmogramme/cosmozend/application/modules/cosmo/controllers/LogsController.php
new file mode 100644
index 0000000000000000000000000000000000000000..c76e029af4c2a789b8287d5d1669043ee4dddfc6
--- /dev/null
+++ b/cosmogramme/cosmozend/application/modules/cosmo/controllers/LogsController.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class Cosmo_LogsController  extends ZendAfi_Controller_Action {
+  use Trait_StormFileSystem;
+
+  public function indexAction() {
+    $this->view->titre = $this->_('Journal des intégrations');
+  }
+
+
+  public function integrationAction() {
+    $this->view->titre = $this->_('Journal des intégrations du %s', $this->_getParam('day'));
+    $this->view->contents = $this->getFileSystem()->fileGetContents($this->_logPath('integration'));
+  }
+
+
+  public function debugAction() {
+    $this->view->titre = $this->_('Journal technique du %s', $this->_getParam('day'));
+    $this->view->contents = $this->getFileSystem()->fileGetContents($this->_logPath('debug'));
+  }
+
+
+  protected function _logPath($type) {
+    return Class_CosmoVar::getValueOf('log_path') . '/' . $type . '_' . $this->_getParam('day') . '.log';
+  }
+}
+?>
\ No newline at end of file
diff --git a/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/logs/debug.phtml b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/logs/debug.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..a73db3cef17c8364bbfa1284683d16f98a312834
--- /dev/null
+++ b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/logs/debug.phtml
@@ -0,0 +1,6 @@
+<h1><?php echo $this->titre ?></h1>
+<div>
+ <?php
+ echo nl2br($this->contents);
+ ?>
+</div>
diff --git a/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/logs/index.phtml b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/logs/index.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..d9c78687dee312dbffa3de880e71701a7d750194
--- /dev/null
+++ b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/logs/index.phtml
@@ -0,0 +1,2 @@
+<h1><?php echo $this->titre ?></h1>
+<?php echo $this->cosmoLogs(); ?>
diff --git a/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/logs/integration.phtml b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/logs/integration.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..8395921351c90a638ed8eb99caeb0370e1110dd6
--- /dev/null
+++ b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/logs/integration.phtml
@@ -0,0 +1,6 @@
+<h1><?php echo $this->titre ?></h1>
+<div>
+ <?php
+ echo $this->contents;
+ ?>
+</div>
diff --git a/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/run-log/by-date.phtml b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/run-log/by-date.phtml
index af66b63f09ac69a0afbb99270566632eed872084..61d08f1976432432f671d25046471bbe69934af4 100644
--- a/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/run-log/by-date.phtml
+++ b/cosmogramme/cosmozend/application/modules/cosmo/views/scripts/run-log/by-date.phtml
@@ -14,7 +14,7 @@
 	</tr>
 	<?php foreach($this->runs as $run) { ?>
 	<tr>
-		<td align="center"><?php 
+		<td align="center"><?php
 		echo $this->tagAnchor(
 			$this->url(['module' => 'cosmo',
 									'controller' => 'run-log',
@@ -26,17 +26,17 @@
 		<td align="center" style="white-space:nowrap">
 			<?php echo $this->getHumanDate($run->getTraite(), 'EEEE d MMMM yyyy');?></td>
 		<td>(<?php echo $run->getBib()->getId();?>)&nbsp;<?php echo $run->getBib()->getNomCourt();?></td>
-		<td><?php 
+		<td><?php
 				echo Class_CosmoVar::getLabelInList(
-					'type_fichier', 
+					'type_fichier',
 					$run->getProfilDonnees()->getTypeFichier())?></td>
-		<td><?php 
-				echo Class_CosmoVar::getLabelInList('import_type_operation', 
+		<td><?php
+				echo Class_CosmoVar::getLabelInList('import_type_operation',
 																						$run->getTypeOperation());?></td>
 		<td><?php echo $run->getFichier();?></td>
 		<td align="right" style="white-space:nowrap">
 			<?php echo number_format((int)$run->getFileSize()/1024, 0, '', ' ');?>&nbsp;ko
-			<?php if (0 < $run->getFileSize()) 
+			<?php if (0 < $run->getFileSize())
 			echo $this->tagAnchor(
 				$this->url(['module' => 'cosmo',
 										'controller' => 'run-log',
@@ -53,8 +53,8 @@
 	<?php } ?>
 </table>
 <br>
-<input type="button" class="bouton" value="Retour" 
-			 onclick="document.location.replace('<?php echo $this->cosmoPath->getCosmoBaseUrl(); ?>php/integre_log.php')" style="margin-left:20px">
+<input type="button" class="bouton" value="Retour"
+			 onclick="document.location.replace('<?php echo $this->url(['module' => 'cosmo', 'controller' => 'logs'], null, true); ?>')" style="margin-left:20px">
 <br>
 <br>
 </div>
diff --git a/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/LogsControllerTest.php b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/LogsControllerTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..725882ca7cfbf771ceab77082378318601f464c7
--- /dev/null
+++ b/cosmogramme/cosmozend/tests/application/modules/cosmo/controllers/LogsControllerTest.php
@@ -0,0 +1,166 @@
+<?php
+/**
+ * Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+require 'application/modules/cosmo/controllers/LogsController.php';
+
+abstract class LogsControllerTestCase extends CosmoControllerTestCase {
+  public function setUp() {
+    parent::setUp();
+    Class_CosmoVar::setValueOf('log_path','/log');
+
+    $filesystem = (new Storm_FileSystem_Volatile())
+      ->mkdir('/log')
+      ->filePutContents('/log/debug_2017-05-12.log',
+                        str_repeat('bugs bugs', 200))
+      ->filePutContents('/log/integration_2017-05-12.log',
+                        "[IntegrationTest] first line\n [IntegrationTest] second line")
+
+      ->filePutContents('/log/integration_2017-05-13.log',
+                        str_repeat('logs logs', 200000))
+      ->filePutContents('/log/debug_2017-05-13.log',
+                        "[LogTest]")
+
+      ->filePutContents('/log/a_file.log', "that should not be there");
+
+    ZendAfi_View_Helper_CosmoLogs::setFileSystem($filesystem);
+    Cosmo_LogsController::setFileSystem($filesystem);
+
+    $this->fixture('Class_Cosmogramme_Integration',
+                   ['id' => 1,
+                    'pointeur_reprise' => 1,
+                    'traite' => '2017-05-12',
+                    'nb_erreurs' => 0,
+                    'nb_warnings' => 7,
+                   ]);
+
+    $this->fixture('Class_Cosmogramme_Integration',
+                   ['id' => 2,
+                    'pointeur_reprise' => 234,
+                    'traite' => '2017-05-12',
+                    'nb_erreurs' => 2,
+                    'nb_warnings' => 1,
+                   ]);
+  }
+
+
+  public function tearDown() {
+    ZendAfi_View_Helper_CosmoLogs::setFileSystem(null);
+    Cosmo_LogsController::setFileSystem(null);
+    parent::tearDown();
+  }
+}
+
+
+
+class LogsControllerIndexTest extends LogsControllerTestCase {
+  public function setUp() {
+    parent::setUp();
+    $this->dispatch('/cosmo/logs', true);
+  }
+
+
+  /** @test */
+  public function firstTRShouldContainsSaturdayThirteenMay2017() {
+    $this->assertXPathContentContains('//table[@id="logs"]//tr[1]//td',
+                                      'samedi 13 mai 2017');
+  }
+
+
+  /** @test */
+  public function firstTRShouldContainsMagnifierIcon() {
+    $this->assertXPath('//table[@id="logs"]//tr[1]//td//img[contains(@src, "loupe")]');
+  }
+
+
+  /** @test */
+  public function firstTRReportLinkToOpenIntegrationLogShouldContaints2Mo() {
+    $this->assertXPathContentContains('//tr[1]//td//a[contains(@href, "/cosmo/logs/integration/day/2017-05-13")]',
+                                      '2 Mo');
+  }
+
+
+  /** @test */
+  public function firstTRRecordProcessedShouldContainsZero() {
+    $this->assertXPath('//tr[1]/td[4][text()="0"]');
+  }
+
+
+  /** @test */
+  public function secondTRShouldContainsFridayTwelveMay2017() {
+    $this->assertXPathContentContains('//table[@id="logs"]//tr[2]//td',
+                                      'vendredi 12 mai 2017');
+  }
+
+
+  /** @test */
+  public function secondTRReportShouldContaints59o() {
+    $this->assertXPathContentContains('//tr[2]//td', '59 o');
+  }
+
+
+  /** @test */
+  public function secondTRShouldContainsLinkToRunLogByDate() {
+    $this->assertXPath('//table[@id="logs"]//tr[2]//td//a[contains(@href, "cosmo/run-log/by-date/date/2017-05-12")]');
+  }
+
+
+  /** @test */
+  public function secondTRReportLinkToOpenDebugLogShouldContaints2Ko() {
+    $this->assertXPathContentContains('//tr[2]//td//a[contains(@href, "/cosmo/logs/debug/day/2017-05-12")]',
+                                      '2 Ko');
+  }
+
+
+  /** @test */
+  public function secondTRRecordProcessedShouldContains235() {
+    $this->assertXPath('//tr[2]/td[4][text()="235"]');
+  }
+
+
+  /** @test */
+  public function secondTRErrorsShouldContains2() {
+    $this->assertXPath('//tr[2]/td[5][text()="2"]');
+  }
+
+
+  /** @test */
+  public function secondTRWarningsShouldContains8() {
+    $this->assertXPath('//tr[2]/td[6][text()="8"]');
+  }
+}
+
+
+
+class LogsControllerDisplayIntegrationTest extends LogsControllerTestCase {
+  /** @test */
+  public function withValidIntegrationLogShouldDisplayFileContent() {
+    $this->dispatch('/cosmo/logs/integration/day/2017-05-12', true);
+    $this->assertXPathContentContains('//div', '[IntegrationTest] first line');
+  }
+
+
+  /** @test */
+  public function withValidDebugLogShouldDisplayFileContent() {
+    $this->dispatch('/cosmo/logs/debug/day/2017-05-13', true);
+    $this->assertXPathContentContains('//div', '[LogTest]');
+  }
+}
+?>
\ No newline at end of file
diff --git a/cosmogramme/php/_menu.php b/cosmogramme/php/_menu.php
index cb7c9447f0371344f7261cfa04067103565ebe42..5cb66594acad9d2c0a151c5d156d7d4934e80200 100644
--- a/cosmogramme/php/_menu.php
+++ b/cosmogramme/php/_menu.php
@@ -68,7 +68,7 @@ else
 	<div class="menu_section">Intégration</div>
 	<?php
 	ligneMenu("Contrôle des intégrations","integre_controle_integrations.php");
-	ligneMenu("Journal des intégrations","integre_log.php");
+	ligneMenu("Journal des intégrations","../cosmozend/cosmo/logs");
 	ligneMenu("Traitements en cours","integre_traitements_attente.php");
 	ligneMenu("Fichiers en attente","integre_fichiers_attente.php");
 	ligneMenu("Lancer les traitements","integre_traite_main.php",true);
@@ -124,7 +124,6 @@ else
 	<?php
 	ligneMenu("Suppression d'exemplaires","integre_supprimer_exemplaires.php");
 	ligneMenu("Test envoi mails","test_envoi_mails.php");
-	ligneMenu("Logs des erreurs SQL","integre_log_sql.php");
 	ligneMenu("Réindexation des identifiants","util_indexation.php");
 	ligneMenu("Réindexation phonétique","util_fulltext.php?action=PARAM");
 	?>
diff --git a/cosmogramme/php/classes/classe_cosmopaths.php b/cosmogramme/php/classes/classe_cosmopaths.php
index c5b932b1f24118f282b0288f0ec9864c32dfa51a..4eaac8a7c8289bc32c04459d47a2198bf31eb722 100644
--- a/cosmogramme/php/classes/classe_cosmopaths.php
+++ b/cosmogramme/php/classes/classe_cosmopaths.php
@@ -35,6 +35,10 @@ class CosmoPaths {
     while ((count($parts)>0) && (end($parts) !== static::$_dir_name))
       array_pop($parts);
     array_pop($parts);
+
+    if (empty($parts))
+      return './';
+
     return ($this->isWindowsPath() ? '' : '/')  . implode('/', $parts) . '/';
   }
 
diff --git a/cosmogramme/php/classes/classe_log.php b/cosmogramme/php/classes/classe_log.php
index 98235bb24314363f0672ea131a8b023380062b94..a70e7bb30ade75360aa09712cf7cc16a53e40966 100644
--- a/cosmogramme/php/classes/classe_log.php
+++ b/cosmogramme/php/classes/classe_log.php
@@ -22,249 +22,129 @@
 // LOGS
 ////////////////////////////////////////////////////////////////////////
 
-class Class_log
-{
-	private $path;							// Chemin pour les logs
-	private $fic;								// Handle du fichier
-	private $typeLog;						// Type de fichier log (préfixe du nom de fichier)
-	private $maxLog;						// Nombre maxi de fichiers pour 1 type de log
-	private $afficher;					// Afficher à l'écran ou pas
-	private $entete;						// Entetes pour les logs de type tableau
+class Class_log {
+  use Trait_Translator;
+
+  private $path;              // Chemin pour les logs
+  private $fic;               // Handle du fichier
+  private $typeLog;           // Type de fichier log (préfixe du nom de fichier)
+  private $maxLog;            // Nombre maxi de fichiers pour 1 type de log
+  private $afficher;          // Afficher à l'écran ou pas
+  private $entete;            // Entetes pour les logs de type tableau
 
 // ----------------------------------------------------------------
 // Contructeur
 // ----------------------------------------------------------------
-	function __construct($typeLog,$afficher=true)
-	{
-		$this->typeLog = $typeLog;
-		$this->afficher=$afficher;
-		$this->path=getVariable("log_path");
-		if(!$this->path) afficherErreur("La variable : log_path n'est pas définie.");
-		if( strRight($this->path,1) != "/" ) $this->path .="/";
-		$this->maxLog=getVariable("log_max");
-		if(!$this->maxLog) $this->maxLog=100;
-
-		// Entetes
-		if($typeLog=="erreur") $this->entete=array("n°","Bibliothèque","Type d'opération","Erreur");
-		elseif($typeLog=="warning") $this->entete=array("n°","Bibliothèque","Type d'opération","Alerte","Valeur");
-	}
+  function __construct($typeLog,$afficher=true)
+  {
+    $this->typeLog = $typeLog;
+    $this->afficher=$afficher;
+    $this->path = getVariable("log_path");
+    if(!$this->path) afficherErreur("La variable : log_path n'est pas définie.");
+    if( strRight($this->path,1) != "/" ) $this->path .="/";
+    $this->maxLog=getVariable("log_max");
+    if(!$this->maxLog) $this->maxLog=100;
+
+    // Entetes
+    if($typeLog=="erreur") $this->entete=array("n°","Bibliothèque","Type d'opération","Erreur");
+    elseif($typeLog=="warning") $this->entete=array("n°","Bibliothèque","Type d'opération","Alerte","Valeur");
+  }
 
 // ----------------------------------------------------------------
 // Ouverture fichier
 // ----------------------------------------------------------------
-	public function open($append=0)
-	{
-		// Controle de l'historique
-		if($append==0)
-		{
-			@$dir = opendir( $this->path) or AfficherErreur("Impossible d'ouvrir le dossier des logs : " .$this->path);
-			while (($file = readdir($dir)) !== false)
-			{
-				if(strLeft($file, strLen($this->typeLog))== $this->typeLog) $liste[]=$file;
-			}
-			closedir( $dir);
-			if( count($liste) > $this->maxLog )
-			{
-				$nb_destroy=count($liste)-$this->maxLog;
-				sort($liste);
-				for($i=0; $i < $nb_destroy; $i++)
-				{
-					unlink($this->path .$liste[$i]);
-					if($this->typeLog != "sql") @unlink($this->path.str_replace($this->typeLog,"notice",$liste[$i]));
-				}
-			}
-		}
-		// Ouverture du nouveau log
-		$nom = $this->path . $this->typeLog . "_" . dateDuJour(0) .".log";
-		//if($append == true )$mode="a"; else $mode="w";
-		$mode='a'; // test en mode append systematique
-		umask(0002);
-		$this->fic=fopen($nom, $mode);
-	}
+  public function open($append=0) {
+    // Controle de l'historique
+    if($append==0) {
+      $this->_removeOldLogs();
+    }
 
-// ----------------------------------------------------------------
-// Ecrire
-// ----------------------------------------------------------------
-	public function ecrire($texte)
-	{
-		global $mode_cron;
-		fwrite($this->fic, $texte ."\n");
-		if($this->afficher == false) return false;
-		if($mode_cron)
-		{
-			$texte=strip_tags($texte);
-			if(trim($texte)) print($texte ."\n");
-		}
-		else print($texte);
-		flush();
-	}
+    // Ouverture du nouveau log
+    $nom = $this->path . $this->typeLog . "_" . dateDuJour(0) .".log";
+    $mode='a'; // test en mode append systematique
+    umask(0002);
+    if (!$this->fic = fopen($nom, $mode))
+      throw new RuntimeException($this->_('Impossible de créer le fichier de log: %s', $nom));
+  }
 
-// ----------------------------------------------------------------
-// Taille des logs
-// ----------------------------------------------------------------
-	public function getTailleLogs()
-	{
-		// Parse directory
-		@$dir = opendir( $this->path) or AfficherErreur("Impossible d'ouvrir le dossier des logs : " .$this->path);
-		$taille=0;
-		$nb_fic=0;
-		while (($file = readdir($dir)) !== false)
-		{
-			$fic=$this->path.$file;
-			if(!is_file($fic)) continue;
-			$nb_fic++;
-			$taille+=filesize($fic);
-		}
-		$ret["nb_fic"]=$nb_fic;
-		$ret["taille"]=(int)($taille / 1024);
-		$ret["taille"]=number_format($ret["taille"], 0, ',', ' ')." ko";
-		return $ret;
-	}
 
-// ----------------------------------------------------------------
-// Liste des logs
-// ----------------------------------------------------------------
-	public function rendListe()
-	{
-		// Parse directory
-		@$dir = opendir( $this->path) or AfficherErreur("Impossible d'ouvrir le dossier des logs : " .$this->path);
-		while (($file = readdir($dir)) !== false)
-		{
-			if(strLeft($file, strLen($this->typeLog))== $this->typeLog) $liste[]=$file;
-		}
-		closedir( $dir);
-		// Liste triee
-		if($liste) sort ($liste);
-		$ret = array();
-		for($i=count($liste); $i > 0; $i--)
-		{
-			$fic=$liste[($i-1)];
-			$index=count($ret);
-			$ret[$index]["taille"]=number_format((filesize($this->path.$fic) /1024),0, ',', ' ')." ko";
-			$ret[$index]["fic"]=$fic;
-			$date=str_replace($this->typeLog . "_", "", $fic);
-			$date=str_replace(".log","",$date);
-			$ret[$index]["date_sql"]=$date;
-			$ret[$index]["date"]=rendDate($date,3);
-		}
-		return $ret;
-	}
+  protected function _removeOldLogs() {
+    @$dir = opendir( $this->path) or AfficherErreur("Impossible d'ouvrir le dossier des logs : " .$this->path);
 
-// ----------------------------------------------------------------
-// Afficher le contenu du log mode texte
-// ----------------------------------------------------------------
-	public function afficher($log)
-	{
-		if($log == "") $log = $this->typeLog . "_" . dateDuJour(0) .".log";
-		if( !fileSize($this->path.$log))
-		{
-			print("Ce fichier log est vide.");
-			return false;
-		}
-		$fic=fopen($this->path.$log,"r");
-		while (!feof($fic))
-		{
-      $buffer = fgets($fic, 4096);
-      print( $buffer);
+    while (($file = readdir($dir)) !== false)  {
+      if(strLeft($file, strLen($this->typeLog))== $this->typeLog) $liste[]=$file;
     }
-    fclose($fic);
-	}
-// ----------------------------------------------------------------
-// Afficher le contenu du log en mode tableau
-// ----------------------------------------------------------------
-	public function afficherTableau($log,$arg_bib="",$arg_type_erreur="")
-	{
-		if($log == "") $log = $this->typeLog . "_" . dateDuJour(0) .".log";
-		if( !fileSize($this->path.$log))
-		{
-			print("Ce fichier log est vide.");
-			return false;
-		}
-		// Entete du tableau
-		print('<table class="blank" cellspacing="0"><tr>');
-		foreach($this->entete as $col) print('<th class="blank">'.$col.'</th>');
-		print('</tr>');
 
-		// Parser les lignes
-		$fic=fopen($this->path.$log,"r");
-		while (!feof($fic))
-		{
-      $buffer = fgets($fic, 4096);
-      $data=explode(chr(9),$buffer);
-      // selection en mode detail
-      if($arg_bib and trim($data[1]) != $arg_bib) continue;
-  		if($arg_type_erreur and trim($data[3]) != $arg_type_erreur) continue;
-      // Afficher ligne
-      $nb++;
-      if($nb > 2000) break;
-      if($data[0])
-      {
-      	print('<tr>');
-      	$prem=true;
-      	foreach($data as $col)
-        {
-        	if($prem==true)
-        	{
-        		$nom_fic="notice".substr($log,strlen($this->typeLog));
-        		$col=rendUrlImg("loupe.png", "analyse_afficher_notice.php","mode=LOG&adresse=".$col."&fichier=".$nom_fic);
-        		$prem=false;
-        	}
-        	if(!trim($col)) $col="&nbsp;";
-        	print('<td class="blank">'.$col.'</td>');
-        }
-        print('</tr>');
+    closedir( $dir);
+
+    if( count($liste) > $this->maxLog ) {
+      $nb_destroy=count($liste)-$this->maxLog;
+      sort($liste);
+      for($i=0; $i < $nb_destroy; $i++) {
+        unlink($this->path .$liste[$i]);
+        if($this->typeLog != "sql") @unlink($this->path.str_replace($this->typeLog,"notice",$liste[$i]));
       }
     }
-    fclose($fic);
-    print('</table>');
-    if($nb > 2000) print('<h3>Arrêt de l\'affichage à 2000 lignes</h3>');
-	}
+  }
+
 // ----------------------------------------------------------------
-// rend le contenu du log en mode Synthese par bibliotheques
+// Ecrire
 // ----------------------------------------------------------------
-	public function getTableauSynthese($log)
-	{
-		if($log == "") $log = $this->typeLog . "_" . dateDuJour(0) .".log";
-		if(!fileSize($this->path.$log))	return false;
+  public function log($texte) {
+    global $mode_cron;
+    fwrite($this->fic, $texte ."\n");
+    if($this->afficher == false) return false;
 
-		// Parser les lignes
-		$fic=fopen($this->path.$log,"r");
-		while (!feof($fic))
-		{
-      $buffer = fgets($fic, 4096);
-      $data=explode(chr(9),$buffer);
-      if($data[0])
-      {
-  			$bib=$data[1];
-  			$erreur=trim($data[3]);
-  			$table[$bib][$this->typeLog][$erreur]++;
-      }
+    if($mode_cron) {
+      $texte=strip_tags($texte);
+      if(trim($texte)) print($texte ."\n");
     }
-    fclose($fic);
-    return $table;
-	}
+    else
+      print($texte);
+
+    flush();
+  }
 
 // ----------------------------------------------------------------
-// Fermeture
+// Taille des logs
 // ----------------------------------------------------------------
-	public function close()
-	{
-		fclose($this->fic);
-	}
+  public function getTailleLogs()
+  {
+    // Parse directory
+    @$dir = opendir( $this->path) or AfficherErreur("Impossible d'ouvrir le dossier des logs : " .$this->path);
+    $taille=0;
+    $nb_fic=0;
+    while (($file = readdir($dir)) !== false)
+      {
+        $fic=$this->path.$file;
+        if(!is_file($fic)) continue;
+        $nb_fic++;
+        $taille+=filesize($fic);
+      }
+    $ret["nb_fic"]=$nb_fic;
+    $ret["taille"]=(int)($taille / 1024);
+    $ret["taille"]=number_format($ret["taille"], 0, ',', ' ')." ko";
+    return $ret;
+  }
 
 
-	public function addError($message) {
-		$this->ecrire('<br><span class="rouge">'.$message.'</span><br>');
-	}
+  public function close() {
+    fclose($this->fic);
+  }
+
+
+  public function error($message) {
+    $this->log('<br><span class="rouge">'.$message.'</span><br>');
+  }
 
 
-  public function addSuccess($message) {
-    $this->ecrire('<span class="vert">' . $message . '</span><br>');
+  public function success($message) {
+    $this->log('<span class="vert">' . $message . '</span><br>');
   }
 
 
-  public function addInfo($message) {
-    $this->ecrire('<br><span class="violet">' . $message . '</span><br>');
+  public function info($message) {
+    $this->log('<br><span class="violet">' . $message . '</span><br>');
   }
 }
 
diff --git a/cosmogramme/php/classes/classe_sql.php b/cosmogramme/php/classes/classe_sql.php
index 5e909c6b548e0f088f502e6b8ab6e5200448e42f..aedb3aeaeda0bfdedad1bf233bd3b52336305af5 100644
--- a/cosmogramme/php/classes/classe_sql.php
+++ b/cosmogramme/php/classes/classe_sql.php
@@ -166,7 +166,7 @@ class sql {
 			$this->log = new Class_log('sql', false);
 
 		$this->log->open(true);
-		$this->log->ecrire($msg);
+		$this->log->log($msg);
 		$this->log->close();
 	}
 }
diff --git a/cosmogramme/php/codif_dewey.php b/cosmogramme/php/codif_dewey.php
index 280a68a0a76327ca11c760d2e1a0da8386317566..647743cb3d0285c8c83d88ceb86f24d33d21a6a8 100644
--- a/cosmogramme/php/codif_dewey.php
+++ b/cosmogramme/php/codif_dewey.php
@@ -174,7 +174,7 @@ if($_REQUEST["action"]=="ECRIRE_LISTE")
 				if($_REQUEST["remplacer"] == "on") 
 				{
 					$mode="Remplacement"; 
-					$majs+=$dewey->ecrire($indice,$libelle);
+					$majs+=$dewey->log($indice,$libelle);
 				}
 				else {$mode="Pas de traitement car existe déjà"; $pas_traites++;}
 			} 
@@ -316,7 +316,7 @@ if($_REQUEST["action"]=="ECRIRE")
 		{
 			$elem=explode("#",$liste[$i]);
 			print($elem[0]." - " .$elem[1]."<br>");
-			$nb+=$dewey->ecrire($elem[0],$elem[1]);
+			$nb+=$dewey->log($elem[0],$elem[1]);
 		}
 		print("<br><h3>".$nb. " indice(s) ont été mis à jour avec succès.</h3>");
 	}
diff --git a/cosmogramme/php/codif_pcdm4.php b/cosmogramme/php/codif_pcdm4.php
index 163b7eeaad64ca0274ec414b83aac21cdf8f7f02..86fb173e8115881a2a93b541a005aac49daea128 100644
--- a/cosmogramme/php/codif_pcdm4.php
+++ b/cosmogramme/php/codif_pcdm4.php
@@ -164,7 +164,7 @@ if($_REQUEST["action"]=="ECRIRE_LISTE")
 				if($_REQUEST["remplacer"] == "on") 
 				{
 					$mode="Remplacement"; 
-					$majs+=$pcdm4->ecrire($indice,$libelle);
+					$majs+=$pcdm4->log($indice,$libelle);
 				}
 				else {$mode="Pas de traitement car existe déjà"; $pas_traites++;}
 			} 
@@ -306,7 +306,7 @@ if($_REQUEST["action"]=="ECRIRE")
 		{
 			$elem=explode("#",$liste[$i]);
 			print($elem[0]." - " .$elem[1]."<br>");
-			$nb+=$pcdm4->ecrire($elem[0],$elem[1]);
+			$nb+=$pcdm4->log($elem[0],$elem[1]);
 		}
 		print("<br><h3>".$nb. " indice(s) ont été mis à jour avec succès.</h3>");
 	}
diff --git a/cosmogramme/php/config_integrations.php b/cosmogramme/php/config_integrations.php
index ba9ec0f99c545db5bad5647784bf734d25cad029..270a4991705e19954c932308eee251802c574876 100644
--- a/cosmogramme/php/config_integrations.php
+++ b/cosmogramme/php/config_integrations.php
@@ -66,7 +66,7 @@ if($_REQUEST["action"]=="VALIDER")
 		// ecriture
 		require_once("classe_bib.php");
 		$ficheBib = new bibliotheque();
-		$ficheBib->ecrire($id_bib,$nom_court,$mail,$qualite,$ecart_ajouts,$sigb,$comm_sigb,$comm_params,$pas_exporter);
+		$ficheBib->log($id_bib,$nom_court,$mail,$qualite,$ecart_ajouts,$sigb,$comm_sigb,$comm_params,$pas_exporter);
 		$id_prog=0;
 	}
 
@@ -74,7 +74,7 @@ if($_REQUEST["action"]=="VALIDER")
 	else
 	{
 		$id_prog=$_REQUEST["id"];
-		$maj->ecrire($id_prog,$id_bib,$libelle,$profil,$type_operation,$fichier,$rang,$type_doc,(int)$taille_min_import_total);
+		$maj->log($id_prog,$id_bib,$libelle,$profil,$type_operation,$fichier,$rang,$type_doc,(int)$taille_min_import_total);
 		if($id_prog == 0 )
 		{
 			$ret=$maj->getDerniereCreation();
diff --git a/cosmogramme/php/integration/domaines.php b/cosmogramme/php/integration/domaines.php
index ec2cbd6179f52576816301656611f8713be17684..90f52996aed298e61cd9d604aba43c28eb069e49 100644
--- a/cosmogramme/php/integration/domaines.php
+++ b/cosmogramme/php/integration/domaines.php
@@ -22,7 +22,7 @@
 setVariable('traitement_phase', 'Indexation des domaines');
 
 if ($phase==16) {
-  $log->ecrire('<h4>Indexation des domaines</h4>');
+  $log->log('<h4>Indexation des domaines</h4>');
   unset($phase_data);
   $reprise = false;
   $phase_data['nombre'] = 0;
@@ -42,7 +42,7 @@ if ($phase==17) {
 
     foreach ($catalogues as $catalogue) {
       $page = $phase_data['pointeur'];
-      $log->ecrire('Indexation du domaine : '.$catalogue->getLibelle().'<br/>');
+      $log->log('Indexation du domaine : '.$catalogue->getLibelle().'<br/>');
       $catalogue->index($page);
 
       $position_domaine++;
@@ -50,15 +50,15 @@ if ($phase==17) {
       $phase_data['pointeur'] = 0;
     }
 
-    $log->ecrire('<h4>Indexation des paniers dans les domaines</h4>');
+    $log->log('<h4>Indexation des paniers dans les domaines</h4>');
     Class_PanierNotice::indexAll();
 
-    $log->ecrire('<h4>Indexation des articles dans les domaines</h4>');
+    $log->log('<h4>Indexation des articles dans les domaines</h4>');
     Class_Article::indexAll();
 
-    $log->ecrire('<h4>Indexation des sitothèques dans les domaines</h4>');
+    $log->log('<h4>Indexation des sitothèques dans les domaines</h4>');
     Class_Sitotheque::indexAll();
   } else {
-    $log->ecrire('<h4>Les indexations des domaines, des paniers, articles et sitothèques dans les domaines ne sont traitées qu\'en mode cron</h4>');
+    $log->log('<h4>Les indexations des domaines, des paniers, articles et sitothèques dans les domaines ne sont traitées qu\'en mode cron</h4>');
   }
 }
\ No newline at end of file
diff --git a/cosmogramme/php/integration/integration_phase.php b/cosmogramme/php/integration/integration_phase.php
index db3877a85afa0eb20ff6f2eda89e83cbb5970fcc..d6087357ae5b259a1b53fd5e6e5edeaaf97dc434 100644
--- a/cosmogramme/php/integration/integration_phase.php
+++ b/cosmogramme/php/integration/integration_phase.php
@@ -20,7 +20,23 @@
  */
 
 function startIntegrationPhase($name) {
-	global $chrono, $chrono_fichier, $chrono100notices, $phase, $phase_data, $mode_cron, $reprise, $log, $compteur;
+	global
+    $chrono,
+    $chrono_fichier,
+    $chrono100notices,
+    $phase,
+    $phase_data,
+    $mode_cron,
+    $reprise,
+    $log,
+    $log_debug,
+    $compteur;
+
+  $logs = (new Class_Cata_Log())
+    ->addDefaultTarget($log)
+    ->addTarget('debug', $log_debug);
+
+  Class_WebService_BibNumerique_RessourceNumerique::setLogger($logs);
 
 	$integration_class_name = 'Class_Cosmogramme_Integration_Phase'.ucfirst($name);
 
@@ -37,7 +53,7 @@ function startIntegrationPhase($name) {
 
 
 	$requested_phase = new $integration_class_name($current_phase,
-																								 $log,
+																								 $logs,
 																								 $current_chrono);
 
 	$new_phase = $requested_phase->run();
diff --git a/cosmogramme/php/integration/periodiques.php b/cosmogramme/php/integration/periodiques.php
index bd00846d2175d791d033c54f70238687af4568f8..5f978ce67f58e8f1a673f415a2698f00f54510bb 100644
--- a/cosmogramme/php/integration/periodiques.php
+++ b/cosmogramme/php/integration/periodiques.php
@@ -32,7 +32,7 @@ $titre="Indexation des articles de périodiques";
 setVariable("traitement_phase",$titre);
 if($phase=="PERIODIQUES_0")
 {
-	$log->ecrire("<h4>$titre</h4>");
+	$log->log("<h4>$titre</h4>");
 	$chrono100notices->start();
 	unset($phase_data);
 	$phase_data["nombre"]=0;
@@ -145,14 +145,14 @@ if($phase == "PERIODIQUES_1")
 	}
 
 	// recap
-	if($phase_data["nombre"]==0) $log->ecrire(BR.'<span class="vert">Aucun article à traiter</span><br>');
+	if($phase_data["nombre"]==0) $log->log(BR.'<span class="vert">Aucun article à traiter</span><br>');
 	else
 	{
-		$log->ecrire(BR.'<span class="vert">'.$phase_data["nombre"].' articles(s) traité(s)</span>'.BR);
+		$log->log(BR.'<span class="vert">'.$phase_data["nombre"].' articles(s) traité(s)</span>'.BR);
 		$chrono->timeStart=$phase_data["timeStart"];
-		$log->ecrire('<span class="vert">Temps de traitement : '.$chrono->end()." (".$chrono->moyenne($phase_data["nombre"],"articles").")</span>".BR);
+		$log->log('<span class="vert">Temps de traitement : '.$chrono->end()." (".$chrono->moyenne($phase_data["nombre"],"articles").")</span>".BR);
 	}
-	if($phase_data["not_found"]) $log->ecrire('<span class="violet">Notices orphelines : '.$phase_data["not_found"].'</span>'.BR);
+	if($phase_data["not_found"]) $log->log('<span class="violet">Notices orphelines : '.$phase_data["not_found"].'</span>'.BR);
 }
 
 // ----------------------------------------------------------------
@@ -165,7 +165,7 @@ function traceTraitementPeriodique()
 	// Affichage toutes les 100
 	if($phase_data["nombre"] % 100 == 0)
 	{
-		$log->ecrire("article ".$phase_data["nombre"]." (" .$chrono100notices->tempsPasse()." secondes)<br>");
+		$log->log("article ".$phase_data["nombre"]." (" .$chrono100notices->tempsPasse()." secondes)<br>");
 		$chrono100notices->start();
 	}
 
diff --git a/cosmogramme/php/integration/prets.php b/cosmogramme/php/integration/prets.php
index 16c759120c5890a3240e576ed8af2fe746fee31d..fe14be27a6d69fbdf6506c3859afacb584a1d9a0 100644
--- a/cosmogramme/php/integration/prets.php
+++ b/cosmogramme/php/integration/prets.php
@@ -28,7 +28,7 @@ $bib=new bibliotheque();
 setVariable("traitement_phase","Intégration des fichiers de prêts");
 if($phase==10)
 {
-	$log->ecrire("<h4>Intégration des fichiers de prêts</h4>");
+	$log->log("<h4>Intégration des fichiers de prêts</h4>");
 	unset($phase_data);
 	$reprise=false;
 	$phase_data["nombre"]=0;
@@ -53,13 +53,13 @@ if($phase == 11)
 		$trace.='<span class="bib">Fichier : '.$fichier."</span><br>";
 		$trace.='<span class="bib">Profil : '.$sql->fetchOne("select libelle from profil_donnees where id_profil=$profil").'</span><br>';
 		$trace.='<span class="bib">Format : ' . Class_IntProfilDonnees::getFormatLabelOf($format) . '</span><br>';
-		if(!$pointeur_reprise) $log->ecrire($trace); else print($trace.BR);
+		if(!$pointeur_reprise) $log->log($trace); else print($trace.BR);
 
 		// Suppression des enregs pour 1 bib si export total
 		if($type_operation == 2 and !$phase_data["nombre"])
 		{
 			$nb_destroy=$sql->execute("delete from prets where ID_SITE=$id_bib");
-			$log->ecrire('<span class="vert">'.$nb_destroy.' fiches supprimées</span>'.BR.BR);
+			$log->log('<span class="vert">'.$nb_destroy.' fiches supprimées</span>'.BR.BR);
 		}
 
 		// Traitement d'un fichier
@@ -77,7 +77,7 @@ if($phase == 11)
 		if( false == $parseur->open( $integration_path . $fichier,$format,$phase_data["pointeur"]) )
 		{
 			incrementeVariable("traitement_erreurs");
-			$log->ecrire('<span class="rouge">Impossible d\'ouvrir le fichier : '. $fichier .'</span><br>');
+			$log->log('<span class="rouge">Impossible d\'ouvrir le fichier : '. $fichier .'</span><br>');
 			continue;
 		}
 
@@ -89,9 +89,9 @@ if($phase == 11)
 			if($ret["statut"]=="erreur")
 			{
 				incrementeVariable("traitement_erreurs");
-				$log->ecrire('<span class="rouge">'.$ret["erreur"].'</span><br>');
+				$log->log('<span class="rouge">'.$ret["erreur"].'</span><br>');
 				if($phase_data["nombre"] > 0) $msg= $phase_data["nombre"] . " fiches ont pu être traitées."; else $msg="aucune fiche n'a pu être traitée.";
-				$log->ecrire('<span class="vert">'.$msg.'</span>');
+				$log->log('<span class="vert">'.$msg.'</span>');
 				break;
 			}
 			if($ret["statut"]=="eof")
@@ -99,10 +99,10 @@ if($phase == 11)
 				if($phase_data["nombre"] == 0 ) $msg="Le fichier ne contenait aucune fiche";
 				else
 				{
-					$log->ecrire(BR.'<span class="vert">'.$phase_data["nombre"].' fiches ont été traitées.</span>');
+					$log->log(BR.'<span class="vert">'.$phase_data["nombre"].' fiches ont été traitées.</span>');
 					$msg="temps de traitement ".$chrono_fichier->end($phase_data["timeStart"])." (".$chrono_fichier->moyenne($phase_data["nombre"],"fiches").")";
 				}
-				$log->ecrire(BR.'<span class="vert">'.$msg.'</span><br>');
+				$log->log(BR.'<span class="vert">'.$msg.'</span><br>');
 				break;
 			}
 			if($ret["statut"]=="ok")
@@ -125,7 +125,7 @@ if($phase == 11)
 	$phase_data["pointeur"]=0;
 	if($phase_data["nb_fic"]> 0) $msg=$phase_data["nb_fic"]. " fichier(s) traité(s).";
 	else $msg="aucun fichier traité";
-	$log->ecrire(BR.'<span class="violet">'.$msg.'</span><br>');
+	$log->log(BR.'<span class="violet">'.$msg.'</span><br>');
 }
 
 // ----------------------------------------------------------------
@@ -142,7 +142,7 @@ function traceTraitementTransaction()
   // Affichage toutes les 100 fiches
   if ($phase_data["nombre"] % 1000 == 0)
   {
-  	$log->ecrire("fiche ".$phase_data["nombre"]." (" .$chrono100notices->tempsPasse()." secondes)<br>");
+  	$log->log("fiche ".$phase_data["nombre"]." (" .$chrono100notices->tempsPasse()." secondes)<br>");
     $chrono100notices->start();
   }
 
diff --git a/cosmogramme/php/integre_analyse_fichier_unimarc.php b/cosmogramme/php/integre_analyse_fichier_unimarc.php
index 2b8c1c98a030fff558d85ac79debe22966c60f44..446c2a0ed4d65993b84dde6c354f7d23bc51095d 100644
--- a/cosmogramme/php/integre_analyse_fichier_unimarc.php
+++ b/cosmogramme/php/integre_analyse_fichier_unimarc.php
@@ -126,11 +126,11 @@ else
 {
 	$buffer->open(false);
 	$timeStart = time();
-	$buffer->ecrire('<h4>Début de l\'analyse</h4>');
-	$buffer->ecrire('Fichier : '.$fichier.BR);
-	$buffer->ecrire('Profil unimarc : '.$sql->fetchOne("select libelle from profil_donnees where id_profil=$profil_unimarc").BR);
-	$buffer->ecrire('Affichage : '.getLibCodifVariable("test_level",$test_level).BR);
-	$buffer->ecrire('Heure :  '.date("G:i:s").BR.BR);
+	$buffer->log('<h4>Début de l\'analyse</h4>');
+	$buffer->log('Fichier : '.$fichier.BR);
+	$buffer->log('Profil unimarc : '.$sql->fetchOne("select libelle from profil_donnees where id_profil=$profil_unimarc").BR);
+	$buffer->log('Affichage : '.getLibCodifVariable("test_level",$test_level).BR);
+	$buffer->log('Heure :  '.date("G:i:s").BR.BR);
 }
 
 if( false == $parseur->open($fichier,0,$pointeur_reprise) )
@@ -177,7 +177,7 @@ while(true)
   			if($nb_notices == $piege_numero or $ret_test["statut"]==1)
   			{
   				$url_notice='<a class="notice" href="'.URL_BASE."php/analyse_afficher_notice.php?fichier=".$fichier."&adresse=".$adresse .'&profil_unimarc='.$profil_unimarc.'">';
-  				$buffer->ecrire('<b>'.$url_notice.'Notice n° '.$nb_notices.' : '.$ret_test["titre"].'</a></b>'.BR);
+  				$buffer->log('<b>'.$url_notice.'Notice n° '.$nb_notices.' : '.$ret_test["titre"].'</a></b>'.BR);
   				if($pave_unimarc > 0)
   				{
   					if($pave_unimarc == 1) $mf="w"; else $mf="a";
@@ -186,7 +186,7 @@ while(true)
   					$handle=fopen(getVariable("ftp_path").$ficmemo,$mf);
   					fwrite($handle,$ret["data"]);
   					fclose($handle);
-  					$buffer->ecrire("La notice a été écrite dans le fichier : ".$ficmemo.BR);
+  					$buffer->log("La notice a été écrite dans le fichier : ".$ficmemo.BR);
   				}
   				// Si le piege est sur le n° on quitte
   				if($piege_numero) break;
@@ -201,20 +201,20 @@ while(true)
   			if($ret_test["statut"]==2) $nb_rejets++;
   			if($ret_test["statut"]==3) $nb_suppr++;
   			$url_notice='<a class="notice" href="'.URL_BASE."php/analyse_afficher_notice.php?fichier=".$fichier."&adresse=".$adresse .'&profil_unimarc='.$profil_unimarc.'">';
-  			$buffer->ecrire('<b>'.$url_notice.'Notice n° '.$nb_notices.' : '.$ret_test["titre"].'</a></b>'.BR);
-  			$buffer->ecrire('<table class="blank" cellspacing="0" cellpadding="5px" style="margin-left:15px;margin-bottom:10px;">');
+  			$buffer->log('<b>'.$url_notice.'Notice n° '.$nb_notices.' : '.$ret_test["titre"].'</a></b>'.BR);
+  			$buffer->log('<table class="blank" cellspacing="0" cellpadding="5px" style="margin-left:15px;margin-bottom:10px;">');
   			foreach($ret_test["lig"] as $item)
   			{
   				$item[1]=str_replace(" ","&nbsp;",$item[1]);
   				if(! $item[2]) $item[2]="&nbsp;";
   				if(! $item[3]) $item[3]="&nbsp;";
-  				$buffer->ecrire('<tr><td class="blank"><span class="vert">'.$item[1].'</span></td>');
-  				if($item[0] > 0 and $item[0] < 3) $buffer->ecrire('<td class="blank"><span class="rouge">'.$item[2].'</span></td>');
-  				else $buffer->ecrire('<td class="blank">'.$item[2].'</td>');
-  				$buffer->ecrire('<td class="blank">'.$item[3].'</td>');
-  				$buffer->ecrire('</tr>');
+  				$buffer->log('<tr><td class="blank"><span class="vert">'.$item[1].'</span></td>');
+  				if($item[0] > 0 and $item[0] < 3) $buffer->log('<td class="blank"><span class="rouge">'.$item[2].'</span></td>');
+  				else $buffer->log('<td class="blank">'.$item[2].'</td>');
+  				$buffer->log('<td class="blank">'.$item[3].'</td>');
+  				$buffer->log('</tr>');
   			}
-  			$buffer->ecrire('</table>');
+  			$buffer->log('</table>');
   		}
    }
    else break;
@@ -229,45 +229,45 @@ if($mode_piege == true)
 }
 
 $chrono->timeStart=$timeStart;
-$buffer->ecrire("<h4>Fin de l'analyse</h4>",true);
-$buffer->ecrire("Heure :  ".date("G:i:s").BR);
-$buffer->ecrire("temps de traitement ".$chrono->end().BR.BR);
+$buffer->log("<h4>Fin de l'analyse</h4>",true);
+$buffer->log("Heure :  ".date("G:i:s").BR);
+$buffer->log("temps de traitement ".$chrono->end().BR.BR);
 
 if($ret["statut"]=="erreur")
 {
-	$buffer->ecrire('<span class="rouge">Le fichier ne respecte pas la norme unimarc</span><br>');
+	$buffer->log('<span class="rouge">Le fichier ne respecte pas la norme unimarc</span><br>');
 	if($nb_notices > 0)
 	{
-		$buffer->ecrire($nb_notices . " notices ont pu être analysées.".BR);
+		$buffer->log($nb_notices . " notices ont pu être analysées.".BR);
 	}
 	else
 	{
-		$buffer->ecrire("aucune notice n'a pu être analysée.".BR);
+		$buffer->log("aucune notice n'a pu être analysée.".BR);
 	}
 }
 else
 {
-	if($nb_notices == 0 ) $buffer->ecrire('<span class="rouge">Le fichier ne contenait aucune notice</span><br>');
+	if($nb_notices == 0 ) $buffer->log('<span class="rouge">Le fichier ne contenait aucune notice</span><br>');
 	else
 	{
-		$buffer->ecrire('<b><span class="vert">Le fichier respecte la norme unimarc</span></b>'.BR);
-		$buffer->ecrire($nb_notices.' notices on été analysées.'.BR);
+		$buffer->log('<b><span class="vert">Le fichier respecte la norme unimarc</span></b>'.BR);
+		$buffer->log($nb_notices.' notices on été analysées.'.BR);
 	}
 }
 if($nb_notices > 0 )
 {
 	if(!$nb_suppr > 0) $nb_suppr="aucune";
-	$buffer->ecrire("Notices à supprimer : " . $nb_suppr.BR);
-	$buffer->ecrire("Notices à mettre à jour : " . ($nb_notices - ($nb_rejets + $nb_suppr)).BR);
-	$buffer->ecrire("Exemplaires à insérer : " . $nb_ex.BR);
-	$buffer->ecrire('Anomalies non bloquantes : '. $nb_warnings.BR);
-	if($nb_rejets>0) $buffer->ecrire('<span class="rouge">Notices non exploitables : '. $nb_rejets.'</span>'.BR);
-	else $buffer->ecrire('Notices non exploitables : aucune'.BR);
-	$buffer->ecrire("Moyenne : ".$chrono->moyenne($nb_notices,"notices").BR);
+	$buffer->log("Notices à supprimer : " . $nb_suppr.BR);
+	$buffer->log("Notices à mettre à jour : " . ($nb_notices - ($nb_rejets + $nb_suppr)).BR);
+	$buffer->log("Exemplaires à insérer : " . $nb_ex.BR);
+	$buffer->log('Anomalies non bloquantes : '. $nb_warnings.BR);
+	if($nb_rejets>0) $buffer->log('<span class="rouge">Notices non exploitables : '. $nb_rejets.'</span>'.BR);
+	else $buffer->log('Notices non exploitables : aucune'.BR);
+	$buffer->log("Moyenne : ".$chrono->moyenne($nb_notices,"notices").BR);
 
 	// Types de docs
-	$buffer->ecrire(BR."<b>Types de documents :</b>".BR);
-	$buffer->ecrire('<table class="blank" cellpadding="5px" style="margin-left:15px;margin-top:5px;">');
+	$buffer->log(BR."<b>Types de documents :</b>".BR);
+	$buffer->log('<table class="blank" cellpadding="5px" style="margin-left:15px;margin-top:5px;">');
 	$td=$sql->fetchOne("select liste from variables where clef='types_docs'");
 	$td=explode(chr(13).chr(10),$td);
 	$td[]="100:articles de périodiques";
@@ -275,12 +275,12 @@ if($nb_notices > 0 )
 	{
 		$elem=explode(":",$td[$i]);
 		if(!$type_doc[$elem[0]]) $type_doc[$elem[0]]=0;
-		$buffer->ecrire('<tr>');
-		$buffer->ecrire('<td class="blank">'.$elem[1].'</td>');
-		$buffer->ecrire('<td class="blank" align="right">'.$type_doc[$elem[0]].'</td>');
-		$buffer->ecrire('</tr>');
+		$buffer->log('<tr>');
+		$buffer->log('<td class="blank">'.$elem[1].'</td>');
+		$buffer->log('<td class="blank" align="right">'.$type_doc[$elem[0]].'</td>');
+		$buffer->log('</tr>');
 	}
-	$buffer->ecrire('</table>'.BR);
+	$buffer->log('</table>'.BR);
 }
 // Réafficher le debut si + d'1 page en buffer
 $page=$buffer->close();
diff --git a/cosmogramme/php/integre_log.php b/cosmogramme/php/integre_log.php
deleted file mode 100644
index ee37020a43a28c461859f60a509372164c1b532e..0000000000000000000000000000000000000000
--- a/cosmogramme/php/integre_log.php
+++ /dev/null
@@ -1,73 +0,0 @@
-<?php
-/**
- * Copyright (c) 2012, Agence Française Informatique (AFI). All rights reserved.
- *
- * BOKEH is free software; you can redistribute it and/or modify
- * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
- * the Free Software Foundation.
- *
- * There are special exceptions to the terms and conditions of the AGPL as it
- * is applied to this software (see README file).
- *
- * BOKEH is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
- *
- * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
- * along with BOKEH; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA 
- */
-
-include '_init_frame.php';
-
-require_once 'classe_log.php';
-$log = new Class_log("integration");
-
-if($_REQUEST["log"]) {
-	print('<h1>Log du '.$_REQUEST["date"].'</h1>');
-	print('<div style="margin-left:20px">');
-	$log->afficher($_REQUEST["log"]);
-	print('</div></body></html>');
-	exit;
-} ?>
-
-<h1>Journal des intégrations</h1>
-<div class="liste">
-	<table width="600px">
-	<tr>
-	<th colspan="2">Date</th>
-	<th colspan="2">Rapport</th>
-	<th width="15%">Notices traitées</th>
-	<th width="15%">Erreurs</th>
-	<th width="15%">Anomalies</th>
-	</tr>
-<?php foreach ($log->rendListe() as $lig) { ?>
-	<tr>
-	<td><?php echo rendUrlImg('loupe.png',
-													 '../cosmozend/cosmo/run-log/by-date/date/' . $lig['date_sql'], 
-													 '', 'Synthèse par bibliothèques');?></td>
-	<td><?php echo $lig["date"];?></td>
-	<?php
-	// Integration
-	$url=rendUrlImg("loupe.png", "integre_log.php","log=".$lig["fic"]."&date=".$lig["date"]."&type=INTEGRATION","Afficher le détail");
-	print('<td>'. $url .'</td>');
-	print('<td>'. $lig["taille"] .'</td>');
-	
-	// Notices traitees
-	$nb=(double)$sql->fetchOne("select sum(pointeur_reprise) from integrations where traite != 'non' and traite='".$lig["date_sql"]."'"); 
-	print('<td align="right">'. number_format($nb, 0, ',', ' ') .'</td>');
-	
-	// Erreurs
-	$nb=(double)$sql->fetchOne("select sum(nb_erreurs) from integrations where traite != 'non' and traite='".$lig["date_sql"]."'"); 
-	print('<td align="right">'. number_format($nb, 0, ',', ' ') .'</td>');
-	
-	// Warnings
-	$nb=(double)$sql->fetchOne("select sum(nb_warnings) from integrations where traite != 'non' and traite='".$lig["date_sql"]."'"); 
-	print('<td align="right">'. number_format($nb, 0, ',', ' ') .'</td>');
-	print('</tr>');
-}
-print('</table></div>');
-print('</body></html>');
-
-?>
\ No newline at end of file
diff --git a/cosmogramme/php/integre_log_sql.php b/cosmogramme/php/integre_log_sql.php
deleted file mode 100644
index 1a8cd7fd098dc0ed1e300c3523540f83170e3721..0000000000000000000000000000000000000000
--- a/cosmogramme/php/integre_log_sql.php
+++ /dev/null
@@ -1,69 +0,0 @@
-<?PHP
-/**
- * Copyright (c) 2012, Agence Française Informatique (AFI). All rights reserved.
- *
- * BOKEH is free software; you can redistribute it and/or modify
- * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
- * the Free Software Foundation.
- *
- * There are special exceptions to the terms and conditions of the AGPL as it
- * is applied to this software (see README file).
- *
- * BOKEH is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
- *
- * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
- * along with BOKEH; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA 
- */
-////////////////////////////////////////////////////////////////////////////////////////////
-// AFFICHAGE DES LOGS D'INTEGRATION
-////////////////////////////////////////////////////////////////////////////////////////////
-include("_init_frame.php");
-
-require_once("classe_log.php");
-$log=new Class_log("integration");
-$log_erreur=new Class_log("erreur");
-$log_warning=new Class_log("warning");
-$log_sql=new Class_log("sql");
-
-////////////////////////
-// AFFICHAGE d'1 LOG
-////////////////////////
-
-if($_REQUEST["log"])
-{
-	print('<h1>Log des erreurs SQL du '.$_REQUEST["date"].'</h1>');
-	print('<div style="margin-left:20px">');
-	$log->afficher($_REQUEST["log"]);
-	print('</div></body></html>');
-	exit;
-}
-
-// ----------------------------------------------------------------
-// Logs des erreurs sql
-// ----------------------------------------------------------------
-print('<h1>Logs des erreurs SQL</h1>');
-
-print('<div class="liste"><table width="600px">');
-print(' <tr>
- <th width="5%" align="center">&nbsp;</th>
- <th width="95%" align="left">Logs des erreurs SQL</th>
-</tr>');
-
-$liste=$log_sql->rendListe();
-foreach($liste as $lig)
-{
-	$url=rendUrlImg("loupe.png", "integre_log_sql.php","log=".$lig["fic"]."&date=".$lig["date"]."&type=ERREUR");
-	print('<tr>');
-	print('<td>'. $url .'</td>');
-	print('<td>'.$lig["date"].'</td>');
-	print('</tr>');
-}
-print('</table></div>');
-
-print('</body></html>');
-
-?>
\ No newline at end of file
diff --git a/cosmogramme/php/integre_traite_main.php b/cosmogramme/php/integre_traite_main.php
index d7b182124faa4ce8ad5ebab826c5051b26272c1a..ebc159141b51c6f52b697e778c6e888de60bd053 100644
--- a/cosmogramme/php/integre_traite_main.php
+++ b/cosmogramme/php/integre_traite_main.php
@@ -49,8 +49,7 @@ require_once 'integration/integration_phase.php';
 
 // Instanciations
 $log = new Class_log('integration');
-$log_erreur = new Class_log('erreur', false);
-$log_warning = new Class_log('warning', false);
+$log_debug = new Class_log('debug', false);
 $chrono = new chronometre();
 $chrono_fichier = new chronometre();
 $chrono100notices = new chronometre();
@@ -82,8 +81,7 @@ $should_skip_records = false;
 // ----------------------------------------------------------------
 if ($_REQUEST['reprise'] == 'oui') {
 	$log->open(true);
-	$log_erreur->open(true);
-	$log_warning->open(true);
+	$log_debug->open(true);
 	restaureContext();
 	$reprise = true;
 
@@ -93,12 +91,11 @@ if ($_REQUEST['reprise'] == 'oui') {
 	setVariable('traitement_warnings', 0);
 	setVariable('traitement_phase', 'Déplacement des fichiers');
 	$log->open(false);
-	$log_erreur->open(false);
-	$log_warning->open(false);
-	$log->ecrire('<h4>Début du traitement</h4>');
-	$log->ecrire('Date : ' . date('d-m-Y') . BR);
-	$log->ecrire('Heure : ' . date('G:i:s') . BR);
-	$log->ecrire('Mode : '
+	$log_debug->open(false);
+	$log->log('<h4>Début du traitement</h4>');
+	$log->log('Date : ' . date('d-m-Y') . BR);
+	$log->log('Heure : ' . date('G:i:s') . BR);
+	$log->log('Mode : '
 							 . (($mode_cron == true) ? 'automatique (cron)' : 'manuel')
 							 . BR);
 
@@ -107,23 +104,23 @@ if ($_REQUEST['reprise'] == 'oui') {
 						'tot' => 'imports totaux uniquement',
 						'inc' => 'imports incrementiels uniquement',
             'init' => 'mise en file d\'attente uniquement'];
-		$log->ecrire('Type d\'import : ' . $txt[$cron_a_traiter] . BR);
+		$log->log('Type d\'import : ' . $txt[$cron_a_traiter] . BR);
 	}
 
 	try {
 		startIntegrationPhase('PrepareIntegrations');
     if ('init' == $cron_a_traiter) {
-      $log->ecrire(BR . BR . '<h4>mise en file d\'attente uniquement : fin du traitement</h4>');
-      $log->ecrire('Déblocage de la base<br>');
+      $log->log(BR . BR . '<h4>mise en file d\'attente uniquement : fin du traitement</h4>');
+      $log->log('Déblocage de la base<br>');
       setVariable('clef_traitements', '0');
       setVariable('traitement_phase', 'Traitement terminé');
       $chrono->timeStart = $timeStart;
-      $log->ecrire('Heure : ' . date('G:i:s') . BR);
-      $log->ecrire('Temps de traitement : ' . $chrono->end() . BR);
+      $log->log('Heure : ' . date('G:i:s') . BR);
+      $log->log('Temps de traitement : ' . $chrono->end() . BR);
       exit;
     }
 	} catch (Class_Cosmogramme_Integration_PhasePrepareIntegrationsException $e) {
-		$log->ecrire(BR . BR
+		$log->log(BR . BR
 								 . '<span class="rouge">' . $e->getMessage() . ' : Abandon du traitement !</span><br>');
 		exit;
 	}
@@ -141,7 +138,7 @@ if ($_REQUEST['reprise'] == 'oui') {
 				and type_fichier = 0");
 
     $logger = function($message, $log) {
-      $log->ecrire(BR . BR
+      $log->log(BR . BR
 									 . '<span class="rouge">' . $message . ' : traitement des notices désactivé !</span>'
                    . BR);
     };
@@ -163,11 +160,11 @@ if ($_REQUEST['reprise'] == 'oui') {
 	// Test blocage de la base
 	// ----------------------------------------------------------------
 	if (getVariable('clef_traitements') == '1') {
-		$log->ecrire('<span class="rouge">La base est bloquée (clef_traitements) : Abandon du traitement !</span><br>');
+		$log->log('<span class="rouge">La base est bloquée (clef_traitements) : Abandon du traitement !</span><br>');
 		$log->close();
 		exit;
 	}
-	$log->ecrire('Blocage de la base<br>');
+	$log->log('Blocage de la base<br>');
 	setVariable('clef_traitements', '1');
 }
 
@@ -176,7 +173,7 @@ if (!$should_skip_records) {
   // ----------------------------------------------------------------
   // Integration des notices (PHASE 0)
   // ----------------------------------------------------------------
-  $log->ecrire('<h4>Traitement des notices</h4>');
+  $log->log('<h4>Traitement des notices</h4>');
   setVariable('traitement_phase', 'Intégration des notices');
   startIntegrationPhase('notice');
 }
@@ -209,7 +206,7 @@ if (!$should_skip_records) {
   // ----------------------------------------------------------------
   // Suppression des notices sans exemplaires (PHASE 2)
   // ----------------------------------------------------------------
-  $log->ecrire('Suppression des notices sans exemplaire<br>');
+  $log->log('Suppression des notices sans exemplaire<br>');
   setVariable("traitement_phase", "Suppression des notices sans exemplaire");
   startIntegrationPhase('DeleteRecordWithoutItem');
 
@@ -236,7 +233,7 @@ if (!$should_skip_records) {
   $ecart = ecartDates($date, $date_homogene);
   if ($phase == 2)
     {
-      $log->ecrire("<h4>Intégration des notices succintes</h4>");
+      $log->log("<h4>Intégration des notices succintes</h4>");
       $phase = 3;
       unset($phase_data);
       $phase_data["nombre"] = 0;
@@ -244,14 +241,14 @@ if (!$should_skip_records) {
       $chrono100notices->start();
       $phase_data["nb_homogene"] = 0;
       $phase_data["id"] = 0;
-      if ($ecart < $frequence) $log->ecrire('<span class="vert">Sera fait dans ' . ($frequence - $ecart) . ' jour(s)</span>');
+      if ($ecart < $frequence) $log->log('<span class="vert">Sera fait dans ' . ($frequence - $ecart) . ' jour(s)</span>');
       elseif (!$mode_cron) sauveContexte();
     }
   if ($phase == 3 and $ecart >= $frequence)
     {
       if (!$mode_cron) print("<h4>Intégration des notices succintes</h4>");
       $chrono->start();
-      if (!$phase_data["nombre"]) $log->ecrire('<span class="vert">Niveau de tentatives d\'homogénéisation : ' . $Z3950_retry_level . '</span>' . BR . BR);
+      if (!$phase_data["nombre"]) $log->log('<span class="vert">Niveau de tentatives d\'homogénéisation : ' . $Z3950_retry_level . '</span>' . BR . BR);
       $result = $sql->prepareListe("select * from notices_succintes where id > '" . $phase_data["id"] . "' and z3950_retry <= $Z3950_retry_level order by id");
       while ($data = $sql->fetchNext($result))
         {
@@ -262,17 +259,17 @@ if (!$should_skip_records) {
           traceSuccinte($ret);
         }
       // Recap
-      $log->ecrire(BR . '<span class="vert">' . ($phase_data["nombre"]) . ' notices traitées</span>' . BR);
+      $log->log(BR . '<span class="vert">' . ($phase_data["nombre"]) . ' notices traitées</span>' . BR);
       $chrono->timeStart = $phase_data["timeStart"];
-      $log->ecrire('<span class="vert">Temps de traitement : ' . $chrono->end() . " (" . $chrono->moyenne($phase_data["nombre"], "notices") . ")</span>" . BR);
+      $log->log('<span class="vert">Temps de traitement : ' . $chrono->end() . " (" . $chrono->moyenne($phase_data["nombre"], "notices") . ")</span>" . BR);
 
       for ($i = 0; $i < 5; $i++) if (!$phase_data[$i]) $phase_data[$i] = "0";
-      $log->ecrire('<table class="blank" cellspacing="0" cellpadding="5px" style="margin-left:25px;margin-bottom:10px;margin-top:10px">');
-      $log->ecrire('<tr><td class="blank">Notices trouvées dans la base</td><td class="blank" align="right">' . $phase_data[1] . '</td></tr>');
-      $log->ecrire('<tr><td class="blank">Notices trouvées sur serveurs z39.50</td><td class="blank" align="right">' . $phase_data[2] . '</td></tr>');
-      $log->ecrire('<tr><td class="blank">Notices non trouvées</td><td class="blank" align="right">' . $phase_data[3] . '</td></tr>');
-      $log->ecrire('<tr><td class="blank">Echecs de connexions</td><td class="blank" align="right">' . $phase_data[4] . '</td></tr>');
-      $log->ecrire('</table>');
+      $log->log('<table class="blank" cellspacing="0" cellpadding="5px" style="margin-left:25px;margin-bottom:10px;margin-top:10px">');
+      $log->log('<tr><td class="blank">Notices trouvées dans la base</td><td class="blank" align="right">' . $phase_data[1] . '</td></tr>');
+      $log->log('<tr><td class="blank">Notices trouvées sur serveurs z39.50</td><td class="blank" align="right">' . $phase_data[2] . '</td></tr>');
+      $log->log('<tr><td class="blank">Notices non trouvées</td><td class="blank" align="right">' . $phase_data[3] . '</td></tr>');
+      $log->log('<tr><td class="blank">Echecs de connexions</td><td class="blank" align="right">' . $phase_data[4] . '</td></tr>');
+      $log->log('</table>');
       setVariable("succintes_date", $date);
     }
 
@@ -290,7 +287,7 @@ if (!$should_skip_records) {
   $ecart = ecartDates($date, $date_homogene);
   if ($phase == 3)
     {
-      $log->ecrire("<h4>Homogénéisation Z39.50 des notices par l'ISBN</h4>");
+      $log->log("<h4>Homogénéisation Z39.50 des notices par l'ISBN</h4>");
       unset($phase_data);
       $phase_data["nombre"] = 0;
       $phase_data["timeStart"] = time();
@@ -298,10 +295,10 @@ if (!$should_skip_records) {
       $phase = 4;
       if ($homogene_actif == 0)
         {
-          $log->ecrire('<span class="rouge">Le processus d\'homogénéisation des notices est désactivé</span>' . BR);
+          $log->log('<span class="rouge">Le processus d\'homogénéisation des notices est désactivé</span>' . BR);
         } else
         {
-          if ($ecart < $frequence) $log->ecrire('<span class="vert">Sera fait dans ' . ($frequence - $ecart) . ' jour(s)</span>');
+          if ($ecart < $frequence) $log->log('<span class="vert">Sera fait dans ' . ($frequence - $ecart) . ' jour(s)</span>');
           else if (!$mode_cron) sauveContexte();
         }
     }
@@ -312,9 +309,9 @@ if (!$should_skip_records) {
       $ret["timeout"] = 10;
       if (!$phase_data["nombre"])
         {
-          $log->ecrire('<span class="vert">Niveau de tentatives d\'homogénéisation : ' . $Z3950_retry_level . '</span>' . BR);
-          $log->ecrire('<span class="vert">Nombre maxi de tentatives de reconnexions : ' . $Z3950_max_reconnect . '</span>' . BR);
-          $log->ecrire('<span class="vert">Mode de recherche sur les serveurs z39.50 : ' . getLibCodifVariable("Z3950_cache_only", $homogene_cache_only) . '</span>' . BR);
+          $log->log('<span class="vert">Niveau de tentatives d\'homogénéisation : ' . $Z3950_retry_level . '</span>' . BR);
+          $log->log('<span class="vert">Nombre maxi de tentatives de reconnexions : ' . $Z3950_max_reconnect . '</span>' . BR);
+          $log->log('<span class="vert">Mode de recherche sur les serveurs z39.50 : ' . getLibCodifVariable("Z3950_cache_only", $homogene_cache_only) . '</span>' . BR);
         }
       $result = $sql->prepareListe("select id_notice,isbn from notices where isbn > '" . $phase_data["isbn"] . "' and qualite < $qualite_homogene and z3950_retry <= $Z3950_retry_level order by isbn");
       try {
@@ -335,7 +332,7 @@ if (!$should_skip_records) {
                 $phase_data["nb_reconnexions"]++;
                 if ($phase_data["nb_reconnexions"] >= $Z3950_max_reconnect)
                   {
-                    $log->ecrire(BR . '<span class="rouge">Abandon du traitement : maximum de tentatives de reconnexions atteint</span>' . BR);
+                    $log->log(BR . '<span class="rouge">Abandon du traitement : maximum de tentatives de reconnexions atteint</span>' . BR);
                     $fin = true;
                     break;
                   }
@@ -346,7 +343,7 @@ if (!$should_skip_records) {
             $phase_data["nombre"]++;
           }
       } catch (PDOException $e) {
-        $log->ecrire('PDOException'.$e);
+        $log->log('PDOException'.$e);
         $cosmo_path = new CosmoPaths();
         $site = '/' . $cosmo_path->getSite() . '/';
         $cfgfile = $cosmo_path->getConfigPath();
@@ -363,7 +360,7 @@ if (!$should_skip_records) {
   $fin = false;
   if ($phase == 4)
     {
-      $log->ecrire("<h4>Homogénéisation Z39.50 des notices par l'EAN</h4>");
+      $log->log("<h4>Homogénéisation Z39.50 des notices par l'EAN</h4>");
       unset($phase_data);
       $phase_data["nombre"] = 0;
       $phase_data["timeStart"] = time();
@@ -372,10 +369,10 @@ if (!$should_skip_records) {
       $phase = 5;
       if ($homogene_actif == 0)
         {
-          $log->ecrire('<span class="rouge">Le processus d\'homogénéisation des notices est désactivé</span>' . BR);
+          $log->log('<span class="rouge">Le processus d\'homogénéisation des notices est désactivé</span>' . BR);
         } else
         {
-          if ($ecart < $frequence) $log->ecrire('<span class="vert">Sera fait dans ' . ($frequence - $ecart) . ' jour(s)</span>');
+          if ($ecart < $frequence) $log->log('<span class="vert">Sera fait dans ' . ($frequence - $ecart) . ' jour(s)</span>');
           else if (!$mode_cron) sauveContexte();
         }
     }
@@ -386,9 +383,9 @@ if (!$should_skip_records) {
       $ret["timeout"] = 10;
       if (!$phase_data["nombre"])
         {
-          $log->ecrire('<span class="vert">Niveau de tentatives d\'homogénéisation : ' . $Z3950_retry_level . '</span>' . BR);
-          $log->ecrire('<span class="vert">Nombre maxi de tentatives de reconnexions : ' . ($Z3950_max_reconnect) . '</span>' . BR);
-          $log->ecrire('<span class="vert">Mode de recherche sur les serveurs z39.50 : ' . getLibCodifVariable("Z3950_cache_only", $homogene_cache_only) . '</span>' . BR);
+          $log->log('<span class="vert">Niveau de tentatives d\'homogénéisation : ' . $Z3950_retry_level . '</span>' . BR);
+          $log->log('<span class="vert">Nombre maxi de tentatives de reconnexions : ' . ($Z3950_max_reconnect) . '</span>' . BR);
+          $log->log('<span class="vert">Mode de recherche sur les serveurs z39.50 : ' . getLibCodifVariable("Z3950_cache_only", $homogene_cache_only) . '</span>' . BR);
         }
       $result = $sql->prepareListe("select id_notice,ean from notices where ean > '" . $phase_data["ean"] . "' and qualite < $qualite_homogene and z3950_retry <= $Z3950_retry_level order by ean");
       while ($data = $sql->fetchNext($result))
@@ -408,7 +405,7 @@ if (!$should_skip_records) {
               $phase_data["nb_reconnexions"]++;
               if ($phase_data["nb_reconnexions"] >= $Z3950_max_reconnect)
                 {
-                  $log->ecrire(BR . '<span class="rouge">Abandon du traitement : maximum de tentatives de reconnexions atteint</span>' . BR);
+                  $log->log(BR . '<span class="rouge">Abandon du traitement : maximum de tentatives de reconnexions atteint</span>' . BR);
                   $fin = true;
                   break;
                 }
@@ -428,7 +425,7 @@ if (!$should_skip_records) {
   $fin = false;
   if ($phase == 5)
     {
-      $log->ecrire("<h4>Homogénéisation Z39.50 des notices par le numéro commercial</h4>");
+      $log->log("<h4>Homogénéisation Z39.50 des notices par le numéro commercial</h4>");
       unset($phase_data);
       $phase_data["nombre"] = 0;
       $phase_data["timeStart"] = time();
@@ -437,10 +434,10 @@ if (!$should_skip_records) {
       $phase = 6;
       if ($homogene_actif == 0)
         {
-          $log->ecrire('<span class="rouge">Le processus d\'homogénéisation des notices est désactivé</span>' . BR);
+          $log->log('<span class="rouge">Le processus d\'homogénéisation des notices est désactivé</span>' . BR);
         } else
         {
-          if ($ecart < $frequence) $log->ecrire('<span class="vert">Sera fait dans ' . ($frequence - $ecart) . ' jour(s)</span>');
+          if ($ecart < $frequence) $log->log('<span class="vert">Sera fait dans ' . ($frequence - $ecart) . ' jour(s)</span>');
           else if (!$mode_cron) sauveContexte();
         }
     }
@@ -451,9 +448,9 @@ if (!$should_skip_records) {
       $ret["timeout"] = 10;
       if (!$phase_data["nombre"])
         {
-          $log->ecrire('<span class="vert">Niveau de tentatives d\'homogénéisation : ' . $Z3950_retry_level . '</span>' . BR);
-          $log->ecrire('<span class="vert">Nombre maxi de tentatives de reconnexions : ' . ($Z3950_max_reconnect) . '</span>' . BR);
-          $log->ecrire('<span class="vert">Mode de recherche sur les serveurs z39.50 : ' . getLibCodifVariable("Z3950_cache_only", $homogene_cache_only) . '</span>' . BR);
+          $log->log('<span class="vert">Niveau de tentatives d\'homogénéisation : ' . $Z3950_retry_level . '</span>' . BR);
+          $log->log('<span class="vert">Nombre maxi de tentatives de reconnexions : ' . ($Z3950_max_reconnect) . '</span>' . BR);
+          $log->log('<span class="vert">Mode de recherche sur les serveurs z39.50 : ' . getLibCodifVariable("Z3950_cache_only", $homogene_cache_only) . '</span>' . BR);
         }
       $result = $sql->prepareListe("select id_notice,id_commerciale from notices where id_commerciale > '" . $phase_data["id_commerciale"] . "' and qualite < $qualite_homogene and z3950_retry <= $Z3950_retry_level order by id_commerciale");
       while ($data = $sql->fetchNext($result))
@@ -473,7 +470,7 @@ if (!$should_skip_records) {
               $phase_data["nb_reconnexions"]++;
               if ($phase_data["nb_reconnexions"] >= $Z3950_max_reconnect)
                 {
-                  $log->ecrire(BR . '<span class="rouge">Abandon du traitement : maximum de tentatives de reconnexions atteint</span>' . BR);
+                  $log->log(BR . '<span class="rouge">Abandon du traitement : maximum de tentatives de reconnexions atteint</span>' . BR);
                   $fin = true;
                   break;
                 }
@@ -545,7 +542,7 @@ if ($phase==16 or $phase==17) {
 setVariable("traitement_phase", "Envoi des mails aux bibliothèques qui ont du retard");
 if ($phase == 20)
 {
-	$log->ecrire("<h4>Envoi des mails aux bibliothèques qui ont du retard</h4>");
+	$log->log("<h4>Envoi des mails aux bibliothèques qui ont du retard</h4>");
 	unset($phase_data);
 	$phase_data["nombre"] = 0;
 	$phase_data["nb_erreurs"] = 0;
@@ -568,7 +565,7 @@ if ($phase == 21)
 		{
 			if (!$mode_cron and $chrono->tempsPasse() > $timeout) sauveContexte();
 			if ($enreg["nom_court"] <= $phase_data["pointeur"]) continue;
-			$log->ecrire('<span class="violet">' . $enreg["nom_court"] . " : " . $enreg["retard"] . ' de retard</span><br>');
+			$log->log('<span class="violet">' . $enreg["nom_court"] . " : " . $enreg["retard"] . ' de retard</span><br>');
 			$data["NOM_BIB"] = $enreg["nom"];
 			$data["DATE_ENVOI"] = $enreg["dernier_ajout"];
 			$data["RETARD"] = $enreg["retard"];
@@ -577,7 +574,7 @@ if ($phase == 21)
 			if ($erreur)
 			{
 				$phase_data["nb_erreurs"]++;
-				$log->ecrire('<span class="rouge" style="margin-left:20px">' . $erreur . '</span><br>');
+				$log->log('<span class="rouge" style="margin-left:20px">' . $erreur . '</span><br>');
 			} else
 			{
 				$phase_data["nombre"]++;
@@ -588,12 +585,12 @@ if ($phase == 21)
 			$phase_data["pointeur"] = $enreg["nom_court"];
 		}
 		$chrono100notices->timeStart = $phase_data["timeStart"];
-		$log->ecrire(BR);
-		if ($phase_data["nb_erreurs"] > 0) $log->ecrire('<span class="rouge">Echecs d\'envois : ' . $phase_data["nb_erreurs"] . '</span><br>');
-		$log->ecrire('<span class="vert">' . $phase_data["nombre"] . ' mail(s) envoyé(s)</span>' . BR);
-		$log->ecrire('<span class="vert">Temps de traitement : ' . $chrono100notices->end() . '</span>' . BR);
+		$log->log(BR);
+		if ($phase_data["nb_erreurs"] > 0) $log->log('<span class="rouge">Echecs d\'envois : ' . $phase_data["nb_erreurs"] . '</span><br>');
+		$log->log('<span class="vert">' . $phase_data["nombre"] . ' mail(s) envoyé(s)</span>' . BR);
+		$log->log('<span class="vert">Temps de traitement : ' . $chrono100notices->end() . '</span>' . BR);
 	}
-	else $log->ecrire('<span class="vert">Aucune alerte de retard à signaler</span>' . BR);
+	else $log->log('<span class="vert">Aucune alerte de retard à signaler</span>' . BR);
 }
 
 // ----------------------------------------------------------------
@@ -606,28 +603,27 @@ startIntegrationPhase('EndProcess');
 
 $chrono->timeStart = $timeStart;
 
-$log->ecrire("Déblocage de la base<br>");
-$log->ecrire("Heure :  " . date("G:i:s") . BR);
-$log->ecrire('Temps de traitement : ' . $chrono->end() . BR);
+$log->log("Déblocage de la base<br>");
+$log->log("Heure :  " . date("G:i:s") . BR);
+$log->log('Temps de traitement : ' . $chrono->end() . BR);
 
 //ecrire le temps de traitement
 $temps_traitement=(int)time()-$timeStart;
 sqlExecute("update integrations set temps_traitement = $temps_traitement where traite='$date'");
 
 // Résumé
-if ($compteur[0] > 0) $log->ecrire('<span class="rouge">Notices rejetées : ' . $compteur[0] . '</span>' . BR);
+if ($compteur[0] > 0) $log->log('<span class="rouge">Notices rejetées : ' . $compteur[0] . '</span>' . BR);
 $lib = $notice->libStatut;
-$log->ecrire(BR . '<table class="blank" cellpadding="5px" style="margin-left:15px;margin-top:5px;">');
+$log->log(BR . '<table class="blank" cellpadding="5px" style="margin-left:15px;margin-top:5px;">');
 for ($i = 1; $i < count($lib); $i++)
 {
 	if (!$compteur[$i]) $compteur[$i] = "aucune";
-	$log->ecrire('<tr class="blank"><td class="blank">' . $lib[$i] . '</td><td class="blank" align="right">' . $compteur[$i] . '</td></tr>');
+	$log->log('<tr class="blank"><td class="blank">' . $lib[$i] . '</td><td class="blank" align="right">' . $compteur[$i] . '</td></tr>');
 }
-$log->ecrire('</table>');
+$log->log('</table>');
 
 $log->close();
-$log_erreur->close();
-$log_warning->close();
+$log_debug->close();
 print(BR . BR . '</body></html>');
 
 
@@ -636,7 +632,7 @@ print(BR . BR . '</body></html>');
 // ----------------------------------------------------------------
 function traceTraitementNotice()
 {
-	global $log, $log_erreur, $log_warning;
+	global $log, $log_debug;
 	global $notice, $compteur, $phase_data, $nb_notices, $chrono100notices, $debug_level;
 	global $nom_bib, $libelle_type_operation, $ret;
 
@@ -654,15 +650,15 @@ function traceTraitementNotice()
 		//incrementeVariable("traitement_erreurs");
 		$phase_data["nb_erreurs"]++;
 		$phase_data["erreurs"][$statut["erreur"]][] = $ret["adresse"];
-		if ($debug_level == 1 or $debug_level == 2) $log->ecrire('<span class="rouge">Notice n° ' . $nb_notices . ' - ' . $statut["erreur"] . '</span>' . BR);
+		if ($debug_level == 1 or $debug_level == 2) $log->log('<span class="rouge">Notice n° ' . $nb_notices . ' - ' . $statut["erreur"] . '</span>' . BR);
 	}
 	if (count($statut["warnings"]) > 0)
 	{
 		//incrementeVariable("traitement_warnings");
-		if ($debug_level == 2) $log->ecrire('<span class="num_notice">notice n° ' . $nb_notices . '</span>' . BR);
+		if ($debug_level == 2) $log->log('<span class="num_notice">notice n° ' . $nb_notices . '</span>' . BR);
 		foreach ($statut["warnings"] as $warning)
 		{
-			if ($debug_level == 2) $log->ecrire('<font color="purple">Anomalie : ' . $warning[0] . " &raquo; " . $warning[1] . '</font>' . BR);
+			if ($debug_level == 2) $log->log('<font color="purple">Anomalie : ' . $warning[0] . " &raquo; " . $warning[1] . '</font>' . BR);
 			if ($warning[0] == "Genre non reconnu" or $warning[0] == "Section non reconnue") continue;
 			$phase_data["nb_warnings"]++;
 			$phase_data["warnings"][$warning[0]][] = $ret["adresse"] . chr(9) . $warning[1];
@@ -672,38 +668,38 @@ function traceTraitementNotice()
 	// Affichage toutes les 100 notices
 	if ($nb_notices % 100 == 0)
 	{
-		$log->ecrire("notice $nb_notices (" . $chrono100notices->tempsPasse() . " secondes)<br>");
+		$log->log("notice $nb_notices (" . $chrono100notices->tempsPasse() . " secondes)<br>");
 		$chrono100notices->start();
 	}
 	// Debug level a 1 on affiche le mode d'identificationde la notice
 	if ($debug_level > 1)
 	{
 		if ($nb_notices == 1) print(BR);
-		$log->ecrire('<span class="num_notice">Notice n° ' . $nb_notices . '</span>' . BR);
-		$log->ecrire('<span>Mode d\'identification ---> ' . $statut["identification"] . '</span>' . BR);
+		$log->log('<span class="num_notice">Notice n° ' . $nb_notices . '</span>' . BR);
+		$log->log('<span>Mode d\'identification ---> ' . $statut["identification"] . '</span>' . BR);
 	}
 	// Tout afficher si debug_level maxi
 	if ($debug_level > 2)
 	{
 		$detail = $notice->getNotice();
-		$log->ecrire('<div style=width:700px;margin-left:15px;margin-bottom:10px;">');
-		$log->ecrire('<table class="blank" cellspacing="0" cellpadding="5px">');
+		$log->log('<div style=width:700px;margin-left:15px;margin-bottom:10px;">');
+		$log->log('<table class="blank" cellspacing="0" cellpadding="5px">');
 		// Statut de retour
-		$log->ecrire('<tr><td class="blank">Traitement</td>');
+		$log->log('<tr><td class="blank">Traitement</td>');
 		if ($statut["erreur"]) $erreur = '<span class="rouge"> - ' . $statut["erreur"] . '</span>'; else $erreur="";
-		$log->ecrire('<td class="blank">' . $notice->libStatut[$code_statut] . $erreur . '</td></tr>');
+		$log->log('<td class="blank">' . $notice->libStatut[$code_statut] . $erreur . '</td></tr>');
 		// warnings
-		$log->ecrire('<tr><td class="blank" style="vertical-align:top">Anomalies</td>');
+		$log->log('<tr><td class="blank" style="vertical-align:top">Anomalies</td>');
 		if (count($statut["warnings"]) > 0)
 		{
-			$log->ecrire('<td class="blank"><font color="purple">');
+			$log->log('<td class="blank"><font color="purple">');
 			foreach ($statut["warnings"] as $warning)
 			{
-				$log->ecrire($warning[0] . " &raquo; " . $warning[1] . BR);
+				$log->log($warning[0] . " &raquo; " . $warning[1] . BR);
 			}
-			$log->ecrire('</font></td></tr>');
+			$log->log('</font></td></tr>');
 		}
-		else $log->ecrire('<td class="blank">aucune</td></tr>');
+		else $log->log('<td class="blank">aucune</td></tr>');
 		// Détail de l'enreg
 		foreach ($detail as $clef => $data)
 		{
@@ -711,10 +707,10 @@ function traceTraitementNotice()
 			{
 				for ($i = 0; $i < count($data); $i++)
 				{
-					$log->ecrire('<tr><td class="blank" style="vertical-align:top">Exemplaire ' . ($i + 1) . '</td>');
-					$log->ecrire('<td class="blank">');
-					foreach ($data[$i] as $key => $valeur) $log->ecrire($key . " = " . $valeur . BR);
-					$log->ecrire('</td></tr>');
+					$log->log('<tr><td class="blank" style="vertical-align:top">Exemplaire ' . ($i + 1) . '</td>');
+					$log->log('<td class="blank">');
+					foreach ($data[$i] as $key => $valeur) $log->log($key . " = " . $valeur . BR);
+					$log->log('</td></tr>');
 				}
 				continue;
 			} elseif ($clef == "warnings") continue;
@@ -724,11 +720,11 @@ function traceTraitementNotice()
 				foreach ($data as $key => $valeur) $aff.=$key . " = " . $valeur . BR;
 				$data = $aff;
 			}
-			$log->ecrire('<tr><td class="blank" style="vertical-align:top">' . $clef . '</td>');
+			$log->log('<tr><td class="blank" style="vertical-align:top">' . $clef . '</td>');
 			if ($data == "") $data = "&nbsp;";
-			$log->ecrire('<td class="blank">' . $data . '</td></tr>');
+			$log->log('<td class="blank">' . $data . '</td></tr>');
 		}
-		$log->ecrire("</table></div>");
+		$log->log("</table></div>");
 	}
 }
 
@@ -742,25 +738,25 @@ function traceHomogene($id_notice, $isbn, $ean, $id_commerciale)
 	$phase_data[$ret["statut_z3950"]]++;
 	if ($debug_level == 0)
 	{
-		if ($ret["statut"] == "erreur") $log->ecrire('<span class="vert">Connexion au serveur : ' . $ret["serveur"] . ' ---> </span><span class="rouge">' . $ret["erreur"] . '</span>' . BR);
-		elseif (!$phase_data["nombre"]) $log->ecrire('<span class="vert">Connexion au serveur : ' . $ret["serveur"] . ' ---> ok</span>' . BR);
+		if ($ret["statut"] == "erreur") $log->log('<span class="vert">Connexion au serveur : ' . $ret["serveur"] . ' ---> </span><span class="rouge">' . $ret["erreur"] . '</span>' . BR);
+		elseif (!$phase_data["nombre"]) $log->log('<span class="vert">Connexion au serveur : ' . $ret["serveur"] . ' ---> ok</span>' . BR);
 		if ($phase_data["nombre"] and $phase_data["nombre"] % 100 == 0)
 		{
-			$log->ecrire("notice " . $phase_data["nombre"] . " (" . $chrono100notices->tempsPasse() . " secondes)" . BR);
+			$log->log("notice " . $phase_data["nombre"] . " (" . $chrono100notices->tempsPasse() . " secondes)" . BR);
 			$chrono100notices->start();
 		}
 		return;
 	}
-	$log->ecrire('<a class="notice" href="' . URL_BASE . "php/analyse_afficher_notice_full.php?id_notice=" . $id_notice . '">Notice n° ' . $id_notice . '</a>' . BR);
-	$log->ecrire('<table class="blank" cellspacing="0" cellpadding="5px" style="margin-left:15px;margin-bottom:10px">');
-	if ($isbn) $log->ecrire('<tr><td class="blank">Isbn</td><td class="blank">' . $isbn . '</td></tr>');
-	if ($ean) $log->ecrire('<tr><td class="blank">Ean</td><td class="blank">' . $ean . '</td></tr>');
-	if ($id_commerciale) $log->ecrire('<tr><td class="blank">No commercial</td><td class="blank">' . $id_commerciale . '</td></tr>');
-	$log->ecrire('<tr><td class="blank">Serveur</td><td class="blank">' . $ret["serveur"] . '</td></tr>');
+	$log->log('<a class="notice" href="' . URL_BASE . "php/analyse_afficher_notice_full.php?id_notice=" . $id_notice . '">Notice n° ' . $id_notice . '</a>' . BR);
+	$log->log('<table class="blank" cellspacing="0" cellpadding="5px" style="margin-left:15px;margin-bottom:10px">');
+	if ($isbn) $log->log('<tr><td class="blank">Isbn</td><td class="blank">' . $isbn . '</td></tr>');
+	if ($ean) $log->log('<tr><td class="blank">Ean</td><td class="blank">' . $ean . '</td></tr>');
+	if ($id_commerciale) $log->log('<tr><td class="blank">No commercial</td><td class="blank">' . $id_commerciale . '</td></tr>');
+	$log->log('<tr><td class="blank">Serveur</td><td class="blank">' . $ret["serveur"] . '</td></tr>');
 	if ($ret["statut_z3950"] > 1) $class = "vert";
-	$log->ecrire('<tr><td class="blank">Statut</td><td class="blank"><span class="' . $class . '">' . communication::getLibelleStatutZ3950($ret["statut_z3950"]) . '</span></td></tr>');
-	if ($ret["erreur"]) $log->ecrire('<tr><td class="blank">Erreur</td><td class="blank"><span class="rouge">' . $ret["erreur"] . '</span></td></tr>');
-	$log->ecrire('</table>');
+	$log->log('<tr><td class="blank">Statut</td><td class="blank"><span class="' . $class . '">' . communication::getLibelleStatutZ3950($ret["statut_z3950"]) . '</span></td></tr>');
+	if ($ret["erreur"]) $log->log('<tr><td class="blank">Erreur</td><td class="blank"><span class="rouge">' . $ret["erreur"] . '</span></td></tr>');
+	$log->log('</table>');
 }
 
 function afficherRecapHomogene($phase_data, $chrono)
@@ -769,14 +765,14 @@ function afficherRecapHomogene($phase_data, $chrono)
 	$compteur[6]+=$phase_data[2] + $phase_data[3]; // Incrementer compteur global d'homogeneisation
 	for ($i = 0; $i < 4; $i++) if (!$phase_data[$i]) $phase_data[$i] = "0";
 
-	$log->ecrire(BR . '<span class="vert">' . ($phase_data["nombre"]) . ' notices traitées</span>' . BR);
+	$log->log(BR . '<span class="vert">' . ($phase_data["nombre"]) . ' notices traitées</span>' . BR);
 	$chrono->timeStart = $phase_data["timeStart"];
-	$log->ecrire('<span class="vert">Temps de traitement : ' . $chrono->end() . " (" . $chrono->moyenne($phase_data["nombre"], "notices") . ")</span>" . BR);
-	$log->ecrire('<table class="blank" cellspacing="0" cellpadding="5px" style="margin-left:25px;margin-bottom:10px;margin-top:10px">');
-	$log->ecrire('<tr><td class="blank">Notices homogenéisées</td><td class="blank" align="right">' . ($phase_data[2] + $phase_data[3]) . '</td></tr>');
-	$log->ecrire('<tr><td class="blank">Notices non trouvées</td><td class="blank" align="right">' . $phase_data[1] . '</td></tr>');
-	$log->ecrire('<tr><td class="blank">Echecs de connexions</td><td class="blank" align="right">' . $phase_data[0] . '</td></tr>');
-	$log->ecrire('</table>');
+	$log->log('<span class="vert">Temps de traitement : ' . $chrono->end() . " (" . $chrono->moyenne($phase_data["nombre"], "notices") . ")</span>" . BR);
+	$log->log('<table class="blank" cellspacing="0" cellpadding="5px" style="margin-left:25px;margin-bottom:10px;margin-top:10px">');
+	$log->log('<tr><td class="blank">Notices homogenéisées</td><td class="blank" align="right">' . ($phase_data[2] + $phase_data[3]) . '</td></tr>');
+	$log->log('<tr><td class="blank">Notices non trouvées</td><td class="blank" align="right">' . $phase_data[1] . '</td></tr>');
+	$log->log('<tr><td class="blank">Echecs de connexions</td><td class="blank" align="right">' . $phase_data[0] . '</td></tr>');
+	$log->log('</table>');
 }
 
 // ----------------------------------------------------------------
@@ -806,26 +802,26 @@ function traceSuccinte($ret)
 	{
 		if ($phase_data["nombre"] and $phase_data["nombre"] % 100 == 0)
 		{
-			$log->ecrire("notice " . $phase_data["nombre"] . " (" . $chrono100notices->tempsPasse() . " secondes)" . BR);
+			$log->log("notice " . $phase_data["nombre"] . " (" . $chrono100notices->tempsPasse() . " secondes)" . BR);
 			$chrono100notices->start();
 		}
 		return;
 	}
-	$log->ecrire('<a class="notice" href="' . URL_BASE . "php/analyse_afficher_notice_full.php?id_notice=" . $ret["id_notice"] . '">Notice n° ' . $ret["id_notice"] . '</a>' . BR);
-	$log->ecrire('<table class="blank" cellspacing="0" cellpadding="5px" style="margin-left:15px;margin-bottom:10px">');
-	$log->ecrire('<tr><td class="blank">Bibliothèque</td><td class="blank">' . $bib->getNomCourt($ret["id_bib"]) . '</td></tr>');
-	if ($ret["isbn"]) $log->ecrire('<tr><td class="blank">Isbn</td><td class="blank">' . $ret["isbn"] . '</td></tr>');
-	if ($ret["ean"]) $log->ecrire('<tr><td class="blank">Ean</td><td class="blank">' . $ret["ean"] . '</td></tr>');
-	if ($ret["id_commerciale"]) $log->ecrire('<tr><td class="blank">No commercial</td><td class="blank">' . $ret["id_commerciale"] . '</td></tr>');
-	if ($ret["statut"] == 4) $log->ecrire('<tr><td class="blank">Statut</td><td class="blank"><span class="vert">Trouvée dans la base</span></td></tr>');
+	$log->log('<a class="notice" href="' . URL_BASE . "php/analyse_afficher_notice_full.php?id_notice=" . $ret["id_notice"] . '">Notice n° ' . $ret["id_notice"] . '</a>' . BR);
+	$log->log('<table class="blank" cellspacing="0" cellpadding="5px" style="margin-left:15px;margin-bottom:10px">');
+	$log->log('<tr><td class="blank">Bibliothèque</td><td class="blank">' . $bib->getNomCourt($ret["id_bib"]) . '</td></tr>');
+	if ($ret["isbn"]) $log->log('<tr><td class="blank">Isbn</td><td class="blank">' . $ret["isbn"] . '</td></tr>');
+	if ($ret["ean"]) $log->log('<tr><td class="blank">Ean</td><td class="blank">' . $ret["ean"] . '</td></tr>');
+	if ($ret["id_commerciale"]) $log->log('<tr><td class="blank">No commercial</td><td class="blank">' . $ret["id_commerciale"] . '</td></tr>');
+	if ($ret["statut"] == 4) $log->log('<tr><td class="blank">Statut</td><td class="blank"><span class="vert">Trouvée dans la base</span></td></tr>');
 	else
 	{
-		$log->ecrire('<tr><td class="blank">Serveur</td><td class="blank">' . $ret["serveur"] . '</td></tr>');
+		$log->log('<tr><td class="blank">Serveur</td><td class="blank">' . $ret["serveur"] . '</td></tr>');
 		if ($ret["statut_z3950"] > 1) $class = "vert";
-		$log->ecrire('<tr><td class="blank">Statut</td><td class="blank"><span class="' . $class . '">' . communication::getLibelleStatutZ3950($ret["statut_z3950"]) . '</span></td></tr>');
+		$log->log('<tr><td class="blank">Statut</td><td class="blank"><span class="' . $class . '">' . communication::getLibelleStatutZ3950($ret["statut_z3950"]) . '</span></td></tr>');
 	}
-	if ($ret["erreur"]) $log->ecrire('<tr><td class="blank">Erreur</td><td class="blank"><span class="rouge">' . $ret["erreur"] . '</span></td></tr>');
-	$log->ecrire('</table>');
+	if ($ret["erreur"]) $log->log('<tr><td class="blank">Erreur</td><td class="blank"><span class="rouge">' . $ret["erreur"] . '</span></td></tr>');
+	$log->log('</table>');
 }
 
 // ----------------------------------------------------------------
diff --git a/cosmogramme/tests/php/classes/CosmoPathsTest.php b/cosmogramme/tests/php/classes/CosmoPathsTest.php
index 962902acceacbb827b055aa7523329912370bf49..41b4ace6588809743564cef11a66d00ad301c671 100644
--- a/cosmogramme/tests/php/classes/CosmoPathsTest.php
+++ b/cosmogramme/tests/php/classes/CosmoPathsTest.php
@@ -244,4 +244,33 @@ class CosmoPathsFromGitlabCiRunnerTest extends PHPUnit_Framework_TestCase {
 
 }
 
+
+
+class CosmoPathsFromCommandLineAtRootTest extends PHPUnit_Framework_TestCase {
+	protected $_cosmo_paths;
+
+	public function setUp() {
+		parent::setUp();
+		unset($_SERVER);
+    $_SERVER = ['SCRIPT_NAME' => 'cosmogramme/php/integre_traite_main.php',
+                'SCRIPT_FILENAME' => 'cosmogramme/php/integre_traite_main.php'];
+		$this->_cosmo_paths = new CosmoPaths();
+		$this->_cosmo_paths->setFileSystem(Storm_Test_ObjectWrapper::mock()
+																			 ->whenCalled('getcwd')
+																			 ->answers('/srv/http/bokeh.fr'));
+	}
+
+	/** @test */
+	public function configPathShouldBeCosmogrammeConfigDotPhp() {
+    $this->assertEquals('./cosmogramme/config.php', $this->_cosmo_paths->getConfigPath());
+	}
+
+
+  /** @test */
+	public function configIniPathShouldBeConfigIni() {
+    $this->assertEquals('./config.ini', $this->_cosmo_paths->getBokehConfigPath());
+	}
+
+}
+
 ?>
\ No newline at end of file
diff --git a/library/Class/Admin/Skin.php b/library/Class/Admin/Skin.php
index 5f9750f6115c6bf688df3a5f2bb7f8a10e39f3bd..c68af274d260567d9bf6a66a3cdccf7e306d0e5c 100644
--- a/library/Class/Admin/Skin.php
+++ b/library/Class/Admin/Skin.php
@@ -87,7 +87,7 @@ class Class_Admin_Skin {
   public function renderMenuIconOn($name, $view, $attribs = []) {
     $attribs = array_merge(['alt' => ''], $attribs);
 
-    if (!$src = $this->renderIconUrlOn('icons', $name))
+    if (!$src = $this->getIconUrl('icons', $name))
       return '';
 
     $attribs['src'] = $src;
@@ -98,7 +98,7 @@ class Class_Admin_Skin {
 
   public function renderActionIconOn($name, $view, $attribs = []) {
     $attribs = array_merge(['alt' => ''], $attribs);
-    $attribs['src'] = $this->renderIconUrlOn('actions', $name);
+    $attribs['src'] = $this->getIconUrl('actions', $name);
 
     return $view->tag('img', null, $attribs);
   }
@@ -107,7 +107,7 @@ class Class_Admin_Skin {
   public function renderButtonIconOn($name, $view, $attribs = []) {
     $attribs = array_merge(['alt' => ''], $attribs);
 
-    if (!$src = $this->renderIconUrlOn('buttons', $name))
+    if (!$src = $this->getIconUrl('buttons', $name))
       return '';
 
     $attribs['src'] = $src;
@@ -116,7 +116,7 @@ class Class_Admin_Skin {
   }
 
 
-  public function renderIconUrlOn($type, $name) {
+  public function getIconUrl($type, $name) {
     $config = $this->_getSkinConfig();
 
     if (!isset($config[$type][$name]))
diff --git a/library/Class/Album.php b/library/Class/Album.php
index da1bcef2ece2088e62d1e51164c32141bfa8079f..0c66bb9263a8f6b5b6fa32d4812fca59286d6f57 100644
--- a/library/Class/Album.php
+++ b/library/Class/Album.php
@@ -1123,11 +1123,14 @@ class Class_Album extends Storm_Model_Abstract {
     $this->check((0==(int)$this->getAnnee())
                  || (($this->getAnnee() >= self::ANNEE_MIN)
                      and ($this->getAnnee() <= $next_year)),
-                 sprintf("L'année doit être comprise entre %s et %s",
+                 sprintf($this->_("L'année doit être comprise entre %s et %s"),
                          self::ANNEE_MIN,
                          $next_year));
 
-    $this->check($this->hasTypeDocId(), 'L\'album doit avoir un type de document');
+    $this->check($this->hasTitre(),
+                 $this->_('Le titre est obligatoire'));
+    $this->check($this->hasTypeDocId(),
+                 $this->_('L\'album doit avoir un type de document'));
   }
 
 
diff --git a/library/Class/Batch/RessourceNumerique.php b/library/Class/Batch/RessourceNumerique.php
index 79f8d55e20c23a5cb51f859e54bfcc9e7509ebfb..8cfec77945d192814eaace227cfef8d149c5d542 100644
--- a/library/Class/Batch/RessourceNumerique.php
+++ b/library/Class/Batch/RessourceNumerique.php
@@ -30,7 +30,9 @@ abstract class Class_Batch_RessourceNumerique extends Class_Batch_Abstract {
 
   public function run() {
     if ($this->isEnabled())
-      $this->_getService()->harvest();
+      $this->_getService()
+           ->setLogger($this->getLogger())
+           ->harvest();
 
     return $this;
   }
diff --git a/library/Class/Cata/Log.php b/library/Class/Cata/Log.php
new file mode 100644
index 0000000000000000000000000000000000000000..84a19f16d6bbc44429b34ddd24b75411b7676e1e
--- /dev/null
+++ b/library/Class/Cata/Log.php
@@ -0,0 +1,84 @@
+<?php
+/**
+ * Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class Class_Cata_Log {
+  const
+    DEFAULT_TARGET = 'default',
+    ALL_TARGETS = '*';
+
+  protected $_targets = [];
+
+  public function addDefaultTarget($logger) {
+    return $this->addTarget(static::DEFAULT_TARGET, $logger);
+  }
+
+
+  public function addTarget($name, $logger) {
+    $this->_targets[$name] = $logger;
+    return $this;
+  }
+
+
+  public function log($message, $targets = ['default']) {
+    return $this->_targetsDo($targets, 'log', [$message]);
+  }
+
+
+  public function info($message, $targets = ['default']) {
+    return $this->_targetsDo($targets, 'info', [$message]);
+  }
+
+
+  public function success($message, $targets = ['default']) {
+    return $this->_targetsDo($targets, 'success', [$message]);
+  }
+
+
+  public function error($message, $targets = ['default']) {
+    return $this->_targetsDo($targets, 'error', [$message]);
+  }
+
+
+  protected function _targetsDo($targets, $method, $params) {
+    array_map(
+              function($logger) use ($method, $params)
+              {
+                call_user_func_array([$logger, $method], $params);
+              },
+              $this->_parseTargets($targets));
+
+    return $this;
+  }
+
+
+  protected function _parseTargets($targets) {
+    if (static::ALL_TARGETS == $targets)
+      return $this->_targets;
+
+    if (!is_array($targets))
+      $targets = [$targets];
+
+    return array_intersect_key($this->_targets,
+                               array_combine($targets, $targets));
+  }
+}
+?>
\ No newline at end of file
diff --git a/library/Class/Cata/LogVolatile.php b/library/Class/Cata/LogVolatile.php
new file mode 100644
index 0000000000000000000000000000000000000000..f20b76e13823bbdf8645751dd74c889a0f246f9f
--- /dev/null
+++ b/library/Class/Cata/LogVolatile.php
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class Class_Cata_LogVolatile {
+  protected $_lines = [];
+
+  public function getLines() {
+    return $this->_lines;
+  }
+
+
+  public function log($message) {
+    $this->_lines []= $message;
+  }
+
+
+  public function info($message) {
+    $this->_lines []= $message;
+  }
+
+
+  public function success($message) {
+    $this->_lines []= $message;
+  }
+
+
+  public function error($message) {
+    $this->_lines []= $message;
+  }
+}
+?>
\ No newline at end of file
diff --git a/library/Class/Cosmogramme/Integration/PhaseAbstract.php b/library/Class/Cosmogramme/Integration/PhaseAbstract.php
index 2b5dc96cf18c4368a2f48c8c96ec4f0ec5c5c76e..63f6de14d9c41583ffc30515ff796c7b4a4f0034 100644
--- a/library/Class/Cosmogramme/Integration/PhaseAbstract.php
+++ b/library/Class/Cosmogramme/Integration/PhaseAbstract.php
@@ -72,7 +72,7 @@ abstract class Class_Cosmogramme_Integration_PhaseAbstract {
       ->beSameCronAs($this->_phase)
       ->beSameCountAs($this->_phase);
 
-    $this->_log->ecrire('<h4>' . $this->_label . '</h4>');
+    $this->_log->log('<h4>' . $this->_label . '</h4>');
     $this->_init($new_phase);
     return $new_phase;
   }
@@ -91,7 +91,7 @@ abstract class Class_Cosmogramme_Integration_PhaseAbstract {
     try {
       $this->_execute();
     } catch (Exception $e) {
-      $this->_log->ecrire('<p class="rouge">' . sprintf('Erreur lors de l\'execution de la phase %s : <br/>%s<br/>%s',
+      $this->_log->log('<p class="rouge">' . sprintf('Erreur lors de l\'execution de la phase %s : <br/>%s<br/>%s',
                                                         $this->_label,
                                                         $e->getMessage(),
                                                         $e->getTraceAsString()) . '</p>');
diff --git a/library/Class/Cosmogramme/Integration/PhaseBatchs.php b/library/Class/Cosmogramme/Integration/PhaseBatchs.php
index 7b44847ed14745e5c09286f6fe082dfc457af2f4..4386ec6685d8d75be0ad75446de11625ed083e1f 100644
--- a/library/Class/Cosmogramme/Integration/PhaseBatchs.php
+++ b/library/Class/Cosmogramme/Integration/PhaseBatchs.php
@@ -34,7 +34,7 @@ class Class_Cosmogramme_Integration_PhaseBatchs
 
   protected function _execute() {
     if (!$this->_phase->isCron()) {
-      $this->_log->ecrire($this->_('Les batchs ne sont traités qu\'en mode cron.'));
+      $this->_log->log($this->_('Les batchs ne sont traités qu\'en mode cron.'));
       return;
     }
 
@@ -60,30 +60,25 @@ class Class_Cosmogramme_Integration_PhaseBatchs
 
 
   protected function _runOne($batch) {
-    $this->_log->addSuccess($batch->getLibelle());
+    $this->_log->success($batch->getLibelle());
     $this->_setData('pointeur_reprise', $batch->getId());
 
     try {
-      $batch->runWithLogger($this);
-      $this->_log->addSuccess($this->_('OK, temps de traitement : %s',
-                                       $this->_chrono->endFile()));
+      $batch->runWithLogger($this->_log);
+      $this->_log->success($this->_('OK, temps de traitement : %s',
+                                    $this->_chrono->endFile()));
 
     } catch (Exception $e) {
-      $this->_log->addError($this->_('Erreur lors de l\'execution du batch %s',
+      $this->_log->error($this->_('Erreur lors de l\'execution du batch %s',
                                      $batch->getLibelle()));
-      $this->_log->addError($e->getMessage());
-      $this->_log->addError($e->getTraceAsString());
+      $this->_log->error($e->getMessage());
+      $this->_log->error($e->getTraceAsString());
     }
 
     $this->_chrono->startOnFile();
   }
 
 
-  public function log($message) {
-    $this->_log->ecrire(nl2br($message) . '<br>');
-  }
-
-
   protected function _init($phase) {
     $phase
       ->resetDatas()
diff --git a/library/Class/Cosmogramme/Integration/PhaseDeleteRecordWithoutItem.php b/library/Class/Cosmogramme/Integration/PhaseDeleteRecordWithoutItem.php
index 3b3995cf0b619beabe809507c5bbbbe9a30ff9a8..b2bc4e26cedd2ca16847f936d15e8bfbc76ec5e4 100644
--- a/library/Class/Cosmogramme/Integration/PhaseDeleteRecordWithoutItem.php
+++ b/library/Class/Cosmogramme/Integration/PhaseDeleteRecordWithoutItem.php
@@ -39,17 +39,17 @@ class Class_Cosmogramme_Integration_PhaseDeleteRecordWithoutItem extends Class_C
       foreach ($records_ids as $record_id)
         $this->_runOne($record_id['id_notice']);
 
-      $this->_log->ecrire($this->_getData('deleted') . ' notices sans exemplaire supprimées<br/>');
+      $this->_log->log($this->_getData('deleted') . ' notices sans exemplaire supprimées<br/>');
       $this->_cleanMemory();
       $page++;
     }
 
     if (0 == $this->_getData('deleted')) {
-      $this->_log->ecrire('Aucune notice sans exemplaire');
+      $this->_log->log('Aucune notice sans exemplaire');
       return;
     }
 
-    $this->_log->ecrire('Temps de traitement: '.$this->_chrono->endMain().' ('.$this->_chrono->mainAverage($this->_getData('deleted'), 'notices').')' );
+    $this->_log->log('Temps de traitement: '.$this->_chrono->endMain().' ('.$this->_chrono->mainAverage($this->_getData('deleted'), 'notices').')' );
   }
 
 
diff --git a/library/Class/Cosmogramme/Integration/PhaseItemFacets.php b/library/Class/Cosmogramme/Integration/PhaseItemFacets.php
index 829bef1673fc8da0b04a03111bb78b29f8620408..d96701fc68222b74366e9952d44bdd8fd94d786d 100644
--- a/library/Class/Cosmogramme/Integration/PhaseItemFacets.php
+++ b/library/Class/Cosmogramme/Integration/PhaseItemFacets.php
@@ -43,7 +43,7 @@ class Class_Cosmogramme_Integration_PhaseItemFacets
         return $this->_phase;
 
       if (0 == ($this->_getData('nombre') % 100))
-        $this->_log->ecrire('<span class="vert"> ' . $this->_getData('nombre') . ' records updated </span>');
+        $this->_log->log('<span class="vert"> ' . $this->_getData('nombre') . ' records updated </span>');
 
       /* @see #23391 : whenever we fetched ths same record page, end loop */
       if ($this->_previous_records && (0 == count(array_filter(array_diff($this->_previous_records, $records)))))
@@ -59,7 +59,7 @@ class Class_Cosmogramme_Integration_PhaseItemFacets
 
     Class_CosmoVar::setValueOf('date_maj_facettes', $this->_last_update_date);
 
-    $this->_log->ecrire('<span class="vert">'.
+    $this->_log->log('<span class="vert">'.
                         'Toutes les exemplaires ont été mis à jour :' .
                         ' pointeur notice : ' . $this->_getData('pointeur_notice') .
                         ' pointeur : ' . $this->_getData('pointeur') .
@@ -70,7 +70,7 @@ class Class_Cosmogramme_Integration_PhaseItemFacets
       . ' (' . $this->_chrono->meanOnFile($this->_getData('nombre'),
                                           'notices') . ')</span>';
 
-    $this->_log->ecrire($msg);
+    $this->_log->log($msg);
   }
 
 
diff --git a/library/Class/Cosmogramme/Integration/PhaseNotice.php b/library/Class/Cosmogramme/Integration/PhaseNotice.php
index be6873e19bbf14a6120807e60a759a47833e1321..98e0668c8e1820405d4ef2851dc5b24988b8a729 100644
--- a/library/Class/Cosmogramme/Integration/PhaseNotice.php
+++ b/library/Class/Cosmogramme/Integration/PhaseNotice.php
@@ -57,16 +57,16 @@ class Class_Cosmogramme_Integration_PhaseNotice
     $data_source = $integration->getDataSource();
     if (!$data_source->isHttp()
         && !$this->getFileSystem()->filesize($data_source->getUri())) {
-      $this->_log->addError($this->_('Le fichier d\'import total est vide : aucun exemplaire supprimé.'));
+      $this->_log->error($this->_('Le fichier d\'import total est vide : aucun exemplaire supprimé.'));
       return;
     }
 
     $id_int_bib = $integration->getIdBib();
-    $this->_log->addInfo($this->_('Préparation des données'));
+    $this->_log->info($this->_('Préparation des données'));
 
     $nb = $this->_markItemsToBeDeleted($id_int_bib);
-    $this->_log->addSuccess($this->_('%d exemplaire(s) marqué(s) pour suppression',
-                                     $nb));
+    $this->_log->success($this->_('%d exemplaire(s) marqué(s) pour suppression',
+                                  $nb));
 
     $nb1 = Class_NoticeSuccincte::countBy(['id_bib' => $id_int_bib]);
     Class_NoticeSuccincte::deleteBy(['id_bib' => $id_int_bib]);
@@ -74,7 +74,7 @@ class Class_Cosmogramme_Integration_PhaseNotice
     Class_CodifThesaurus::deleteBy(['code' => null,
                                     'rules' => null]);
 
-    $this->_log->addSuccess($this->_('%d notices succinctes supprimées', $nb1));
+    $this->_log->success($this->_('%d notices succinctes supprimées', $nb1));
   }
 
 
@@ -109,7 +109,7 @@ class Class_Cosmogramme_Integration_PhaseNotice
 
     $nb = Class_Exemplaire::countBy($args);
     Class_Exemplaire::deleteBy($args);
-    $this->_log->addSuccess($this->_('%d exemplaire(s) supprimé(s)', $nb));
+    $this->_log->success($this->_('%d exemplaire(s) supprimé(s)', $nb));
   }
 
 
diff --git a/library/Class/Cosmogramme/Integration/PhaseOnDataSource.php b/library/Class/Cosmogramme/Integration/PhaseOnDataSource.php
index b8deeaa917654c2502ef137d6691995521802107..79f139c8faadfc920c7ec2ea83c6fa73f32ba7bb 100644
--- a/library/Class/Cosmogramme/Integration/PhaseOnDataSource.php
+++ b/library/Class/Cosmogramme/Integration/PhaseOnDataSource.php
@@ -40,7 +40,7 @@ abstract class Class_Cosmogramme_Integration_PhaseOnDataSource extends Class_Cos
       'aucun fichier traité';
 
     if (!$this->_phase->isCron() && !$this->isTimeOut())
-      $this->_log->ecrire('<br><span class="violet">' . $msg . '</span><br>');
+      $this->_log->log('<br><span class="violet">' . $msg . '</span><br>');
   }
 
 
@@ -58,7 +58,7 @@ abstract class Class_Cosmogramme_Integration_PhaseOnDataSource extends Class_Cos
     $data_source = $integration->getDataSource();
     if (!$data_source->isValid()) {
       Class_CosmoVar::increment('traitement_erreurs');
-      $this->_log->ecrire('<span class="rouge">Impossible d\'ouvrir la source : '
+      $this->_log->log('<span class="rouge">Impossible d\'ouvrir la source : '
                           . $data_source->getUri()
                           . '</span><br>');
       return;
@@ -132,14 +132,14 @@ abstract class Class_Cosmogramme_Integration_PhaseOnDataSource extends Class_Cos
 
     $line->withErrorDo(
                        function($error) {
-                            $this->_log->ecrire('<span class="rouge">' . $error . '</span><br>');
+                            $this->_log->log('<span class="rouge">' . $error . '</span><br>');
                        });
 
     $processed = $this->_getData('nombre');
     $msg = ($processed > 0) ?
       $processed . ' fiches ont pu être traitées.' :
       'aucune fiche n\'a pu être traitée.';
-    $this->_log->ecrire('<span class="vert">' . $msg . '</span>');
+    $this->_log->log('<span class="vert">' . $msg . '</span>');
 
     return true;
   }
@@ -151,15 +151,15 @@ abstract class Class_Cosmogramme_Integration_PhaseOnDataSource extends Class_Cos
 
     $processed = $this->_getData('nombre');
     if ($processed == 0) {
-      $this->_log->ecrire('<br><span class="vert">Le fichier ne contenait aucune fiche</span><br>');
+      $this->_log->log('<br><span class="vert">Le fichier ne contenait aucune fiche</span><br>');
       return true;
     }
 
-    $this->_log->ecrire('<br><span class="vert">' . $processed . ' fiches ont été traitées.</span>');
+    $this->_log->log('<br><span class="vert">' . $processed . ' fiches ont été traitées.</span>');
     $msg = "temps de traitement " . $this->_chrono->endFile()
       . ' (' . $this->_chrono->meanOnFile($processed, 'fiches') . ')';
 
-    $this->_log->ecrire('<br><span class="vert">' . $msg . '</span><br>');
+    $this->_log->log('<br><span class="vert">' . $msg . '</span><br>');
     return true;
   }
 
@@ -177,7 +177,7 @@ abstract class Class_Cosmogramme_Integration_PhaseOnDataSource extends Class_Cos
 
     $processed = $this->_getData('nombre');
     if (0 == $processed % 1000) {
-      $this->_log->ecrire('fiche ' . $processed
+      $this->_log->log('fiche ' . $processed
                           . ' (' . $this->_chrono->elapsedOnRecords()
                           . ' secondes)<br>');
       $this->_chrono->startOnRecords();
@@ -226,7 +226,7 @@ abstract class Class_Cosmogramme_Integration_PhaseOnDataSource extends Class_Cos
     $trace .= $this->_headerOfHook($integration);
 
     (!$integration->getPointeurReprise()) ?
-      $this->_log->ecrire($trace) :
+      $this->_log->log($trace) :
       $this->_getPrinter()->nextPutAll($trace . '<br>');
   }
 
diff --git a/library/Class/Cosmogramme/Integration/PhasePanier.php b/library/Class/Cosmogramme/Integration/PhasePanier.php
index 600af5daea6ab3665a34d51386e2f4950cee8317..48a62a069898b681fe6d907dfa5666d82cef83e1 100644
--- a/library/Class/Cosmogramme/Integration/PhasePanier.php
+++ b/library/Class/Cosmogramme/Integration/PhasePanier.php
@@ -41,7 +41,7 @@ class Class_Cosmogramme_Integration_PhasePanier extends Class_Cosmogramme_Integr
         && false === array_search('MAIL', $fields))
       $errors[] = 'Configuration: colonne IDABON ou MAIL requise';
 
-    array_map([$this->_log, 'addError'], $errors);
+    array_map([$this->_log, 'error'], $errors);
 
     return empty($errors);
   }
@@ -91,14 +91,14 @@ class Class_Cosmogramme_Integration_PhasePanier extends Class_Cosmogramme_Integr
 
   protected function importBasketRecord($datas, $integration) {
     if(!$map = $this->mapRecordColumns($integration, $datas))
-      return $this->_log->addError($this->_('Pas de donnée trouvée avec le profil de données sélectionné'));
+      return $this->_log->error($this->_('Pas de donnée trouvée avec le profil de données sélectionné'));
 
     if(!$map['libelle'])
-      return $this->_log->addError($this->_('Ligne non traitée car le libellé n\'a pas pu être lu'));
+      return $this->_log->error($this->_('Ligne non traitée car le libellé n\'a pas pu être lu'));
 
     if (!$exemplaire = Class_Exemplaire::findFirstBy(['id_origine' => $map['id_notice_sigb'],
                                                       'id_int_bib' => $integration->getIdBib()])) {
-      $this->_log->addError($this->_('L\'exemplaire id_origine : %s / id_int_bib : %s n\'a pas été trouvé.',
+      $this->_log->error($this->_('L\'exemplaire id_origine : %s / id_int_bib : %s n\'a pas été trouvé.',
                                      $map['id_notice_sigb'],
                                      $integration->getIdBib()));
       $exemplaire = new Class_Entity();
@@ -107,7 +107,7 @@ class Class_Cosmogramme_Integration_PhasePanier extends Class_Cosmogramme_Integr
     $owners = $this->findPossibleOwnersOfBasketRecord($map);
     if ($owners->isEmpty()) {
       $user = Class_Users::find(1);
-      $this->_log->addError($this->_('Le panier "%s" est orphelin. Il sera rattaché à l\'utilisateur "%s"',
+      $this->_log->error($this->_('Le panier "%s" est orphelin. Il sera rattaché à l\'utilisateur "%s"',
                                      $map['libelle'],
                                      $user->getLogin()));
       $owners->addAll([$user]);
diff --git a/library/Class/Cosmogramme/Integration/PhasePatrons.php b/library/Class/Cosmogramme/Integration/PhasePatrons.php
index 6a0c8517b8d678ef31727a56ce397ec54cd6c159..3da2a30e1bd73a711c3085a1d08b57e0d102e477 100644
--- a/library/Class/Cosmogramme/Integration/PhasePatrons.php
+++ b/library/Class/Cosmogramme/Integration/PhasePatrons.php
@@ -121,7 +121,7 @@ class Class_Cosmogramme_Integration_PhasePatrons extends Class_Cosmogramme_Integ
                                      ['IDABON']
                            ));
 
-    array_map([$this->_log, 'addError'], $errors);
+    array_map([$this->_log, 'error'], $errors);
 
     return empty($errors);
   }
@@ -132,7 +132,7 @@ class Class_Cosmogramme_Integration_PhasePatrons extends Class_Cosmogramme_Integ
                                         'statut' => Class_Users::STATUT_TO_BE_DELETED]))
       return;
 
-    $this->_log->ecrire('<span class="violet">'
+    $this->_log->log('<span class="violet">'
                         . $this->_('%d abonné(s) marqué(s) pour suppression',
                                    $count)
                         . '</span>');
diff --git a/library/Class/Cosmogramme/Integration/PhasePrepareIntegrations.php b/library/Class/Cosmogramme/Integration/PhasePrepareIntegrations.php
index 71ebad6015ddc59c8f014d3647a149e67c258599..48cf6a01287df1d2ec0d69905f012e61c5238d37 100644
--- a/library/Class/Cosmogramme/Integration/PhasePrepareIntegrations.php
+++ b/library/Class/Cosmogramme/Integration/PhasePrepareIntegrations.php
@@ -48,13 +48,13 @@ class Class_Cosmogramme_Integration_PhasePrepareIntegrations extends Class_Cosmo
   public function _execute() {
     (new Class_Systeme_Report_Publication())->push($this->_log);
 
-    $this->_log->ecrire('<h4>' . $this->_('Déplacement des intégrations en file d\'attente') . '</h4>');
-    $this->_log->ecrire('<br><table class="blank" cellspacing="0" cellpadding="5px">');
+    $this->_log->log('<h4>' . $this->_('Déplacement des intégrations en file d\'attente') . '</h4>');
+    $this->_log->log('<br><table class="blank" cellspacing="0" cellpadding="5px">');
 
     foreach (Class_IntMajAuto::findAllBy(['order' => 'rang']) as $majauto)
       $this->_runOne($majauto);
 
-    $this->_log->ecrire('</table>');
+    $this->_log->log('</table>');
 
     Class_CosmoVar::setValueOf('integration_date',
                                $this->getTimeSource()->dateDayAndHours());
@@ -66,7 +66,7 @@ class Class_Cosmogramme_Integration_PhasePrepareIntegrations extends Class_Cosmo
     if(!$bib = Class_IntBib::find($id_bib))
       return;
 
-    $this->_log->ecrire( '<tr><td class="blank"><span class="bib">' . $bib->getNomCourt($id_bib) .'</span></td><td class="blank">'.$majauto->getNomFichier().'</td><td class="blank">');
+    $this->_log->log( '<tr><td class="blank"><span class="bib">' . $bib->getNomCourt($id_bib) .'</span></td><td class="blank">'.$majauto->getNomFichier().'</td><td class="blank">');
 
     $ftpfile = $this->_getFtpFile($majauto->getNomFichier());
     $id_upload = Class_CosmoVar::get('ID_upload') + 1;
@@ -78,14 +78,14 @@ class Class_Cosmogramme_Integration_PhasePrepareIntegrations extends Class_Cosmo
                                                       'fichier' => $uri]))
         return $this;
 
-      $this->_log->ecrire('<span class="vert">Création de l\'intégration pour '. $uri .'</span></td>');
+      $this->_log->log('<span class="vert">Création de l\'intégration pour '. $uri .'</span></td>');
       $this->_newIntegration($uri, $majauto);
       return $this;
     }
 
 
     if (!$ftpfile || !$this->getFileSystem()->is_file($ftpfile)) {
-      $this->_log->ecrire("pas de transfert pour: $ftpfile</td>");
+      $this->_log->log("pas de transfert pour: $ftpfile</td>");
       return $this;
     }
 
@@ -93,12 +93,12 @@ class Class_Cosmogramme_Integration_PhasePrepareIntegrations extends Class_Cosmo
       return $this;
 
     if (true !== $this->getFilesystem()->rename($ftpfile, $this->_integration_path.$newfile)) {
-        $this->_log->ecrire('<span class="rouge">erreur au transfert du fichier</span></td>');
+        $this->_log->log('<span class="rouge">erreur au transfert du fichier</span></td>');
         $this->_incrementData('traitement_erreurs');
         return $this;
     }
 
-    $this->_log->ecrire('<span class="vert">transfert vers '.$newfile .'</span></td>');
+    $this->_log->log('<span class="vert">transfert vers '.$newfile .'</span></td>');
     $this->_newIntegration($newfile, $majauto);
     Class_CosmoVar::setValueOf('ID_upload', $id_upload);
   }
@@ -125,7 +125,7 @@ class Class_Cosmogramme_Integration_PhasePrepareIntegrations extends Class_Cosmo
     }
 
     if (!$dir = $this->getFileSystem()->opendir($ftp_path)) {
-      $this->_log->ecrire('<span class="rouge">répertoire inaccessible: '.$ftp_path.'</span>');
+      $this->_log->log('<span class="rouge">répertoire inaccessible: '.$ftp_path.'</span>');
       $this->_incrementData('traitement_erreurs');
       return null;
     }
@@ -157,7 +157,7 @@ class Class_Cosmogramme_Integration_PhasePrepareIntegrations extends Class_Cosmo
         $file_size = (int) (($file_size / 1024) / 1024);
 
       if($file_size < $minsize) {
-        $this->_log->ecrire('<span class="rouge">Le fichier est trop petit : '.$file_size.' mo -> taille minimun attendue : '.$minsize.' mo</span></td>');
+        $this->_log->log('<span class="rouge">Le fichier est trop petit : '.$file_size.' mo -> taille minimun attendue : '.$minsize.' mo</span></td>');
           return false;
       }
     }
diff --git a/library/Class/Cosmogramme/Integration/PhasePseudoRecord.php b/library/Class/Cosmogramme/Integration/PhasePseudoRecord.php
index 3ead13c40dc59b242cb8867285249f7a2300f00b..3f47f68b5248bc4c843911d7f736b120105638a7 100644
--- a/library/Class/Cosmogramme/Integration/PhasePseudoRecord.php
+++ b/library/Class/Cosmogramme/Integration/PhasePseudoRecord.php
@@ -62,7 +62,7 @@ abstract class Class_Cosmogramme_Integration_PhasePseudoRecord
 
 
   protected function _runPage($models) {
-    $this->_log->ecrire($this->_getData('nombre') . '<br>');
+    $this->_log->log($this->_getData('nombre') . '<br>');
     foreach($models as $model) {
       if ($this->isTimeOut())
         return;
@@ -99,7 +99,7 @@ abstract class Class_Cosmogramme_Integration_PhasePseudoRecord
 
   protected function _summarize() {
     if (!$processed = $this->_getData('nombre')) {
-      $this->_log->ecrire($this->_tagGreen($this->_('Aucune notice à traiter')) . '<br>');
+      $this->_log->log($this->_tagGreen($this->_('Aucune notice à traiter')) . '<br>');
       return;
     }
 
@@ -108,7 +108,7 @@ abstract class Class_Cosmogramme_Integration_PhasePseudoRecord
                                . $this->_chrono->endFile()
                                . ' (' . $this->_chrono->meanOnFile($processed, 'notices') . ')')];
 
-    $this->_log->ecrire(implode('<br>', $trace));
+    $this->_log->log(implode('<br>', $trace));
   }
 
 
diff --git a/library/Class/Cosmogramme/Integration/PhaseReviews.php b/library/Class/Cosmogramme/Integration/PhaseReviews.php
index 6a465b155e7bd19f03de2c3f64cfda24c559431d..2667043c92646140321146a3909c40266715409d 100644
--- a/library/Class/Cosmogramme/Integration/PhaseReviews.php
+++ b/library/Class/Cosmogramme/Integration/PhaseReviews.php
@@ -56,7 +56,7 @@ class Class_Cosmogramme_Integration_PhaseReviews extends Class_Cosmogramme_Integ
         return $this->_phase;
 
       if ($this->_log && (0 == ($this->_getData('nombre') % 100)))
-        $this->_log->ecrire('<span class="vert"> ' . $this->_getData('nombre') . ' avis mis à jour </span>');
+        $this->_log->log('<span class="vert"> ' . $this->_getData('nombre') . ' avis mis à jour </span>');
 
       $this->runUpdateForRecords($records);
 
@@ -66,7 +66,7 @@ class Class_Cosmogramme_Integration_PhaseReviews extends Class_Cosmogramme_Integ
     }
 
     if ($this->_log) {
-      $this->_log->ecrire('<span class="vert">'.
+      $this->_log->log('<span class="vert">'.
                           'Tous les avis ont été mis à jour :' .
                           '<br>' . $this->_getData('nombre') . ' avis traités.</span>');
 
@@ -75,7 +75,7 @@ class Class_Cosmogramme_Integration_PhaseReviews extends Class_Cosmogramme_Integ
         . ' (' . $this->_chrono->meanOnFile($this->_getData('nombre'),
                                           'notices') . ')</span>';
 
-      $this->_log->ecrire($msg);
+      $this->_log->log($msg);
     }
   }
 
diff --git a/library/Class/Systeme/Report/Publication.php b/library/Class/Systeme/Report/Publication.php
index 942f95f6ba4b1b1ffb55de5d24f0e8324442cf1a..0e29370c138318ca2b2f5d9e33f9d395e219d33f 100644
--- a/library/Class/Systeme/Report/Publication.php
+++ b/library/Class/Systeme/Report/Publication.php
@@ -30,7 +30,7 @@ class Class_Systeme_Report_Publication extends Class_WebService_Abstract {
     if (!(new ZendAfi_Validate_Url())->isValid($url))
       return $this;
 
-    $log->addInfo($this->_('Publication du rapport système'));
+    $log->info($this->_('Publication du rapport système'));
 
     $json = (new ZendAfi_View_Helper_Status_Json())->status_Json();
 
@@ -38,7 +38,7 @@ class Class_Systeme_Report_Publication extends Class_WebService_Abstract {
       $this->getHttpClient()->postData($url,
                                        ['report' => $json]);
     } catch (Exception $e) {
-      $log->addError($this->_('Echec de la publication du rapport sur %s (%s)',
+      $log->error($this->_('Echec de la publication du rapport sur %s (%s)',
                               $url,
                               $e->getMessage()));
     }
diff --git a/library/Class/WebService/Abstract.php b/library/Class/WebService/Abstract.php
index 3ee8d4a09056e36e4661b5342bb1f015dab6a80b..ddb1052ef6b698e784389b1ae62d1c875a8112b6 100644
--- a/library/Class/WebService/Abstract.php
+++ b/library/Class/WebService/Abstract.php
@@ -20,7 +20,7 @@
  */
 
 class Class_WebService_Abstract {
-  use Trait_Timesource;
+  use Trait_TimeSource, Trait_Logger;
 
   protected static $_http_client;
 
diff --git a/library/Class/WebService/BibNumerique/Abstract.php b/library/Class/WebService/BibNumerique/Abstract.php
index 04c97f564d878bbe83c47af2b5a057ea37e96279..9e3315f68c3d3dedf2a847d9b816cfa6b827aea6 100644
--- a/library/Class/WebService/BibNumerique/Abstract.php
+++ b/library/Class/WebService/BibNumerique/Abstract.php
@@ -54,18 +54,6 @@ abstract class Class_WebService_BibNumerique_Abstract extends Class_WebService_A
     return $this->_web_client;
   }
 
-  public function setLogger($logger) {
-    $this->_logger = $logger;
-    return $this;
-  }
-
-
-  public function getLogger() {
-    if (null == $this->_logger)
-      return new Zend_Log(new Zend_Log_Writer_Null());
-    return $this->_logger;
-  }
-
 
   public function harvestPage($page_number = 1) {
     if (1 == $page_number)
diff --git a/library/Class/WebService/BibNumerique/AbstractOAI.php b/library/Class/WebService/BibNumerique/AbstractOAI.php
index 5e2e21f59a1b86fe03d2eab0dea0b7629137a295..bea20e00742163ecf106fa18f3a40c51e35da627 100644
--- a/library/Class/WebService/BibNumerique/AbstractOAI.php
+++ b/library/Class/WebService/BibNumerique/AbstractOAI.php
@@ -21,12 +21,19 @@
 
 
 abstract class Class_WebService_BibNumerique_AbstractOAI extends Class_WebService_BibNumerique_Abstract {
+  use Trait_Translator;
 
-  protected $_harvested_ids = [], $_oaiws;
+  protected
+    $_harvested_ids = [],
+    $_oaiws;
 
   public function harvest() {
-    while($this->getOaiWS()->hasRecordsToHarvest())
-      $this->addHarvestedIds($this->_importRessources($this->loadPage()));
+    $page = 0;
+
+    while($this->getOaiWS()->hasRecordsToHarvest()) {
+      $page = $page + 1;
+      $this->addHarvestedIds($this->_importRessources($this->loadPage($page)));
+    }
 
     return $this->_logRun();
   }
@@ -40,6 +47,11 @@ abstract class Class_WebService_BibNumerique_AbstractOAI extends Class_WebServic
 
 
   protected function loadPage($page_number = 1) {
+    $this->getLogger()->log($this->_('Traitement de la page %d (nombre d\'enregistrements: %d)',
+                                     $page_number,
+                                     $this->getOaiWS()->getTotalNumberOfRecords()),
+                            'debug');
+
     return $this->getOaiWS()
                 ->getRecordsResourcesNumerique($this->_addFromTo([]));
   }
diff --git a/library/Class/WebService/BibNumerique/ArteVOD.php b/library/Class/WebService/BibNumerique/ArteVOD.php
index 6407d646165a0ec0a60949ed3efb49d4b78bdcd7..91355452974d2cb29f4d7a707b6b3b3310090ec7 100644
--- a/library/Class/WebService/BibNumerique/ArteVOD.php
+++ b/library/Class/WebService/BibNumerique/ArteVOD.php
@@ -33,7 +33,7 @@ class Class_WebService_BibNumerique_ArteVOD extends Class_WebService_BibNumeriqu
     $url = self::BASE_URL . self::FILMS . ((1 != $page_number) ? '?page_nb=' . $page_number: '');
     $content = $this->open_authenticated_url($url);
     if ('' == $content) {
-      $this->getLogger()->err('Erreur de communication');
+      $this->getLogger()->error('Erreur de communication');
       return;
     }
 
@@ -48,7 +48,7 @@ class Class_WebService_BibNumerique_ArteVOD extends Class_WebService_BibNumeriqu
   public function loadRessource($film) {
     $content = $this->open_authenticated_url(self::BASE_URL . self::FILMS . '/' . $film->getId());
     if ('' == $content) {
-      $this->getLogger()->err(sprintf('Erreur de communication lors de la récupération du film %s',
+      $this->getLogger()->error(sprintf('Erreur de communication lors de la récupération du film %s',
                                       $film->getId()));
       return;
     }
diff --git a/library/Class/WebService/BibNumerique/RessourceNumerique.php b/library/Class/WebService/BibNumerique/RessourceNumerique.php
index fdffff34f6a53d53e4652651a099efa0d537baf0..24ea8306df1911d1fa20cc3e019e7bad747c69e9 100644
--- a/library/Class/WebService/BibNumerique/RessourceNumerique.php
+++ b/library/Class/WebService/BibNumerique/RessourceNumerique.php
@@ -21,6 +21,7 @@
 
 
 class Class_WebService_BibNumerique_RessourceNumerique {
+  protected static $_logger;
 
   protected
     $_id,
@@ -43,6 +44,25 @@ class Class_WebService_BibNumerique_RessourceNumerique {
     $_authors = [];
 
 
+  static public function getLogger() {
+    if (!static::$_logger)
+      static::$_logger = new Class_Cata_Log();
+    return static::$_logger;
+  }
+
+
+  static public function setLogger($logger) {
+    static::$_logger = $logger;
+  }
+
+
+  protected function _debug($message) {
+    $ressource_name = str_replace('Class_WebService_BibNumerique_', '', get_class($this));
+    $this->getLogger()->log('[' . $ressource_name . '] ' . $message,
+                            'debug');
+  }
+
+
   public function setId($id) {
     $this->_id = $id;
     return $this;
@@ -246,9 +266,14 @@ class Class_WebService_BibNumerique_RessourceNumerique {
 
 
   public function import() {
-    if ($album = $this->findAlbumInDB())
+    $resource_log = '"' . $this->getTitle() . '" (' . $this->getId() . ')';
+
+    if ($album = $this->findAlbumInDB()) {
+      $this->_debug('update [' . $album->getId() . '] with ' . $resource_log) ;
       return $this->updateAlbum($album);
+    }
 
+    $this->_debug('create ' . $resource_log) ;
     return $this->createAlbum(Class_Album::newInstance());
   }
 
@@ -256,6 +281,10 @@ class Class_WebService_BibNumerique_RessourceNumerique {
   protected function updateAlbum($album) {
     $album->setRessources($this->getRessources());
     $album->save();
+
+    if ($album->hasErrors())
+      $this->_debug('errors: ' . implode(',', $album->getErrors()));
+
     Class_Album::clearCache();
     Class_AlbumRessource::clearCache();
     return $album;
@@ -286,8 +315,13 @@ class Class_WebService_BibNumerique_RessourceNumerique {
     $this->fillAlbumTypeDoc($album);
     $this->updateRessourceNumeriqueNotes($album);
 
-    if ($album->save())
+    if ($album->save()) {
+      $this->_debug('new album id: ' . $album->getId());
       Class_WebService_BibNumerique_Vignette::getInstance()->updateAlbum($album);
+    }
+
+    if ($album->hasErrors())
+      $this->_debug('errors: ' . implode(',', $album->getErrors()));
 
     Class_Album::clearCache();
     Class_AlbumRessource::clearCache();
diff --git a/library/Class/WebService/BibNumerique/ToutApprendre.php b/library/Class/WebService/BibNumerique/ToutApprendre.php
index 0522e8ce43b6a11775e20d43e3c1d537454ea953..79b5aeb832615c28d8fd23d5e2d57039f3fb05be 100644
--- a/library/Class/WebService/BibNumerique/ToutApprendre.php
+++ b/library/Class/WebService/BibNumerique/ToutApprendre.php
@@ -16,7 +16,7 @@
  *
  * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
  * along with BOKEH; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA 
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
 
 class Class_WebService_BibNumerique_ToutApprendre extends Class_WebService_BibNumerique_Abstract {
@@ -37,16 +37,16 @@ class Class_WebService_BibNumerique_ToutApprendre extends Class_WebService_BibNu
 
 
   public function harvest() {
-      
+
     $http_client = self::getHttpClient();
     $content = $http_client->open_url($this->url( Class_AdminVar::get('TOUTAPPRENDRE_BIB_ID')));
     if (!$content) {
-      $this->getLogger()->err('Erreur de communication');
+      $this->getLogger()->error('Erreur de communication');
       return;
     }
-      
+
     $this->getLogger()->info('Réponse reçue');
-    $this->parseXML($content);  
+    $this->parseXML($content);
     $this->_deleteNonHarvested();
     $this->getLogger()->info(sprintf('%d formations dans la base', count($this->_albums)));
   }
diff --git a/library/Class/WebService/BibNumerique/Vodeclic.php b/library/Class/WebService/BibNumerique/Vodeclic.php
index 04d848e66c4b26a1e7f5d38baa02acd1b4f7b70a..c12fc82e6e8350654534da50742178e306a0242a 100644
--- a/library/Class/WebService/BibNumerique/Vodeclic.php
+++ b/library/Class/WebService/BibNumerique/Vodeclic.php
@@ -46,7 +46,7 @@ class Class_WebService_BibNumerique_Vodeclic extends Class_WebService_BibNumeriq
                                                  Class_AdminVar::get('VODECLIC_KEY'),
                                                  Class_AdminVar::get('VODECLIC_BIB_ID')));
     if (!$content) {
-      $this->getLogger()->err('Erreur de communication');
+      $this->getLogger()->error('Erreur de communication');
       return;
     }
 
diff --git a/library/Class/WebService/ResumptionToken.php b/library/Class/WebService/ResumptionToken.php
index e669ffc9d52a9ead4c77b4f2b01e3f95e945a28a..aff89e3d23b398c032a0973eb0d1637c33659992 100644
--- a/library/Class/WebService/ResumptionToken.php
+++ b/library/Class/WebService/ResumptionToken.php
@@ -25,7 +25,9 @@
  */
 
 class Class_WebService_ResumptionToken {
-  protected $_token;
+  protected
+    $_token,
+    $_list_size;
 
   public function __construct($token=null) {
     $this->_token = $token;
diff --git a/library/Trait/Logger.php b/library/Trait/Logger.php
index c41ba4b23a07fb9e60d75e712e93aa3569106f15..48128194e0377812364cec081a267d84576ba8d4 100644
--- a/library/Trait/Logger.php
+++ b/library/Trait/Logger.php
@@ -30,12 +30,8 @@ trait Trait_Logger {
 
 
   public function getLogger() {
-    return $this->_logger ? $this->_logger : new Trait_LoggerNullLogger();
+    return $this->_logger
+      ? $this->_logger
+      : new Class_Cata_Log();
   }
-}
-
-
-
-class Trait_LoggerNullLogger {
-  public function log() {}
 }
\ No newline at end of file
diff --git a/library/ZendAfi/View/Helper/Bouton.php b/library/ZendAfi/View/Helper/Bouton.php
index 8d53127b23d2bf6e1b1187124f3f61c35fda8b64..15a040143b804a0d4364b43d6194ac34b9c61b38 100644
--- a/library/ZendAfi/View/Helper/Bouton.php
+++ b/library/ZendAfi/View/Helper/Bouton.php
@@ -54,7 +54,7 @@ class ZendAfi_View_Helper_Bouton extends ZendAfi_View_Helper_BaseHelper {
       $attrib = explode('=', $args[$i], 2);
       switch($attrib[0]) {
         case "id":$id=$attrib[1]; break;
-        case "picto" : $picto = Class_Admin_Skin::current()->renderIconUrlOn('buttons', $attrib[1]); break;
+        case "picto" : $picto = Class_Admin_Skin::current()->getIconUrl('buttons', $attrib[1]); break;
         case "texte"  : $texte=$attrib[1]; break;
         case "url" : $url=$attrib[1];
           $onclick="window.location.replace('".$url."')"; break;
@@ -67,7 +67,7 @@ class ZendAfi_View_Helper_Bouton extends ZendAfi_View_Helper_BaseHelper {
           if( $attrib[1]=="V")
           {
             if(!$id) $id="975";
-            $picto = Class_Admin_Skin::current()->renderIconUrlOn('buttons', 'validate');
+            $picto = Class_Admin_Skin::current()->getIconUrl('buttons', 'validate');
             if (!$texte)
               $texte = $this->translate()->_('Valider');
             if(!$largeur)
diff --git a/library/ZendAfi/View/Helper/CosmoLogs.php b/library/ZendAfi/View/Helper/CosmoLogs.php
new file mode 100644
index 0000000000000000000000000000000000000000..9fdcd6e6d708f37a7696ed52ed406c4c366c91fe
--- /dev/null
+++ b/library/ZendAfi/View/Helper/CosmoLogs.php
@@ -0,0 +1,180 @@
+<?php
+/**
+ * Copyright (c) 2012-2014, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class ZendAfi_View_Helper_CosmoLogs extends ZendAfi_View_Helper_BaseHelper {
+  use Trait_StormFileSystem;
+
+  const DAY_LOG_REGEX ='/integration_([0-9]{4}-[0-9]{2}-[0-9]{2})\.log/';
+
+  public function cosmoLogs() {
+    $table = (new Class_TableDescription('logs'))
+          ->addColumn($this->_('Date'),
+                      ['callback' => [$this, 'renderDay'],
+                       'options' => ['data-sorter' => "false"]])
+
+          ->addColumn($this->_('Rapport'),
+                      ['callback' => [$this, 'renderReport']])
+
+          ->addColumn($this->_('Debug'),
+                      ['callback' => [$this, 'renderDebugLog']])
+
+          ->addColumn($this->_('Notices traitées'),
+                      ['callback' => [$this, 'renderProcessedRecords']])
+
+          ->addColumn($this->_('Erreurs'),
+                      ['callback' => [$this, 'renderErrors']])
+
+          ->addColumn($this->_('Anomalies'),
+                      ['callback' => [$this, 'renderWarnings']]);
+
+    return  $this->view->renderTable($table, $this->_getDays());
+  }
+
+
+  public function renderDay($day) {
+    return
+      $this->view
+      ->tagAnchor(['module' => 'cosmo',
+                   'controller' => 'run-log',
+                   'action' => 'by-date',
+                   'date' => $day->getDay()],
+
+                  Class_Admin_Skin::current()->renderActionIconOn('loupe', $this->view)
+                  . $day->getHumanDate(),
+
+                  ['title' => $this->_('Lister les intégrations du %s',
+                                       $day->getHumanDate())]);
+  }
+
+
+  public function renderProcessedRecords($day) {
+    return $day->getProcessedRecords();
+  }
+
+
+  public function renderErrors($day) {
+    return $day->getErrors();
+  }
+
+
+  public function renderWarnings($day) {
+    return $day->getWarnings();
+  }
+
+
+  public function renderReport($day) {
+    return
+      $this->view
+      ->tagAnchor(['module' => 'cosmo',
+                   'controller' => 'logs',
+                   'action' => 'integration',
+                   'day' => $day->getDay()],
+
+                  Class_Admin_Skin::current()->renderActionIconOn('loupe', $this->view)
+                  . $this->_formatFileSize($day->getIntegrationSize()),
+
+                  ['title' => $this->_('Afficher le rapport d\'intégration du %s',
+                                       $day->getHumanDate())]);
+  }
+
+
+  public function renderDebugLog($day) {
+    return
+      $this->view
+      ->tagAnchor(['module' => 'cosmo',
+                   'controller' => 'logs',
+                   'action' => 'debug',
+                   'day' => $day->getDay()],
+
+                  Class_Admin_Skin::current()->renderActionIconOn('loupe', $this->view)
+                  . $this->_formatFileSize($day->getDebugSize()),
+
+                  ['title' => $this->_('Afficher le journal technique du %s',
+                                       $day->getHumanDate())]);
+  }
+
+
+  protected function _formatFileSize($size) {
+    $units = explode(',', $this->_('o,Ko,Mo,Go'));
+    $power = $size > 0 ? floor(log($size, 1024)) : 0;
+    return round($size / pow(1024, $power)) . ' ' . $units[$power];
+  }
+
+
+  protected function _getDays() {
+    $days = $this->_filesInLogDir()
+         ->select(function ($filename) {
+                    return preg_match(static::DAY_LOG_REGEX,
+                                      $filename); })
+         ->collect(function ($filename) {
+                    return $this->_newDay($filename);
+          });
+
+    $days->uasort(function($a, $b) {
+                    return strcmp($b->getDay(),
+                                  $a->getDay()); });
+    return $days;
+  }
+
+
+  protected function _newDay($filename) {
+    $day = preg_replace(static::DAY_LOG_REGEX,
+                        '$1',
+                        $filename);
+
+    $integrations = new Storm_Model_Collection(
+            Class_Cosmogramme_Integration::findAllBy(['traite' => $day]));
+
+    $sum_all = function($field) use ($integrations) {
+      return array_sum($integrations->collect($field)->getArrayCopy());
+    };
+
+    return (new Class_Entity())
+      ->setDay($day)
+      ->setHumanDate(strftime('%A %e %B %Y',  strtotime($day)))
+      ->setIntegrationSize($this->_getFileSize($filename))
+      ->setDebugSize($this->_getFileSize(str_replace('integration', 'debug', $filename)))
+      ->setProcessedRecords($sum_all('pointeur_reprise'))
+      ->setErrors($sum_all('nb_erreurs'))
+      ->setWarnings($sum_all('nb_warnings'));
+  }
+
+
+  protected function _filesInLogDir() {
+    return
+      new Storm_Collection($this->getFileSystem()
+                           ->fileNamesAt($this->_getLogPath()));
+  }
+
+
+  protected function _getLogPath() {
+    return Class_CosmoVar::getValueOf('log_path');
+  }
+
+
+  protected function _getFileSize($filename) {
+    return $this->getFileSystem()
+                ->fileGetSize($this->_getLogPath() . '/' . $filename);
+  }
+}
+
+?>
\ No newline at end of file
diff --git a/library/ZendAfi/View/Helper/Permalink.php b/library/ZendAfi/View/Helper/Permalink.php
index e1a300254b195b36d327f7a877297da2ea60f6fc..6f73582fd5d847eefe189b8667ce9f270f58bcb5 100644
--- a/library/ZendAfi/View/Helper/Permalink.php
+++ b/library/ZendAfi/View/Helper/Permalink.php
@@ -24,7 +24,7 @@ class ZendAfi_View_Helper_Permalink extends ZendAfi_View_Helper_BaseHelper {
     $icon = 'reseaux/permalink.png';
     $icon_url = $profil->skinHasImage($icon)
       ? $profil->getUrlImage($icon)
-      : Class_Admin_Skin::current()->renderIconUrlOn('actions', 'permalink');
+      : Class_Admin_Skin::current()->getIconUrl('actions', 'permalink');
 
     $lien_permanent = $this->view->_('Lien permanent');
 
diff --git a/library/ZendAfi/View/Helper/RenderTable.php b/library/ZendAfi/View/Helper/RenderTable.php
index 92f431dacf65e6a3bc33afbb6f6cbfb623364b88..a9777c7f63443fc70953cba0c5fb6331da8b2155 100644
--- a/library/ZendAfi/View/Helper/RenderTable.php
+++ b/library/ZendAfi/View/Helper/RenderTable.php
@@ -27,7 +27,7 @@ class ZendAfi_View_Helper_RenderTable extends ZendAfi_View_Helper_BaseHelper {
    * @param options Array
    */
   public function renderTable($description, $grouped_models, $options = []) {
-    $grouped_models = is_array($grouped_models)
+    $grouped_models = (is_array($grouped_models) || is_a($grouped_models, 'ArrayObject'))
       ? new Class_TableDescription_Models($grouped_models)
       : $grouped_models;
 
diff --git a/library/storm b/library/storm
index 57fb2c7f9ae96f2cb825484e4576619ffa2d91e7..90b15dfb0bcd36552ae16116b0e45c75b1ffcd89 160000
--- a/library/storm
+++ b/library/storm
@@ -1 +1 @@
-Subproject commit 57fb2c7f9ae96f2cb825484e4576619ffa2d91e7
+Subproject commit 90b15dfb0bcd36552ae16116b0e45c75b1ffcd89
diff --git a/public/admin/css/global.css b/public/admin/css/global.css
index 4add6a93cb74144c18d525105ab3b9cbc0128b3e..3cbe5b1cc85c2034318548aacee5b6ca1910059b 100644
--- a/public/admin/css/global.css
+++ b/public/admin/css/global.css
@@ -1520,3 +1520,8 @@ div.ColorPickerDivSample {
 [class*=edit-multiple] .modules form tr:hover {
     background-color: rgba(0, 0 , 0 , 0.15);
 }
+
+
+table#logs img {
+    vertical-align: middle;
+}
\ No newline at end of file
diff --git a/public/admin/skins/bokeh74/global.css b/public/admin/skins/bokeh74/global.css
index 3f9e333250649f65c73f8b5799dd7799654ba9bc..10ba904efb461be555a1c263d6b69aceb31e8871 100755
--- a/public/admin/skins/bokeh74/global.css
+++ b/public/admin/skins/bokeh74/global.css
@@ -863,3 +863,8 @@ form .droite {
 .modules .bokeh-days > a:hover {
     color: #6AA5FF;
 }
+
+
+table#logs img {
+    vertical-align: middle;
+}
\ No newline at end of file
diff --git a/scripts/branchcode_indexation.php b/scripts/branchcode_indexation.php
index 7335935aafd271a0a7ce305daddc19537ef22f78..03a0f4f5f88fcae73aa5f72164a4dc7e1e28c11a 100644
--- a/scripts/branchcode_indexation.php
+++ b/scripts/branchcode_indexation.php
@@ -54,10 +54,10 @@ $phase = Class_Cosmogramme_Integration_Phase::fromLegacyState(6,
 $append_log = function($content) { echo "\n" . $content . "\n"; };
 
 $log = (new Class_Entity())
-  ->whenCalledDo('addError', $append_log)
-  ->whenCalledDo('addSuccess', $append_log)
-  ->whenCalledDo('addInfo', $append_log)
-  ->whenCalledDo('ecrire', $append_log);
+  ->whenCalledDo('error', $append_log)
+  ->whenCalledDo('success', $append_log)
+  ->whenCalledDo('info', $append_log)
+  ->whenCalledDo('log', $append_log);
 
 (new Class_Cosmogramme_Integration_PhaseItemFacets($phase,
                                                    $log,
diff --git a/tests/application/modules/admin/controllers/AlbumControllerPharoVideosTest.php b/tests/application/modules/admin/controllers/AlbumControllerPharoVideosTest.php
index 71af3eb883d8dfab2e8631232e65bfa44ef3f4bd..3231403b7855ec0e4c6ee826fa29b1fd66738477 100644
--- a/tests/application/modules/admin/controllers/AlbumControllerPharoVideosTest.php
+++ b/tests/application/modules/admin/controllers/AlbumControllerPharoVideosTest.php
@@ -27,12 +27,14 @@ abstract class Admin_AlbumControllerPharoVideosTestCase extends Admin_AbstractCo
   public function setUp() {
     parent::setUp();
 
-    $this->fixture('Class_Album', ['id' =>'777',
-                                   'status' => Class_Album::STATUS_VALIDATED,
-                                   'categorie' => $this->fixture('Class_AlbumCategorie',
-                                                                 ['id' => 1,
-                                                                  'libelle' => 'Languages de prog.'])
-                     ]);
+    $this->fixture('Class_Album',
+                   ['id' =>'777',
+                    'titre' => 'Pharo',
+                    'status' => Class_Album::STATUS_VALIDATED,
+                    'categorie' => $this->fixture('Class_AlbumCategorie',
+                                                  ['id' => 1,
+                                                   'libelle' => 'Languages de prog.'])
+                   ]);
   }
 }
 
@@ -68,9 +70,11 @@ class Admin_AlbumControllerPharoVideosAddTest extends Admin_AlbumControllerPharo
   public function durationShouldBe2min30() {
     $this->assertXPath( '//input[@type="text"][@name="duration"]');
   }
-
 }
 
+
+
+
 class Admin_AlbumControllerPharoVideosPostAddTest extends Admin_AlbumControllerPharoVideosTestCase {
   protected $new_ressource;
 
@@ -115,6 +119,8 @@ class Admin_AlbumControllerPharoVideosPostAddTest extends Admin_AlbumControllerP
 }
 
 
+
+
 class Admin_AlbumControllerPharoVideosEditTest extends Admin_AlbumControllerPharoVideosTestCase {
   public function setUp() {
     parent::setUp();
diff --git a/tests/application/modules/admin/controllers/AlbumControllerTest.php b/tests/application/modules/admin/controllers/AlbumControllerTest.php
index 8aa9d9d95288bf86afefed2f2c08b93b2384c2fd..e06f7c5b555b2808ef1151740cdd92b26e21554f 100644
--- a/tests/application/modules/admin/controllers/AlbumControllerTest.php
+++ b/tests/application/modules/admin/controllers/AlbumControllerTest.php
@@ -78,10 +78,10 @@ abstract class Admin_AlbumControllerTestCase extends Admin_AbstractControllerTes
                                            'from_target' => 'A pour diaporama']);
 
     $this->fixture('Class_Album', ['id' => 43,
+                                   'titre' => 'Mes BD',
                                    'pcdm4' => 'Musique;Dessin',
                                    'notes' => 'a:3:{s:5:"305$a";s:12:"XIIe siècle";s:5:"200$b";s:9:"Parchemin";s:5:"316$a";s:12:"Reliure bois";}'])
 
-         ->setTitre('Mes BD')
          ->setTags('bd;dessin')
          ->setDescription('Les préférées')
          ->setAnnee(1978)
@@ -99,8 +99,8 @@ abstract class Admin_AlbumControllerTestCase extends Admin_AbstractControllerTes
          ->setCategorie($favoris)
          ->save();
 
-    $this->fixture('Class_Album', ['id' => 44])
-      ->setTitre('Bible Souvigny')
+    $this->fixture('Class_Album', ['id' => 44,
+                                   'titre' => 'Bible Souvigny'])
       ->setStatus(Class_Album::STATUS_VALIDATED)
       ->beLivreNumerique()
       ->setThumbnailAttributes(['thumbnail_width' => 350,
diff --git a/tests/application/modules/admin/controllers/OpdsControllerTest.php b/tests/application/modules/admin/controllers/OpdsControllerTest.php
index 91a91791a82802888a4b41a89d47eda964a1f30b..90636df1ac13f0a8d66679c63cf97346bb35a464 100644
--- a/tests/application/modules/admin/controllers/OpdsControllerTest.php
+++ b/tests/application/modules/admin/controllers/OpdsControllerTest.php
@@ -18,9 +18,10 @@
  * along with BOKEH; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
-require_once 'AdminAbstractControllerTestCase.php';
 
 abstract class Admin_OpdsControllerTestCase extends Admin_AbstractControllerTestCase {
+  protected $_storm_default_to_volatile  = true;
+
   public function setUp() {
     parent::setUp();
     Storm_Test_ObjectWrapper::onLoaderOfModel('Class_OpdsCatalog')
@@ -360,12 +361,6 @@ class Admin_OpdsControllerUnknownIdsActionErrorsTest extends Admin_OpdsControlle
 
 
 class Admin_OpdsControllerActionsWithUnknowCatalogTest extends Admin_OpdsControllerTestCase {
-  public function setUp() {
-    parent::setUp();
-    Class_OpdsCatalog::beVolatile();
-  }
-
-
   /** @test */
   public function browseShouldRedirectToIndex() {
     $this->dispatch('/admin/opds/browse/id/666');
@@ -508,6 +503,8 @@ class Admin_OpdsControllerBrowseActionTest extends Admin_OpdsControllerBrowseEbo
 }
 
 
+
+
 class Admin_OpdsControllerBrowseEbooksGratuitsLastUpdatedTest extends Admin_OpdsControllerBrowseEbooksGratuitsTestCase  {
   public function setUp() {
     parent::setUp();
@@ -558,15 +555,18 @@ class Admin_OpdsControllerBrowseEbooksGratuitsImportTest extends Admin_OpdsContr
   public function setUp() {
     parent::setUp();
 
+    $this->fixture('Class_CosmoVar', ['id' => 'types_docs', 'liste' => '']);
+
     Class_OpdsCatalog::getLoader()->find(1)
       ->getWebClient()
       ->whenCalled('open_url')
       ->with('http://www.opacsgratuits.com/opds/feed.php?mode=maj')
       ->answers(OPDSFeedFixtures::ebooksGratuitsLastUpdatedXml());
 
-    $this->fixture('Class_Album', ['id'=>776]);
-    Class_AlbumRessource::beVolatile();
-    Class_AlbumCategorie::beVolatile();
+    $this->fixture('Class_Album',
+                   ['id'=>776,
+                    'titre' => 'Free book !']);
+
     $codif_type_doc=$this->fixture('Class_CodifTypeDoc', ['id' => Class_TypeDoc::EPUB,
                                                           'famille_id' => Class_CodifTypeDoc::INCONNU,
                                                           'bibliotheques' => '1;5',
@@ -642,8 +642,6 @@ class Admin_OpdsControllerBrowseSearchPostActionTest extends Admin_OpdsControlle
   public function setUp() {
     parent::setUp();
 
-
-
     $this->postDispatch('/admin/opds/browse/id/1', array('search' => 'dracula'));
   }
 
diff --git a/tests/application/modules/admin/controllers/UploadControllerTest.php b/tests/application/modules/admin/controllers/UploadControllerTest.php
index 027a1d36dde58929b46714d456706849f1fe711d..ed42f18d319adc45d26ab91c0fffb12fff21055d 100644
--- a/tests/application/modules/admin/controllers/UploadControllerTest.php
+++ b/tests/application/modules/admin/controllers/UploadControllerTest.php
@@ -18,7 +18,6 @@
  * along with BOKEH; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
-require_once 'AbstractControllerTestCase.php';
 
 class UploadControllerMultipleActionTest extends AbstractControllerTestCase {
   public function setUp() {
@@ -96,7 +95,7 @@ class UploadControllerMultipleProcessPostAction extends AbstractControllerTestCa
 
   /** @test */
   public function withModelShouldCallFileProcessingMethod() {
-    $album = Storm_Test_ObjectWrapper::on(Class_Album::getLoader()->newInstance())
+    $album = Storm_Test_ObjectWrapper::on(Class_Album::getLoader()->newInstance(['titre' => 'Pomdapi']))
       ->whenCalled('addFile')->answers(array('success' => 'true'))
       ->whenCalled('index')->answers(null)
       ->getWrapper();
diff --git a/tests/application/modules/opac/controllers/BibNumeriqueControllerDilicomTest.php b/tests/application/modules/opac/controllers/BibNumeriqueControllerDilicomTest.php
index a157ca7817a6ef01ea9efe4d542db1cfe3c50c28..c708628df4265e51485c3cdbce736c9396bb8438 100644
--- a/tests/application/modules/opac/controllers/BibNumeriqueControllerDilicomTest.php
+++ b/tests/application/modules/opac/controllers/BibNumeriqueControllerDilicomTest.php
@@ -51,7 +51,7 @@ abstract class BibNumeriqueContollerDilicomTestCase extends AbstractControllerTe
 
     $this->book = $this->fixture('Class_Album',
                                  ['id' => 3,
-                                  'libelle' => 'Totem et Thora',
+                                  'titre' => 'Totem et Thora',
                                   'id_origine' => 'Dilicom-88817216',
                                   'external_uri' => 'http://www.edenlivres.fr/p/23416',
                                   'type_doc_id' => Class_TypeDoc::DILICOM,
diff --git a/tests/application/modules/opac/controllers/NoticeAjaxControllerTest.php b/tests/application/modules/opac/controllers/NoticeAjaxControllerTest.php
index 33e751c02ca1ee748075f336500162c929b22e19..f6ec64e54b6be5423a0fcbb5930dc36fa112f51c 100644
--- a/tests/application/modules/opac/controllers/NoticeAjaxControllerTest.php
+++ b/tests/application/modules/opac/controllers/NoticeAjaxControllerTest.php
@@ -297,6 +297,7 @@ class NoticeAjaxControllerResNumeriquesTest extends AbstractControllerTestCase {
   /** @test */
   public function bookletShouldBeLoadedWithAlbumTypeLivreNumerique() {
     $album = $this->fixture('Class_Album', ['id' => 8,
+                                            'titre' => 'old book',
                                             'type_doc_id' => Class_TypeDoc::LIVRE_NUM]);
 
     $this->dispatch('noticeajax/resnumeriques?id_notice=123');
@@ -320,6 +321,7 @@ class NoticeAjaxControllerResNumeriquesTest extends AbstractControllerTestCase {
   /** @test */
   public function diaporamaShouldBeLoadedWithAlbumTypeDiaporama() {
     $album = $this->fixture('Class_Album', ['id' => 8,
+                                            'titre' => 'diapo vacances',
                                             'type_doc_id' => Class_TypeDoc::DIAPORAMA]);
 
     $this->dispatch('noticeajax/resnumeriques?id_notice=123', true);
@@ -2214,9 +2216,11 @@ class NoticeAjaxControllerRessourceEpubPictoTypeTest extends AbstractControllerT
   public function withPictoInSkinShouldUseIt() {
     $album = $this->fixture('Class_Album',
                             ['id' => 12,
+                             'titre' => 'Cowboy Bebop',
                              'type_doc_id' => Class_TypeDoc::EPUB,
                              'ressources' => [$this->fixture('Class_AlbumRessource',
                                                              ['id' => 22,
+                                                              'titre' => 'Cowboy Bebop epub',
                                                               'fichier' => 'my.epub'])]]);
 
     $this->fixture('Class_Notice',
diff --git a/tests/application/modules/telephone/controllers/AbonneControllerTest.php b/tests/application/modules/telephone/controllers/AbonneControllerTest.php
index cf900818eb940a7839bf5b706651dc610f44369d..843eea8d1e7bd644f0866948df4872fe19e035b7 100644
--- a/tests/application/modules/telephone/controllers/AbonneControllerTest.php
+++ b/tests/application/modules/telephone/controllers/AbonneControllerTest.php
@@ -166,7 +166,10 @@ class AbonneControllerTelephoneFicheWithPNBTest extends AbonneControllerTelephon
     parent::setUp();
 
     $this->fixture('Class_Album',
-                   ['id' => 64, 'id_origine' => 'Dilicom-8907', 'notice_id' => '2367']);
+                   ['id' => 64,
+                    'titre' => 'Dilicomotion',
+                    'id_origine' => 'Dilicom-8907',
+                    'notice_id' => '2367']);
 
     $this->fixture('Class_Loan_Pnb',
                    ['id' => 42,
diff --git a/tests/fixtures/DilicomFixtures.php b/tests/fixtures/DilicomFixtures.php
index 3e97a0b15f47baaba6efcfbd9a196fdf8ce2b484..db1304b30ae08a387291f2601a84c727454de64e 100644
--- a/tests/fixtures/DilicomFixtures.php
+++ b/tests/fixtures/DilicomFixtures.php
@@ -173,7 +173,7 @@ class DilicomFixtures {
   public function albumTotemThora() {
     return $this->fixture('Class_Album',
                           ['id' => 3,
-                           'libelle' => 'Totem et Thora',
+                           'titre' => 'Totem et Thora',
                            'id_origine' => 'Dilicom-88817216',
                            'external_uri' => 'http://www.edenlivres.fr/p/23416',
                            'type_doc_id' => Class_TypeDoc::DILICOM,
diff --git a/tests/fixtures/onedtouch_oai.xml b/tests/fixtures/onedtouch_oai.xml
index 3dd5b5b1d65770e171e13ee62f08160dbb92c0a2..a8cf7077a9267fcfbbdb0c7d767ddbd729e7af48 100644
--- a/tests/fixtures/onedtouch_oai.xml
+++ b/tests/fixtures/onedtouch_oai.xml
@@ -5,6 +5,13 @@
   <request metadataPrefix="oai1dtouch_dc" verb="ListRecords">http://dev.1dtouch.com/oai
   </request>
   <ListRecords>
+    <record>
+      <header status="deleted">
+	<identifier>oai:oai1dtouch.com/album2</identifier>
+	<datestamp>2017-02-22T12:46:19Z</datestamp>
+	<setSpec>music</setSpec>
+      </header>
+    </record>
     <record>
       <header>
 	<identifier>oai:oai1dtouch.com:124
diff --git a/tests/library/Class/Album/UsageConstraintTest.php b/tests/library/Class/Album/UsageConstraintTest.php
index 75a16b6f17703c13a9b563f010fbd3fbb23d5efd..8bb6b0967abc84699ee343b58d5f2b0fb30c05e4 100644
--- a/tests/library/Class/Album/UsageConstraintTest.php
+++ b/tests/library/Class/Album/UsageConstraintTest.php
@@ -25,7 +25,8 @@ class Class_Album_UsageConstraintTest extends Storm_Test_ModelTestCase {
     Storm_Model_Loader::defaultToVolatile();
 
     $this->fixture('Class_Album',
-                   ['id' => 23]);
+                   ['id' => 23,
+                   'titre' => 'cybersecurity explained']);
 
 
     $this->fixture('Class_Album_Item',
diff --git a/tests/library/Class/AlbumRessourceTest.php b/tests/library/Class/AlbumRessourceTest.php
index 3d7da1ec745d6d88232c0fd65fe507e7b9308be5..b7eccd32b8ca8ba5ac1fd7a7aed0b4e76ca06740 100644
--- a/tests/library/Class/AlbumRessourceTest.php
+++ b/tests/library/Class/AlbumRessourceTest.php
@@ -144,7 +144,9 @@ class AlbumRessourceLoaderTest extends ModelTestCase {
                                             'id_album' => 999,
                                             'ordre' => 6]);
 
-    $album = $this->fixture('Class_Album', ['id' => 999]);
+    $album = $this->fixture('Class_Album',
+                            ['id' => 999,
+                             'titre' => 'Harlock']);
     $this->assertEquals(7,Class_AlbumRessource::getNextOrderFor($album));
   }
 
diff --git a/tests/library/Class/Batch/DilicomTest.php b/tests/library/Class/Batch/DilicomTest.php
index d597396837cdbe64fddf84973199816aa2a1398a..a4bf4ee1b76976eea8c92f9807d69348539b14e2 100644
--- a/tests/library/Class/Batch/DilicomTest.php
+++ b/tests/library/Class/Batch/DilicomTest.php
@@ -24,7 +24,8 @@ require_once 'tests/fixtures/DilicomFixtures.php';
 abstract class Class_Batch_DilicomTestCase extends ModelTestCase {
   protected
     $_storm_default_to_volatile = true,
-    $_log = '';
+    $_log = '',
+    $_debug_log = '';
 
   public function setUp() {
     parent::setUp();
@@ -35,7 +36,11 @@ abstract class Class_Batch_DilicomTestCase extends ModelTestCase {
     return $this->logger = $this->mock()
                                 ->whenCalled('log')
                                 ->willDo(
-                                         function($message) {
+                                         function($message, $target = '') {
+                                           if ($target == 'debug') {
+                                             $this->_debug_log .= $message . "\n";
+                                             return;
+                                           }
                                            $this->_log .= $message;
                                          });
   }
@@ -138,6 +143,8 @@ abstract class Class_Batch_DilicomJobOnixTestCase extends Class_Batch_DilicomTes
 
     Class_Batch_DilicomJobOnix::setFileSystem($file_system);
 
+    Class_WebService_BibNumerique_RessourceNumerique::setLogger($this->getLogger());
+
     (new Class_Batch_DilicomJobOnix(new Class_Batch_Dilicom))
       ->setFtpClient($this->getFtpClient())
       ->setLogger($this->getLogger())
@@ -145,6 +152,12 @@ abstract class Class_Batch_DilicomJobOnixTestCase extends Class_Batch_DilicomTes
   }
 
 
+  public function tearDown() {
+    Class_WebService_BibNumerique_RessourceNumerique::setLogger(null);
+    parent::tearDown();
+  }
+
+
   protected function _prepareFixtures() { }
 
 
@@ -297,6 +310,16 @@ class Class_Batch_DilicomJobOnixWithFullTest extends Class_Batch_DilicomJobOnixT
     $this->assertEquals('diffusion_pnb_3056309900005_20150728T050431Z.xml',
                         (new Class_Batch_Dilicom)->getModel()->getData());
   }
+
+
+  /** @test */
+  public function debugLogShouldContainsImportLaReineDesNeiges() {
+    $this->assertContains('[Dilicom_Book] create "La Reine des Neiges" (Dilicom-9782290123409)',
+                          $this->_debug_log);
+
+    $this->assertContains('new album id: 1',
+                          $this->_debug_log);
+  }
 }
 
 
diff --git a/tests/library/Class/BatchTest.php b/tests/library/Class/BatchTest.php
index a9a5c284c1dc341bc4cfbfd5bfd065b20333c109..9b52b3119796d4b2ac3611f485b8ea0b937c9e5e 100644
--- a/tests/library/Class/BatchTest.php
+++ b/tests/library/Class/BatchTest.php
@@ -124,7 +124,7 @@ class BatchLoaderWithoutRessourcesNumeriquesTest extends Storm_Test_ModelTestCas
 class BatchIndexRessourcesNumeriquesTest extends Storm_Test_ModelTestCase {
   public function setUp() {
     $album = $this->fixture('Class_Album', ['id' => 1,
-                                            'libelle' => 'Mon Album',
+                                            'titre' => 'Mon Album',
                                             'status' => Class_Album::STATUS_VALIDATED]);
     Class_Notice::beVolatile();
 
@@ -136,11 +136,13 @@ class BatchIndexRessourcesNumeriquesTest extends Storm_Test_ModelTestCase {
     (new Class_Batch_IndexRessourcesNumeriques())->run();
   }
 
+
   /** @test */
   public function afterRunNoticeShouldExists() {
     $this->assertCount(1, Class_Notice::findAll());
   }
 
+
   /** @test */
   public function afterRunCacheShouldBeCleaned() {
     $this->assertEmpty($this->cache->load('data'));
diff --git a/tests/library/Class/Cata/LogTest.php b/tests/library/Class/Cata/LogTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..ce7150ed0d12267bed654ff07a6d90c1c52821c7
--- /dev/null
+++ b/tests/library/Class/Cata/LogTest.php
@@ -0,0 +1,100 @@
+<?php
+/**
+ * Copyright (c) 2012-2017, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+
+class Class_Cata_LogTest extends ModelTestCase {
+  protected $_logs;
+
+  protected function newLog($target) {
+    $append_log = function($message) use ($target) {
+      $this->_logs[$target][] = $message;
+    };
+
+    $mock = $this->mock();
+    foreach(['log', 'info', 'success', 'error'] as $method)
+      $mock->whenCalled($method)->willDo($append_log);
+    return $mock;
+  }
+
+
+  public function setUp() {
+    parent::setUp();
+
+    $this->_logs = ['default' => [],
+                    'error' => [],
+                    'warning' => []];
+
+    (new Class_Cata_Log())
+      ->addDefaultTarget($this->newLog('default'))
+      ->addTarget('error', $this->newLog('error'))
+      ->addTarget('warning', $this->newLog('warning'))
+      ->log('Cooking chocolate fondant')
+      ->log('Trying 2.0 version', ['warning', 'error'])
+      ->log('1.0 was buggy', 'error')
+      ->log('Starting', '*')
+      ->info('Gather ingredients', '*')
+      ->success('250g Sugar')
+      ->success('250g Butter')
+      ->error('Not enough Butter', 'default')
+      ->error('Go buy butter', '*')
+      ->log('Then eat', 'nowhere');
+  }
+
+
+  public function expectedLogs() {
+    return
+      [
+       ['default', ['Cooking chocolate fondant',
+                    'Starting',
+                    'Gather ingredients',
+                    '250g Sugar',
+                    '250g Butter',
+                    'Not enough Butter',
+                    'Go buy butter']],
+
+       ['error', ['Trying 2.0 version',
+                  '1.0 was buggy',
+                  'Starting',
+                  'Gather ingredients',
+                  'Go buy butter']],
+
+       ['warning', ['Trying 2.0 version',
+                    'Starting',
+                    'Gather ingredients',
+                    'Go buy butter']]
+      ];
+  }
+
+
+  /**
+   * @dataProvider expectedLogs
+   * @test */
+  public function targetShouldContainLines($target, $lines) {
+    $this->assertEquals($this->_logs[$target], $lines);
+  }
+
+
+  /** @test */
+  public function catalogWithoutDefaultTargeShouldBeSilent() {
+    (new Class_Cata_Log())->log('no exception please');
+  }
+}
+?>
\ No newline at end of file
diff --git a/tests/library/Class/Cosmogramme/Integration/PhaseReservationTest.php b/tests/library/Class/Cosmogramme/Integration/PhaseReservationTest.php
index 1a5d66e22217a969999c0499008e2cc55d52ebc9..4ba44a4acbf9d6cbfb06003cd3777b310f71aede 100644
--- a/tests/library/Class/Cosmogramme/Integration/PhaseReservationTest.php
+++ b/tests/library/Class/Cosmogramme/Integration/PhaseReservationTest.php
@@ -66,7 +66,7 @@ class PhaseReservationBadPreviousPhaseCronFirstRunTest extends PhaseReservationT
 
   /** @test */
   public function logShouldNotHaveBeenCalled() {
-    $this->assertFalse($this->_log->methodHasBeenCalled('ecrire'));
+    $this->assertFalse($this->_log->methodHasBeenCalled('log'));
   }
 
 
diff --git a/tests/library/Class/Cosmogramme/Integration/PhaseTestCase.php b/tests/library/Class/Cosmogramme/Integration/PhaseTestCase.php
index 4e5624b086364035c5ad785e0ffdbe31f1cd7134..2c632e4ed25df1c39cd1bce70095cf5e66dff0b7 100644
--- a/tests/library/Class/Cosmogramme/Integration/PhaseTestCase.php
+++ b/tests/library/Class/Cosmogramme/Integration/PhaseTestCase.php
@@ -38,10 +38,10 @@ abstract class Class_Cosmogramme_Integration_PhaseTestCase extends ModelTestCase
 
     $append_log = function($content) { $this->_log_content .= ' ' . $content; };
     $this->_log = $this->mock()
-                       ->whenCalled('addError')->willDo($append_log)
-                       ->whenCalled('addSuccess')->willDo($append_log)
-                       ->whenCalled('addInfo')->willDo($append_log)
-                       ->whenCalled('ecrire')->willDo($append_log);
+                       ->whenCalled('error')->willDo($append_log)
+                       ->whenCalled('success')->willDo($append_log)
+                       ->whenCalled('info')->willDo($append_log)
+                       ->whenCalled('log')->willDo($append_log);
 
     $this->_chrono = new Class_Cosmogramme_Integration_Chronometre();
     $this->_printer = $this->mock()
diff --git a/tests/library/Class/NoticeTest.php b/tests/library/Class/NoticeTest.php
index f1e2d74d9d64f8c4a400bbc2fa30edb486f0b9db..d6232f81d735f56676aeceb96ddf38249cf1fe9c 100644
--- a/tests/library/Class/NoticeTest.php
+++ b/tests/library/Class/NoticeTest.php
@@ -223,6 +223,7 @@ class NoticeVignetteTest extends ModelTestCase {
 
     $album = $this->fixture('Class_Album',
                             ['id' => 2,
+                             'titre' => 'Winnie the poo',
                              'type_doc_id' => Class_TypeDoc::DIAPORAMA,
                              'fichier' => 'a_thumb.jpg']);
 
@@ -256,6 +257,7 @@ class NoticeVignetteTest extends ModelTestCase {
 
     $album = $this->fixture('Class_Album',
                             ['id' => 2,
+                             'titre' => 'Winnie the poo',
                              'type_doc_id' => Class_TypeDoc::DIAPORAMA]);
 
     $album
diff --git a/tests/library/Class/WebService/Dilicom/HubTest.php b/tests/library/Class/WebService/Dilicom/HubTest.php
index 52167cbdc59eb46d385e645cd13173841b7386c5..d2b8ddc6e21140b218191ae46d4d9a9b692fe57e 100644
--- a/tests/library/Class/WebService/Dilicom/HubTest.php
+++ b/tests/library/Class/WebService/Dilicom/HubTest.php
@@ -168,6 +168,7 @@ class Class_Webservice_Dilicom_UpdateLoansReturnDateTest extends Class_Webservic
                                           ['id' => $i,
                                            'album' => $this->fixture('Class_Album',
                                                                      ['id' => $i,
+                                                                      'titre' => 'Dr House',
                                                                       'id_origine' => 'Dilicom-' . $i])
                                           ]);
                        },
diff --git a/tests/library/Class/WebService/OneDTouchTest.php b/tests/library/Class/WebService/OneDTouchTest.php
index 1846ddbdae974724c91d55ef599a9be7d88bf97a..8dd6dbc7c9d8e8054f7595f1e62b9728927171c7 100644
--- a/tests/library/Class/WebService/OneDTouchTest.php
+++ b/tests/library/Class/WebService/OneDTouchTest.php
@@ -20,7 +20,7 @@
  */
 include_once('tests/fixtures/RessourcesNumeriquesFixtures.php');
 
-class OneDTouchTest extends ModelTestCase {
+class OneDTouchFullTest extends ModelTestCase {
   protected $_storm_default_to_volatile = true;
 
   public function setUp() {
@@ -144,11 +144,35 @@ class OneDTouchTest extends ModelTestCase {
 
 
 class OneDTouchIncTest extends ModelTestCase {
-  protected $_storm_default_to_volatile = true;
+  protected
+    $_storm_default_to_volatile = true,
+    $_logger,
+    $_debug_log = '';
+
+
+  protected function _setupLogger() {
+    $append_log = function($message, $target = '')
+      {
+        if (!in_array($target, ['*', 'debug']))
+          return;
+        $this->_debug_log .= $message . "\n";
+      };
+
+
+    $this->_logger = $this->mock()
+                   ->whenCalled('log')
+                   ->willDo($append_log)
+                          ->whenCalled('info')
+                          ->willDo($append_log);
+    Class_WebService_BibNumerique_RessourceNumerique::setLogger($this->_logger);
+  }
+
 
   public function setUp() {
     parent::setUp();
 
+    $this->_setupLogger();
+
     RessourcesNumeriquesFixtures::activate1Dtouch();
     $catalogue_xml = file_get_contents(realpath(dirname(__FILE__)). '/../../../fixtures/onedtouch_oai.xml');
 
@@ -193,11 +217,18 @@ class OneDTouchIncTest extends ModelTestCase {
     $this->_service = new Class_WebService_BibNumerique_OneDTouch();
     $this->_service->setTimeSource(new TimeSourceForTest('2015-03-18 10:00:00'));
     Class_WebService_BibNumerique_OneDTouch::setDefaultHttpClient($this->_http_client);
+    $this->_service->setLogger($this->_logger);
     $this->_service->harvest();
     Class_Album::clearCache();
   }
 
 
+  public function tearDown() {
+    Class_WebService_BibNumerique_RessourceNumerique::setLogger(null);
+    parent::tearDown();
+  }
+
+
   /** @test */
   public function shouldHave4Albums() {
     $this->assertEquals(4, count(Class_Album::findAll()));
@@ -212,13 +243,33 @@ class OneDTouchIncTest extends ModelTestCase {
 
 
   /** @test */
-  public function albumShouldHaveBeenUpdated() {
-    $this->assertEquals(1, Class_Album::findFirstBy(['titre' => 'WOLFEP026'])->getId());
+  public function album1DTouchRessourcesShouldHaveBeenUpdated() {
+    $this->assertCount(4,
+                       Class_Album::findFirstBy(['titre' => '1Dtouch res'])->getRessources());
+  }
+
+
+  /** @test */
+  public function debugLogShouldContainsUpdateAlbumOne() {
+    $this->assertContains('update [1] with "WOLFEP026" (128)', $this->_debug_log);
+  }
+
+
+  /** @test */
+  public function debugLogShouldContainsTitleMandatory() {
+    $this->assertContains('errors: Le titre est obligatoire', $this->_debug_log);
+  }
+
+
+  /** @test */
+  public function debugLogShouldContainsTraitementdelapage() {
+    $this->assertContains('Traitement de la page', $this->_debug_log);
   }
 }
 
 
 
+
 class oneDTouchWithErrorResponseTest extends ModelTestCase {
  protected $_storm_default_to_volatile = true;
 
diff --git a/tests/library/ZendAfi/View/Helper/Accueil/PretsTest.php b/tests/library/ZendAfi/View/Helper/Accueil/PretsTest.php
index 10fc40437aa38aa6beb87034e2cf6c0b7e446b32..4706358997ccde085bffdc4b546812c582d32bcc 100644
--- a/tests/library/ZendAfi/View/Helper/Accueil/PretsTest.php
+++ b/tests/library/ZendAfi/View/Helper/Accueil/PretsTest.php
@@ -55,7 +55,9 @@ class PretsTestWithConnectedUser extends ViewHelperTestCase {
       ->setFicheSigb(['fiche' => $emprunteur]);
 
     $this->fixture('Class_Album',
-                   ['id' => 64, 'id_origine' => 'Dilicom-8907']);
+                   ['id' => 64,
+                    'titre' => 'Totem et Tabou',
+                    'id_origine' => 'Dilicom-8907']);
 
     $this->fixture('Class_Loan_Pnb',
                    ['id' => 12,
diff --git a/tests/library/ZendAfi/View/Helper/RenderAlbumTest.php b/tests/library/ZendAfi/View/Helper/RenderAlbumTest.php
index f9ee91dd3911babe16a2e39045f6ed608a73f154..7769c4262d20dc9e896f4025e9a7088b30a4da26 100644
--- a/tests/library/ZendAfi/View/Helper/RenderAlbumTest.php
+++ b/tests/library/ZendAfi/View/Helper/RenderAlbumTest.php
@@ -164,7 +164,7 @@ class ZendAfi_View_Helper_RenderAlbumNumeriquePremiumTest extends ZendAfi_View_H
     parent::setUp();
     $this->book = $this->fixture('Class_Album',
                                  ['id' => 3,
-                                  'libelle' => 'Emile Zola',
+                                  'titre' => 'Emile Zola',
                                   'external_uri' => 'http://www.numeriquepremium.com/content/books/9782760622173'])
                        ->beNumeriquePremium();
   }
@@ -215,7 +215,7 @@ class ZendAfi_View_Helper_RenderAlbumCyberlibrisTest extends ZendAfi_View_Helper
 
     $this->book = $this->fixture('Class_Album',
                                  ['id' => 3,
-                                  'libelle' => 'Totem et Thora',
+                                  'titre' => 'Totem et Thora',
                                   'id_origine' => '88817216',
                                   'external_uri' => 'http://www.bibliovox.com/bookdetails.aspx?docID=88817216'])
                        ->beCyberlibris();
diff --git a/tests/library/ZendAfi/View/Helper/Status/TestCase.php b/tests/library/ZendAfi/View/Helper/Status/TestCase.php
index d9cd2d931d70efe9dc20cb8d418a1b4a4ee47b29..f527ad91e558914c68d80b64a33abed98dd9a9be 100644
--- a/tests/library/ZendAfi/View/Helper/Status/TestCase.php
+++ b/tests/library/ZendAfi/View/Helper/Status/TestCase.php
@@ -108,6 +108,7 @@ abstract class ZendAfi_View_Helper_Status_TestCase extends ViewHelperTestCase {
     RessourcesNumeriquesFixtures::deactivateOrphea();
     $this->fixture('Class_Album',
                    ['id' => 1,
+                    'titre' => 'Be happy',
                     'type_doc_id' => Class_TypeDoc::SOUNDCLOUD]);
     return $this;
 
diff --git a/tests/scenarios/Manager/ManagerTest.php b/tests/scenarios/Manager/ManagerTest.php
index 7641ac2588f6c5d28aa6956977c3d7f814ccf44e..47836055925e473c8f2268c369ac6710baa0b1af 100644
--- a/tests/scenarios/Manager/ManagerTest.php
+++ b/tests/scenarios/Manager/ManagerTest.php
@@ -165,7 +165,7 @@ class ManagerAlbumTest extends Admin_AbstractControllerTestCase {
 
     $this->fixture('Class_Album',
                    ['id' => 32,
-                    'libelle' => 'Tokyo ghoul']);
+                    'titre' => 'Tokyo ghoul']);
 
     $this->dispatch('/admin/album/index', true);
   }
@@ -394,7 +394,7 @@ class ManagerHeaderActionsTest extends Admin_AbstractControllerTestCase {
 
     $this->fixture('Class_Album',
                    ['id' => 32,
-                    'libelle' => 'Tokyo ghoul']);
+                    'titre' => 'Tokyo ghoul']);
 
 
     $this->dispatch('/admin/album/edit_album/id/32', true);