Azure Camp 9 Décembre - slides session développeurs webmedia
Paris RailsCamp 2009
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. La Seule Vraie Question
“euh , il s ’est p assé
quoi, là ?”
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. 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
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.
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
19. 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
20. 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.
22. 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
23. 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
24. 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
35. 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
36. ScribeServer HDFS
Uploader Hadoop/Hive
S3 Analyzer
Business Developer
Web front-end Indexer
Metrics Tools
37. 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
38. 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)
39. 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
44. “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 ?
45. 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
46. 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
47. 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
48. 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 ?