pg_explain

enviat per Ramon Salvadó al bloc assert_response :success el dimecres 19 de Desembre del 2007 a les 08:19 hores

He publicat un petit plugin de rails que afegeix als logs els “explain” o “explain analyze” de les consultes sql. Solament funciona si estem utilitzant una base de dades postgresql.

Podeu consultar-ne els detalls aquí.

Un exemple de la sortida als logs:

1
2
3
4
5
6
7
8
9
10
11
12
Component Load (0.039698)   SELECT components.* FROM components INNER JOIN web_module_components ON components.id = web_module_components.component_id WHERE ((web_module_components.web_module_id = 5)) ORDER BY web_module_components.order ASC

  Explain Component Load
   
  Sort  (cost=42.37..42.38 rows=5 width=565)
    Sort Key: web_module_components."order"
    ->  Hash Join  (cost=30.48..42.31 rows=5 width=565)
          Hash Cond: (components.id = web_module_components.component_id)
          ->  Seq Scan on components  (cost=0.00..11.30 rows=130 width=561)
          ->  Hash  (cost=30.38..30.38 rows=8 width=8)
                ->  Seq Scan on web_module_components  (cost=0.00..30.38 rows=8 width=8)
                      Filter: (web_module_id = 5)

Nova versió del plugin de rails gettext_localize

enviat per Ramon Salvadó al bloc assert_response :success el dijous 29 de Novembre del 2007 a les 12:53 hores

Hem publicat una nova versió del plugin d’internacionalització de rails gettext_localize (que és una de les opcions que podeu utilizar si voleu desenvolupar aplicacions rails en català).

Els canvis en aquesta versió:

1
2
3
4
5
6
Version 0.4 28/11/2007
----

- Included french translation (thanks to Michel Loiseleur)
- Relaxed gettext gem requirements to include 1.10
- Fixed bug to make it work with ruby 1.8.6 (thanks to Luis E. Guardiola)

Per a més informació podeu consultar-ne la documentació.

Leopard i lookupd

enviat per Ramon Salvadó al bloc assert_response :success el divendres 23 de Novembre del 2007 a les 08:49 hores

De vegades ens interessa refrescar el “caché” de dns per exemple quan modifiquem el fitxer /etc/hosts, per a fer-ho en leopard:

1
2
# El que abans era: lookupd -flushcache
dscacheutil -flushcache

Segons el man:

dscacheutil does various operations against the Directory Service cache including gathering statistics, initiating lookups, inspection, cache flush, etc. This tool replaces most of the functionality of the lookupd tool previously available in the OS.

Rutes a la consola

enviat per Ramon Salvadó al bloc assert_response :success el dilluns 19 de Novembre del 2007 a les 12:10 hores

Per a depurar les rutes mitjançant la consola de Rails:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ script/console
Loading development environment.
# Carreguem la definició de les rutes
>> rs = ActionController::Routing::Routes
=> #<actioncontroller::routing::routeset:0x61d76c>> puts rs.routes
ANY    /feed/suggest/                           {:action=>"suggest", :controller=>"public"}
ANY    /feed/thanks/                            {:action=>"thanks", :controller=>"public"}
ANY    /:page/                                  {:action=>"index", :controller=>"public"}
ANY    /:controller/:action/:id.:format/        {}
ANY    /:controller/:action/:id/                {}
=> nil
# Reconeixement de rutes
>> rs.recognize_path "/feed"
=> {:action=>"index", :page=>"feed", :controller=>"public"}
>> rs.recognize_path "/feed/thanks"
=> {:action=>"thanks", :controller=>"public"}
>> rs.generate :controller => :public, :page => 2
=> "/2"
# Per a testejar rutes de controladors inexistents
>> ActionController::Routing.use_controllers! [ "undefined", "test" ]
=> ["undefined", "test"]
>> load "config/routes.rb"
=> []
>> rs.recognize_path "/undefined/show/1"
=> {:action=>"show", :id=>"1", :controller=>"undefined"}

Ruby 1.8.5 en Leopard

enviat per Ramon Salvadó al bloc assert_response :success el dilluns 12 de Novembre del 2007 a les 22:08 hores

