Note :

Surveiller Oracle Cloud Infrastructure Database avec PostgreSQL à l'aide de Datadog

Présentation

Oracle Cloud Infrastructure (OCI) est une plate-forme en nuage robuste et hautement évolutive conçue pour répondre aux besoins des entreprises modernes. Il offre une suite complète de services pour le calcul, le stockage, la mise en réseau, la base de données et le développement d'applications, optimisés pour la performance, la sécurité et l'efficacité des coûts. OCI est idéal pour exécuter à la fois des charges de travail natives en nuage et traditionnelles, en offrant aux entreprises une infrastructure flexible et fiable.

Datadog est une plateforme complète de surveillance et d'analyse en nuage conçue pour aider les organisations à obtenir une visibilité de bout en bout de leur infrastructure informatique, de leurs applications et de leurs services. Il permet la surveillance en temps réel, le dépannage et l'optimisation de la performance dans les environnements en nuage dynamiques et hybrides. Datadog s'intègre parfaitement à un large éventail d'outils, de plates-formes et de services, ce qui en fait une solution polyvalente pour les équipes d'opérations informatiques et DevOps modernes.

Ce tutoriel explique comment les utilisateurs d'OCI Database avec PostgreSQL et Datadog peuvent configurer des solutions efficaces et évolutives pour transmettre de façon transparente des mesures d'OCI vers Datadog à l'aide du centre de connecteurs OCI et du service des fonctions pour OCI.

Objectifs

Préalables

Tâche 1 : Créer un compte Datadog

  1. Configurez un compte dans l'outil d'intégration Datadog à l'aide du site Web Datadog. Fournissez les détails de compte nécessaires et terminez la configuration de l'agent en configurant les paramètres d'environnement appropriés.

  2. Installez l'agent Datadog pour collecter des mesures et des événements à partir de la base de données OCI avec PostgreSQL. Pour plus d'informations sur la configuration et la configuration de l'agent Datadog, voir Configurer l'agent Datadog. Pour plus de détails sur le dépannage et le débogage sur l'agent Datadog, voir Utilisation de base de l'agent Datadog.

  3. Sélectionnez OCI comme intégration et poursuivez son installation. L'image suivante présente la post-installation de l'intégration OCI pour Datadog.

    Image

  4. Cliquez sur Ajouter une location et entrez vos informations sur l'OCID de la location et la région principale.

    Image

Tâche 2 : Créer des ressources d'authentification Datadog

Créez un utilisateur, un groupe et une politique d'authentification Datadog dans Oracle Cloud Infrastructure (OCI).

  1. Pour créer un domaine, naviguez jusqu'à Identité et créez un domaine nommé DataDog.

  2. Créez un groupe nommé DatadogAuthGroup.

  3. Créez un utilisateur nommé DatadogAuthUser à l'aide de votre adresse de courriel (le même courriel utilisé pour vous connecter à l'outil de surveillance Datadog) et affectez DatadogAuthGroup comme groupe.

  4. Copiez l'OCID de l'utilisateur et collez-le dans le champ OCID de l'utilisateur de la vignette d'intégration OCI de Datadog pour configurer l'OCID de l'utilisateur.

  5. définition de l'API;

    1. Naviguez jusqu'à votre profil et sélectionnez votre nom d'utilisateur.

    2. Naviguez jusqu'à Ressources dans le coin inférieur gauche et sélectionnez Clés d'API.

    3. Cliquez sur Ajouter une clé d'API, puis téléchargez la clé privée, puis cliquez sur Ajouter.

    4. Fermez la fenêtre Prévisualisation du fichier de configuration. Aucune action n'est nécessaire.

    5. Copiez la valeur Empreinte numérique et collez-la dans le champ Empreinte numérique de la vignette d'intégration de Datadog OCI.

  6. Configurez la clé privée.

    1. Ouvrez le fichier de clé privée téléchargé (.pem) dans un éditeur de texte ou utilisez une commande de terminal (par exemple, cat) pour voir son contenu.

    2. Copiez la clé entière, y compris les lignes -----BEGIN PRIVATE KEY----- et -----END PRIVATE KEY-----.

    3. Collez la clé privée dans le champ Clé privée de la vignette d'intégration Datadog OCI.

  7. Créez une politique nommée DataDogPolicy dans le compartiment postgresqlinteg (racine).

  8. Utilisez le générateur de politiques en mode d'éditeur manuel pour entrer l'énoncé de politique requis.

    Allow group DatadogAuthGroup to read all-resources in tenancy
    

