Nota

Monitora Oracle Cloud Infrastructure Database con PostgreSQL utilizzando Datadog

Introduzione

Oracle Cloud Infrastructure (OCI) è una piattaforma cloud solida e altamente scalabile progettata per soddisfare le esigenze delle aziende moderne. Offre una suite completa di servizi per lo sviluppo di elaborazione, storage, rete, database e applicazioni, ottimizzati per prestazioni, sicurezza ed efficienza in termini di costi. OCI è la soluzione ideale per eseguire carichi di lavoro sia cloud nativi che tradizionali, offrendo alle aziende un'infrastruttura flessibile e affidabile.

Datadog è una piattaforma completa di monitoraggio e analisi basata su cloud progettata per aiutare le organizzazioni a ottenere visibilità end-to-end sulla loro infrastruttura IT, applicazioni e servizi. Consente il monitoraggio in tempo reale, la risoluzione dei problemi e l'ottimizzazione delle prestazioni in ambienti cloud dinamici e ibridi. Datadog si integra perfettamente con una vasta gamma di strumenti, piattaforme e servizi, rendendola una soluzione versatile per i moderni team operativi DevOps e IT.

Questa esercitazione descrive in che modo gli utenti di OCI Database con PostgreSQL e Datadog possono impostare soluzioni efficienti e scalabili per trasmettere senza problemi le metriche da OCI a Datadog utilizzando OCI Connector Hub e OCI Functions.

Obiettivi

Prerequisiti

Task 1: Crea un account Datadog

  1. Impostare un account nello strumento di integrazione Datadog utilizzando il sito Web Datadog. Fornire i dettagli dell'account necessari e completare l'impostazione dell'agente configurando le impostazioni di ambiente appropriate.

  2. Installare l'agente Datadog per raccogliere metriche ed eventi dal database OCI con PostgreSQL. Per ulteriori informazioni sull'impostazione e la configurazione dell'agente Datadog, vedere Imposta agente Datadog. Per ulteriori dettagli sulla risoluzione dei problemi e il debug dell'agente Datadog, vedere Utilizzo di base dell'agente Datadog.

  3. Selezionare OCI come integrazione e procedere con la relativa installazione. L'immagine riportata di seguito mostra la postinstallazione dell'integrazione OCI per Datadog.

    immagine

  4. Fare clic su Aggiungi tenancy e immettere le informazioni relative all'OCID tenancy e all'area home.

    immagine

Task 2: Crea risorse di autenticazione di Datadog

Crea un utente, un gruppo e un criterio di autenticazione Datadog in Oracle Cloud Infrastructure (OCI).

  1. Per creare un dominio, passare a Identità e creare un dominio denominato DataDog.

  2. Creare un gruppo denominato DatadogAuthGroup.

  3. Creare un utente denominato DatadogAuthUser utilizzando il proprio indirizzo e-mail (lo stesso indirizzo e-mail utilizzato per eseguire il login allo strumento di monitoraggio Datadog) e assegnare DatadogAuthGroup come gruppo.

  4. Copiare l'OCID utente e incollarlo nel campo OCID utente della casella di integrazione OCI Datadog per configurare l'OCID utente.

  5. Imposta API.

    1. Accedi al tuo profilo e seleziona il tuo nome utente.

    2. Passare a Risorse nell'angolo inferiore sinistro e selezionare Chiavi API.

    3. Fare clic su Aggiungi chiave API, quindi scaricare la chiave privata e fare clic su Aggiungi.

    4. Chiudere la finestra Anteprima file di configurazione. Non è richiesta alcuna azione.

    5. Copiare il valore Impronta e incollarlo nel campo Impronta nella casella di integrazione OCI Datadog.

  6. Configurare la chiave privata.

    1. Aprire il file della chiave privata scaricato (.pem) in un editor di testo o utilizzare un comando del terminale (ad esempio, cat) per visualizzarne il contenuto.

    2. Copiare l'intera chiave, comprese le righe -----BEGIN PRIVATE KEY----- e -----END PRIVATE KEY-----.

    3. Incollare la chiave privata nel campo Chiave privata nella casella di integrazione OCI Datadog.

  7. Creare un criterio denominato DataDogPolicy nel compartimento postgresqlinteg (radice).

  8. Utilizzare la Costruzione guidata criteri in modalità editor manuale per immettere l'istruzione criterio richiesta.

    Allow group DatadogAuthGroup to read all-resources in tenancy
    

