Top Topic ?

Logging into CouchDb using Zend Framework

Posted in php by Ladislav Prskavec on September 10, 2010

Logging in web applications are common task. Mostly i’m using logging into files. When you can some statistics data is better use database for logs. You can use RBMS (MySQL, PostgreSQL) but is problem with changing schema. NoSQL database as CouchDb can be solution. Here is my implementation in Zend Framework.

For writing into database i use log writer:

class App_Log_Writer_CouchDb extends Zend_Log_Writer_Abstract
{
    /**
     * Db
     * @var Phly_Couch
     */
    private $_db;
    /**
     * CouchDb host localhost default
     * @var string
     */
    private $_host;
    /**
     * Couchdb port 3184 default
     * @var int
     */
    private $_port;
    /**
     *
     * @param array $params
     * @return void
     */
    public function __construct($dbname, $options = null)
    {
        if (is_null($options)) {
            $options['host'] = "localhost";
            $options['port'] = "5984";
            $options['db'] = $dbname;
        }
        $this->_db = new Phly_Couch($options);
    }

    static public function factory($config)
    {
        $config = self::_parseConfig($config);
        return $config;
    }
    /**
     * @param array $event
     * @return void
     */
    protected function _write($event)
    {
        // action body
        $doc = new Phly_Couch_Document($event);
        $result = $this->_db->docSave($doc);
        // return array ok, id, rev
        $info = $result->getInfo();
        if (!$info['ok']) {
            throw new Zend_Log_Exception("Error in save to CouchDb");
        }
    }

}

In application ini have to set libraries and options for connect to CouchDb database, you can make yours on http://couchone.com or use local instalation. More info for instalation you can find in Couch Db wiki.

autoloaderNamespaces.phly = "Phly_"
autoloaderNamespaces.app = "App_"
; Options for CouchDb
couchdb.host = prskavec.couchone.com
couchdb.port = 80
couchdb.db = "test-log"

in indexController i have two action, indexAction for display logs and logAction for creating some dummy log records.

class IndexController extends Zend_Controller_Action
{
    protected $_config;

    public function preDispatch()  
    {
            $this->_config = new Zend_Config_Ini('../application/configs/'.
                    'application.ini', APPLICATION_ENV);
    }

    public function indexAction()
    {
         $db = new Phly_Couch($this->_config->couchdb);

         $this->view->form = $form = new App_Form_Filter();
         if ($this->getRequest()->isPost()) {
             $formData = $this->getRequest()->getPost();
             if ($form->isValid($formData)) {
                 $filterValue = $form->getValue('filter');
                 $dateFrom = $form->getValue('datefrom');
                 $dateTo = $form->getValue('dateto');
                 if (empty($filterValue) || $filterValue===0) $filterValue = null;
                 if (empty($dateFrom)) $dateFrom = null;
                 if (empty($dateTo)) $dataTo = null;
                 if (!is_null($dateFrom) && !is_null($dateTo)) {
                 $result = $db->view('logger','log_by_timestamp', array($dateFrom, $dateTo), array("db"=>$this->_config->couchdb->db));
                 } else {
                 $result = $db->view('logger','log_by_prior', $filterValue, array("db"=>$this->_config->couchdb->db));
                 }

             } else {
             $form->populate($formData);
             }
         } else {
            $result = $db->view('logger','log_by_prior', null, array("db"=>$this->_config->couchdb->db));         
         }         
         $this->view->docs = $result->toArray();
         $this->view->messages = $this->_helper->flashMessenger->getMessages();
        
         $logger = new Zend_Log();
         $r = new ReflectionClass($logger);
         $this->view->priorities = array_flip($r->getConstants());

    }

    public function logAction()
    {
          $id = $this->_request->getParam('id', 0);  

          $logger = new Zend_Log();
          $format = '%timestamp% %priorityName% (%priority%): '.
            '[%module%] [%controller%] %message%';                                                                                                
          $formatter = new Zend_Log_Formatter_Simple($format);
          
          $writer = new App_Log_Writer_CouchDb($this->_config->couchdb->db, $this->_config->couchdb);
          $writer->setFormatter($formatter);

          $logger->addWriter($writer);
          $logger->setEventItem('module', $this->getRequest()->getModuleName());
          $logger->setEventItem('controller', $this->getRequest()->getControllerName());                        
          $logger->log("Testovani chyba", $id);
          $this->_helper->flashMessenger->addMessage('Log item saved');
          $this->_helper->redirector('index');
    }


}