Voici un exemple de vignette d'intégration OCI Datadog après l'ajout des détails de location et d'utilisateur.

Image

Tâche 3 : Créer une pile OCI

Image

Naviguez jusqu'à votre section Identité et créez une pile de politiques sous le compartiment racine. Cela permet aux hubs de connecteur de lire les mesures et d'appeler des fonctions avec les instructions suivantes.

Allow dynamic-group DatadogAuthGroup to read metrics in tenancy
Allow dynamic-group DatadogAuthGroup to use fn-function in tenancy
Allow dynamic-group DatadogAuthGroup to use fn-invocation in tenancy

Pour configurer des politiques d'identité et déployer des piles de transfert de mesures dans OCI pour l'intégration avec Datadog, procédez comme suit :

Tâche 3.1 : Créer une pile de politiques (ORM_policy_stack)

  1. Cliquez sur Créer une pile de politiques dans la vignette d'intégration Datadog OCI, assurez-vous d'utiliser le lien fourni, qui inclut le script Terraform nécessaire et acceptez les conditions d'utilisation d'Oracle.

  2. Cliquez sur le menu déroulant Répertoire de travail et sélectionnez datadog-oci-orm/policy-setup.

  3. Désélectionnez Utiliser des fournisseurs Terraform personnalisés.

  4. Entrez un nom descriptif (par exemple, datadog-metrics-policy-setup) et sélectionnez le compartiment à déployer.

  5. Cliquez sur Suivant, nommez le groupe dynamique et la politique (ou utilisez les noms par défaut), assurez-vous que la région principale de la location est sélectionnée, puis cliquez sur Créer.

Tâche 3.2 : Créer une pile de transmission de mesure

