Créer une intégration
Rapport de recherche Datadog : Bilan sur l'adoption de l'informatique sans serveur Rapport : Bilan sur l'adoption de l'informatique sans serveur

Créer une intégration

Pour qu’une intégration basée sur l’Agent soit considérée comme complète, et donc prête à être incluse dans le référentiel principal et intégrée au paquet de l’Agent, un certain nombre d’exigences doivent être satisfaites :

  • Le fichier README.md doit être au bon format et inclure le contenu adéquat.
  • Une batterie de tests doit être effectuée afin de vérifier la bonne collecte de métriques.
  • Le fichier metadata.csv doit énumérer toutes les métriques recueillies.
  • Le fichier manifest.json doit être complet.
  • Si l’intégration recueille des checks de service, le fichier service_checks.json doit également être présent.

Ces exigences forment une checklist de vérification qui est passée en revue durant le processus d’examen du code. Cette documentation vous expliquera comment satisfaire ces exigences et implémenter correctement votre nouvelle intégration.

Prérequis

  • Python 3.8+ doit être disponible sur votre système. Python 2.7 est facultatif, mais conseillé.
  • Docker pour exécuter l’ensemble des tests.

Si la création et l’activation d’environnements virtuels Python est généralement conseillé pour isoler l’environnement de développement, ce n’est toutefois pas obligatoire. Pour en savoir plus, consultez la documentation sur l’environnement Python.

Configuration

Clonez le référentiel integrations-extras. Par défaut, ces outils s’attendent à ce que vous travailliez dans le répertoire $HOME/dd/. Ce n’est toutefois pas obligatoire, et vous aurez la possibilité de modifier ce paramètre ultérieurement.

mkdir $HOME/dd && cd $HOME/dd       # facultatif
git clone https://github.com/DataDog/integrations-extras.git

Kit de développement

Le kit de développement est complet et intègre de nombreuses fonctionnalités. Pour démarrer, exécutez cette commande :

pip install "datadog-checks-dev[cli]"

Si vous avez choisi de cloner ce référentiel à un emplacement autre que $HOME/dd/, vous devrez modifier le fichier de configuration :

ddev config set extras "/chemin/vers/integrations-extras"

Si vous prévoyez de travailler principalement sur integrations-extras, définissez-le comme référentiel de travail par défaut :

ddev config set repo extras

Remarque : si vous sautez cette étape, vous devrez utiliser l’option -e à chaque appel pour vérifier que le contexte est integrations-extras :

ddev -e COMMANDE [OPTIONS]

Architecture

L’une des fonctionnalités du kit de développement est la commande create, qui crée la structure de fichiers et de chemins générale (c’est-à-dire l’« architecture ») nécessaire pour toute nouvelle intégration.

Test d’exécution

Pour effectuer un test d’exécution, utilisez le flag -n/--dry-run, qui n’effectue aucune écriture sur le disque.

ddev create -n awesome

Cette commande affiche le chemin où les fichiers auraient été écrits, ainsi que la structure. Pour le moment, contentez-vous de vérifier que le chemin dans la première ligne de la sortie correspond à l’emplacement de votre référentiel Extras.

Mode interactif

Le mode interactif est un assistant conçu pour vous aider à créer des intégrations. Il suffit de répondre à quelques questions pour que l’architecture soit automatiquement définie et préconfigurée.

ddev create awesome

Après avoir répondu aux questions, la sortie correspond à celle du test d’exécution ci-dessus, à la différence près que l’architecture de votre nouvelle intégration existe vraiment.

Écrire le check

Introduction

Un Check est une classe Python qui doit :

  • Les intégrations qui s’exécutent via l’Agent 7+ doivent être compatibles avec Python 3. À l’inverse, les versions 5 et 6 de l’Agent utilisent toujours Python 2.7.
  • Être dérivée de AgentCheck
  • Fournir une méthode avec la signature check(self, instance)

Les checks se présentent sous la forme de paquets Python classiques stockés dans l’espace de nommage datadog_checks ; votre code résidera donc dans awesome/datadog_checks/awesome. La seule exigence est que le nom du paquet soit le même que le nom du check. Aucune restriction particulière n’est appliquée quant au nom des modules Python dans ce paquet, ni quant au nom de la classe qui implémente le check.

Implémenter la logique du check

Supposons que vous souhaitez créer un check d’Agent composé uniquement d’un check de service appelé awesome.search qui recherche une chaîne sur une page Web. Il renverra OK si la chaîne est présente, WARNING si la page est accessible mais que la chaîne est absente, et CRITICAL si la page est inaccessible. Consultez la section Envoi de métriques : check custom d’Agent pour découvrir comment envoyer des métriques à l’aide de votre check d’Agent.

Le code contenu dans awesome/datadog_checks/awesome/awesome.py ressemblerait à ceci :

import requests

from datadog_checks.base import AgentCheck, ConfigurationError