In controller I call view in CouchDb database and this use parametr log level or time interval for display logs. For manage views in CouchDb can use Futon.

In controller i create two views.

First for priority, save as: logger/log_by_prior

function(doc) {
  if (doc.priority) {
     emit(doc.priority, [doc.priorityName, doc.timestamp, doc.message, doc.module, doc.controller]);
  }
}

Second for timestamp, save as: logger/log_by_timestamp

function(doc) {
  if (doc.timestamp) {
     emit(doc.timestamp, [doc.priorityName, doc.message, doc.module, doc.controller]);
  }
}

Whole example you can find on my github. In example using CouchDb library make by Matthew Weier O’Phinney and I make some improvement for actual version CouchDb 1.0.1.

I think this is useful solution for many applications.

Advertisements
Tagged with:

Backup jobs for Hudson

Posted in php by Ladislav Prskavec on November 11, 2009

Hudson has new version every week. Before migration I recommend backup jobs and plugins. For backup you can used my hudson-manager. It’s Ant script with some targets. Source you can see at http://gist.github.com/231775.

In manager.properties you set directories and days after delete old backups.

To run backup use cron with this parameters:

05 10,15 * * 1-5 /usr/bin/ant -f /srv/hudson/hudson-manager/manager.xml backupOnlyJobs
05 19 * * 1-5 /usr/bin/ant -f /srv/hudson/hudson-manager/manager.xml backup

Bigger backup i make one per day and minor backup (jobs only) twice per day. In full backup are stored plugins and jobs. Sometimes you can after upgrade plugins and backup is useful.

Tagged with: ,

Zend Server CE and Xdebug install on Ubuntu

Posted in php by Ladislav Prskavec on May 21, 2009

Install Zend Server CE

  1. Open terminal and login as root root sudo -i
  2. Edit sources list nano /etc/apt/sources.list
  3. Add row: deb http://repos.zend.com/deb/ce ce non-free
  4. Get and install key: wget http://repos.zend.com/deb/zend.key -O- |apt-key add -
  5. Update repository: apt-get update
  6. Install Zend Server CE: aptitude install zend-ce

Install Xdebug

  1. You have to have this packages installed: build-essential, autoconf.

    sudo apt-get install build-essential
    sudo apt-get install autoconf
  2. Get Xdebug source, unpack and compile.

    wget http://www.xdebug.org/files/xdebug-2.0.4.tgz
    tar -xzf xdebug-2.0.4.tgz
    cd xdebug-2.0.4/
    /usr/local/zend/bin/phpize
    ./configure --enable-xdebug --with-php-config=/usr/local/zend/bin/php-config
    make
  3. Compiled library is in xdebug-2.0.4/modules/xdebug.so
  4. Copy library into /usr/local/zend/lib/debugger/xdebug.so

    cp modules/xdebug.so /usr/local/zend/lib/debugger/xdebug.so

  5. Edit file /usr/local/zend/etc/ext.d/debugger.ini and comment row (add semicolon)

    ;zend_extension_manager.dir.debugger=/usr/local/zend/lib/debugger

  6. Add at end /usr/local/zend/etc/php.ini new row with

    zend_extension=/usr/local/zend/lib/debugger/xdebug.so

  7. Restart server /etc/init.d/zend-server restart
Tagged with: ,

PHP Class for Hudson

Posted in php by Ladislav Prskavec on April 29, 2009

