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:
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 )
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)