Di seguito è riportato un esempio di casella di integrazione OCI Datadog dopo l'aggiunta dei dettagli della tenancy e dell'utente.

immagine

Task 3: creare uno stack OCI

immagine

Passare alla sezione Identità e creare uno stack di criteri nel compartimento radice. Ciò consente agli hub connettore di leggere le metriche e richiamare le funzioni con le istruzioni riportate di seguito.

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

Per configurare i criteri di identità e distribuire gli stack di inoltro delle metriche in OCI per l'integrazione di Datadog, attenersi ai task riportati di seguito.

Task 3.1: Creare uno stack di criteri (ORM_policy_stack)

  1. Fare clic su Crea stack di criteri nella casella di integrazione OCI Datadog, assicurarsi di utilizzare il collegamento fornito, che include lo script Terraform necessario e accettare le condizioni d'uso Oracle.

  2. Fare clic sul menu a discesa Directory di lavoro e selezionare datadog-oci-orm/policy-setup.

  3. Deselezionare Usa provider Terraform personalizzati.

  4. Immettere un nome descrittivo (ad esempio, datadog-metrics-policy-setup) e selezionare il compartimento per la distribuzione.

  5. Fare clic su Successivo, assegnare un nome al gruppo dinamico e al criterio o utilizzare i nomi predefiniti, assicurarsi che l'area di origine della tenancy sia selezionata e fare clic su Crea.

Task 3.2: Crea stack di inoltro metriche

Le risorse vengono distribuite nel compartimento specificato. Assicurarsi che l'utente che esegue lo stack disponga dei diritti di accesso appropriati.

  1. Fare clic su Crea stack di criteri nella casella Integrazione OCI Datadog e accettare le condizioni d'uso Oracle.

  2. Fare clic sul menu a discesa Directory di lavoro, selezionare datadog-oci-orm/metrics-setup e deselezionare Usa provider Terraform personalizzati.

  3. Assegnare un nome allo stack e selezionare il compartimento di distribuzione, quindi fare clic su Successivo.

  4. Lasciare i valori della tenancy non modificati, immettere la chiave API Datadog e selezionare l'endpoint US5 (ocimetrics-intake.us5.datadoghq.com).

  5. Per la configurazione di rete, assicurarsi che l'opzione Crea VCN sia selezionata e selezionare il compartimento appropriato per la creazione della VCN.

  6. Nella sezione Impostazioni funzione mantenere la forma predefinita dell'applicazione come GENERIC_ARM. Immettere il nome utente e la password del registro Docker OCI (password di fabbrica).

  7. Impostare la dimensione batch dell'hub connettore servizio su 5000 e fare clic su Avanti.

  8. Fare clic su Crea.

Task 3.3: Finalizzare la configurazione

  1. Tornare alla casella Integrazione OCI Datadog e fare clic su Crea configurazione per completare l'impostazione.

  2. Questo processo garantisce che le metriche e le funzioni di Datadog siano configurate correttamente per l'integrazione con OCI.

    immagine

Task 4: Crea funzioni OCI

