El auge de los generadores de sitios en texto plano

Hace ya casi una década cuando uno desarrollaba su página web con Dreamweaver o con FrontPage.

Como todo lo antiguo vuelve, en pleno siglo 21th y tras haber superado la web 2.0 y la 3.0 resulta que lo cool ahora es editar de nuevo tu web en local o a través de tocar los ficheros de contenido directamente.

Y aunque hay algunas diferencias, y ha llovido mucho, volvemos a escribir contenido web desde nuestro ordenador y una aplicación de escritorio.

Los motivos son muy diferentes. Y aunque el porcentaje de penetración de Wordpress y otros blogs de edición online siguen siendo mayoritarios, ahora tenemos entornos completos de creación de webs sin necesidad de bases de datos, loque ahora se llama Flat-File-CMS o Static Web Generators.

Tenemos que distinguir entre dos tipos. Sistemas desarrollados en PHP que trabajan con ficheros de texto, y generadores de webs. y En ambos casos de forma predominante, el contenido se escribe en formato Markdown, pero el resultado es diferente a la hora de trabajar, aunque visualmente un usuario no podría distinguir si una web está hecha con un sistema u otro.

La ventaja, además de poder escribir más rápido y concentrarse en el contenido y no en la forma en que se muestra, es que, al no usar base de datos, la carga de la web es mucho más rápida.

Por otro lado las webs generadas estáticamente ni tan siquiera necesitarían de PHP, u otro soporte de lenguaje de programación en el servidor web. Cualquier espacio web incluso Github podría ser hosting para este tipo de webs.

Del primer grupo estos serían los proyectos más interesantes:

Flat File CMS

  • Pico CMS. Es todo un clásico, funciona sobre PHP con plantillas TWIG, soporte de contenido en Markdown y un buen puñado de templates.
  • HTMLy. Más reciente, permite editar online el contenido y tiene interfaz de administración. Este blog está funcionando sobre este proyecto.
  • Grav. Un proyecto interesante, también funcionando sobre Twig, Symfony y muy extensible con una buena cantidad de plugins. También permite edición online así como configuración con ficheros YAML, generación de tipos especiales de contenido. En definitiva,un sistema muy versátil.
  • Dokuwiki. Lleva años con nosotros, un wiki rápido de editar, ideal para documentar proyectos, edición online y todo almacenado sobre ficheros. El backup es trivial, solo hay que copiar toda la carpeta a otro sitio para tenerlo funcionando.

Static Web Generators

  • Hexo. Genera una web estática con NodeJS. Dispone de diferentes temas para modificar el aspecto del resultado.
  • WinterSmith. También sobre NodeJS, fue de los pioneros aunque muy básico comparado con los demás.
  • MkDocs. Si has escrito documentación en Markdown,seguro que te suena, o al menos su theme por defecto, multitud de proyectos lo usan para generar la web de documentación. Funciona sobre Python, que necesitarás tener instalado.
  • Sculpin. Sobre PHP y TWIG, genera webs estáticas, y no necesitarás posteriormente PHP para visualizar el resultado.
  • Hugo. El ganador por goleada es Hugo,un sistema versátil, al estar hecho en GO, solo necesitas un ejecutable disponible en Windows, Linux y Mac para generar tu web a partir de Markdown. Tiene un catálogo de themes impresionante para el poco tiempo que lleva. Sin duda el más recomendable.

Ahora solo te queda elegir el que más te guste.

Descubriendo las aplicaciones compiladas en Go

Hace poco tiempo que estoy profundamente interesado en Go, no tanto como lenguaje, que me parece atractivo, sino todas las aplicaciones que se han creado con este lenguaje.

La principal ventaja de las aplicaciones creadas con Go es que se compilan en un solo ejecutable, por lo general puedes compilar ejecutables para Windows, Linux y MacOSX con el mismo código, simplemente diciendo al compilador, para que sistema quieres sacarlo.

Luego Go es un lenguaje que genera código compilado próximo a C o C++, por lo que su velocidad de ejecución es muy rápida, y además pensado para facilitar las tareas concurrentes utilizando varios procesadores. El resultado es siempre unas aplicaciones de gran rendimiento y escalabilidad.

El sitio para buscar aplicaciones hechas en Go es GoLandLibs, busca por la etiqueta applications.

