Présentation

Pour envoyer vos logs à Datadog, activez la journalisation au sein d’un fichier avec lograge et suivez ce fichier avec l’Agent Datadog. Lorsque vous configurez la journalisation avec Ruby, veillez à ne pas oublier les attributs réservés.

Au lieu d’obtenir un log Rails comme celui-ci :

Started GET "/" for 127.0.0.1 at 2012-03-10 14:28:14 +0100
Processing by HomeController#index as HTML
  Rendered text template within layouts/application (0.0ms)
  Rendered layouts/_assets.html.erb (2.0ms)
  Rendered layouts/_top.html.erb (2.6ms)
  Rendered layouts/_about.html.erb (0.3ms)
  Rendered layouts/_google_analytics.html.erb (0.4ms)
Completed 200 OK in 79ms (Views: 78.8ms | ActiveRecord: 0.0ms)

Vous obtenez une entrée de log avec les informations suivantes au format JSON :

{
  "timestamp": "2016-01-12T19:15:19.118829+01:00",
  "level": "INFO",
  "logger": "Rails",
  "method": "GET",
  "path": "/jobs/833552.json",
  "format": "json",
  "controller": "jobs",
  "action": "show",
  "status": 200,
  "duration": 58.33,
  "view": 40.43,
  "db": 15.26
}

Configuration

Cette section décrit les étapes de configuration minimales requises pour transmettre les logs de votre application Rails à Datadog. Une version plus approfondie de cette configuration est disponible dans l’article Comment recueillir, personnaliser et gérer les logs d’une application Rails (en anglais).

  1. Ajoutez le gem Lograge à votre projet :

    gem 'lograge'
    
  2. Configurez Lograge. Dans votre fichier de configuration, définissez ce qui suit :

    # Lograge config
    config.lograge.enabled = true
    
    # This specifies to log in JSON format
    config.lograge.formatter = Lograge::Formatters::Json.new
    
    ## Disables log coloration
    config.colorize_logging = false
    
    # Log to a dedicated file
    config.lograge.logger = ActiveSupport::Logger.new(File.join(Rails.root, 'log', "#{Rails.env}.log"))
    
    # This is useful if you want to log query parameters
    config.lograge.custom_options = lambda do |event|
        { :ddsource => 'ruby',
          :params => event.payload[:params].reject { |k| %w(controller action).include? k }
        }
    end
    

    Remarque : vous pouvez également demander à Lograge d’ajouter des informations contextuelles à vos logs. Consultez la documentation Lograge (en anglais) pour en savoir plus.

  3. Configurez votre Agent Datadog. Créez un fichier ruby.d/conf.yaml dans votre dossier conf.d/ avec le contenu suivant :

      logs:
        - type: file
          path: "<RUBY_LOG_FILE_PATH>.log"
          service: ruby
          source: ruby
          sourcecategory: sourcecode
          ## Uncomment the following processing rule for multiline logs if they
          ## start by the date with the format yyyy-mm-dd
          #log_processing_rules:
          #  - type: multi_line
          #    name: new_log_start_with_date
          #    pattern: \d{4}\-(0?[1-9]|1[012])\-(0?[1-9]|[12][0-9]|3[01])
    

    En savoir plus sur la collecte de logs avec l’Agent.

  4. Redémarrez l’Agent.

Concepts avancés

Associer vos logs à vos traces

Si l’APM est activée pour cette application, vous pouvez améliorer la corrélation entre les traces et les logs d’application en suivant les instructions de journalisation Ruby pour l’APM afin d’ajouter automatiquement des identifiants de trace et de span à vos logs.

Conseils pour la journalisation dans votre application

Maintenant que votre configuration de journalisation envoie du contenu JSON valide, vous pouvez l’exploiter autant que nécessaire.

Durant la journalisation, ajoutez le plus de contexte possible (utilisateur, session, action et métriques).

Au lieu d’enregistrer de simples messages dans des chaînes, utilisez les hashs de log comme dans l’exemple suivant :

my_hash = {'user' => '1234', 'button_name'=>'save','message' => 'User 1234 clicked on button saved'};
logger.info(my_hash);

Le hash est converti en contenu JSON. Vous pouvez alors analyser l’utilisateur user et le nom de bouton button_name :

{
  "timestamp": "2016-01-12T19:15:18.683575+01:00",
  "level": "INFO",
  "logger": "WelcomeController",
  "message": {
    "user": "1234",
    "button_name": "save",
    "message": "User 1234 clicked on button saved"
  }
}

Configuration de journalisation suggérée pour RocketPants

Dans le fichier config/initializers/lograge_rocketpants.rb (le chemin varie en fonction de votre projet), configurez Lograge de façon à prendre en charge les contrôleurs rocket_pants :

# Tiré de :
#   https://github.com/Sutto/rocket_pants/issues/111
app = Rails.application
if app.config.lograge.enabled
  ActiveSupport::LogSubscriber.log_subscribers.each do |subscriber|
    case subscriber
      when ActionController::LogSubscriber
        Lograge.unsubscribe(:rocket_pants, subscriber)
    end
  end
  Lograge::RequestLogSubscriber.attach_to :rocket_pants
end

Configuration de journalisation suggérée pour Grape

Ajoutez le gem grape_logging :

gem 'grape_logging'

Envoyez des informations de configuration supplémentaires à Grape :

use GrapeLogging::Middleware::RequestLogger,
      instrumentation_key: 'grape', 
      include: [ GrapeLogging::Loggers::Response.new,
                 GrapeLogging::Loggers::FilterParameters.new ]

Créez le fichier config/initializers/instrumentation.rb et ajoutez la configuration suivante :

# S'abonner à la requête Grape et enregistrer les logs avec un logger dédié à Grape
grape_logger = Logging.logger['Grape']
ActiveSupport::Notifications.subscribe('grape') do |name, starts, ends, notification_id, payload|
    grape_logger.info payload
end

Pour aller plus loin