Les ressources sont déployées dans le compartiment spécifié. Assurez-vous que l'utilisateur qui exécute la pile dispose des droits d'accès appropriés.

  1. Cliquez sur Créer une pile de politiques dans la vignette d'intégration d'OCI Datadog et acceptez les conditions d'utilisation d'Oracle.

  2. Cliquez sur le menu déroulant Répertoire de travail, sélectionnez datadog-oci-orm/metrics-setup et désélectionnez Utiliser des fournisseurs Terraform personnalisés.

  3. Nommez la pile et sélectionnez le compartiment de déploiement, puis cliquez sur Suivant.

  4. Laissez les valeurs de location non modifiées, entrez votre clé d'API Datadog et sélectionnez le point d'extrémité US5 (ocimetrics-intake.us5.datadoghq.com).

  5. Pour la configuration du réseau, assurez-vous que l'option Créer un VCN est cochée et sélectionnez le compartiment approprié pour la création du VCN.

  6. Dans la section Paramètres de fonction, conservez la forme d'application par défaut GENERIC_ARM. Entrez le nom d'utilisateur et le mot de passe du registre OCI Docker (mot de passe d'usine).

  7. Réglez la taille de lot du centre de connecteurs de service à 5000 et cliquez sur Suivant.

  8. Cliquez sur Créer.

Tâche 3.3 : Finaliser la configuration

  1. Retournez à la vignette d'intégration de Datadog OCI et cliquez sur Créer une configuration pour terminer la configuration.

  2. Ce processus garantit que les mesures et les fonctions Datadog sont correctement configurées pour l'intégration avec OCI.

    Image

Tâche 4 : Créer le service des fonctions pour OCI

Pour créer une application dans la console OCI, procédez comme suit :

  1. Naviguez jusqu'à Applications et sélectionnez Créer une application.

  2. Entrez le nom de l'application, sélectionnez le réseau en nuage virtuel (VCN) et les détails du sous-réseau appropriés, puis cliquez sur Créer.

  3. Pour accéder à la nouvelle application, sous Ressources, sélectionnez Démarrage.

    Image

  4. Cliquez sur Lancer Cloud Shell et copiez les commandes suivantes à partir de Utiliser le contexte pour votre région.

    fn list context
    fn use context <region name>
    
  5. Mettez à jour le contexte pour inclure l'ID compartiment de la fonction.

    fn update context oracle.compartment-id <compartment-id>
    
  6. Mettez à jour le contexte pour inclure l'emplacement du registre à utiliser.

    fn update context registry phx.ocir.io/<tenancy_name>/[YOUR-OCIR-REPO]
    

    Note : Remplacez phx par le code de région à trois chiffres.

  7. Connectez-vous au registre en utilisant le jeton d'authentification comme mot de passe.

    docker login -u 'TENACNY_NAME/OCI_USERNAME' phx.ocir.io
    
  8. Vous serez invité avec le mot de passe. Indiquez votre mot de passe approprié.

    Note :

    • Remplacez phx par le code de région à trois chiffres.
    • Si vous utilisez Oracle Identity Cloud Service, votre nom d'utilisateur est <tenancyname>/oracleidentitycloudservice/<username>.
  9. Générer une fonction standard hello-world.

    fn list apps
    fn init --runtime python datadog
    

    La commande fn init générera un dossier nommé datadog avec trois fichiers à l'intérieur : func.py, func.yaml et requirements.txt.

  10. Exécutez la commande cd datadog.

  11. Ouvrez func.py et remplacez le contenu du fichier par l'extrait de code suivant.

    # oci-monitoring-metrics-to-datadog version 1.0.
    #
    # Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
    # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
    
    import io
    import json
    import logging
    import os
    import re
    import requests
    from fdk import response
    from datetime import datetime
    
    """
    This sample OCI Function maps OCI Monitoring Service Metrics to the DataDog
    REST API 'submit-metrics' contract found here:
    
    https://docs.datadoghq.com/api/latest/metrics/#submit-metrics
    
    """
    
    # Use OCI Application or Function configurations to override these environment variable defaults.
    
    api_endpoint = os.getenv('DATADOG_METRICS_API_ENDPOINT', 'not-configured')
    api_key = os.getenv('DATADOG_API_KEY', 'not-configured')
    is_forwarding = eval(os.getenv('FORWARD_TO_DATADOG', "True"))
    metric_tag_keys = os.getenv('METRICS_TAG_KEYS', 'name, namespace, displayName, resourceDisplayName, unit')
    metric_tag_set = set()
    
    # Set all registered loggers to the configured log_level
    
    logging_level = os.getenv('LOGGING_LEVEL', 'INFO')
    loggers = [logging.getLogger()] + [logging.getLogger(name) for name in logging.root.manager.loggerDict]
    [logger.setLevel(logging.getLevelName(logging_level)) for logger in loggers]
    
    # Exception stack trace logging
    
    is_tracing = eval(os.getenv('ENABLE_TRACING', "False"))
    
    # Constants
    
    TEN_MINUTES_SEC = 10 * 60
    ONE_HOUR_SEC = 60 * 60
    
    # Functions
    
    def handler(ctx, data: io.BytesIO = None):
        """
        OCI Function Entry Point
        :param ctx: InvokeContext
        :param data: data payload
        :return: plain text response indicating success or error
        """
    
        preamble = " {} / event count = {} / logging level = {} / forwarding to DataDog = {}"
    
        try:
            metrics_list = json.loads(data.getvalue())
            logging.getLogger().info(preamble.format(ctx.FnName(), len(metrics_list), logging_level, is_forwarding))
            logging.getLogger().debug(metrics_list)
            converted_event_list = handle_metric_events(event_list=metrics_list)
            send_to_datadog(event_list=converted_event_list)
    
        except (Exception, ValueError) as ex:
            logging.getLogger().error('error handling logging payload: {}'.format(str(ex)))
            if is_tracing:
                logging.getLogger().error(ex)
    
    
    def handle_metric_events(event_list):
        """
        :param event_list: the list of metric formatted log records.
        :return: the list of DataDog formatted log records
        """
    
        result_list = []
        for event in event_list:
            single_result = transform_metric_to_datadog_format(log_record=event)
            result_list.append(single_result)
            logging.getLogger().debug(single_result)
    
        return result_list
    
    
    def transform_metric_to_datadog_format(log_record: dict):
        """
        Transform metrics to DataDog format.
        See: https://github.com/metrics/spec/blob/v1.0/json-format.md
        :param log_record: metric log record
        :return: DataDog formatted log record
        """
    
        series = [{
            'metric': get_metric_name(log_record),
            'type' : get_metric_type(log_record),
            'points' : get_metric_points(log_record),
            'tags' : get_metric_tags(log_record),
        }]
    
        result = {
            'series' : series
        }
        return result
    
    
    def get_metric_name(log_record: dict):
        """
        Assembles a metric name that appears to follow DataDog conventions.
        :param log_record:
        :return:
        """
    
        elements = get_dictionary_value(log_record, 'namespace').split('_')
        elements += camel_case_split(get_dictionary_value(log_record, 'name'))
        elements = [element.lower() for element in elements]
        return '.'.join(elements)
    
    
    def camel_case_split(str):
        """
        :param str:
        :return: Splits camel case string to individual strings
        """
    
        return re.findall(r'[A-Z](?:[a-z]+|[A-Z]*(?=[A-Z]|$))', str)
    
    
    def get_metric_type(log_record: dict):
        """
        :param log_record:
        :return: The type of metric. The available types are 0 (unspecified), 1 (count), 2 (rate), and 3 (gauge).
        Allowed enum values: 0,1,2,3
        """
    
        return 0
    
    
    def get_now_timestamp():
        return datetime.now().timestamp()
    
    
    def adjust_metric_timestamp(timestamp_ms):
        """
        DataDog Timestamps should be in POSIX time in seconds, and cannot be more than ten
        minutes in the future or more than one hour in the past.  OCI Timestamps are POSIX
        in milliseconds, therefore a conversion is required.
    
        See https://docs.datadoghq.com/api/latest/metrics/#submit-metrics
        :param oci_timestamp:
        :return:
        """
    
        # positive skew is expected
        timestamp_sec = int(timestamp_ms / 1000)
        delta_sec = get_now_timestamp() - timestamp_sec
    
        if (delta_sec > 0 and delta_sec > ONE_HOUR_SEC):
            logging.getLogger().warning('timestamp {} too far in the past per DataDog'.format(timestamp_ms))
    
        if (delta_sec < 0 and abs(delta_sec) > TEN_MINUTES_SEC):
            logging.getLogger().warning('timestamp {} too far in the future per DataDog'.format(timestamp_ms))
    
        return timestamp_sec
    
    
    def get_metric_points(log_record: dict):
        """
        :param log_record:
        :return: an array of arrays where each array is a datapoint scalar pair
        """
    
        result = []
    
        datapoints = get_dictionary_value(dictionary=log_record, target_key='datapoints')
        for point in datapoints:
            dd_point = {'timestamp': adjust_metric_timestamp(point.get('timestamp')),
                        'value': point.get('value')}
    
            result.append(dd_point)
    
        return result
    
    
    def get_metric_tags(log_record: dict):
        """
        Assembles tags from selected metric attributes.
        See https://docs.datadoghq.com/getting_started/tagging/
        :param log_record: the log record to scan
        :return: string of comma-separated, key:value pairs matching DataDog tag format
        """
    
        result = []
    
        for tag in get_metric_tag_set():
            value = get_dictionary_value(dictionary=log_record, target_key=tag)
            if value is None:
                continue
    
            if isinstance(value, str) and ':' in value:
                logging.getLogger().warning('tag contains a \':\' / ignoring {} ({})'.format(key, value))
                continue
    
            tag = '{}:{}'.format(tag, value)
            result.append(tag)
    
        return result
    
    
    def get_metric_tag_set():
        """
        :return: the set metric payload keys that we would like to have converted to tags.
        """
    
        global metric_tag_set
    
        if len(metric_tag_set) == 0 and metric_tag_keys:
            split_and_stripped_tags = [x.strip() for x in metric_tag_keys.split(',')]
            metric_tag_set.update(split_and_stripped_tags)
            logging.getLogger().debug("tag key set / {} ".format (metric_tag_set))
    
        return metric_tag_set
    
    
    def send_to_datadog (event_list):
        """
        Sends each transformed event to DataDog Endpoint.
        :param event_list: list of events in DataDog format
        :return: None
        """
    
        if is_forwarding is False:
            logging.getLogger().debug("DataDog forwarding is disabled - nothing sent")
            return
    
        if 'v2' not in api_endpoint:
            raise RuntimeError('Requires API endpoint version "v2": "{}"'.format(api_endpoint))
    
        # creating a session and adapter to avoid recreating
        # a new connection pool between each POST call
    
        try:
            session = requests.Session()
            adapter = requests.adapters.HTTPAdapter(pool_connections=10, pool_maxsize=10)
            session.mount('https://', adapter)
    
            for event in event_list:
                api_headers = {'Content-type': 'application/json', 'DD-API-KEY': api_key}
                logging.getLogger().debug("json to datadog: {}".format (json.dumps(event)))
                response = session.post(api_endpoint, data=json.dumps(event), headers=api_headers)
    
                if response.status_code != 202:
                    raise Exception ('error {} sending to DataDog: {}'.format(response.status_code, response.reason))
    
        finally:
            session.close()
    
    
    def get_dictionary_value(dictionary: dict, target_key: str):
        """
        Recursive method to find value within a dictionary which may also have nested lists / dictionaries.
        :param dictionary: the dictionary to scan
        :param target_key: the key we are looking for
        :return: If a target_key exists multiple times in the dictionary, the first one found will be returned.
        """
    
        if dictionary is None:
            raise Exception('dictionary None for key'.format(target_key))
    
        target_value = dictionary.get(target_key)
        if target_value:
            return target_value
    
        for key, value in dictionary.items():
            if isinstance(value, dict):
                target_value = get_dictionary_value(dictionary=value, target_key=target_key)
                if target_value:
                    return target_value
    
            elif isinstance(value, list):
                for entry in value:
                    if isinstance(entry, dict):
                        target_value = get_dictionary_value(dictionary=entry, target_key=target_key)
                        if target_value:
                            return target_value
    
    
    def local_test_mode(filename):
        """
        This routine reads a local json metrics file, converting the contents to DataDog format.
        :param filename: cloud events json file exported from OCI Logging UI or CLI.
        :return: None
        """
    
        logging.getLogger().info("local testing started")
    
        with open(filename, 'r') as f:
            transformed_results = list()
    
            for line in f:
                event = json.loads(line)
                logging.getLogger().debug(json.dumps(event, indent=4))
                transformed_result = transform_metric_to_datadog_format(event)
                transformed_results.append(transformed_result)
    
            logging.getLogger().debug(json.dumps(transformed_results, indent=4))
            send_to_datadog(event_list=transformed_results)
    
        logging.getLogger().info("local testing completed")
    
    
    """
    Local Debugging
    """
    
    if __name__ == "__main__":
        local_test_mode('oci-metrics-test-file.json')
    
  12. Mettez à jour func.yaml avec le code suivant. Remplacez DATADOG_TOKEN par votre clé d'API Datadog et DATADOG_HOST par le point d'extrémité REST - https://http-intake.logs.datadoghq.com/v1/input. Pour plus d'informations sur le point d'extrémité REST, voir Collecte et intégrations de journaux.

    schema_version: 20180708
    name: datadogapp
    version: 0.0.1
    runtime: python
    entrypoint: /python/bin/fdk /function/func.py handler
    memory: 1024
    timeout: 120
    config:
    DATADOG_HOST: https://http-intake.logs.datadoghq.com/v1/input
    DATADOG_TOKEN: ZZZZZzzzzzzzzzz
    
  13. Mettez à jour requirements.txt avec le code suivant.

    fdk
    dattime
    requests
    oci
    
  14. Exécutez la commande suivante pour créer l'application et déployer les fonctions pour terminer la configuration.

    fn create app datadog01 --annotation oracle.com/oci/subnetIds='["Provide your subnet OCID"]'
    
  15. Exécutez la commande suivante pour déployer les fonctions afin de terminer la configuration.

    fn -v deploy --app datadog
    

Tâche 5 : Configurer un centre de connecteurs OCI

  1. Allez à la console OCI, naviguez jusqu'à Journalisation, Connecteurs et cliquez sur Créer un connecteur.

  2. Réglez la source à surveillance et la cible à Fonctions.

  3. Sous Configurer la connexion source, sélectionnez le compartiment de mesures et l'espace de noms appropriés. Par exemple, oci_postgresql pour la surveillance de base de données.

  4. Sous Configurer la cible, sélectionnez le compartiment, l'application de fonction et la fonction créées dans la tâche 4.

  5. Si vous y êtes invité, cliquez sur Créer pour créer la politique nécessaire.

  6. Cliquez sur Créer pour finaliser la configuration du centre de connecteurs OCI.

Image

Tâche 6 : Voir les mesures dans Datadog

Le centre de connecteurs OCI est maintenant configuré pour déclencher la fonction, ce qui permet l'ingestion des mesures dans Datadog chaque fois que de nouvelles mesures sont détectées. Dans la vignette Intégration de Datadog, naviguez jusqu'à Mesures et vérifiez le sommaire pour voir les mesures liées à OCI.

Image

Dans la vignette Intégration Datadog, cliquez sur Explorer pour analyser et sélectionner les mesures OCI requises, au besoin.

Image

Dépannage

Si aucune donnée ne s'affiche dans la page Sommaire des mesures, sélectionnez Activer le journal pour permettre à vos fonctions de vérifier les journaux et de déboguer le problème.

Image

Remerciements

Autres ressources d'apprentissage

Explorez d'autres laboratoires sur le site docs.oracle.com/learn ou accédez à plus de contenu d'apprentissage gratuit sur le canal Oracle Learning YouTube. De plus, visitez education.oracle.com/learning-explorer pour devenir un explorateur Oracle Learning.

Pour obtenir la documentation sur le produit, visitez Oracle Help Center.