Estas son las aplicaciones en Go que más me gustan y uso:

  • Sup. Una herramienta tipo Deployer para lanzar comandos remotos a multitud de servidores en paralelo, como hace Ansible, Capistrano, Deployer, y otros, pero más sencillo y rápido.
  • Capze. Genera una estructura de despliegue tipo Capistrano rápidamente, se integra muy bien con Sup.
  • Restic. Permite generar backups y backups incrementales rápidamente, más rápido que duplicity.
  • Duplicacy. Aún mejor que Restic, permite subir el backup a múltples servicios online de disco: S3, Onedrive, Google Drive, Dropbox, FTP, etc...
  • LNAV. Un visor de logs hypervinaminado, multitud de utilidades como leer directamente de históricos guardados en TGZ sin tener que cambiar de fichero.
  • Hugo. Un generador de webs estáticas. Para qué necesitas Wordpress si puedes tener algo como esto...
  • Fast Reverse Proxy. Permite montar un proxy que exponga los puertos de ordenadores dentro de un NAT a una IP pública. Muy rápido y gran utilidad para desarrollar servicios web en modo pruebas.
  • Minio. Directamente todo un servidor S3 personal en un solo ejecutable. Impresionante.
  • Caddy. Un servidor web con soporte para HTTP2, certificados, gran rendimiento y fácil configuración en un solo fichero. Lo uso principalmente para no tener que montar un Apache o Nginx en un entorno de desarrollo, el fichero de configuración puede ir en el mismo repo GIT y arrancar el proyecto en segundos arrancando las dependencias al mismo tiempo (servidor MySQL, Redis, o lo que sea).
  • NATS. Uno de los grandes descubrimientos, gestiona un sistema de paso de mensajes Pub-Sub y gestión de colas de forma instantánea sin grandes requerimientos como pasa con RabbitMQ. Permite montar cluster del servicio de forma sencilla y aguanta cientos de miles de mensajes por segundo.
  • Aurora. Si buscas un servidor de Beanstalk rápido y sencillo esto es lo que necesitas.
  • Fabio. Un balanceador para microservicios web. Muy rápido.
  • MeshBird. Genera una red virtual distribuida entre tus servidores, contenedores Docker, ordenadores personales y lo que quieras. Muy bueno.
  • GoRush. Un servidor de notificaciones push propio, para no depender de Pushbush y otros...
  • ImageServer. Todo lo que necesitas para recortar, retocar imágenes, resamplear y lo que te imagines como microservicio web con API.
  • Flynn. Escala de forma horizontal servidores de bases de datos o aplicaciones a través de contenedores docker de forma transparente y automática.
  • GoGS. Impresionante, tu propio Github, mil veces más fácil de instalar que Gitlab.

Como veréis hay proyectos muy interesantes usandose en sistemas de producción enormes. y con una fiabilidad asombrosa.

Habrá que estar atentos a los proyectos que vayan surgiendo con este lenguaje.

Web migrada a FlatCMS

Han pasado casi dos años desde que empecé y dejé de escribir en este blog.

En este tiempo, han intentado forzar el Wordpress con mil problemas de seguridad, me han hackeado la web varias veces y he tenido que recuperarla otras tantas.

Todo para que al final ni tan siquiera escribiese. Así que finalmente he decidido pasarme al Markdown y a un FlatCMS sin plugins, sin extensiones ni problemas.

Ha sido un poco pesado convertir los posts a Markdown, pero al menos ya está todo listo. Probaremos que tal va este HTMLy.

Magento convenciones y programación orientada a eventos

Son muchos los entornos que se han pasado a la programación orientada a eventos. Aunque de forma descafeinada, pues no siempre es lo que entendemos como eventos que se disparan y se ejecutan en segundo plano.

Llevo ya unas semanas intensivas desarrollando sobre Magento para cerrar un proyecto. Al igual que Wordpress, Magento tiene una serie de eventos sobre los que uno puede establecer sus rutinas que se ejecutarán cuando se lancen estos eventos.

Al contrario que en JavaScript, Node, C# y otros, los eventos en PHP se ejecutan de forma secuencial y nos sirven básicamente para ejecutar rutinas de código en mitad del código principal de la aplicación sin necesidad de tocar el core de la misma. Una clase que ejerce de controlador de eventos almacena todas las funciones de callback junto al evento con el que se tienen que ejecutar, y las lanza de forma secuencial cuando este evento es llamado.

