Pair program with me! profile for carousel at Stack Overflow, Q&A for professional and enthusiast programmers

4/27/2014

Laravel with OnApp cloud

Developing in (and for) the cloud has become defacto standard skill for any modern web developer. Without knowing how to, for example, setup Apache server on AWS Linux instance - important tools will be missing in your development toolset.
Many providers are moving to cloud. Fortrabbit (my provider of choice) is offering SSH connection to all application resources, so it is important to become familiar with cloud concepts.

These days I am working on one awesome project - it is basically Laravel SaaS application that connects to cloud servers, with the help of OnApp. OnApp is cloud management system for service providers.

There is no Laravel package for OnApp, but there is great  OnApp PHP wrapper, for API calls to virtual server. That wrapper is just an abstraction over php_curl, which internally handles all HTTP calls to servers, and returns response in one of two forms - XML of JSON.

Now, that PHP wrapper is very nicely designed, and allows easily communication with servers through native API. It has some very neat solutions, that makes pleasure working with API.

I will point some key features, that are crucial for understanding how it works.

First, to make use of wrapper, you will have to include it in your app. First line of code should be call to OnAppInit.php file, which autoloads all dependencies. Something like:

//based on my path
require "/lib/Onapp/OnAppInit.php";


With this line, all classes are autoloaded, and we can move to actual connection to server. This is where the beauty comes. Connection is made with the help of Factory class instance, which implements factory design patterns, that can instantiate all internal OnApp classes. Next, all OnApp classes inherits from base OnApp class, and allows unified interface for all inherited classes. It is done with the help of factory.

To connect to server, just call Factory class like this:


$factory = new OnApp_Factory($server,$user,$password);



Where $server represents full url to server (not just server.com), but requires protocol (http://server.com). If you made mistake, leaving out the protocol type, you can spend days trying to figure out where is the problem :)

After that you are connected, and ready to use API. But with basic connection, you can't go far. Factory class has factory method, that is responsible for instatiation of all other classes.
To make it more clear, here if that factory method (from the main Factory class):

public function factory( $name, $debug = false ) {
    $class_name = 'OnApp_' . $name;

    $result = new $class_name();
    $result->logger->setDebug( $debug );

    $result->setOption( ONAPP_OPTION_DEBUG_MODE, $debug );
    $result->logger->setTimezone();
    $result->version = $this->getAPIVersion();
    $result->options = $this->options;
    $result->_ch     = $this->_ch;
    $result->initFields( $this->getAPIVersion() );
    return $result;
}


Now things are more clear. Factory argument name will become OnApp clas name. Factory method also serves as configuration method, that will return new instance for chaining.

So to return User class, just call this:

$user = $factory->factory("User");

//or some other, useful classes
$user = $factory->factory("Log");

//or
$user = $factory->factory("BillingPlan");


Now, with those instances, you can use OnApp methods, that allows easily working with API. All instances have getList method. User class is used commonly (there have to be users :), so to list all users, you will do:

//list all server users
$user = $factory->factory("User")->getList($user_id);

// or to list all server logs
$user = $factory->factory("Log")->getList($user_id);


Remember that you are connected as user, with the help of base Factory class. Depending on you permisions (user of admin) you can list different users.

In a nutshell, this API allows creating powerfull SaaS applications, from your base code. In my case, all incoming data (in the form of JSON) are part of application, and I can manage users and server state easily from one central point. There is much more then this - you can pull statistics, work with hypervisors, work with virtual machines... It is really rich set of tools for cloud management.

Thanks for reading.

4/10/2014

How to use Xdebug profiler and Kcachegrind tools in PHP project?

I use more and more awesome Xdebug profiler in combination with Vdebug plugin and Kcachegrind.

Xdebug is standard PHP debugger. Vdebug is Vim plugin that let's you easily debug and trace PHP (and not just PHP) code from Vim. Kcachegrind is amazing piece of software which let's you visually represent whole application calling stack, and do a memory profile and discover bottlenecks.

You need some time and slight tweaks to enable all this tools to work.
But when you do that, you have awesome toolset that let's you dissect you code in a number of different ways. I mostly use it for learning new API-s, writing my extensions and looking at architecture and design of existing code (these days mostly Laravel).

Fist step is to install and enable xdebug. Here is how to do that on ubuntu:

    suto apt-get install php5-xdebug

And check in your php.ini that xdebug is enabled.

Here is my Xdebug setup from /etc/php5/apache2/php.ini file:

    zend_extension=/usr/lib/php5/20121212/xdebug.so
    xdebug.remote_enable=on
    xdebug.remote_handler=dbgp
    xdebug.remote_autostart=1
    xdebug.remote_host=localhost
    xdebug.remote_port=9000
    xdebug.profiler_output_dir="/var/log/xprofile/"
    xdebug.profiler_append=On
    xdebug.profiler_enable_trigger=On
    xdebug.profiler_output_name="%R-%u.trace"
    xdebug.trace_options=1
    xdebug.collect_params=4
    xdebug.collect_return=1
    xdebug.collect_vars=0  
    xdebug.profiler_enable=1
     ;xdebug.auto_trace=Off

As you can see it is divided into xdebug settings that let's you debug, and setting that allows profiling. Here you can find some advanced settings, which let's you save file names based on function call. By default profiler saves all files with some random prefix, and it is hard to distinguish between them

To install Vdebug on Vim, just install this plugin
https://github.com/joonty/vdebug and follow installation process. After that you wil be able to dubug and set breakpoints with builtin vim mappings.

In order to save and use output from profiles, you need to create default location for files. This is my location:

    xdebug.profiler_output_dir="/var/log/xprofile/"

Now, every time you start a project in the browser, a new profile file will be created.

Next tool is Kcachegrind. This is project home:

    http://kcachegrind.sourceforge.net/html/Home.html

But it can be easily installed through CLI of software center. Kcachegrind allows you to have visually insight into project calling stack. For me it was  far better learning experience then reading tons and tons of books. With this, I am actually "in the source code", without external explanation about that code. I can see how authors were designing whole application and have some advanced insight into whole process of app creation.

There is one gotcha with Xprofile. If you don't delete generated files, they can easily accumulate and consume lot of memory. You won't be always  using xdebug but profiler will always generate those files. So you need to manually delete them. It can be also done with some kind of deamon process and backround script.

This is how I solve this problem, with one command. I created alias like this:

     alias xd="sudo find /var/log/xprofile/* -mmin +0 -exec rm {} \;"

And placed it into my .zshrc file. With this alias command, all files inside xprofile directory older then 0 minutes will be deleted - which means all files will be deleted.

Alternatively, you can create new bash script/file, with this command:

    #!/usr/bin/sh
    sudo find /var/log/xprofile/* -mmin +0 -exec rm {} \;

Place it somewhere on your path, provide permissions and you will have globally executable command that will clean xprofile folder.

Thanks for reading.