Hinweis:

Oracle Cloud Infrastructure Database mit PostgreSQL mit Datadog überwachen

Einführung

Oracle Cloud Infrastructure (OCI) ist eine robuste und hoch skalierbare Cloud-Plattform, die auf die Anforderungen moderner Unternehmen ausgelegt ist. Es bietet eine umfassende Suite von Services für Computing, Speicher, Netzwerk, Datenbank und Anwendungsentwicklung, die für Performance, Sicherheit und Kosteneffizienz optimiert sind. OCI eignet sich ideal für die Ausführung von cloudnativen und traditionellen Workloads und bietet Unternehmen eine flexible und zuverlässige Infrastruktur.

Datadog ist eine umfassende cloudbasierte Überwachungs- und Analyseplattform, mit der Unternehmen End-to-End-Visibilität in ihre IT-Infrastruktur, -Anwendungen und -Services erhalten können. Sie ermöglicht Echtzeitüberwachung, Fehlerbehebung und Performanceoptimierung in dynamischen Hybrid-Cloud-Umgebungen. Datadog lässt sich nahtlos in eine Vielzahl von Tools, Plattformen und Services integrieren und ist so eine vielseitige Lösung für moderne DevOps- und IT-Betriebsteams.

Dieses Tutorial zeigt, wie OCI Database mit PostgreSQL- und Datadog-Benutzern effiziente, skalierbare Lösungen einrichten kann, um Metriken mithilfe von OCI Connector Hub und OCI Functions nahtlos von OCI an Datadog zu übertragen.

Ziele

Voraussetzungen

Aufgabe 1: Datadog-Konto erstellen

  1. Richten Sie mit der Datadog-Website ein Konto im Datadog-Integrationstool ein. Geben Sie die erforderlichen Accountdetails an, und schließen Sie das Agent-Setup ab, indem Sie die entsprechenden Umgebungseinstellungen konfigurieren.

  2. Installieren Sie den Datadog-Agent, um Metriken und Ereignisse aus der OCI-Datenbank mit PostgreSQL zu erfassen. Weitere Informationen zum Einrichten und Konfigurieren des Datadog-Agent finden Sie unter Datadog-Agent einrichten. Weitere Details zur Fehlerbehebung und zum Debugging auf dem Datadog-Agent finden Sie unter Grundlegende Verwendung des Datadog-Agent.

  3. Wählen Sie OCI als Integration aus, und fahren Sie mit der Installation fort. Die folgende Abbildung zeigt die Nachinstallation der OCI-Integration für Datadog.

    image

  4. Klicken Sie auf Mandanten hinzufügen, und geben Sie Ihre Informationen zu Mandanten-OCID und Home-Region ein.

    image

Aufgabe 2: Datadog-Authentifizierungsressourcen erstellen

Erstellen Sie einen Datadog-Authentifizierungsbenutzer, eine Datadog-Gruppe und eine Oracle Cloud Infrastructure-(OCI-)Policy.

  1. Um eine Domain zu erstellen, navigieren Sie zu Identität, und erstellen Sie eine Domain namens DataDog.

  2. Erstellen Sie eine Gruppe namens DatadogAuthGroup.

  3. Erstellen Sie einen Benutzer namens DatadogAuthUser mit Ihrer E-Mail-Adresse (dieselbe E-Mail, mit der Sie sich beim Datadog-Überwachungstool anmelden), und weisen Sie DatadogAuthGroup als Gruppe zu.

  4. Kopieren Sie die Benutzer-OCID, und fügen Sie sie in das Feld Benutzer-OCID in der Datadog-OCI-Integrationskachel ein, um die Benutzer-OCID zu konfigurieren.

  5. API einrichten

    1. Navigieren Sie zu Ihrem Profil, und wählen Sie Ihren Benutzernamen aus.

    2. Navigieren Sie in der unteren linken Ecke zu Ressourcen, und wählen Sie API-Schlüssel aus.

    3. Klicken Sie auf API-Schlüssel hinzufügen, laden Sie den Private Key herunter, und klicken Sie auf Hinzufügen.

    4. Schließen Sie das Fenster Konfigurationsdateivorschau. Keine Maßnahme erforderlich.

    5. Kopieren Sie den Wert für Fingerprint, und fügen Sie ihn in das Feld Fingerprint in der Datadog-OCI-Integrationskachel ein.

  6. Private Key konfigurieren

    1. Öffnen Sie die heruntergeladene Private-Key-Datei (.pem) in einem Texteditor, oder verwenden Sie einen Terminalbefehl (z.B. cat), um den Inhalt anzuzeigen.

    2. Kopieren Sie den gesamten Schlüssel, einschließlich der Zeilen -----BEGIN PRIVATE KEY----- und -----END PRIVATE KEY-----.

    3. Fügen Sie den Private Key in das Feld Private Key in der Datadog-OCI-Integrationskachel ein.

  7. Erstellen Sie eine Policy mit dem Namen DataDogPolicy im Compartment postgresqlinteg (Root).

  8. Verwenden Sie den Policy Builder im manuellen Editormodus, um die erforderliche Policy-Anweisung einzugeben.

    Allow group DatadogAuthGroup to read all-resources in tenancy
    

