Capturer des traces Ruby on Rails avec Jaeger

Logo Jaeger

Suite à la sortie de AWS-Otel-Collector, j'ai tenté d'instrumenter un project Ruby-On-Rail.

Premier constat, il n'y a pas encore de librairie disponible (au sens version final) pour OpenTelemetry pour Ruby et encore moins pour Rails.

Par contre, il existe une librairie pour Ruby nommée Opencensus qui supporte plus de langages dont le Ruby (Langages supportés). A terme, le projet Opencensus sera intégré dans OpenTelemetry et a vocation a devenir le nouveau standard.

Pour ruby, il faut donc installer la gem "opencensus" et pour exporter vers jeager la gem "opencensus-jaeger

gem 'opencensus'
gem 'opencensus-jaeger'

Ajouter ensuite un initializer (opencensus.rb)

OpenCensus.configure do |c|

  c.trace.default_max_attributes = 64
  c.trace.exporter = OpenCensus::Trace::Exporters::JaegerExporter.new(
      service_name: 'myApplication',
      host: 'localhost', # default to 'localhost'
      port: '6831', # default to 6831
      tags: { 'something': 'useful' },
      max_packet_length: 12_345, # config if you want something smaller than DEFAULT_MAX_LENGTH,
      protocol_class: ::Thrift::CompactProtocol # currently supporting only compact protocol
  )
end

Dans application.rb

require 'opencensus/trace/integrations/rails'

Et cela va commencer à tracer par défaut les évenements suivants (la liste est configurable):

- sql.active_record
- render_template.action_view
- send_file.action_controller
- send_data.action_controller
- deliver.action_mailer

Dans l'interface Jaeger, cela va donner la visualisation suivante:

Capture Jaeger

Voici le docker-compose que j'utilise:

version: '3'

services:

  jaeger-agent:
    image: jaegertracing/jaeger-agent:latest
    command: ["--reporter.grpc.host-port", "otel-agent:14268"]
    ports:
      - "6831:6831/udp"
    depends_on:
      - otel-agent

  # Jaeger
  jaeger-all-in-one:
    image: jaegertracing/all-in-one:latest
    ports:
      - "16686:16686"
      - "14268"
      - "14250"

  aws-otel-collector:
    image: amazon/aws-otel-collector:latest
    volumes:
    - ./otel-config.yaml:/etc/otel-config.yaml
    environment:
      - AWS_REGION=eu-west-1
      - AWS_ACCESS_KEY_ID=XXXXX
      - AWS_SECRET_ACCESS_KEY=XXXXXXX
    ports:
      - "55680:55680"
      - "55681:55681"

  # Agent
  otel-agent:
    image: otel/opentelemetry-collector-dev:latest
    command: ["--config=/etc/otel-agent-config.yaml"]
    volumes:
      - ./otel-agent-config.yaml:/etc/otel-agent-config.yaml
    ports:
      - "14268"       # Jaeger receiver
    depends_on:
#      - otel-collector
      - aws-otel-collector
      - jaeger-all-in-one

Explication

Une fois que Opencensus pour Rails a capturé des traces, il doit pouvoir les exporter.

C'est pourquoi, j'ai configuré un Exporter de type Jaeger (d'autres sont disponibles).

Afin de réceptionner les traces au format, j'ai besoin d'un jaeger-agent (sur Kubernetes ce sera un sidecar container) qui va transmettre à un collecteur.

  jaeger-agent:
    image: jaegertracing/jaeger-agent:latest
    command: ["--reporter.grpc.host-port", "otel-agent:14268"]
    ports:
      - "6831:6831/udp"
    depends_on:
      - otel-agent

On donne à l'agent le host et le port du collecteur (sur Kubernetes le fqdn du service et le port), afin qu'il puisse transmettre.

Concernant le collecteur, on mettra généralement le jaeger-collector qui va s'occuper de la persistance, mais ici mon but est de faire arriver tout ca jusqu'à AWS XRay, je vais donc utiliser un collecteur OpenTelemetry qui supporte les données envoyées par jaeger-agent (grpc).

  # Agent
  otel-agent:
    image: otel/opentelemetry-collector-dev:latest
    command: ["--config=/etc/otel-agent-config.yaml"]
    volumes:
      - ./otel-agent-config.yaml:/etc/otel-agent-config.yaml
    ports:
      - "14268"       # Jaeger receiver

Le collecteur OpenTelemetry a la capacité de traiter et convertir les données vers le format désiré. Dans mon cas, je souhaite pouvoir voir les traces dans Jaeger et les voir dans AWS XRay. J'ai donc chainé mes exports:

service:
  extensions: [health_check, pprof, zpages]
  pipelines:
    traces:
      receivers: [jaeger]
      exporters: [otlp, jaeger, logging ]
      processors: [batch/traces, queued_retry]

Source: jaeger, Exports: OTLP (OpenTelemetry) + Jaeger

Si j'ajoute Jaeger dans ma stack:

  jaeger-all-in-one:
    image: jaegertracing/all-in-one:latest
    ports:
      - "16686:16686"
      - "14268"
      - "14250"

Je peux me rendre sur l'interface Jaeger UI: http://localhost:16686/ et observer les traces capturées.

J'ajoute AWS-Otel-Collector:

  aws-otel-collector:
    image: amazon/aws-otel-collector:latest
    volumes:
    - ./otel-config.yaml:/etc/otel-config.yaml
    environment:
      - AWS_REGION=eu-west-1
      - AWS_ACCESS_KEY_ID=XXX
      - AWS_SECRET_ACCESS_KEY=YYY
    ports:
      - "55680:55680"
      - "55681:55681"

Pour l'instant, je vois uniquement des traces vides arriver jusqu'a AWS X-Ray, mais j'ai bon espoir d'arriver à mes fins prochainement. (Je discute ici sur le Gitter du projet )

X-Ray Traces vides

Les fichiers de configuration actuel ainsi que le docker-compose.yml est disponible sur mon dépot Gitlab

Reste à faire sur Ruby on Rails

  • Capture des métriques et les envoyer des CloudWatch
  • Instrumenter et capturer des traces Faraday (Client HTTP pour Ruby)

Chargement en cours

Ajouter un commentaire

Photo Thibault Cordier

Thibault Cordier

Freelance DevOps & Cloud