A menudo es fácil darse cuenta que este tipo de programación no es la que estamos acostumbrados en PHP y he visto cantidad de código de extensiones que deciden sobreescribir todo el código antes que usar eventos, rompiendo así en ocasiones la funcionalidad de otras extensiones.

Siempre que trabajo con Software Libre y extensiones de terceros compradas, me viene la sensación que, aunque la funcionalidad esté desarrollada, el código a veces, dista de ser bueno, suponiendo auténticos quebraderos de cabeza al resto de desarrolladores.

Desarrollo web y el presupuesto de un cerrajero

Como cualquier otra persona con una casa, las cosas se rompen, la puerta del patio llevaba rota desde hace algún tiempo. Aprovechando el verano y las vacaciones llamé a un cerrajero para que me presupuestara el arreglo de la cerradura, que estaba atascada y se quedaba bloqueada.

Como era gratis que viniesen a presupuestarme el arreglo, llamé sin dudarlo. Vinieron dos chavales jóvenes, el que iba detrás aún más joven, diría que menos de 20 años. Sin ni tan siquiera desarmarla, me presupuestaron el arreglo en 90 euros.

En otro momento les habría dicho que sí (además porque el casero me reembolsaría el coste), pero sabía que era absurdo, no se tardaría ni 15 minutos en arreglarlo, y la pieza dudo mucho que costase tanto, porque ya había visto como funcionaba.

Finalmente esta mañana he arreglado la cerradora, 3 tornillos que faltaban y un eje que estaba suelto (un martillazo y listo), 20 minutos sin dedicarme a esto.

Todo esto me ha hecho pensar, la mayoría de personas es capaz de pagar 90e por una cerradura, y mucho más por instalar un aire acondicionado, un grifo roto, etc..

Pero cuando se trata de hacer una aplicación web o móvil, aunque lleve horas, incluso meses de trabajo de una o varias personas (diseñador, programador, sistemas,...), el cliente siempre ve el presupuesto desmesurado... además pide continuos cambios sobre la marcha, como si fuese gratuito, como un si de un "todo incluido" se tratase, pide y pide, semanas después de haber aceptado un presupuesto en el que no se incluía nada de lo que ahora está pidiendo.

A menudo me pregunto porqué en la cabeza de todos, no existe aún el concepto del coste de la mano de obra y la cualificación necesaria para construir aplicaciones o páginas webs. No se en qué momento aprenderemos que todo esto, intangible pero que genera finalmente tráfico y dinero para el cliente, tiene un coste que merece la pena pagar.

Introducción a Vagrant, la mejor forma de preparar un proyecto web. Parte I

Y es que después de su par de años de maduración, Vagrant ya es una de las herramientas más utilizadas por todos los desarrolladores web, administradores de sistemas y cualquier profesional IT que quiera testear un entorno de servidores, ya sea Linux o Windows (aunque principalmente Linux).

Para que el que no lo conozca, Vagrant es una herramienta que permite generar una máquina virtual (para Virtualbox, VirtualPC o VMWare) preconfigurada y con acceso remoto, en unos pocos minutos, y fácilmente distribuible.

¿Para qué sirve?. Bien, pensemos que estamos desarrollando una página web en PHP, y necesitaremos por tanto en nuestro ordenador poder disponer de un servidor web con PHP y seguramente MySQL. Esto en el mejor de los casos, porque realmente nos podríamos encontrar con entornos con Dyango, RubyOnRails, NodeJS y alguno de sus innumerables frameworks web. Instalar todo esto en nuestro ordenador de trabajo además de ser tedioso, termina siendo insufrible debido a las diferencias en entornos Windows, Linux y OSX, cuando al final tendrá que estar funcionando sobre un servidor Unix de un hosting.

Hasta hace muy poco, la mayoría acudíamos a algún entorno LAMP (si hablamos de Apache+PHP+MySQL), un WAMP (en Windows) o quizás un MAMP (en OSX). Esto era bastante fácil, pero si tu proyecto empezaba a requerir más requisitos en cuestión de nuevos módulos de PHP, acceso a indexadores como ElasticSearch, Sphinx, etc... la instalación y compilación de estos módlos y dependencias se iba complicando.