Leopard porta tot l’entorn de desenvolupament per a Ruby on Rails i Ruby integrat, cosa que està molt bé ja que facilita enormement l’arrencada de la gent que comença a desenvolupar amb aquestes tecnologies.

La versió de Ruby instal·lada es la 1.8.6 (amb alguns patchs interessants com ara el de suport per a dtrace). Algunes distribucions com ara centos 5 o debian etch utilitzen la versió 1.8.5. Això vol dir que si tenim aplicacions en producció corrent sobre aquestes distribucions probablement voldrem desenvolupar sobre la mateixa versió de Ruby per tal d’evitar “sorpreses”.

Per a aconseguir això podem compilar directament dels fonts o utilitzar macports. La cosa es que en el cas de voler utilitzar macports ens trobarem que no existeix variant per la versió 1.8.5.

El que podem fer es crear el nostre port a partir de la revisió de subversion del repositori macports del port de ruby que es corresponia a la versió 1.8.5:

Primer hem de crear un repositori de ports local:

1
2
mkdir /Users/Shared/dports
sudo sed -e '1i file:///Users/Shared/dports' -i~ /opt/local/etc/macports/sources.conf

Seguidament treiem la versió del repositori que ens interessi:

1
2
3
cd /Users/Shared/dports
svn co --revision 21487 http://svn.macports.org/repository/macports/trunk/dports/lang/ruby/ lang/ruby/
portindex /Users/Shared/dports

Llavors en un món ideal ja podríem instal·lar fent:


sudo port install ruby

I això instal·laria la versió del port en el nostre repositori local (1.8.5), el que passa es que per a que Ruby funcioni en Leopard cal aplicar uns patchs d’apple al codi font segons s’explica aquí

Així doncs el que caldrà fer es descarregar els fitxers dels patchs al directori files del nostre port i modificar el fixter Portfile per a que els apliqui. Si fem això veurem que s’apliquen netament excepte un que falla degut a que aquests patchs estan pensats per a la versió 1.8.6 de Ruby.

El que cal fer quan falla la instal·lació és anar al directori de treball del port, revisar el patch que falla i veure si podem modificar-lo per a aplicar-lo a la versió 1.8.5.

La modificació és molt senzilla, es tracta del fitxer ignore-gsetcontext.diff i un cop modificat per a la versió 1.8.5 queda així:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
--- eval.c.orig        2007-10-31 12:03:10.000000000 +0100
+++ eval.c        2007-10-31 12:03:10.000000000 +0100
@@ -29,9 +29,17 @@
 #endif
 
 #include <stdio>
-#if defined(HAVE_GETCONTEXT) && defined(HAVE_SETCONTEXT)
-#include <ucontext>
-#define USE_CONTEXT
+#if defined(HAVE_GETCONTEXT) && defined(HAVE_SETCONTEXT) 
+# if defined(__APPLE__)
+#   include <availabilitymacros>
+#   if MAC_OS_X_VERSION_MAX_ALLOWED <= 1040
+#     include <ucontext>
+#     define USE_CONTEXT
+#   endif
+# else
+#   include <ucontext>
+#   define USE_CONTEXT
+# endif
 #endif
 #include <setjmp>

Arribats a aquest punt podem instal·lar el port amb la comanda habitual:


sudo port install ruby

Un cop fet tot això disposarem de 2 versions de ruby instal·lades la 1.8.6 que es la que ve per defecte en Leopard i la 1.8.5 que es la que hem instal·lat via macports.

Podem fer servir una o altra segons ens convingui en funció de l’ordre de càrrega dels binaris de macports en la nostra variable PATH, si posem primer la de macports (/opt/local/bin i /opt/local/sbin) s’utilitzarà per defecte la versió 1.8.5 de Ruby i en cas contrari la 1.8.6.

Systemtap, alternativa a dtrace per a Linux

enviat per Ramon Salvadó al bloc assert_response :success el diumenge 11 de Novembre del 2007 a les 01:23 hores

Solaris disposa d’algunes característiques molt interessants, per a mi destaquen sobretot dtrace i el sistema de fitxers ZFS.

Pel que fa a ZFS la seva llicència fa impossible un port per a Linux, si bé sembla que es pot utilitzar mitjançant FUSE tal i com s’explica a ZFS on FUSE/Linux.

