O documento apresenta exemplos de logs de uma aplicação SVN que registam as ações dos utilizadores no repositório. São apresentadas duas formas de fazer logging: de forma errada, apenas registando mensagens de erro, e de forma correta, usando uma biblioteca de logging estruturada e gravando logs de diferentes níveis. É explicado como a instrumentação e testes automatizados ajudam a detetar e corrigir problemas mais rapidamente.
Como não entalar os dedos nas janelas: Finger-based apps no Windows 8
Como ser programador durante o dia e mesmo assim dormir bem à noite
1. 2ª Reunião Porto - 14/04/2012 http://netponto.org
Como ser programador durante o dia e
mesmo assim dormir bem à noite
Bruno Lopes
2. Bruno Lopes
• Co-founder de uma startup
• Tirei o curso há 6 anos
• 80% do que fiz e faço é web e .Net
• Éramos uma empresa de custom development
• Agora estamos agora a
vender, desenvolver, comercializar e suportar
um produto
6. Logging
• Registo da aplicação de
– Acções
– Avisos
– Erros
• Serve acima de tudo para diagnóstico
• Muitas formas de fazer mal
• Muitas formas de fazer bem
16. Como é que Logging me ajuda a
dormir melhor?
• Menos tempo à procura de erros
• Mais informação de diagnóstico
• Não preciso de ligar à Maya para saber o que
se passou
• Boas mensagens de erro ajudam-me a
resolver problemas mais depressa
30. Como é que Instrumentação me ajuda
a dormir melhor?
• Consigo identificar
– Quais os problemas
– Antes que o cliente note
• Observar o comportamento do sistema
enquanto ele corre
• Não tenho que divinar qual o problema
– Consigo verificar, corrigir e refactorizar
32. Testes unitários
• Quem conhece o conceito?
• Quem regularmente usa?
• Quem acha que lhes poupa trabalho?
• Quem acha que é banha da cobra?
33. Testes unitários
[Fact]
public void CanImportJustOneItemIntoPythonClassUsingDecorator()
{
var pythonCode =
@"
class StringItemSource:
@import_one(IActOnItem)
def import_action(self, action):
self.action = action
";
var engine = Python.CreateEngine();
var script = engine.CreateScriptSourceFromString(pythonCode);
var typeExtractor = new ExtractTypesFromScript(engine);
var exports = typeExtractor.GetPartsFromScript(script).ToList();
var container = new CompositionContainer(new TypeCatalog(typeof(MockExporter), typeof(MockImportActions)));
var batch = new CompositionBatch(exports, new ComposablePart[] {});
container.Compose(batch);
object action = exports.First().Instance.action;
Assert.NotNull(action);
Assert.IsAssignableFrom<IActOnItem>(action);
}
34. Testes unitários
[Fact]
public void CanImportJustOneItemIntoPythonClassUsingDecorator()
{
var pythonCode = Arrange
@"
class StringItemSource:
@import_one(IActOnItem)
def import_action(self, action):
self.action = action
";
var engine = Python.CreateEngine();
var script = engine.CreateScriptSourceFromString(pythonCode);
var typeExtractor = new ExtractTypesFromScript(engine);
var exports = typeExtractor.GetPartsFromScript(script).ToList();
Act
var container = new CompositionContainer(new TypeCatalog(typeof(MockExporter), typeof(MockImportActions)));
var batch = new CompositionBatch(exports, new ComposablePart[] {});
container.Compose(batch);
object action = exports.First().Instance.action; Assert
Assert.NotNull(action);
Assert.IsAssignableFrom<IActOnItem>(action);
}
35. Testes unitários
public class MakeSureIDoNotScrewUpHashingTests : TestClass
{
[Fact]
public void DidIScrewUpHashingInNewVersion()
{
var correctHash = GetSha1("converter", "id", "sourceid");
var newHash = new DocumentId("converter", "id", "sourceid", "learningid").GetId();
Assert.Equal(correctHash, newHash);
}
// Previous algorithm:
private string GetSha1(string converterId, string Id, string SourceId)
{
var sha1 = SHA1.Create();
sha1.Initialize();
return
BitConverter.ToString(
sha1.ComputeHash(Encoding.UTF8.GetBytes(converterId)
.Concat(Encoding.UTF8.GetBytes(Id))
.Concat(Encoding.UTF8.GetBytes(SourceId))
.ToArray()))
.Replace("-", "");
}
}
37. Testes unitários
automáticos
• A correrem sempre em background
– (eu falei disto na minha apresentação de integração
continua)
• Não servem só para testar código
– Também podem testar (supostas invariantes)
• Já me salvaram o couro várias vezes
– Novo requisito do cliente num projecto antigo
– Especificamos novo comportamento com testes
– Implementamos requisito e testes passam
– Mas testes antigos falham
– Eu não me ia lembrar de verificar isso
• Mas a máquina de integração contínua lembra-se
38. Testes unitários
automáticos
• Se repetimos, vemos se podemos automatizar
– Computador não se cansa nem se engana por
estar com sono
– Computador não se chateia por fazer a mesma
coisa várias vezes
– Bruno pode ir beber descafeinado enquanto
Computador faz coisas sozinho
39. Testes unitários
automáticos
Setup Desenvolvimento Produção
• Ir buscar • Templates • Deployment
dependências • Sanity checks • Updates
• Configurar BD • Testing
• Montar
ambiente
40. Como é que Automatização me ajuda
a dormir melhor?
• Computadores a verificar comportamento
enquanto durmo
• Posso actualizar sistemas enquanto durmo
• Posso passar tarefas para um colega mais
facilmente
– Corre “.psake.ps1 update-whole-world” e já está
44. Próximas reuniões presenciais
• 14/04/2012 – Abril
• 21/04/2012 – Abril (Lisboa)
• 12/05/2012 – Maio (Coimbra)
• 26/05/2012 – Maio (Lisboa)
Reserva estes dias na agenda! :)
** Se o contexto onde estiverem for diferente, as lições podem ser aplicadas de forma diferente** Podem também ter incentivos suficientemente fortes para se tornarem pouco relevantes** Caveat emptor
Que é quegostavaque me tivessemchamadado a atençãonafaculdadeQue me tinhaajudadonaweListen
O foco aqui não é as ferramentas em siÉ as metodologias, pitfals e dicas
E por melhores que sejamos, vai ser sempre preciso fazer diagnóstico, nem que seja durante o desenvolvimento** Ou melhor, feedback correcto do que aconteceu
Quando me falamem logs, é nistoquecostumopensarCasomuitoconhecido, logs de servidor web (apache, nestecaso)
Windows tem o event viewer, queagregaeventos de log de váriossitios e é um serviçofornecidopelosistemaoperativoEstesdoiscasossão a perspectiva “persistida” dos eventos, queapenas é uma 3 partes.É o resultado final de fazer loggingEunãoquerofalardesta parte.
Logging tem 3 componentesAplicação é o quevocesdesenvolvem, e é a origemInfrastrutura e persistencianão é paravocestocarem (em 99% dos casos)Nlog é uma das infrastruturasem.net, outraseria log4net
Info maissensivelfoiremovidaExcepçãoguardadana Base de dadosMas cortamalipelomeio a stacktraceNestecasonãotemosinformaçãonenhuma de ondeestá a darerro, porquetoda a stack tarce é ocupadapor frames de infrastrutura
Quantasrazõesparafuzilar o autordestecódigoencontram?ExcepçãoignoradaRetornar null!!111Console.Out.WriteMesmocorrigindoisso:Printf é um mau exemplo porque em aplicações que são mais do que pequenos spikes, vamos querer:Redirecionarparabd/event viewerFilterbaseado no tipo/origem/nivelNãoincluiinformação de ondefoifeitoNão tem standard para output de excepçõesRseponder
NugetEmvez de irmos á consola, usamos um Logger Este logger podia serinjectadocomodependenciapor DI, mas essa é outraapresentaçãoTambém se calharnaodeviamosapanhar a excepçãoaqui, mas essa é outraapresentação
Configuramos (fazemos o wiring) de ondevaipara o quê.Em runtime devemos poder ligar/desligarPorque nem sempre queremos info de debugNem em todo o ladoQuando houver problemas, não queremos ter que estar a recompilar a aplicação e fazer outro deploy.Idealmente, enquanto se alterarmos o ficheiro enquanto corre, a aplicaçºao apanharia isso
O resultado é melhor, tem maisinformaçãoE se quiserempodemortogonalmenteaocódigoquefaz logging, acrescentarmaisparâmetros(layout renderer emNlog)Uma entrada de log deve ser explicitaWhoWhatWhenWhereTambém podemos incluir o URL e currentuser, mas isso será ortogonal aoLog.Info
E mesmo mesmomesmo fixe é quando as mensagens de erro nos ajudamIdealmente mensagens de erro, excepções devem nos ajudar a corrigirUm bom exemplo de excepção (aparte de algum Engrish):- Indica a causa mais provavel de erro e como corrigir
Mesmo abstrair uma biblioteca de logging é duvidoso, na minha opiniãoExcepto talvez para bibliotecas
Profiler é uma aplicação, módulo ou parecido que ligamos na aplicação e nos mostra “as entranhas”Pode fazer profile a CódigoMemóriaLigações a bases de dados
Eu falo imenso desta ferramenta porque a acho genialÉ um profiler que “se atarracha” a aplicações de Nhibernate que nos permite tudo o que se passa entre a aplicação e a BD, com NhibernateMostra QueriesOnde é que foram executadosTempos de sessãoEstatisticasFerramenta indispensavel paraMonitorizar que não estou a fazer asneiraQuando estou a fazer asneira, perceber exactamente que asneira
Mini ProfilerFerramenta brutal, e mostra não só timings internos no servidor, como no browser webEste funciona em produção
Counters são apenas numeros que são guardados e analisadosTipicamente são dados “em barda”, com grande volume mas cada um é muito pequeno.Emitir este tipo de dados não deve ter impacto na performance da aplicação, e pode servir para análise histórica
Casomais simples: Performance counters de windowsQualquermaquina windows tem istoNestecaso de exemploestamos a olharpara dados de tempo de CPU no total, e dados de memória de umaaplicaçãochamada “ILoveLucene”Se nósestivermos com um problema de memóriaporexemplo, podiamosusarestegráfico e analisarquando é que a memóriasaltacoordenado com acções no software.
Aqui olhamos para “counters” que são emitidos por RavenDB (document database em .net).É informação “raw” que podemos guardar, ou apenas inspecionar momentaneamente para perceber o que se passa cá dentroNeste caso particular temos tambem alguma informação de diagnostico, como extensões activas
http://codeascraft.etsy.com/2011/02/15/measure-anything-measure-everything/Um caso muito interessante, na etsy eles monitorizam milhares de contadores, e aqui consegue-se não só detectar padrões, como permite “empurrar” código com mais confiança. Se algum contador começar a ter comportamentos fora do comum, consegue-se detectar e relacionar com uma actualizaçãoEtsy é um marketplace global para “handmade goods” e falam publicamente de como guardam dados para tudo.
SQLMonitor, uma ferramenta de monitorização de SQL, inclui info sobre top 10 queries, problemas de performance, carga
Esta é um toolkit para construir dashboards, por exemplo.
Este terceiro acto começa com testes unitários.Quem conhece? Usa?Fixe, não fixe? Limitações?
Exemplo de um projecto opensource meuTetes tipicamente teem um padrao
AAAPermiteguiar o design da aplicação
Mas também podem servir para validar que não fazemos asneira (foco no nome do metodo)Capturoestainformaçãonumtestequepossocorrersempre
E se há coisa importante em testes unitários, e não só, é este ciclo
Invariantes como:- Todas as stored procedures na BD têm de estar configuradas para o role public as poder executar - Um teste pode verificar isto em todos os commitsUm determinado método tem que responder a todos os valores de um enum(se bem que neste caso pode fazer mais sentidoabstrair para uma classe em vez de enum)Verificar que todos os textos se encontram traduzidos em todas as linguasPor isso falo em testes automáticosDe unidade, para “comportamentos pequenos”De integração, para verifcar mapeamentos com base de dados, comportamento de componentes inteirosDe performance, para validar De interface, porque é o que o utilizador vê
Antes de terminar.Espero que esta apresentação vos tenha ajudado e mostrado algumas formas de melhorar o processo de desenvolver, manter e suportar software.