A esto sumamos a este bonito cuadro, que nuestros compañeros con los que trabajamos en el mismo proyecto, uno tiene un Mac, otro un Windows y otro quizás un Linux. Resultaba imposible ayudar a nuestro compañero dándole instrucciones de cómo han montado el entorno, puesto que cada uno lo ha hecho en su propio sistema operativo.

Vagrant nos elimina todos estos problemas además de poder generar un entorno homogéneo para todo el equipo y que puede ser un clon de lo que tendremos en nuestro servidor más adelante a la hora de publicar nuestro proyecto en producción. Podremos pasar la configuración de nuestra máquina Vagrant, y un proceso de setup que instalará todo el entorno que necesitemos.

Lo primero que necesitamos saber es que podemos usar Vagrant de muchas maneras. La primera es instalar un sistema base, por ejemplo Ubuntu 14.04 escribiendo:

mkdir ubuntu
cd ubuntu
vagrant init precise32

Esto nos creará un fichero Vagrantfile, que podemos editar con un editor de texto.Desde este fichero podemos modificar la memoria RAM asignada, asignar carpetar compartidas, etc...

Una vez configurado podemos ejecutar:

vagrant up

Todos los comandos de vagrant deberemos ejecutarlos sobre la carpeta donde tenemos el Vagrantfile, de otra manera Vagrant no sabrá con que maquina virtual está trabajando. Esto descarga Ubuntu, y genera una máquina virtual ya preinstalada con este SO. Podremos entrar en la máquina virtual a través de SSH por línea de comandos, aunque si nunca hemos manejado un linux, es posible que se nos atragante.

vagrant ssh

Aquí tenemos una ligera diferencia, si usamos Windows, no tenemos de serie un cliente SSH, por lo que necesitaremos o bien instalar CygWin, GIT for Windows, o mejor aún Babun (una versión retocada de CygWin mejorada para Windows de la que hablaré próximamente).

Una vez instalado en Windows, con Babun podremos trabajar normalmente.

Lo interesante aquí es que podamos generar una máquina virtual que nos permita que no trabajemos continuamente con la línea de comandos, y que podamos configurar el servidor fácilmente desde una interfaz web.

Podemos sobre este sistema base configurarlo y posteriormente exportarlo como un fichero .box que podemos pasar al resto del equipo, una vez tenemos exportada la máquina virtual, podemos compartirla con la comunidad desde la web de Hashcorp, la empresa que está detrás de Vagrant, de forma gratuita.

He compartido una máquina Vagrant que tiene lo necesario para trabajar con Apache, Nginx, PHP 5.5, MySQL (MariaDB 5.5), NodeJS, Composer, Bower.

Podéis descargarla en: https://github.com/sevir/vagrant-webserver una vez descargado, entrar en la carpeta para ejecutar un vagrant up.

Esta máquina virtual además de llevar preinstalado gran parte del sistema, actualiza e instala ciertos componentes en el momento de generar una nueva máquina virtual. A esto le llamamos provisioning, con Vagrant podemos provisionar un servidor de varias maneras, la más sencilla es ejecutar scripts de shell con los comandos que nosotros queramos, otra forma es utilizar algún software de provision de servidores como Puppet, Chef o Ansible de los que hablaremos próximamente.

_Actualización: _Esta mañana en el trabajo me han hablado de la existencia de una extensión para Vagrant que podemos instalar para mantener siempre actualizada la versión de las VBGuest Additions que instalan mayor soporte para VirtualBox en la máquina virtual (en resumen hace que vaya más rápida). Simplemente ejecuta antes del vagrant up:

vagrant plugin install vagrant-vbguest

PicPick una de las mejores utilidades para el desarollador web

Pocas veces me he encontrado con una herramienta tan versátil.Hace muchos años  usaba un par de herramientas imprescindibles para mí, una regla en pantalla para medir píxeles de cualquier cosa que vea, y un _color picker _para seleccionar cualquier color en la pantalla (algo que ayuda cuando uno se es un poco daltónico).

Para Mac sin duda lo mejor es el Color Schemer Studio, una estupenda herramienta para seleccionar colores y ver variaciones sobre el mismo, hasta obtener una paleta de colores similar.

Para Windows, el _Color Schemer Studio _no es exactamente igual que la versión de Mac y no es igual de manejable. Y no encontraba una regla en pantalla que me convenciese.