I make php class for work with Hudson (http://code.google.com/p/php4hudson/). Is useful for save all jobs configs and deploy jobs on another server or some multichanges in jobs. Useful is easy and some example is in wiki.

Save all config.xml


/**
* Retrive all config.xml and save into directory
*/
require_once ("src/phphudson.php");
$hudson = new PhpHudson('http://localhost:8080/');
// save all jobs config into temp
$hudson->getAllConfigs("/tmp/hudson/");

Recreate all jobs


/**
* Read all config.xml from directory and create jobs in Hudson
*/
require_once ("src/phphudson.php");
$hudson = new PhpHudson('http://localhost:8080/');
$dir = '/tmp/hudson/';
if ($handle = opendir($dir)) {
echo "Directory handle: $handle\n";
echo "Files:\n";
while (false !== ($file = readdir($handle))) {
echo "$file\n";
$hudson->createJob(basename(str_replace("-config.xml", "", $file)), file_get_contents($dir . $file));
}
closedir($handle);
}

Tagged with:

phpDepend and php frameworks

Posted in php, qa by Ladislav Prskavec on March 21, 2009

Php Depend

Php Depend is php fork of JDepend. pDepend traverses Php class file directories and generates design quality metrics for each php package. At chart you can see abstractness and instability at axis. This metric is an indicator of the package’s balance between abstractness and stability. At pyramid some data as  NOP (number of packages), NOC (number of classes), NOM (number of methods), LOC (line of code). Details about pyramid you find at Using the Overview Pyramid.  

Php Frameworks in Php Depend

Akelos

akelos-jdepend

akelos-pyramid

CakePHP

cake-jdepend

 

cake-pyramid

CodeIgniter

ci171-jdepend

 

ci171-pyramid

Kohana

kohana-jdepend

 

kohana-pyramid

 

Nette

nette-jdepend

 

nette-pyramid

Prado3

prado3-jdepend

 

prado3-pyramid

Symfony 1.2

sf12-jdepend

 

sf12-pyramid

Solar

solar-jdepend

 

solar-pyramid

Zend Framework

zend-jdepend

 zend-pyramid

 

Others

Ez components

ez-jdepend

 

ez-pyramid

Summary

I’m not expert in QA. I have some experiences with integration php. I use phpunit, phpcs and Hudson for CPD, PMD, Code Coverage and Unit testing. For integration tests we use Selenuim and phpunit. Php Depend is good for some comparism between frameworks. Matrics can’t say how good is code in framework or if is good  for my project. Some numbers as ANDC (Average Number of Derived Classes) and AHH (Average Hierarchy Height) can give some image about programming style.

In article you have some comparism and i make this test every 6 months and after that will be results about progress in frameworks.

Tagged with: ,

PHP and Hudson

Posted in php by Ladislav Prskavec on February 26, 2009

Hudson is extensible continuous integration engine used for Java projects. It’s architecture can be used for others languages as PHP too.

Install

  1. download war file
  2. run direct in console java -jar hudson.war (free port 8080 andJDK 1.5+)
  3. or make install to servlet server (Tomcat, Jetty, JBoss, …)
  4. after that go http://localhost:8080
  5. plugins recommended for php

Build

For build can use phing (example) or ant.

<?xml version="1.0" encoding="UTF-8"?>
<project name="start_page" basedir="." default="main">
<!-- $Id: build.xml 102 2009-02-26 14:39:10Z abtris $ -->
<property name="tmp" value="/tmp" />
<property name="wsname" value="source" />
<property name="package"  value="${phing.project.name}" override="true" />
<property name="builddir" value="${tmp}/build/${phing.project.name}" override="true" />
<property name="srcdir"   value="./src/" override="true" />

<!-- Main Target -->
<target name="main" description="main target">

<!-- Create dirs -->
<mkdir dir="${builddir}/reports"/>
<mkdir dir="${builddir}/reports/coverage"/>

<!-- PHP API Documentation -->
<phpdoc title="API Documentation"
destdir="${builddir}/apidocs"
sourcecode="yes"
defaultpackagename="StartPage"
output="HTML:Smarty:PHP">
<fileset dir=".">
<include name="*/*.php" />
</fileset>
</phpdoc>

<!-- PHP CodeSniffer -->
<exec command="phpcs --standard=ZEND --report=checkstyle ${ws}/${wsname}/src/ > ${builddir}/reports/checkstyle.xml" escape="false" />

<!-- PHPUnit -->
<exec command="phpunit --log-xml ${builddir}/reports/phpunit.xml --log-pmd ${builddir}/reports/phpunit.pmd.xml --coverage-clover ${builddir}/reports/coverage/clover.xml --coverage-html ${builddir}/reports/coverage/ tests/AllTests.php"/>

</target>
</project>

Example configuration

Project name: StartPage
Source Code Management: Subversion
Repository URL: https://localhost/svn/start_page/trunk
Local module directory (optional): source
Use update: true

Build

Execute shell: phing -f $WORKSPACE/source/build.xml -Dws=$WORKSPACE -Dtmp=$WORKSPACE

Post-build action

Publish Javadoc
Javadoc directory = build/start_page/apidocs/
Retain javadoc for each successful build = false
Publish JUnit test result report
Test report XMLs = build/start_page/reports/phpunit.xml
Publish Checkstyle analysis results
Checkstyle results = build/start_page/reports/checkstyle.xml
Publish PMD analysis results
PMD results = build/start_page/reports/phpunit.pmd.xml
Publish Clover Coverage Report
Clover report directory = build/start_page/reports/coverage/