class AwesomeCheck(AgentCheck):
    """AwesomeCheck est dérivé d'AgentCheck et fournit la méthode de check requise."""

    def check(self, instance):
        url = instance.get('url')
        search_string = instance.get('search_string')

        # Il convient de réaliser quelques contrôles d'intégrité basiques.
        # Soyez aussi précis que possible avec les exceptions.
        if not url or not search_string:
            raise ConfigurationError('Configuration error, please fix awesome.yaml')

        try:
            response = requests.get(url)
            response.raise_for_status()
        # En cas de problème sérieux
        except Exception as e:
            # Un message plus spécifique serait préférable
            self.service_check('awesome.search', self.CRITICAL, message=str(e))
        # La page est accessible
        else:
            # search_string est présent
            if search_string in response.text:
                self.service_check('awesome.search', self.OK)
            # search_string est introuvable
            else:
                self.service_check('awesome.search', self.WARNING)

Pour en savoir plus sur la classe Python de base, consultez la documentation sur l’API Python (en anglais).

Écrire des tests

Il existe deux types de tests de base :

  • Les tests d’unités, qui permettent de tester une fonctionnalité spécifique
  • Les tests d’intégration, qui exécutent la méthode check et vérifient la bonne collecte des métriques

Les tests sont obligatoires si vous souhaitez que votre intégration soit ajoutée à integrations-extras. Notez que pytest et tox sont utilisés pour exécuter les tests.

Pour en savoir plus, consultez la documentation sur le développement de checks Datadog.

Test d’unité

La première partie de la méthode check récupère et vérifie deux éléments du fichier de configuration. Un test d’unité serait donc particulièrement utile. Ouvrez le fichier awesome/tests/test_awesome.py et remplacez son contenu pour qu’il ressemble à ceci :

import pytest

# N'oubliez pas d'importer votre intégration !
from datadog_checks.awesome import AwesomeCheck
from datadog_checks.base import ConfigurationError


@pytest.mark.unit
def test_config():
    instance = {}
    c = AwesomeCheck('awesome', {}, [instance])

    # instance vide
    with pytest.raises(ConfigurationError):
        c.check(instance)

    # url uniquement
    with pytest.raises(ConfigurationError):
        c.check({'url': 'http://foobar'})

    # chaîne de recherche uniquement
    with pytest.raises(ConfigurationError):
        c.check({'search_string': 'foo'})

    # aucune erreur ne devrait survenir
    c.check({'url': 'http://foobar', 'search_string': 'foo'})

pytest permet d’utiliser ce que l’on appelle des marqueurs, qui servent à regrouper les tests par catégorie. Notez que le marqueur unit a été appliqué à test_config.

L’architecture a déjà été configurée de façon à ce que tous les tests situés dans awesome/tests soient exécutés. Pour exécuter ces tests :

ddev test awesome

Créer un test d’intégration

Ce test d’unité ne vérifie pas la logique de collecte ; nous allons donc ajouter un test d’intégration. docker est utilisé pour lancer un conteneur Nginx et laisser le check récupérer la page d’accueil. Créez un fichier compose awesome/tests/docker-compose.yml avec le contenu suivant :

version: "3"

services:
  nginx:
    image: nginx:stable-alpine
    ports:
      - "8000:80"

Ouvrez ensuite le fichier awesome/tests/conftest.py et remplacez le contenu de cette manière :

import os

import pytest

from datadog_checks.dev import docker_run, get_docker_hostname, get_here

URL = 'http://{}:8000'.format(get_docker_hostname())
SEARCH_STRING = 'Thank you for using nginx.'
INSTANCE = {'url': URL, 'search_string': SEARCH_STRING}


@pytest.fixture(scope='session')
def dd_environment():
    compose_file = os.path.join(get_here(), 'docker-compose.yml')

    # On accomplit ici 3 choses :
    #
    # 1. Lancer les services définis dans le fichier compose
    # 2. Attendre que l'URL soit disponible avant de lancer les tests
    # 3. Démonter les services lorsque les tests sont terminés
    with docker_run(compose_file, endpoints=[URL]):
        yield INSTANCE


@pytest.fixture
def instance():
    return INSTANCE.copy()

Test d’intégration

Enfin, ajoutez un test d’intégration au fichier awesome/tests/test_awesome.py :

@pytest.mark.integration
@pytest.mark.usefixtures('dd_environment')
def test_service_check(aggregator, instance):
    c = AwesomeCheck('awesome', {}, [instance])

    # le check doit renvoyer OK
    c.check(instance)
    aggregator.assert_service_check('awesome.search', AwesomeCheck.OK)

    # le check doit renvoyer WARNING
    instance['search_string'] = 'Apache'
    c.check(instance)
    aggregator.assert_service_check('awesome.search', AwesomeCheck.WARNING)

Pour un développement plus rapide, lancez les tests d’intégration uniquement avec l’option -m/--marker :

ddev test -m integration awesome

Le check est quasiment fini. Apportons la touche finale en ajoutant les configurations d’intégration.

Créer les ressources du check

Pour qu’un check puisse être inclus, l’ensemble des ressources créées par l’architecture ddev doit être complet :