Finalmente la semana pasada encontré PicPick que además es gratuita para uso personal. No solo dispone de un Color Picker y de una regla en pantalla, también de un transportador de ángulos, un medidor de puntos, un capturador de pantalla con editor para poder marcar capturas de pantallas con multitud de elementos y finalmente una pizarra virtual para dibujar directamente sobre la pantalla.

Sin duda altamente recomendable.

http://www.picpick.org/en/

La verdad de los sistemas operativos, hablamos de Windows

Con años de historia a sus espaldas, cuando alguien habla de sistemas operativos, lo primero que se le viene a la cabeza es Windows. Amado y criticado, no podemos ignorar que ha sido durante mucho tiempo el sistema operativo de escritorio más utilizado.

Dice la leyenda que Microsoft saca una versión buena y la siguiente será mala. Esto se ha cumplido con Windows Millenium, Windows Vista, Windows 8 (dicen... aunque yo no opino lo mismo con Windows 8.1).

Pero el tiempo y la competencia han hecho que Microsoft se ponga las pilas y podemos encontrar en Windows 10 muchas cosas buenas y algunas buenas intenciones (espero que no me fulminen por decir todo esto).

En Windows 10 vemos muchos puntos buenos que llevamos viendo años en MacOSX o Linux, la panel lateral de notificaciones, escritorios virtuales (sí, por fin en Windows de serie y oliendo mucho al comportamiento de MacOSX). Lo que mas me gusta no es tanto una funcionalidad, sino una intención por parte de Microsoft, el programa Insider permite a personas inquietas, probar las últimas versiones de Windows, actualizaciones, etc... Además Windows viene de serie con una herramienta para que cualquier usuario pueda realizar comentarios y opinar sobre cualquier aplicación de Windows.

El resultado, Windows 10 obtiene un flujo de mejoras  casi a diario gracias a las aportaciones de los usuarios. Además los usuarios de Insider obtienen una licencia de Windows 10 Profesional. Pero además Microsoft ha querido gamificar las aportaciones de los Insiders, añadiendo retos, galones o medallas cuando se realizan aportaciones.

Aunque muchos han comentado todo lo que trae el recién llegado Windows 10, pocos han hablando de las herramientas de colaboración de los usuarios, y que supone un importante cambio de rumbo en Microsoft.

Deployer, una buena alternativa a Capistrano

Durante mucho tiempo hemos dado vueltas en DIGIO a cómo hacer un mejor deploy de los proyectos en el servidor. Nuestra forma de trabajar era sobre un repositorio GIT que se actualizaba desde el servidor con un simple git pull de forma que en caso de problemas podríamos hacer un reset a una versión dentro del histórico de GIT.

Además añadimos algunas cosas más como cargar configuración de cron a través de un fichero .crontab dentro del proyecto de forma que se actualizan los procesos por cron cada vez que hacemos un deploy. También un fichero .deploy que actúa como script de shell permitía ejecutar acciones una vez se había actualizado el código, para hacer migraciones de base de datos por ejemplo o borrar los ficheros de cache.

El mayor problema que veía es en proyectos con mucha afluencia de usuarios, si estamos actualizando el código, puede llegar una petición donde parte del código está actualizado, pero otras partes no, JavaScript, controladores, modelos, etc... Esto puede producir fallos en el sistema por tener código a medio utilizar e incidencias en los usuarios.

En mi última visita a Emagister en Barcelona, me contaron que ellos usaban Capistrano y Jenkins, el proceso de deploy es similar en cuanto podemos lanzar migraciones, y ejecución de otras tareas, pero resolvía el problema que teníamos nosotros de dar la posibilidad de tener código a medio actualizar cuando llega una petición web.

Capistrano, herramienta de deploy sobre múltiples servidores en Ruby

Capistrano genera una carpeta de release con código nuevo (por lo general de un repositorio GIT), y no se hace el cambio en la carpeta raíz hasta que no se haya copiado todo a la nueva carpeta de release, pudiendo configurar cuántas carpetas de releases queremos conservar así como la posibilidad de volver hacia atrás en caso de error de forma inmediata simplemente apuntando el DocumentRoot a la carpeta de release anterior.

