• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Paris RailsCamp 2009
 

Paris RailsCamp 2009

on

  • 888 views

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

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

Statistics

Views

Total Views
888
Views on SlideShare
888
Embed Views
0

Actions

Likes
0
Downloads
1
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />
  • <br />

Paris RailsCamp 2009 Paris RailsCamp 2009 Presentation Transcript

  • 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
  • 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é • Analyse en batch • Usages applicatifs, business, métriques
  • 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
  • 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 receiving mail at a rate that prevents additional messages from being delivered.
  • 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 route matches "/hello-world" with {:method=>:get} Notification dans notre canal IRC interne
  • 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
  • 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(doc['date'], doc['message'])); } Définition ‘live’ d’une requête, conservable si besoin
  • 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.
  • 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
  • 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
  • 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
  • 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
  • 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 • Divers logs infrastructure • mysql-slow.log, ...
  • Flot de traitement • Acquérir les logs en place • Store-n-forward • Perennisation des logs bruts • Traitement itératif des logs bruts
  • 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
  • MySQL High-level Rails Log HTTP Log Log action log Multitail Multitail Scribe Scribe ScribeServer
  • 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
  • ScribeServer HDFS Uploader Hadoop/Hive S3 Analyzer Business Developer Web front-end Indexer Metrics Tools
  • 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
  • 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)
  • 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
  • hadoop_ec2:setup hadoop_ec2:setup_os_instances hadoop_ec2:mkfs hadoop_ec2:local_execution_directory hadoop_ec2:setup_hadoop hadoop_ec2:run
  • hadoop_ec2:run batchr:hadoop_setup batchr:prepare_hive batchr:dfs_accesslog batchr:dfs_buslog batchr:dfs_old_datasets
  • GeoIPCountryWhois.csv batchr:dfs_ips batchr:dfs_geoips batchr:table_ips batchr:table_update_datasets batchr:table_old_datasets batchr:table_datasets
  • batchr:table_datasets batchr:dfs_datasets batchr:dfs_stats batchr:s3_datasets batchr:s3_stats batchr:app_stats batchr:daily_attempt
  • “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 ?
  • 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
  • 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
  • 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
  • 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 ?