quarta-feira, 31 de julho de 2013

Garimpando acessos ao Apex

O Oracle Apex é muito interessante para desenvolvimento rápido de aplicações, mas tem a característica duvidosa de armazenar os dados das sessões no banco de dados. Por isso é importante, de tempos em tempos, descobrir por que um determinado cliente está iniciando muitas sessões.

Uma URL do Apex termina sempre com algo assim:
    /f?p=10702:1:2602444723283688:::::

O único parâmetro p recebe todos os dados separados por ponto-e-vírgula. O primeiro número é o número da aplicação, o segundo é o número da página e o terceiro é o número da sessão.

Nos logs do Apache, encontrei o seguinte:
180.76.5.93 - - [31/Jul/2013:00:00:21 -0300] "GET /aplicprod/f?p=10702:1:2602444723283688::::: HTTP/1.1" 302 -

E a minha missão era a de descobrir quais IPs iniciaram maior número de sessões distintas. A solução é trivial:

perl -ne 'print "$1 $2\n" if /^(\S+).+p=\d+:\d+:(\d{2,})/' access_log \
  | sort | uniq | grep -Po "(\d+\.){3}\d+" | uniq -c | sort -nr 

O primeiro passo é extrair o IP e o número da sessão e colocá-los lado-a-lado assim:

180.76.5.93 2602444723283688

Isso resolvemos com o Perl. Depois, ordeno todas as linhas e elimino as repetições (que são linhas com o mesmo IP e mesmo número de sessão). Nesse ponto, cada IP aparece tantas vezes quantas sessões distintas tiver abertas para si. Então, retiro o IP de cada linha (com o grep) e conto as ocorrências com os dois últimos comandos (uniq -c | sort -nr).

A conclusão é que o Perl facilita muito a estrepolias com a linha-de-comando e que há uns engraçadinhos nos Estêites e na China que gostam de iniciar sessões do Apex.

sexta-feira, 5 de julho de 2013

Treze meses

O número treze não é muito querido e talvez por isso nunca se dê muita atenção ao fato de que o nosso ano estaria melhor dividido em treze meses que pelos atuais doze. Ou talvez, como eu, as pessoas simplesmente não pensem muito sobre isso.

Supreendeu-me que treze divida 365 tão melhor que doze. O resto é apenas um para o treze, enquanto é cinco para o doze. Além disso, um ano de treze meses produziria meses de exatamente quatro semanas de sete dias (28 dias, portanto).

Esse dia extra poderia viver fora dos treze meses como um dia especial (no primeiro dia do ano, por exemplo), de forma que os dias das semanas caíssem sempre nos mesmos dias de cada mês. Então, o primeiro dia de Janeiro seria sempre uma segunda-feira. E o última dia do ano seria sempre um domingo. Os anos bissextos teriam um segundo dia especial.

Eu nunca tenho ilusões de ser original, dada a quantidade de gente no planeta, então fui pesquisar se isso já havia sido proposto. Descobri que Augusto Compte propôs um "Calendário Positivista" em 1849. Ele também queria renomear totalmente os meses, mas acho que seria mais fácil que o calendário fosse aceito sem uma alteração tão radical.

Resta, então, achar um novo nome para o décimo-terceiro mês. Penso que Minerva seria um bom nome. Em primeiro lugar, para termos ao menos um nome feminino de mês. Em segundo lugar, para manter a tradição de ter nomes romanos. Em terceiro lugar, a expressão "voto de minerva" refere-se justamente a uma votação envolvendo doze jurados e que foi desempatada pela deusa grega Atena (que corresponde à deusa romana Minerva).

Essa alteração seria, ademais, ecológica! Não haveria necessidade de imprimir calendários novos a cada ano. Com a prática, as pessoas sequer precisariam de um calendário para saber que o dia 16 é uma terça-feira, por exemplo. Talvez as oficinas mecânicas sofram um pouco para achar uma desculpa para colocar mulheres exiguamente vestidas nas paredes.

terça-feira, 2 de julho de 2013

Garimpanho logs com expressões regulares

Depois de analisar os logs do Apache, precisei investigar logs do JBoss. Como são logs de aplicações, as linhas não têm formato uniformizado. Logo, é preciso aplicar expressões regulares.

Com a ajuda do Perl, posso extrair o texto de interesse e depois ordenar com sort e uniq.

Por exemplo, o seguinte comando extrai endereços IPs do arquivo server.log:

perl -ne 'print "$1\n" if /((\d+.){3}\.\d+)/' server.log

Então, para ordenar os IPs por frequência, entram sort e uniq:

perl -ne 'print "$1\n" if /((\d+.){3}\.\d+)/' server.log \
  | sort | uniq -c | sort -nr | more

Se a busca não requer mais que uma expressão regular, pode-se usar a opção -o do grep, que indica que deve ser impressa apenas a parte da linha identificada pela expressão regular.

grep -Po "(\d+.){3}\.\d+" server.log

A opção -P indica que a expressão regular é da sintaxe do Perl