Pero tengo una pequeña manía y es que, siendo desarrollador PHP y JS, intento buscar siempre una alternativa a tener que instalar un intérprete de Ruby, Python o cosas similares, igual que no me gustan los Frameworks que trabajan con XML, YAML y PHP al mismo tiempo cuando se puede hacer todo en un solo lenguaje.

Y buscando buscando encontré un par de proyectos interesantes: Rocketeer y Deployer, pero quizás este último por su simplicidad, y por, admitámoslo, tiene una página web más agradable de leer, fue el que más me gustó.

Ambos proyectos son una copia de Capistrano, ambos funcionan con un phar como Composer, por lo que es muy cómodo y solo necesitamos un fichero para poder ejecutarlo. Quizás Deployer tiene algo más de versatilidad con menos configuración.

Deployer versátil y fácil de configurar en PHP

Con Deployer asegurarmos un proceso de deploy seguro, posibilidad de revertir al instante a una versión anterior, lanzar comandos fácilmente en el servidor remoto o en el servidor de deploy, soporte para claves SSH, usuario y password y múltiples servidores por entorno (por ejemplo poder lanzar nuevos cambios a varios servidores de nuestro cluster).

Con Deployer definimos entornos (producción, desarrollo), dentro de cada uno, definimos un grupo de servidores sobre los que mandaremos actualizaciones (normalmente solo hay uno), y finalmente tareas para lanzar a estos servidores. Que en nuestro caso es enviar la última versión del código en Git.

Si juntamos esto con Jenkins o nuestra herramienta de deploy online podremos actualizar el código de nuestro proyecto fácilmente por todo el equipo.

Incrementando la velocidad del log de PHP en nuestro proyecto web

Recientemente trabajamos sobre un framework desarrollado por el equipo de Emagister y como es normal aunque tiene similitudes en cuanto a características con nuestro framework Creamture, hay otras cosas que son diferentes y no encontramos un rendimiento óptimo.

Una de estas cosas es el tema del log de errores utilizando para ello una tabla en base de datos. El uso de base de datos para escribir en un log es bastante lento comparado con la escritura directamente en un fichero en disco, aunque mantiene algunas esperadas ventajas como la posibilidad de disponer de un visor de log mediante consultas SQL, lo que permite lectura únicamente de las entradas ordenadas por fecha, paginación, sin tener que volcar todo el fichero de log que podría ser muy grande. Aunque la escritura en base de datos es mucho más lenta que la escritura en fichero, el impacto no es muy grande pues únicamente pasan a log los errores o excepciones.

CodeIgniter, y Creamture crea un fichero de log en formato texto por cada día, lo que minimiza que los ficheros crezcan excesivamente, pero al usar el log no solo para volcar errores graves sino como bitácora para cualquier tipo de información que los desarrolladores queremos visualizar, podemos encontrarnos con ficheros diarios de varios megas.

Reciéntemente he mejorado el visor de log que teníamos en Creamture, que permite visualizar los ficheros de logs de CI 1.7 hasta CI 2.2 (Creamture). Disponiendo de un modo para visualizar el log actual en tiempo real, realizando lecturas parciales del fichero en disco. Podéis descargarlo este GIST.

El caso es que pensando en cómo mejorar, esta tarde me dispuse hacer un pequeño test utilizando una instalación base de CodeIgniter 1.7. Se me ocurrió que podría ser más práctico si se usaba un sistema de almacenamiento más organizado y mejor que un fichero, pero que siga siendo más rápido que una base de datos.

El impacto del log normal sobre un controlador

Activando únicamente el log de errores, y no de debug ni info, para minimizar el impacto (CodeIgniter genera log de debug al pasar por casi cualquier librería), y creamos un controlador con un método muy muy simple:

function index()
{
    echo 'OK';
}

Usaremos para probar el funcionamiento normal en nuestro sistema, un pequeño programa para nodejs, llamado webstress-tool con el que podemos lanzar peticiones concurrentes y obtener una media de las mismas, generaremos 10 bloques de peticiones de 50 peticiones concurrentes, cada bloque estará separado por 1 segundo de diferencia.

$ webstress GET http://www.ci17.com 10 50
about to send 500 GET requests to url http://www.ci17.com over 10 seconds
done, took total over: 12034, avg response time: 240.68
done, took total over: 8849, avg response time: 176.98
done, took total over: 7800, avg response time: 156
done, took total over: 7804, avg response time: 156.08
done, took total over: 7686, avg response time: 153.72
done, took total over: 7636, avg response time: 152.72
done, took total over: 7701, avg response time: 154.02
done, took total over: 7713, avg response time: 154.26
done, took total over: 7171, avg response time: 143.42
done, took total over: 7073, avg response time: 141.46

