Envoyer des quantités importantes de métriques

DogStatsD transmet des métriques générées à partir de votre application à l’Agent via un protocole de transport, à savoir UDP (User Datagram Protocol) ou UDS (Unix Domain Socket).

Lorsque DogStatsD est utilisé pour transmettre un volume important de métriques à un seul Agent, si vous ne prenez pas les mesures appropriées, il est courant de rencontrer les problèmes suivants :

  • Utilisation intensive du processeur par l’Agent
  • Datagrammes/métriques perdus
  • Erreurs (UDS) renvoyées par la bibliothèque client DogStatsD

Dans la plupart des cas, ces inconvénients peuvent être atténués en ajustant certaines options de configuration décrites ci-dessous.

Conseils généraux

Utiliser des clients officiels Datadog

Datadog recommande d’utiliser la dernière version des clients DogStatsD officiels pour chaque langage de programmation important.

Activer la mise en mémoire tampon sur votre client

Certaines clients StatsD et DogStatsD envoient par défaut une métrique par datagramme. Cela ajoute une charge importante au niveau du client, du système d’exploitation et de l’Agent. Si votre client prend en charge la mise en mémoire tampon de plusieurs métriques dans un datagramme, activez cette option pour réduire considérablement les volumes d’échange.

Si vous utilisez un client DogStatsD créé par la communauté et prenant en charge la mise en mémoire tampon, veillez à configurer pour les datagrammes une taille limite inférieure à la taille du buffer pour chaque datagramme de l'Agent (8 Ko par défaut, modifiable avec le paramètre dogstatsd_buffer_size de l'Agent) et à la taille limite de datagramme du réseau ou du système d'exploitation.

Voici quelques exemples de clients DogStatsD officiels pris en charge :

L’exemple ci-dessous repose sur la bibliothèque Python officielle de Datadog datadogpy, ainsi que sur un client DogStatsD en mémoire tampon qui envoie les métriques par l’intermédiaire d’un nombre restreint de paquets. Pour la mise en mémoire tampon, un vidage automatique est effectué dès que la limite de taille des paquets est atteinte, ainsi que toutes les 300 ms (valeur configurable).

from datadog import DogStatsd


# Pour un client v0.43.0+
dsd = DogStatsd(host="127.0.0.1", port=8125, disable_buffering=False)
dsd.gauge('example_metric.gauge_1', 123, tags=["environment:dev"])
dsd.gauge('example_metric.gauge_2', 1001, tags=["environment:dev"])
dsd.flush()  # Vidage manuel facultatif

# Pour une version du client antérieure à la 0.43.0, un gestionnaire de contexte est requis pour la mise en mémoire tampon
dsd = DogStatsd(host="127.0.0.1", port=8125)
with dsd:
    dsd.gauge('example_metric.gauge_1', 123, tags=["environment:dev"])
    dsd.gauge('example_metric.gauge_2', 1001, tags=["environment:dev"])
