Logs, exceptions, mails, et
  autres désagréments
L’architecture de data-mining et de remontée d’erreurs chez Fotonauts


...
La Seule Vraie Question



 “euh , il s ’est p assé
     quoi,    là ?”
La Seule Vraie Réponse

         les


LOGS
2 usages
Global et éternel
• Toutes les machines
• Sur tous les composants voulus
• A tous les niveaux
• Aussi longtemps que désiré...
Local et focalisé
• Axé sur les situations d’erreur
• Sur quelques composants (Rails, Merb)
• Autant d’informations que po...
ErrorMailerx
     e d u
   R
Idée Géniale #1


• Envoyons un mail à chaque exception Rails
Google tried to deliver your
  message, but it was rejected.
   The user you are trying to
            contact
is receivin...
Hey !
Solution 1




MPW-C Compiler
 ”Too many errors
    on one line
  (make fewer)”
Solution 1I




    Jean Cocteau
 “Puisque ces mystères
 me dépassent, feignons
d'en être l'organisateur”
Une situation classique
irc://internal #infra


<rapportr> [prod][amz-prod-xx.fotonauts.net]
           [picor][exception][error]
           No ro...
irc://internal #infra
<rapportr> [prod][aws-prod-xx.fotonauts.net]
           [picor][exception][error]
           No rout...