Entonces modifiqué nuestro pequeño método para añadir una llamada a log_message: log_message('ERROR', 'Hola mundo!'); con lo que al probar de nuevo, encontramos cómo afecta el log a la media de las respuestas:

$ webstress GET http://www.ci17.com 10 50
about to send 500 GET requests to url http://www.ci17.com over 10 seconds
done, took total over: 15360, avg response time: 307.2
done, took total over: 10872, avg response time: 217.44
done, took total over: 11044, avg response time: 220.88
done, took total over: 11931, avg response time: 238.62
done, took total over: 11037, avg response time: 220.74
done, took total over: 10955, avg response time: 219.1
done, took total over: 11189, avg response time: 223.78
done, took total over: 12869, avg response time: 257.38
done, took total over: 11121, avg response time: 222.42
done, took total over: 11744, avg response time: 234.88

Podemos ver como una única llamada al log tiene un importante impacto aunque la llamada sea simple. Por lo que no podemos ignorar que aún utilizando ficheros de texto, el impacto es significativo.

Probando con SQLite

La idea es generar un fichero de SQLite por día, y poder guardar la misma información que los ficheros de log, para eso creamos un método log_message alternativo que abrirá una bbdd sqlite nombrada con la fecha actual, intentamos siempre insertar, en caso de error crearemos la tabla ya que el error será por no existir la tabla, pero será más rápido que comprobar siempre si la tabla existe.

El resultado es desalentador:

$ webstress GET http://www.ci17.com 10 50
about to send 500 GET requests to url http://www.ci17.com over 10 seconds
done, took total over: 30964, avg response time: 619.28
done, took total over: 27871, avg response time: 557.42
done, took total over: 30341, avg response time: 606.82
done, took total over: 28935, avg response time: 578.7
done, took total over: 24958, avg response time: 499.16
done, took total over: 27928, avg response time: 558.56
done, took total over: 21769, avg response time: 435.38
done, took total over: 23220, avg response time: 464.4
done, took total over: 26227, avg response time: 524.54
done, took total over: 25003, avg response time: 500.06

Sí sería posible leer el log mediante un visor con consultas SQL, pero la penalización por insertar una simple entrada resulta excesiva.

Usando Redis para guardar el log

Después de leer la velocidad con la que funcionan los sistemas noSQL de almacenamiento key,value probamos Redis, cuyo funcionamiento es muy muy simple, y tenemos una librería muy probada para PHP.

Así que después de bajarnos una versión de Redis para Windows (existe versión para cualquier Unix, OSX y una compilación para Windows que ocupa algo menos de 2 megas.

El nuevo método que construimos es muy simple:

function log_message2($level = 'error', $message, $php_error = FALSE)
{
    $redis = new Redis();
    $redis->connect('127.0.0.1', 6379);
    $redis->lpush('ci17-'.(date('Y-M-d')), (date('Y-M-d H:i:s')).' - '.$level.' --> '.$message);
}

El resultado es casi tan bueno que el impacto sobre la versión sin log es mínimo, y además podemos recuperar las entradas rápidamente ordenadas por fecha y pudiendo paginar. Vemos que efectívamente Redis es muy útil si queremos guardar una bitácora para proyectos web de uso intensivo.

$ webstress GET http://www.ci17.com 10 50
about to send 500 GET requests to url http://www.ci17.com over 10 seconds
done, took total over: 10579, avg response time: 211.58
done, took total over: 8524, avg response time: 170.48
done, took total over: 8419, avg response time: 168.38
done, took total over: 8616, avg response time: 172.32
done, took total over: 8254, avg response time: 165.08
done, took total over: 8351, avg response time: 167.02
done, took total over: 8383, avg response time: 167.66
done, took total over: 8320, avg response time: 166.4
done, took total over: 8017, avg response time: 160.34
done, took total over: 7932, avg response time: 158.64

Lo próximo será actualizar nuestro framework y el visor de logs para usar Redis y establecer un fallback para utilizar ficheros en caso de no detectar un servidor Redis funcionando.