Slide 1

Slide 1 text

Logs: Porque um ElePHPant tem que ter boa memória! Logs: Porque um ElePHPant tem que ter boa memória! www.galvao.eti.br CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 1 / 36 Some icons by IconFinder

Slide 2

Slide 2 text

Presidente da ABRAPHP – Associação Brasileira de Profissionais PHP Diretor da PHP Conference Brasil Contribui para a tradução da documentação oficial Atua como Zend Framework Evangelist para o ZTeam, da Zend. Professor (Especialista) de Pós-Graduação UNOESC (SC) e Faculdade Alfa (PR) 20+ anos desenvolvendo sistemas e aplicações com interface web 15+ destes com PHP 7+ com Zend Framework Palestrante em eventos nacionais e internacionais Instrutor de cursos presenciais e a distância Fundador e líder do GU PHPBR Fundador* e membro do GU PHPRS Site: http://www.galvao.eti.br/ http://people.php.net/galvao Twitter: @galvao Slides e Documentos: http://speakerdeck.com/galvao http://slideshare.net/ergalvao Github: http://github.com/galvao Posts: https://medium.com/@galvao Quem?! CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 2 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória!

Slide 3

Slide 3 text

Logs CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 3 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! Logs são a memória de um Sistema, a sua História: são a forma de encontrar eventuais situações importantes em um mar de 'irrelevância'. “ “

Slide 4

Slide 4 text

Logs CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 4 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! Logs são a memória de um Sistema, a sua História: são a forma de encontrar eventuais situações importantes em um mar de 'irrelevância'. “ “ – Eu

Slide 5

Slide 5 text

Padrões CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 5 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! Camadas de Log: Conteúdo Aplicação Transporte Informação contida Geração, Interpretação, Roteamento e Armazenamento Coloca e remove na “fila” Mensagens de Log

Slide 6

Slide 6 text

F.A.Q. CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 6 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! X X

Slide 7

Slide 7 text

Logs !≃ Erros CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 7 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! + + Timestamp Severidade Debug Info Notice Warning Error Critical Alert Emergency Mensagem

Slide 8

Slide 8 text

Logs !≃ Erros CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 8 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória!

Slide 9

Slide 9 text

Logs !≃ Erros CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 9 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! Similaridades nas Ocorrências Disputas Situações peculiares Problemas potenciais Gargalos Falhas humanas Análise } } } }

Slide 10

Slide 10 text

CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 10 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! Monolog FTW! composer require monolog/monolog --- use Monolog\Logger; use Monolog\Handler\StreamHandler; $logger = new Logger('LoggerName'); $logger->pushHandler(new StreamHandler(path_to_log_file));

Slide 11

Slide 11 text

Monolog CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 11 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! Camadas de Log: Conteúdo Aplicação Transporte Monolog\Formatter Monolog\Handler* Monolog\Logger Mensagens de Log

Slide 12

Slide 12 text

CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 12 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! Um exemplo real* pushHandler(new StreamHandler($absLogPath)); return self::$logger; } }

Slide 13

Slide 13 text

CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 13 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! public function authenticate() { $this->logger->info('Trying to authenticate to Pocket API'); try { $response = $this->client->post( self::POCKET_AUTHENTICATION_URI, [ 'headers' => self::$requestHeaders, 'form_params' => [ 'consumer_key' => self::$key, 'redirect_uri' => self::$redirectURI, ], 'timeout' => 10, ] ); } catch (ClientException $e) { $pocketExtraInfo = $e->getResponse()->getHeaders(); $this->logger->error('Failed to authenticate to Pocket API.', $pocketExtraInfo); throw new \Exception('Autnenticaton with the Pocket API has failed: ' . $e->getMessage()); } $this->logger->info('Successfully authenticated to Pocket API'); ... Um exemplo real*

Slide 14

Slide 14 text

CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 14 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! public function authenticate() { $this->logger->info('Trying to authenticate to Pocket API'); try { $response = $this->client->post( self::POCKET_AUTHENTICATION_URI, [ 'headers' => self::$requestHeaders, 'form_params' => [ 'consumer_key' => self::$key, 'redirect_uri' => self::$redirectURI, ], 'timeout' => 10, ] ); } catch (ClientException $e) { $pocketExtraInfo = $e->getResponse()->getHeaders(); $this->logger->error('Failed to authenticate to Pocket API.', $pocketExtraInfo); throw new \Exception('Autnenticaton with the Pocket API has failed: ' . $e->getMessage()); } $this->logger->info('Successfully authenticated to Pocket API'); ... Um exemplo real*

Slide 15

Slide 15 text

CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 15 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! public function authenticate() { $this->logger->info('Trying to authenticate to Pocket API'); try { $response = $this->client->post( self::POCKET_AUTHENTICATION_URI, [ 'headers' => self::$requestHeaders, 'form_params' => [ 'consumer_key' => self::$key, 'redirect_uri' => self::$redirectURI, ], 'timeout' => 10, ] ); } catch (ClientException $e) { $pocketExtraInfo = $e->getResponse()->getHeaders(); $this->logger->error('Failed to authenticate to Pocket API.', $pocketExtraInfo); throw new \Exception('Autnenticaton with the Pocket API has failed: ' . $e->getMessage()); } $this->logger->info('Successfully authenticated to Pocket API'); ... Um exemplo real*

Slide 16

Slide 16 text

CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 16 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! public function authenticate() { $this->logger->info('Trying to authenticate to Pocket API'); try { $response = $this->client->post( self::POCKET_AUTHENTICATION_URI, [ 'headers' => self::$requestHeaders, 'form_params' => [ 'consumer_key' => self::$key, 'redirect_uri' => self::$redirectURI, ], 'timeout' => 10, ] ); } catch (ClientException $e) { $pocketExtraInfo = $e->getResponse()->getHeaders(); $this->logger->error('Failed to authenticate to Pocket API.', $pocketExtraInfo); throw new \Exception('Autnenticaton with the Pocket API has failed: ' . $e->getMessage()); } $this->logger->info('Successfully authenticated to Pocket API'); ... Um exemplo real*

Slide 17

Slide 17 text

CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 17 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! $ cat data/logs/comphpartment.log [2016-08-11 08:40:02] cLogger.INFO: Trying to authenticate to Pocket API [] [] [2016-08-11 08:40:03] cLogger.ERROR: Failed to authenticate to Pocket API. {"Cache-Control":["private"],"Content-Type":["text/html; charset=UTF-8"], "Date":["Thu, 11 Aug 2016 11:40:03 GMT"],"Expires":["Thu, 19 Nov 1981 08:52:00 GMT"], "P3P":["policyref=\"/w3c/p3p.xml\", CP=\"ALL CURa ADMa DEVa OUR IND UNI COM NAV INT STA PRE\""], "Pragma":["no-cache"],"Server":["Apache"],"Set-Cookie":["PHPSESSID=8r2q9fs3hejuunl7dn4s9s6l37; path=/"],"Status":["403 Forbidden"],"Vary":["Accept-Encoding"],"X-Error":["Invalid consumer key."], "X-Error-Code":["152"],"X-Source":["Pocket"],"Content-Length":["13"],"Connection":["keep-alive"]} [] [2016-08-11 10:20:55] cLogger.INFO: Trying to authenticate to Poket API [] [] [2016-08-11 10:20:56] cLogger.INFO: Successfully authenticated to Pocket API [] [] [2016-08-11 10:34:50] cLogger.INFO: Trying to authenticate to Pocket API [] [] [2016-08-11 10:34:52] cLogger.INFO: Successfully authenticated to Pocket API [] [] [2016-08-11 10:34:57] cLogger.INFO: Waiting for User Authorization [] [] Um exemplo real*

Slide 18

Slide 18 text

CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 18 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! $ cat data/logs/comphpartment.log|grep Failed [2016-08-11 08:25:13] cLogger.ERROR: Failed to authenticate to Pocket API: Client error: `POST https://getpocket.com/v3/oauth/request` resulted in a `403 Forbidden` response: 403 Forbidden [] [] [2016-08-11 08:27:51] cLogger.ERROR: Failed to authenticate to Pocket API: Client error: `POST https://getpocket.com/v3/oauth/request` resulted in a `403 Forbidden` response: 403 Forbidden [] [] [2016-08-11 08:28:08] cLogger.ERROR: Failed to authenticate to Pocket API: Client error: `POST https://getpocket.com/v3/oauth/request` resulted in a `403 Forbidden` response: 403 Forbidden [] [] Um exemplo real*

Slide 19

Slide 19 text

Monolog: Padrões CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 19 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! [2016-08-11 06:35:08] cLogger.INFO: Trying to authenticate to Pocket API [] [] $ cat data/logs/comphpartment.log Formatter padrão:

Slide 20

Slide 20 text

Monolog: Padrões CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 20 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! [2016-08-11 06:35:08] cLogger.INFO: Trying to authenticate to Pocket API [] [] Data/Hora $ cat data/logs/comphpartment.log Formatter padrão:

Slide 21

Slide 21 text

Monolog: Padrões CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 21 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! [2016-08-11 06:35:08] cLogger.INFO: Trying to authenticate to Pocket API [] [] Data/Hora Nome do Logger/Severidade $ cat data/logs/comphpartment.log Formatter padrão:

Slide 22

Slide 22 text

Monolog: Padrões CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 22 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! [2016-08-11 06:35:08] cLogger.INFO: Trying to authenticate to Pocket API [] [] Data/Hora Nome do Logger/Severidade Mensagem $ cat data/logs/comphpartment.log Formatter padrão:

Slide 23

Slide 23 text

Monolog: Padrões CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 23 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! [2016-08-11 06:35:08] cLogger.INFO: Trying to authenticate to Pocket API [] [] Data/Hora Nome do Logger/Severidade Mensagem Contexto $ cat data/logs/comphpartment.log Formatter padrão: Extra

Slide 24

Slide 24 text

Monolog: Melhorias e Customizações CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 24 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! public static function getWrapper($loggerName = 'accessLogger') { switch ($loggerName) { case 'accessLogger': $folder = 'access'; break; case 'errorLogger': $folder = 'error'; break; } self::$logFile = date('Y-m-d') . '.log'; $absLogPath = ComPHPartment::getBasePath() . self::LOG_PATH . '/' . $folder . '/' . self::$logFile; self::$log = new Logger($loggerName); ... ...

Slide 25

Slide 25 text

Monolog: Melhorias e Customizações CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 25 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! public static function getWrapper($loggerName = 'accessLogger') { switch ($loggerName) { case 'accessLogger': $folder = 'access'; break; case 'errorLogger': $folder = 'error'; break; } self::$logFile = date('Y-m-d') . '.log'; $absLogPath = ComPHPartment::getBasePath() . self::LOG_PATH . '/' . $folder . '/' . self::$logFile; self::$log = new Logger($loggerName); ... ...

Slide 26

Slide 26 text

Monolog: Melhorias e Customizações CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 26 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! public static function getWrapper($loggerName = 'accessLogger') { switch ($loggerName) { case 'accessLogger': $folder = 'access'; break; case 'errorLogger': $folder = 'error'; break; } self::$logFile = date('Y-m-d') . '.log'; $absLogPath = ComPHPartment::getBasePath() . self::LOG_PATH . '/' . $folder . '/' . self::$logFile; self::$log = new Logger($loggerName); ... ...

Slide 27

Slide 27 text

Monolog: Melhorias e Customizações CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 27 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! public static function getWrapper($loggerName = 'accessLogger') { switch ($loggerName) { case 'accessLogger': $folder = 'access'; break; case 'errorLogger': $folder = 'error'; break; } self::$logFile = date('Y-m-d') . '.log'; $absLogPath = ComPHPartment::getBasePath() . self::LOG_PATH . '/' . $folder . '/' . self::$logFile; self::$log = new Logger($loggerName); ... ...

Slide 28

Slide 28 text

Monolog: Melhorias e Customizações CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 28 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! … use Monolog\Formatter\LineFormatter; ... $tsFormat = date('H:i:s'); $output = "%datetime% > %level_name% > %message% %context% %extra%" . PHP_EOL; $formatter = new LineFormatter($output, $tsFormat); $stream = new StreamHandler($absLogPath); $stream->setFormatter($formatter); self::$log = new Logger($loggerName); self::$log->pushHandler($stream);

Slide 29

Slide 29 text

Monolog: Melhorias e Customizações CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 29 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! … use Monolog\Formatter\LineFormatter; ... $tsFormat = date('H:i:s'); $output = "%datetime% > %level_name% > %message% %context% %extra%" . PHP_EOL; $formatter = new LineFormatter($output, $tsFormat); $stream = new StreamHandler($absLogPath); $stream->setFormatter($formatter); self::$log = new Logger($loggerName); self::$log->pushHandler($stream);

Slide 30

Slide 30 text

Monolog: Melhorias e Customizações CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 30 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! … use Monolog\Formatter\LineFormatter; ... $tsFormat = date('H:i:s'); $output = "%datetime% > %level_name% > %message% %context% %extra%" . PHP_EOL; $formatter = new LineFormatter($output, $tsFormat); $stream = new StreamHandler($absLogPath); $stream->setFormatter($formatter); self::$log = new Logger($loggerName); self::$log->pushHandler($stream);

Slide 31

Slide 31 text

Monolog: Melhorias e Customizações CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 31 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! … use Monolog\ErrorHandler; ... public static function getWrapper($loggerName = 'accessLogger') { … ErrorHandler::register(self::$logger); ...

Slide 32

Slide 32 text

Monolog: Melhorias e Customizações CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 32 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! … use Monolog\ErrorHandler; ... public static function getWrapper($loggerName = 'accessLogger') { … ErrorHandler::register(self::$logger); ...

Slide 33

Slide 33 text

Monolog++ CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 33 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! Handlers Syslog Process [NativeMail|SwiftMailer] Slack MongoDB ElasticSearch Redis FirePHP LogStash LogEntries NewRelic ZendMonitor ...

Slide 34

Slide 34 text

CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 34 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! Formatters HTML JSON … Processors Web MemoryUsage MemoryPeak ProcessId Git Tag ... Monolog++

Slide 35

Slide 35 text

Referências CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 35 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! RFC 5424 – Protocolo Syslog PSR 3 – Logger Interface Monolog ComPHPartment

Slide 36

Slide 36 text

Obrigado! CC Attribution-ShareAlike 3.0 Unported License by Er Galvão Abbott - 11/10/16 - 36 / 36 www.galvao.eti.br Logs: Porque um ElePHPant tem que ter boa memória! ? Dúvidas? ↓ Críticas? ↑ Elogios?!