Inclusion directe du hash généré par Rails dans CouchDB
function(doc) {
      if (doc['data']['env']['HTTP_X_FORWARDED_FOR']
           ==   "81.57.x.x, 127.0.0.1")
        emit(...
Bono-bots
             Rails App          stomp   AMQP Exchange


                                                        ...
Error “Mailer”
def self.deliver_exception(exception)
  evt = {
    :app     => 'picor',
    :type    => 'exception',
    :...
InfraBot - Couch
class InfraLogger < Bono::Bot::Service::Base
  def start
    options = {:queue => "#{Bono::Bot.uid}.servi...
InfraBot - IRC
class IrcLogger < Bono::Bot::Service::Base
  def start
    @c = EventMachine::connect(IRC_SERVER, IRC_PORT,...
Idées en l’air

• Si plus de n erreur sur action par jour
  Entrer un bug automatiquement
• Si plus de n erreur sur user x...
Logs globaux
Usage final

• Statistiques applicatif utilisateur
 • Page views, country views
• Search
 • Rating, ...
• Business metrics
Sources
• Frontaux Web
 • Varnish / Nginx / Lighttpd
• Rails
 • production.log
 • Log d’actions utilisateur haut niveau
• ...
Flot de traitement

• Acquérir les logs en place
• Store-n-forward
• Perennisation des logs bruts
• Traitement itératif de...
Flot de traitement

• Acquérir les logs en place : multitail
• Store-n-forward : Scribe
• Perennisation des logs bruts : S...
MySQL          High-level
Rails Log   HTTP Log
                                         Log           action log




     ...
Outils externes
• EC2 / S3 : Amazon Web Services
• Hadoop: Framework Map/Reduce
• Hive: Data-mining sur Hadoop
• Scribe: l...
ScribeServer           HDFS




                            Uploader            Hadoop/Hive




                          ...
Batchr
• Acquisition des données “historiques”
• Importation des données journalières en
  DFS Hadoop
 • Analyse des logs ...
Implémentation
• Gestion globale du batch par Rake
 • Gestion des instances EC2 (setup cluster
    hadoop, gestion de l’er...
Hadoop EC2
• Réécriture du setup des images Hadoop-
  EC2 en rake
 • Boot d’une image Ubuntu standard
 • Configuration Rake...
hadoop_ec2:setup




hadoop_ec2:setup_os_instances          hadoop_ec2:mkfs




                                          ...
hadoop_ec2:run




                                                        batchr:hadoop_setup




                       ...
GeoIPCountryWhois.csv           batchr:dfs_ips




                         batchr:dfs_geoips




                        ...
batchr:table_datasets




batchr:dfs_datasets                batchr:dfs_stats




batchr:s3_datasets                batchr...
“Stateful Rake”
• Rake
 • Expression des dépendances
 • Exécution manuelle d’une étape
• Avec des ajouts...
 • Etapes inte...
class TaskOnce < Rake::Task
  def execute(args)
    time = Time.now
    begin
      super(args)
      File.open(".done."+ ...
desc "extract unique ips from log"

once :dfs_ips => :table_accesslog do
  @hadoop.hive_string <<-HIVE, "dfs_ips"
  INSERT...
desc "run me every day"
task :daily do
  begin
    Rake::Task["batchr:daily_attempt"].invoke
  ensure
    Rake::Task["batc...
Idées en l’air
• Vraie reprise sur panne (Cluster EC2)
• Réconciliation de logs
• Accès filtré à une fenêtre de logs
• Web ...
Paris RailsCamp 2009
Paris RailsCamp 2009
Paris RailsCamp 2009
Paris RailsCamp 2009
Paris RailsCamp 2009
Paris RailsCamp 2009
Upcoming SlideShare
Loading in...5
×

Paris RailsCamp 2009

745

Published on

An (old) Fotopedia presentation we gave at Paris RailsCamp 2009 about our log/error infrastructure

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
745
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
2
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide















































  • Paris RailsCamp 2009

    1. 1. Logs, exceptions, mails, et autres désagréments L’architecture de data-mining et de remontée d’erreurs chez Fotonauts Olivier Gutknecht Aymerick Jéhanne Mathieu Poumeyrol olg@fotonauts.com aymerick@fotonauts.com kali@fotonauts.com
    2. 2. La Seule Vraie Question “euh , il s ’est p assé quoi, là ?”
    3. 3. La Seule Vraie Réponse les LOGS
    4. 4. 2 usages
    5. 5. Global et éternel • Toutes les machines • Sur tous les composants voulus • A tous les niveaux • Aussi longtemps que désiré • Analyse en batch • Usages applicatifs, business, métriques
    6. 6. Local et focalisé • Axé sur les situations d’erreur • Sur quelques composants (Rails, Merb) • Autant d’informations que possible • Persistence à court/moyen terme • Analyse minimal et quasi-live • Usage axé développement
    7. 7. ErrorMailerx e d u R
    8. 8. Idée Géniale #1 • Envoyons un mail à chaque exception Rails
    9. 9. Google tried to deliver your message, but it was rejected. The user you are trying to contact is receiving mail at a rate that prevents additional messages from being delivered.
    10. 10. Hey !
    11. 11. Solution 1 MPW-C Compiler ”Too many errors on one line (make fewer)”
    12. 12. Solution 1I Jean Cocteau “Puisque ces mystères me dépassent, feignons d'en être l'organisateur”
    13. 13. Une situation classique
    14. 14. irc://internal #infra <rapportr> [prod][amz-prod-xx.fotonauts.net] [picor][exception][error] No route matches "/hello-world" with {:method=>:get} Notification dans notre canal IRC interne
    15. 15. irc://internal #infra <rapportr> [prod][aws-prod-xx.fotonauts.net] [picor][exception][error] No route matches "/hello-world" with {:method=>:get} => http://xxx.fotonauts.net:5984/_utils/browse/ document.html?infra-events/ picor_exception_error_9b0b24e0- e817-012b-2ea4-12313800e821 ... avec le lien vers un document CouchDB
    16. 16. Inclusion directe du hash généré par Rails dans CouchDB
    17. 17. function(doc) { if (doc['data']['env']['HTTP_X_FORWARDED_FOR'] == "81.57.x.x, 127.0.0.1") emit(doc['date'], doc['message'])); } Définition ‘live’ d’une requête, conservable si besoin
    18. 18. Bono-bots Rails App stomp AMQP Exchange amqp amqp Toute action de haut niveau génère un message sur notre système bus Rapportr bots InfraLogger asynchrone / agents de traitements (bono-bots) pour gestion des notifications utilisateurs, etc... http irc On profite de la même infrastructure pour véhiculer les IRC Server CouchDB notifications d’exceptions.
    19. 19. Error “Mailer” def self.deliver_exception(exception) evt = { :app => 'picor', :type => 'exception', :level => 'error', :message => exception.message, :grid => grid, :fqdn => fqdn, } evt[:session][:params] = controller.params evt[:session][:env] = controller.request.env evt[:data][:backtrace] = exception.backtrace Bono::Bus::Infra.publish(Bono::Event.new(evt)) end
    20. 20. InfraBot - Couch class InfraLogger < Bono::Bot::Service::Base def start options = {:queue => "#{Bono::Bot.uid}.service.infra_logger"} @queue = Bono::Bus::Infra.watch_events(options) do |event| infra_event_received(event) end super end # callback fired when an infra event is received def infra_event_received(event) # format document doc = event.to_hash doc['_id'] = doc.delete('uid') # save to CouchDB database Bono::Database::CouchDB.store_document_async('infra-events', doc, 'infra_logger') end end
    21. 21. InfraBot - IRC class IrcLogger < Bono::Bot::Service::Base def start @c = EventMachine::connect(IRC_SERVER, IRC_PORT, BonoIrc, self) @c {|conn| conn.send_data("JOIN #infran") } @c do |conn| options = {:queue => "#{Bot.uid}.service.irc_logger.infra_events"} @infra_events_queue = Bono::Infra.watch_events(options) do |e| infra_event_received(e) end end end # callback fired when an infra event is received def infra_event_received(e) send_message(“#infra”, e.to_s) send_message(“#infra”, "http://xxx:5984/_utils/browse/document.html?infra-events/#{e}") end end
    22. 22. Idées en l’air • Si plus de n erreur sur action par jour Entrer un bug automatiquement • Si plus de n erreur sur user x Envoyer un mail d’investigation • Si plus de n tentatives d’attaque Blacklister l’IP pour x heures
    23. 23. Logs globaux
    24. 24. Usage final • Statistiques applicatif utilisateur • Page views, country views • Search • Rating, ... • Business metrics
    25. 25. Sources • Frontaux Web • Varnish / Nginx / Lighttpd • Rails • production.log • Log d’actions utilisateur haut niveau • Divers logs infrastructure • mysql-slow.log, ...
    26. 26. Flot de traitement • Acquérir les logs en place • Store-n-forward • Perennisation des logs bruts • Traitement itératif des logs bruts
    27. 27. Flot de traitement • Acquérir les logs en place : multitail • Store-n-forward : Scribe • Perennisation des logs bruts : S3 • Traitement itératif des logs bruts : Batchr
    28. 28. MySQL High-level Rails Log HTTP Log Log action log Multitail Multitail Scribe Scribe ScribeServer
    29. 29. Outils externes • EC2 / S3 : Amazon Web Services • Hadoop: Framework Map/Reduce • Hive: Data-mining sur Hadoop • Scribe: logger distribué / hiérarchique basé sur Thrift: RPC bas niveau très efficace
    30. 30. ScribeServer HDFS Uploader Hadoop/Hive S3 Analyzer Business Developer Web front-end Indexer Metrics Tools
    31. 31. Batchr • Acquisition des données “historiques” • Importation des données journalières en DFS Hadoop • Analyse des logs (GeoIP, comptage, ...) • Update historique + journalière • Réinjection S3 • Réinjection applicatif
    32. 32. Implémentation • Gestion globale du batch par Rake • Gestion des instances EC2 (setup cluster hadoop, gestion de l’erreur) • Import/Export S3 ←→ HDFS • Extraction/Analyse avec Hadoop/HIVE • Réinjection dans l’applicatifs (Ruby DBI)
    33. 33. Hadoop EC2 • Réécriture du setup des images Hadoop- EC2 en rake • Boot d’une image Ubuntu standard • Configuration Rake Net::SSH::Multi • Download d’un hadoop standard • Drivé par le clustermaster via rake
    34. 34. hadoop_ec2:setup hadoop_ec2:setup_os_instances hadoop_ec2:mkfs hadoop_ec2:local_execution_directory hadoop_ec2:setup_hadoop hadoop_ec2:run
    35. 35. hadoop_ec2:run batchr:hadoop_setup batchr:prepare_hive batchr:dfs_accesslog batchr:dfs_buslog batchr:dfs_old_datasets
    36. 36. GeoIPCountryWhois.csv batchr:dfs_ips batchr:dfs_geoips batchr:table_ips batchr:table_update_datasets batchr:table_old_datasets batchr:table_datasets
    37. 37. batchr:table_datasets batchr:dfs_datasets batchr:dfs_stats batchr:s3_datasets batchr:s3_stats batchr:app_stats batchr:daily_attempt
    38. 38. “Stateful Rake” • Rake • Expression des dépendances • Exécution manuelle d’une étape • Avec des ajouts... • Etapes intermédiaires non fiables • Qu’est-ce qu’une tache terminée ?
    39. 39. class TaskOnce < Rake::Task def execute(args) time = Time.now begin super(args) File.open(".done."+ name, "w") do |o| o.puts(Time.now - time).to_s + "sn" end rescue Exception => e File.open(".fail."+ name, "w") { |o| o.puts e.inspect } raise e end end def needed? !File.exist?(".done." + name) end end def once(args, &block) TaskOnce.define_task(args, &block) end
    40. 40. desc "extract unique ips from log" once :dfs_ips => :table_accesslog do @hadoop.hive_string <<-HIVE, "dfs_ips" INSERT OVERWRITE DIRECTORY 'ips' SELECT distinct(remote_addr_int) FROM accesslog SORT BY remote_addr_int HIVE end
    41. 41. desc "run me every day" task :daily do begin Rake::Task["batchr:daily_attempt"].invoke ensure Rake::Task["batchr:cleanup"].invoke end end desc "run me every day, no cleanup on error" task :daily_attempt => [ :pick_yesterday, :picor_stats, :s3_datasets, :statr_datasets ] do end
    42. 42. Idées en l’air • Vraie reprise sur panne (Cluster EC2) • Réconciliation de logs • Accès filtré à une fenêtre de logs • Web Rake (monitoring, dashboard, ...) • Frameworkiser EC2/Hadoop/Rake • Prototypage des requêtes data-mining • Quid de l’usage/pertinence de Hive ?
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×