Per a Linux en comptes de dtrace tenim systemtap que proporciona funcionalitats similars. Podem veure una taula comparativa que detalla les diferències entre ambdós sistemes.

De moment no es possible d’utilitzar-lo en llenguatges script com ruby o python (cosa que si és possible amb dtrace).

Per a instal·lar systemtap en Centos 5 solament hem de fer:


yum install systemtap

A més també haurem d’instal·lar els paquets:

  • kernel-devel
  • kernel-headers
  • kernel-debuginfo
  • kernel-debuginfo-common

Les versions dels 2 darrers paquets s’han de correspondre amb la versió de kernel instal·lada i es poden trobar aquí

Amb systemtap podem fer coses força interessants, per exemple amb l’script següent podem veure una llista de processos ordenada en funció de l’ample de banda de xarxa que consumeixen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
global ifxmit, ifrecv, ifdevs, ifpid, execname, user

probe netdev.transmit
{
        p = pid()
        execname[p] = execname()
        user[p] = uid()
        ifdevs[p, dev_name] = dev_name
        ifxmit[p, dev_name] <<< length
        ifpid[p, dev_name] ++
}

probe netdev.receive
{
        p = pid()
        execname[p] = execname()
        user[p] = uid()
        ifdevs[p, dev_name] = dev_name
        ifrecv[p, dev_name] <<< length
        ifpid[p, dev_name] ++
}


function print_activity()
{
        printf("%5s %5s %-7s %7s %7s %7s %7s %-15s\n",
                "PID", "UID", "DEV", "XMIT_PK", "RECV_PK",
                "XMIT_KB", "RECV_KB", "COMMAND")

        foreach ([pid, dev] in ifpid-) {
                n_xmit = @count(ifxmit[pid, dev])
                n_recv = @count(ifrecv[pid, dev])
                printf("%5d %5d %-7s %7d %7d %7d %7d %-15s\n",
                        pid, user[pid], dev, n_xmit, n_recv,
                        n_xmit ? @sum(ifxmit[pid, dev])/1024 : 0,
                        n_recv ? @sum(ifrecv[pid, dev])/1024 : 0,
                        execname[pid])
        }

        print("\n")

        delete execname
        delete user
        delete ifdevs
        delete ifxmit
        delete ifrecv
        delete ifpid
}

probe timer.ms(5000)
{
        print_activity()
}

Un exemple de la sortida si l’executem:

1
2
3
4
PID   UID DEV     XMIT_PK RECV_PK XMIT_KB RECV_KB COMMAND        
    0     0 eth0          0      13       0       2 swapper        
 1947   501 eth0          4       0       0       0 ping           
 1873     0 eth0          1       0       0       0 sshd

Podem veure més exemples d’scripts en el wiki.

Un enigma aparentment difícil...

enviat per Lleïr Borràs al bloc Lleïr Borràs el divendres 29 de Juny del 2007 a les 00:05 hores

Avui he llegit una noticia curiosa a una web que solo seguir http://meneame.net/story/se-busca-hacker on deien que una empresa del Regne unit estava oferint un lloc per un programador de Perl/Php, i per tal d'enviar el CV havies de resoldre a quina adreça s'havia de fer. Ells et donaven una seqüència de nombres i lletres com a pista.

43616c6c204a756c69616e206f6e203032302037393234203636323 2206f7220656d61696c206a756c69616e406c6f6e7265732e636f6d

Només fer un cop d'ull tothom haurà vist que es tracta d'un nombre hexadecimal, i això ha ens dona una pista. Si contem el nombre de caràcters ens surt que és parell.

1
2
3
a='43616c6c204a756c69616e206f6e2030323020373932342036363232206f7220656d61696c206a756c69616e406c6f6e7265732e636f6d'
a.size
=> 110

Així doncs he decidit fer un petit algoritme que agafés els caràcters de la cadena de dos en dos en format hexadecimal i ens retornés el caràcter que formen segons la taula de codi "ASCII".

Aquí teniu la meva solució:

1
2
3
a='43616c6c204a756c69616e206f6e2030323020373932342036363232206f7220656d61696c206a756c69616e406c6f6e7265732e636f6d'
(0..(a.size.div(2)-1)).each{|x| print((a[(x*2)..(x*2+1)].to_s).hex.chr)}
=> Call Julian on 020 7924 6622 or email julian@lonres.com