Per creare un'applicazione in OCI Console, effettuare le operazioni riportate di seguito.

  1. Passare a Applicazioni e selezionare Crea applicazione.

  2. Immettere il nome dell'applicazione, selezionare la rete cloud virtuale (VCN) e i dettagli della subnet appropriati, quindi fare clic su Crea.

  3. Per accedere all'applicazione appena creata, in Risorse selezionare Introduzione.

    immagine

  4. Fare clic su Avvia Cloud Shell e copiare i comandi seguenti da Usa il contesto per l'area.

    fn list context
    fn use context <region name>
    
  5. Aggiornare il contesto in modo da includere l'ID compartimento della funzione.

    fn update context oracle.compartment-id <compartment-id>
    
  6. Aggiornare il contesto in modo da includere la posizione del registro che si desidera utilizzare.

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

    Nota: sostituire phx nel contesto con il codice area a tre cifre.

  7. Eseguire il login al registro utilizzando il token di autenticazione come password.

    docker login -u 'TENACNY_NAME/OCI_USERNAME' phx.ocir.io
    
  8. Verrà richiesto di immettere la password. Fornire la password appropriata.

    Nota:

    • Sostituire phx con il codice dell'area a tre cifre.
    • Se si utilizza Oracle Identity Cloud Service, il nome utente è <tenancyname>/oracleidentitycloudservice/<username>.
  9. Generare una funzione di testo standard hello-world.

    fn list apps
    fn init --runtime python datadog
    

    Il comando fn init genererà una cartella denominata datadog con tre file all'interno; func.py, func.yaml e requirements.txt.

  10. Eseguire il comando cd datadog.

  11. Aprire func.py e sostituire il contenuto del file con il seguente snippet di codice.

    # 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. Aggiornare func.yaml con il codice seguente. Sostituire DATADOG_TOKEN con la chiave API Datadog e DATADOG_HOST con l'endpoint REST: https://http-intake.logs.datadoghq.com/v1/input. Per ulteriori informazioni sull'endpoint REST, vedere Raccolta dei log e integrazioni.

    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. Aggiornare requirements.txt con il codice seguente.

    fdk
    dattime
    requests
    oci
    
  14. Eseguire il comando seguente per creare l'applicazione e distribuire le funzioni per completare l'impostazione.

    fn create app datadog01 --annotation oracle.com/oci/subnetIds='["Provide your subnet OCID"]'
    
  15. Eseguire il comando seguente per distribuire le funzioni per completare l'installazione.

    fn -v deploy --app datadog
    

Task 5: impostare un hub connettore OCI

  1. Andare alla console OCI, andare a Log, Connettori e fare clic su Crea connettore.

  2. Impostare l'origine su Monitoraggio e la destinazione su Funzioni.

  3. In Configura connessione di origine selezionare il compartimento metrica e lo spazio di nomi appropriati. Ad esempio, oci_postgresql per il monitoraggio del database.

  4. In Configura destinazione, selezionare il compartimento, l'applicazione funzione e la funzione create nel task 4.

  5. Se richiesto, fare clic su Crea per creare il criterio necessario.

  6. Fare clic su Crea per finalizzare l'impostazione dell'hub connettore OCI.

immagine

Task 6: Visualizza metriche in Datadog

OCI Connector Hub è ora configurato per attivare la funzione, abilitando l'inclusione delle metriche nel Datadog ogni volta che vengono rilevate nuove metriche. Nella casella Integrazione Datadog, andare a Metriche ed esaminare il riepilogo per visualizzare le metriche correlate a OCI.

immagine

Nella casella Integrazione Datadog, fare clic su Explorer per analizzare e selezionare le metriche OCI necessarie,

immagine

Risoluzione dei problemi

Se nella pagina Riepilogo metriche non vengono visualizzati dati, selezionare Abilita log per abilitare il log per consentire alle funzioni di rivedere i log ed eseguire il debug del problema.

immagine

Conferme

Altre risorse di apprendimento

Esplora altri laboratori su docs.oracle.com/learn o accedi a più contenuti gratuiti sulla formazione su Oracle Learning YouTube channel. Inoltre, visita education.oracle.com/learning-explorer per diventare un Oracle Learning Explorer.

Per la documentazione del prodotto, visita l'Oracle Help Center.