Par défaut, les instances de client DogStatsD Python (y compris l'instance globale statsd) ne peuvent pas être partagées entre des processus, mais sont thread-safe. De ce fait, le processus parent et chaque processus enfant doivent créer leurs propres instances du client, ou la mise en mémoire tampon doit être explicitement désactivée en définissant disable_buffering sur True. Consultez la documentation sur datadog.dogstatsd pour en savoir plus.

Échantillonner vos métriques

Vous pouvez réduire le trafic depuis votre client DogStatsD vers l’Agent en définissant une valeur de taux d’échantillonnage pour votre client. Par exemple, un taux d’échantillonnage de 0.5 réduit de moitié le nombre de paquets UDP transmis. Cette solution constitue un compromis acceptable : vous réduisez le trafic, mais perdez légèrement en précision et en granularité.

Pour en savoir plus et obtenir des exemples de code, consultez le paragraphe Sample Rate de la page DogStatsD.

Utiliser DogStatsD via UDS (Unix Domain Socket)

UDS est un protocole de communication inter-processus utilisé pour transporter les charges utiles DogStatsD. Comparé au protocole UDP, il sollicite peu de ressources et réduit l’empreinte globale de DogStatsD sur votre système.

Agrégation côté client

Les bibliothèques client peuvent agréger des métriques côté client. Cela a pour effet de limiter le nombre de messages devant être transmis à l’Agent Datadog, d’améliorer les performances d’E/S et d’optimiser le débit.

L’agrégation côté client est uniquement disponible pour les clients Go à partir de la v5.0.0.

Consultez la rubrique Agrégation côté client (en anglais) pour en savoir plus.

Exécuter plusieurs pipelines de traitement des métriques pour limiter les pertes de paquets

Si votre serveur DogStatsD utilise UDS et perd un nombre excessif de paquets, configurez le serveur de façon à utiliser plus de ressources CPU pour tenter d’augmenter la vitesse de traitement et de réduire les pertes de paquets.

Vous pouvez également configurer votre serveur DogStatsD si les données de télémétrie client indiquent des pertes de paquets et que le serveur n’utilise pas plus de 2 CPU ou 2 cœurs même lorsqu’ils sont disponibles.

Pour réduire les pertes de paquets :

  1. Augmentez la taille de la file d’attente du client en la définissant sur 8192. Pour en savoir plus, référez-vous à la configuration de la bibliothèque client. Le nombre de paquets perdus devrait alors diminuer, mais votre application risque d’utiliser plus de RAM.
  2. Vous pouvez également activer la fonctionnalité dogstatsd_pipeline_autoadjust: true dans la configuration de votre Agent Datadog. L’Agent utilisera plusieurs cœurs pour traiter les métriques custom, ce qui pourrait réduire le nombre de paquets perdus mais augmenter la charge CPU.

Buffers kernel des systèmes d’opération

La plupart des systèmes d’exploitation ajoutent des datagrammes UDP et UDS entrants, qui contiennent vos métriques, dans un buffer avec une taille limitée. Une fois cette limite atteinte, les datagrammes comprenant vos métriques sont perdues. Vous pouvez ajuster certaines valeurs afin d’accorder davantage de temps à l’Agent pour le traitement des métriques entrantes :

Via UDP (User Datagram Protocol)

Linux

Sur la plupart des distributions Linux, la taille maximale du buffer kernel est par défaut définie sur 212992 (208 KiB). Pour vous en assurer, utilisez la commande suivante :

$ sysctl net.core.rmem_max
net.core.rmem_max = 212992

Pour définir la taille maximale du buffer du socket DogStatsD sur 25 MiB, exécutez :

sysctl -w net.core.rmem_max=26214400

Ajoutez la configuration suivante à /etc/sysctl.conf pour appliquer de façon permanente ce changement :

net.core.rmem_max = 26214400

Définissez ensuite l’option de configuration dogstatsd_so_rcvbuf de l’Agent sur le même nombre dans datadog.yaml :

dogstatsd_so_rcvbuf: 26214400

Consultez la section Remarque sur sysctl dans Kubernetes si vous déployez l’Agent ou DogStatsD dans Kubernetes.

Via UDS (Unix Domain Socket)

Linux

Pour les sockets UDS, si le lecteur est plus lent que l’enregistreur, Linux effectue en interne la mise en mémoire tampon des datagrammes avec une liste d’attente. La taille de cette file d’attente représente le nombre maximal de datagrammes que Linux met en mémoire tampon par socket. Cette valeur peut être obtenue avec la commande suivante :

sysctl net.unix.max_dgram_qlen

Si la valeur est inférieure à 512, vous pouvez l’augmenter en la définissant sur 512 ou sur un nombre supérieur à l’aide de cette commande :

sysctl -w net.unix.max_dgram_qlen=512

Ajoutez la configuration suivante à /etc/sysctl.conf pour appliquer de façon permanente ce changement :

net.unix.max_dgram_qlen = 512

De la même manière, le paramètre net.core.wmem_max peut atteindre jusqu’à 4 MiB afin d’améliorer les performances d’écriture du client :

net.core.wmem_max = 4194304

Définissez ensuite l’option de configuration dogstatsd_so_rcvbuf de l’Agent sur le même nombre dans datadog.yaml :

dogstatsd_so_rcvbuf: 4194304

Remarque sur sysctl dans Kubernetes

Si vous utilisez Kubernetes pour déployer l’Agent et/ou DogStatsD et que vous souhaitez configurer les sysctls comme mentionné ci-dessus, configurez leur valeur au niveau de chaque conteneur. Si les sysctl net.* sont dotés d’un espace de nommage, vous pouvez les configurer au niveau des pods. Consultez la section Utilisation de sysctls dans un cluster Kubernetes de la documentation Kubernetes officielle (en anglais) pour en savoir plus.

Vérifier la conformité des tailles des paquets

Réduisez l’utilisation du processeur en envoyant des paquets de la bonne taille au serveur DogStatsD dans l’Agent Datadog. Les dernières versions des clients DogStatsD officiels optimisent la taille des paquets envoyés afin d’améliorer les performances.

Vous pouvez ignorer cette section si vous utilisez l’un des derniers clients Datadog DogStatsD.

Si les paquets envoyés sont trop petits, l’Agent Datadog en regroupe plusieurs afin de les traiter par lots par la suite dans le pipeline. Les clients DogStatsD officiels sont capables de regrouper des métriques afin d’optimiser le nombre de métriques par paquet.

Pour optimiser les performances de l’Agent Datadog, les clients DogStatsD doivent envoyer des paquets d’une taille correspondant à dogstatsd_buffer_size. La taille des paquets ne doit pas dépasser celle du buffer. Le cas contraire, l’Agent ne peut pas les charger entièrement dans le buffer sans entraîner des anomalies pour certaines métriques. Utilisez le champ de configuration correspondant dans vos clients DogStatsD.

Remarque pour le protocole UDP : étant donné que les paquets UDP passent généralement par la couche Ethernet et IP, vous pouvez éviter de fragmenter les paquets IP en limitant la taille des paquets à une valeur inférieure à une seule trame Ethernet sur votre réseau. La plupart du temps, les réseaux IPv4 sont configurés avec une MTU de 1 500 octets. Dans ce cas, la taille des paquets envoyés ne doit pas dépasser 1 472 octets.
Remarque pour le protocole UDS : pour optimiser les performances, les paquets UDS doivent être composés de 8 192 octets.

Limiter l’utilisation maximale de la mémoire de l’Agent

Pour pouvoir traiter l’avalanche de métriques envoyées par les clients DogStatsD, l’Agent a recours à la mémoire. Bien que cette opération ne dure qu’une courte période et que la mémoire soit rapidement rendue au système d’exploitation, ce processus entraîne un pic. Ce phénomène peut s’avérer problématique pour les environnements conteneurisés qui expulsent les pods ou conteneurs en cas de manque de mémoire.

Pour éviter que l’Agent Datadog atteigne son seuil d’utilisation de la mémoire, répartissez les envois de métriques pour votre application.

Pour limiter l’utilisation maximale de la mémoire, pensez également à réduire la mise en mémoire tampon. Le buffer principal du serveur DogStatsD dans l’Agent peut être configuré avec le champ dogstatsd_queue_size (depuis l’Agent Datadog 6.1.0). Sa valeur par défaut 1024 limite l’utilisation maximale de la mémoire à environ 768 Mo.

Remarque : la réduction de la taille du buffer peut entraîner une augmentation du nombre de paquets perdus.

Cet exemple réduit l’utilisation maximale de la mémoire de DogStatsD à environ 384 Mo :

dogstatsd_queue_size: 512

Consultez la section suivante dédiée à la détection des salves pour découvrir comment détecter les salves de métriques de vos applications.

Activer les statistiques de traitement des métriques et la détection des salves

DogStatsD possède un mode statistique vous permettant de visualiser les métriques les plus traitées.

Remarque : l'activation du mode statistique pour les métriques peut nuire aux performances de DogStatsD.

Pour activer le mode statistique, vous pouvez :

  • Définir dogstatsd_stats_enable sur true dans votre fichier de configuration
  • Définir la variable d’environnement DD_DOGSTATSD_STATS_ENABLE sur true
  • Utilisez la commande datadog-agent config set dogstatsd_stats true pour activer le mode lors de l’exécution. Vous pouvez le désactiver lors de l’exécution avec la commande datadog-agent config set dogstatsd_stats false.

Lorsque ce mode est activé, exécutez la commande datadog-agent dogstatsd-stats pour obtenir la liste des métriques traitées. Les métriques les plus souvent reçues apparaissent en premier.

Lors de l’exécution de ce mode, le serveur DogStatsD utilise un mécanisme de détection de pics d’utilisation. Si un pic est détecté, un log d’avertissement est généré. Exemple :

A burst of metrics has been detected by DogStatSd: here is the last 5 seconds count of metrics: [250 230 93899 233 218]

Télémétrie côté client

Par défaut, les clients DogStatsD envoient des métriques de télémétrie à l’Agent. Cela vous permet d’identifier plus facilement les goulots d’étranglement. Chaque métrique comporte un tag avec le langage du client ainsi que la version du client. Ces métriques ne sont pas considérées comme des métriques custom.

Chaque client partage un ensemble de tags communs.

TagDescriptionExemple
clientLe langage du client.client:py
client_versionLa version du client.client_version:1.2.3
client_transportLe protocole de transport utilisé par le client (udp ou uds).client_transport:uds

Remarque : lorsque vous utilisez le protocole UDP, le client ne peut pas détecter les erreurs réseau, et les métriques correspondantes ne tiennent pas compte des octets ou paquets perdus.

La télémétrie a été ajoutée avec la version 0.34.0 du client Python.

datadog.dogstatsd.client.metrics
Type de métrique : count
Le nombre de metrics envoyées au client DogStatsD par votre application (avant l’échantillonnage).
datadog.dogstatsd.client.events
Type de métrique : count
Le nombre d’events envoyés au client DogStatsD par votre application.
datadog.dogstatsd.client.service_checks
Type de métrique : count
Le nombre de service_checks envoyés au client DogStatsD par votre application.
datadog.dogstatsd.client.bytes_sent
Type de métrique : count
Le nombre d’octets envoyés à l’Agent.
datadog.dogstatsd.client.bytes_dropped
Type de métrique : count
Le nombre d’octets perdus par le client DogStatsD.
datadog.dogstatsd.client.packets_sent
Type de métrique : count
Le nombre de datagrammes envoyés à l’Agent.
datadog.dogstatsd.client.packets_dropped
Type de métrique : count
Le nombre de datagrammes perdus par le client DogStatsD.

Pour désactiver la télémétrie, utilisez la méthode disable_telemetry :

statsd.disable_telemetry()

Consultez le référentiel DataDog/datadogpy pour en savoir plus sur la configuration du client.

Pour aller plus loin