Vía | Menéame.

Presentacions Railsconf 2007

enviat per Ramon Salvadó al bloc assert_response :success el divendres 18 de Maig del 2007 a les 22:52 hores

Per si voleu anar seguint les sessions de la Railsconf, aquest enllaç us pot resultar interessant.

Avui hi han hagut sessions molt interessants a veure si més tard tinc temps de donar-ne la meva opinió i fer-ne un breu resum.

Railsconf 2007. Scaling a Rails Application from the Bottom Up

enviat per Ramon Salvadó al bloc assert_response :success el divendres 18 de Maig del 2007 a les 07:26 hores

Aquest “tutorial” estava a càrrec d’en Jason Hoffman de Joyent . La veritat es que d’entrada prometia bastant ja que ells porten alguns dels “deployments” d’aplicacions Rails de més gran escala en l’actualitat com ara twitter per exemple.

La sessió ha tractat desde la selecció de servidors, consideracions de consum d’energia, costos d’ample de banda a alguns temes més específics d’aplicacions Rails.

Personalment pensava que tractaria més a fons temes específics sobre les bones pràctiques a l’hora d’escalar aplicacions Rails però les 2 primeres hores s’han centrat en temes de caire general, malgrat això la darrera hora ha estat prou interessant.

Algunes coses que he trobat especialment interessants:

  1. Varnish balancejador de càrrega, aquest tema es important ja que sembla ser que a partir d’un cert nombre de req/s la combinació d’apache amb el mod_proxy_balancer no escala per més mongrels que afegim per tant no és una solució viable per a grans deployments.
  2. Un truquet interessant que no havia pensat mai, es que podem utilitzar backtics (per a executar comandes de sistema) en els fitxers de configuració yml del mongrel_cluster per exemple de manera que els podem fer més genèrics. En el seu cas concret ho utilitzaven per determinar la ip i el hostname.
  3. Utilitzar múltiples hosts per a distribuir els continguts estàtics. Això accelera les nostres pàgines ja que els navegadors sols obren 2 conexions per host. Això vol dir que si utilitzem 4 hosts (que es el que han recomanat) per distribuir el contingut estàtic això vol dir que s’obriran 8 conexions simultanies enlloc de les 2 si ho fessim amb un de sol. Més informació sobre el tema aquí
  4. Powerdns un servidor de noms interessant que pot llegir les dades d’una base de dades mysql entre d’altre opcions. (O sigui que afegint un registre a una taula de la base de dades podem donar d’alta un subdomini, molt interessant per segons quin tipus d’aplicacions).
  5. Mongrels més ràpids i estables aka event driven mongrels

Evidentment s’han tractat molts d’altres temes: com escalar la base de dades, Jruby o la separació dels controladors de la nostra aplicació amb mongrels específics.

En resum molt interessant però he trobat a faltar certa manca de profunditat a l’hora de tractar temes més específics de Rails.

Personalitzar rails (configurar els plurals)

enviat per Lleïr Borràs al bloc Lleïr Borràs el divendres 18 de Maig del 2007 a les 01:51 hores

Un dels grans problemes que m'he trobat sempre amb rails és els plurals. Aquesta framework ha esta pensada per treballar en anglès, i per aixo molts cops els plurals, que es fan servir per lligar les tauls amb els models entre altres, no són correctes.

Per solucionar aixó podem editar l'arxiu "environment.rb" i tocar l'apartat "inflector":

1
2
3
4
5
6
7
8
# Add new inflection rules using the following format 
# (all these examples are active by default):
 Inflector.inflections do |inflect|
#   inflect.plural /^(ox)$/i, '\1en'
#   inflect.singular /^(ox)en/i, '\1'
#   inflect.irregular 'singular', 'plural'
#   inflect.uncountable %w( fish sheep )
 end

Podem configurar casos com els plurals regulars, les coses que es poden contar, ... mitjançant expresions regulars per fefinir patrons.

Segurament el més interessant i que farem servir més és l'apartat "inflect.irregular 'singular' 'plural'" que ens permet definir un cas particular.

Sobretot hem de tenir en compte de descomentar les línies "Inflector.inflections do |inflect|" i "end".