Im Folgenden finden Sie eine Beispiel-Datadog-OCI-Integrationskachel nach dem Hinzufügen von Mandanten- und Benutzerdetails.

image

Aufgabe 3: OCI-Stack erstellen

image

Navigieren Sie zum Abschnitt Identität, und erstellen Sie einen Policy-Stack unter dem Root Compartment. Auf diese Weise können Connector Hubs Metriken lesen und Funktionen mit den folgenden Anweisungen aufrufen.

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

So konfigurieren Sie Identitäts-Policys und stellen Metrikweiterleitungsstacks in OCI für die Datadog-Integration bereit:

Aufgabe 3.1: Policy-Stack erstellen (ORM_policy_stack)

  1. Klicken Sie in der Datadog-OCI-Integrationskachel auf Policy-Stack erstellen. Stellen Sie sicher, dass Sie den angegebenen Link verwenden, der das erforderliche Terraform-Skript enthält, und akzeptieren Sie die Oracle-Nutzungsbedingungen.

  2. Klicken Sie auf das Dropdown-Menü Arbeitsverzeichnis, und wählen Sie datadog-oci-orm/policy-setup aus.

  3. Deaktivieren Sie die Option Benutzerdefinierte Terraform-Provider verwenden.

  4. Geben Sie einen aussagekräftigen Namen ein (z.B. datadog-metrics-policy-setup), und wählen Sie das Compartment für das Deployment aus.

  5. Klicken Sie auf Weiter, benennen Sie die dynamische Gruppe und Policy (oder verwenden Sie Standardnamen), stellen Sie sicher, dass die Hauptregion des Mandanten ausgewählt ist, und klicken Sie auf Erstellen.

Aufgabe 3.2: Metrikweiterleitungsstapel erstellen

Ressourcen werden im angegebenen Compartment bereitgestellt. Stellen Sie sicher, dass der Benutzer, der den Stack ausführt, über die entsprechenden Zugriffsrechte verfügt.

  1. Klicken Sie in der Datadog-OCI-Integrationskachel auf Policy-Stack erstellen, und akzeptieren Sie die Oracle-Nutzungsbedingungen.

  2. Klicken Sie auf das Dropdown-Menü Arbeitsverzeichnis, wählen Sie datadog-oci-orm/metrics-setup aus, und deaktivieren Sie Benutzerdefinierte Terraform-Provider verwenden.

  3. Benennen Sie den Stack, und wählen Sie das Deployment Compartment aus. Klicken Sie dann auf Weiter.

  4. Lassen Sie die Mandantenwerte unverändert, geben Sie den Datadog-API-Schlüssel ein, und wählen Sie den US5-Endpunkt (ocimetrics-intake.us5.datadoghq.com) aus.

  5. Stellen Sie bei der Netzwerkkonfiguration sicher, dass VCN erstellen aktiviert ist, und wählen Sie das entsprechende Compartment für die VCN-Erstellung aus.

  6. Behalten Sie im Abschnitt Funktionseinstellungen die Standardanwendungsausprägung als GENERIC_ARM bei. Geben Sie den Benutzernamen und das Kennwort für die OCI Docker-Registry ein (fertiges Kennwort).

  7. Legen Sie die Batchgröße für Service Connector Hub auf 5000 fest, und klicken Sie auf Weiter.

  8. Klicken Sie auf Erstellen.

Aufgabe 3.3: Konfiguration abschließen

  1. Kehren Sie zur Datadog-OCI-Integrationskachel zurück, und klicken Sie auf Konfiguration erstellen, um das Setup abzuschließen.

  2. Dieser Prozess stellt sicher, dass Datadog-Metriken und -Funktionen für die Integration mit OCI ordnungsgemäß konfiguriert sind.

    image

Aufgabe 4: OCI Functions erstellen