Dans cet exemple, ces fichiers ressembleraient à ce qui suit :

Voici le fichier awesome/datadog_checks/awesome/data/conf.yaml.example pour le check de service Awesome :

init_config:
  ## Commentaire de bloc dans la partie
  ## init_config.

## Commentaire de bloc en dehors de
## la partie init_config.

instances:
  ## @param url  : chaîne (obligatoire)
  ## L'URL à vérifier
  ## (notez l'indentation avec le trait d'union)
  #
  - url: http://example.org

    ## @param search_string : chaîne (obligatoire)
    ## La chaîne  à rechercher
    #
    search_string: "Exemple de domaine"

    ## @param user  : objet (facultatif)
    ## L'utilisateur doit respecter la structure
    ## {'name': ['<PRÉNOM>', '<NOM>'], 'username': <NOMUTILISATEUR>, 'password': <MOTDEPASSE>}
    #
    # user:
    #   name:
    #     - <PRÉNOM>
    #     - <NOM>
    #   username: <NOMUTILISATEUR>
    #   password: <MOTDEPASSE>

    ## @param options : objet (obligatoire)
    ## Les flags que vous souhaitez définir
    #
    options:
      ## @param follow_redirects : booléen (facultatif) ; valeur par défaut : false
      ## Définir sur true pour suivre la redirection 301
      #
      # follow_redirects: false

Le fichier awesome/manifest.json pour le check de service Awesome. Notez que le guid doit être unique (et valide). N’utilisez donc pas celui de cet exemple. Cet identifiant sera de toute façon automatiquement géré :

{
  "display_name": "awesome",
  "maintainer": "email@example.org",
  "manifest_version": "1.0.0",
  "name": "awesome",
  "metric_prefix": "awesome.",
  "metric_to_check": "",
  "creates_events": false,
  "short_description": "",
  "guid": "x16b8750-df1e-46c0-839a-2056461b604x",
  "support": "contrib",
  "supported_os": ["linux", "mac_os", "windows"],
  "public_title": "Intégration Datadog/Awesome",
  "categories": ["web"],
  "type": "check",
  "is_public": false,
  "integration_id": "awesome",
  "assets": {
    "dashboards": {
      "Awesome Overview": "assets/dashboards/overview.json",
      "Awesome Investigation Dashboard": "assets/dashboards/investigation.json"
    },
    "monitors": {},
    "service_checks": "assets/service_checks.json"
  }
}

L’exemple d’intégration n’envoie aucune métrique. Le fichier awesome/metadata.csv généré contient donc uniquement la ligne avec les noms de colonne CSV.

L’exemple d’intégration contient un check de service. Vous devez donc l’ajouter au fichier awesome/assets/service_checks.json :

[
  {
    "agent_version": "6.0.0",
    "integration": "awesome",
    "check": "awesome.search",
    "statuses": ["ok", "warning", "critical"],
    "groups": [],
    "name": "Recherche Awesome",
    "description": "Renvoie `CRITICAL` si le check n'accède pas à la page, `WARNING` si la chaîne de recherche n'a pas été trouvée ou `OK` pour les autres cas."
  }
]

Compilation

setup.py contient le script de configuration setuptools, qui facilite la compilation d’un paquet au format wheel. Pour en savoir plus sur les paquets Python, consultez la documentation Python officielle (en anglais).

Une fois votre fichier setup.py prêt, créez un wheel :

  • Avec l’outil ddev (conseillé) : ddev release build <NOM_INTÉGRATION>
  • Sans l’outil ddev : cd <RÉPERTOIRE_INTÉGRATION> && python setup.py bdist_wheel

Que contient le wheel ?

Le wheel contient tous les fichiers nécessaires au bon fonctionnement de l’intégration. Il s’agit notamment du check, de l’exemple de fichier de configuration et de certains artefacts générés durant la compilation du wheel. Tous les autres éléments, y compris les fichiers de métadonnées, ne sont pas supposés se trouver dans le wheel. Ces éléments sont utilisés ailleurs par l’écosystème et la plateforme Datadog.

Installation

Le wheel est installé via la commande integration de l’Agent, disponible dans les versions 6.10.0 et ultérieures de l’Agent. En fonction de votre environnement, il est possible que vous deviez utiliser un utilisateur spécifique ou certaines autorisations précises pour exécuter cette commande :

Linux (en tant que dd-agent) :

sudo -u dd-agent datadog-agent integration install -w /chemin/vers/wheel.whl

OSX (en tant qu’admin) :

sudo datadog-agent integration install -w /chemin/vers/wheel.whl

Windows (veillez à ce que votre session shell dispose des privilèges administrateur) :

Pour les versions <= 6.11 de l’Agent :

"C:\Program Files\Datadog\Datadog Agent\embedded\agent.exe" integration install -w /chemin/vers/wheel.whl

Pour les versions >= 6.12 de l’Agent :

"C:\Program Files\Datadog\Datadog Agent\bin\agent.exe" integration install -w /chemin/vers/wheel.whl