So erstellen Sie eine Anwendung in der OCI-Konsole:

  1. Navigieren Sie zu Anwendungen, und wählen Sie Anwendung erstellen aus.

  2. Geben Sie den Anwendungsnamen ein, wählen Sie das entsprechende virtuelle Cloud-Netzwerk (VCN) und Subnetzdetails aus, und klicken Sie auf Erstellen.

  3. Um auf die neu erstellte Anwendung zuzugreifen, wählen Sie unter Ressourcen die Option Erste Schritte aus.

    image

  4. Klicken Sie auf Cloud Shell starten, und kopieren Sie die folgenden Befehle aus Kontext für Ihre Region verwenden.

    fn list context
    fn use context <region name>
    
  5. Aktualisieren Sie den Kontext, um die Compartment-ID der Funktion einzuschließen.

    fn update context oracle.compartment-id <compartment-id>
    
  6. Aktualisieren Sie den Kontext, um den Speicherort der gewünschten Registry einzuschließen.

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

    Hinweis: Ersetzen Sie phx im Kontext durch den dreistelligen Regionscode.

  7. Melden Sie sich mit dem Authentifizierungstoken als Kennwort bei der Registry an

    docker login -u 'TENACNY_NAME/OCI_USERNAME' phx.ocir.io
    
  8. Sie werden aufgefordert, das Kennwort einzugeben. Geben Sie das entsprechende Kennwort an.

    Hinweis:

    • Ersetzen Sie phx durch den dreistelligen Regionscode.
    • Wenn Sie Oracle Identity Cloud Service verwenden, lautet Ihr Benutzername <tenancyname>/oracleidentitycloudservice/<username>.
  9. Generieren Sie eine hello-world-Boilerplate-Funktion.

    fn list apps
    fn init --runtime python datadog
    

    Mit dem Befehl fn init wird ein Ordner namens datadog mit drei darin enthaltenen Dateien generiert: func.py, func.yaml und requirements.txt.

  10. Führen Sie den Befehl cd datadog aus.

  11. Öffnen Sie func.py, und ersetzen Sie den Inhalt der Datei durch das folgende Code-Snippet.

    # 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. Aktualisieren Sie func.yaml mit dem folgenden Code. Ersetzen Sie DATADOG_TOKEN durch den Datadog-API-Schlüssel und DATADOG_HOST durch den REST-Endpunkt https://http-intake.logs.datadoghq.com/v1/input. Weitere Informationen zum REST-Endpunkt finden Sie unter Logerfassung und Integrationen.

    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. Aktualisieren Sie requirements.txt mit dem folgenden Code.

    fdk
    dattime
    requests
    oci
    
  14. Führen Sie den folgenden Befehl aus, um die Anwendung zu erstellen und die Funktionen bereitzustellen, um das Setup abzuschließen.

    fn create app datadog01 --annotation oracle.com/oci/subnetIds='["Provide your subnet OCID"]'
    
  15. Führen Sie den folgenden Befehl aus, um die Funktionen bereitzustellen und das Setup abzuschließen.

    fn -v deploy --app datadog
    

Aufgabe 5: OCI Connector Hub einrichten

  1. Gehen Sie zur OCI-Konsole, navigieren Sie zu Logging, Connectors, und klicken Sie auf Connector erstellen.

  2. Setzen Sie die Quelle auf Monitoring und das Ziel auf Funktionen.

  3. Wählen Sie unter Quellverbindung konfigurieren das entsprechende Metrik-Compartment und den Namespace aus. Beispiel: oci_postgresql für das Datenbankmonitoring.

  4. Wählen Sie unter Ziel konfigurieren das in Aufgabe 4 erstellte Compartment, die Funktionsanwendung und die Funktion aus.

  5. Wenn Sie dazu aufgefordert werden, klicken Sie auf Erstellen, um die erforderliche Policy zu erstellen.

  6. Klicken Sie auf Erstellen, um das OCI Connector Hub-Setup abzuschließen.

image

Aufgabe 6: Metriken in Datadog anzeigen

Der OCI Connector Hub ist jetzt so konfiguriert, dass er die Funktion auslöst und die Aufnahme von Metriken in Datadog ermöglicht, wenn neue Metriken erkannt werden. Navigieren Sie in der Kachel "Datadog-Integration" zu Metriken, und prüfen Sie die Übersicht, um OCI-bezogene Metriken anzuzeigen.

image

Klicken Sie in der Kachel "Datadog-Integration" auf Explorer, um die erforderlichen OCI-Metriken nach Bedarf zu analysieren und auszuwählen.

image

Problembehandlung

Wenn auf der Seite Metrikübersicht keine Daten angezeigt werden, wählen Sie Log aktivieren aus, um das Logging zu aktivieren, damit Ihre Funktionen Logs prüfen und das Problem debuggen können.

image

Danksagungen

Weitere Lernressourcen

Sehen Sie sich andere Übungen zu docs.oracle.com/learn an, oder greifen Sie im Oracle Learning YouTube-Channel auf weitere kostenlose Lerninhalte zu. Besuchen Sie außerdem education.oracle.com/learning-explorer, um Oracle Learning Explorer zu werden.

Die Produktdokumentation finden Sie im Oracle Help Center.