Nota:

Publique métricas personalizadas de Oracle Autonomous Database mediante el servicio Oracle Cloud Infrastructure Monitoring

Introducción

Oracle Autonomous Database está revolucionando cómo se gestionan los datos con la introducción de la primera base de datos "autogestionada" del mundo. Oracle Autonomous Database impulsa las aplicaciones empresariales clave de todo el mundo como origen de datos principal.

Oracle Autonomous Database proporciona muchas métricas de servicio importantes relacionadas con la base de datos listas para usar, gracias a su profunda integración con el servicio de control de Oracle Cloud Infrastructure (OCI). Dicho esto, muchos de nuestros clientes innovadores quieren dar un paso más en su recorrido de observación. Estos clientes desean recopilar, publicar y analizar sus propias métricas sobre los datos de la aplicación almacenados en Oracle Autonomous Database. Llamamos a estas métricas personalizadas y son las métricas que las aplicaciones pueden recopilar y publicar en el servicio OCI Monitoring mediante una API de REST simple proporcionada por el SDK de OCI.

En este tutorial se muestra la facilidad con la que puede publicar métricas personalizadas desde Oracle Autonomous Database con solo unos pocos scripts PL/SQL y algunos clics en la consola de Oracle Cloud.

En este tutorial se utiliza un esquema de base de datos de órdenes de compra de comercio electrónico como ejemplo para mostrar cómo puede calcular y recopilar métricas sobre datos. Verá cómo puede calcular periódicamente una métrica que representa el recuento de cada estado de orden (completado, aceptado, rechazado, etc.) para cada orden que reciba la aplicación de ecommerce. Por último, publicará estas métricas personalizadas en el servicio de control de Oracle Cloud.

Requisitos

  1. Acceda a una cuenta de pago o nivel gratuito de Oracle Cloud.
  2. Cualquier tipo de instancia de Oracle Autonomous Database, compartida o dedicada.

    Nota: Para este tutorial, utilice Oracle Autonomous Database para una instancia de Oracle Autonomous Transaction Processing con solo 1 OCPU y 1 TB de almacenamiento en una infraestructura compartida. Puede crearlo mediante una cuenta de nivel gratuito de Oracle Cloud.

  3. Conocimientos básicos de PL/SQL.
  4. Familiaridad con la consola de Oracle Cloud.
  5. Puede utilizar cualquiera de los clientes de Oracle Database, como SQL Developer o SQL*Plus. Si es nuevo en Oracle Autonomous Transaction Processing, consulte Conexión a Autonomous Database. Para Oracle Autonomous Transaction Processing, consulte SQL Developer Web, disponible en la página de la consola de Oracle Cloud de Oracle Autonomous Transaction Processing. No es necesario Oracle Wallet al utilizar SQL Developer Web.
  6. Acceso de usuario ADMIN a la instancia de Oracle Autonomous Transaction Processing.
  7. Familiaridad básica con conceptos de Oracle Cloud como el servicio de supervisión de OCI, la API PostMetricData para publicar métricas personalizadas y los grupos dinámicos y principios de recursos.

Resumen de la solución

Tendremos un script PL/SQL simple desplegado en nuestra instancia de Oracle Autonomous Database, que está programado para ejecutarse periódicamente para calcular, recopilar y publicar las métricas personalizadas en el servicio OCI Monitoring.

Además, la instancia de Oracle Autonomous Database puede tener un punto final privado o público. La comunicación entre Oracle Autonomous Database y el servicio OCI Monitoring se lleva a cabo en la red de Oracle Cloud, ultrarrápida y altamente disponible. No es necesario configurar una puerta de enlace de servicio.

En este tutorial, trataremos todo lo que necesita saber hasta que necesite obtener las métricas personalizadas de Oracle Autonomous Database al servicio OCI Monitoring.

Visión general

  1. Cree un grupo dinámico para la instancia de Oracle Autonomous Transaction Processing y autorícelo para publicar métricas en el servicio Oracle Cloud Infrastructure (OCI) Monitoring con una política.
  2. Cree un nuevo usuario o esquema de base de datos con los privilegios necesarios en la instancia de Oracle Autonomous Transaction Processing o actualice el esquema o el usuario de base de datos existente con los privilegios necesarios.
  3. Cree una tabla denominada SHOPPING_ORDER para almacenar datos para nuestra aplicación de comercio electrónico de ejemplo (puede calcular métricas personalizadas en los pedidos de cliente almacenados en esta tabla).
  4. Defina el script PL/SQL para rellenar datos aleatorios de pedidos de clientes en la tabla SHOPPING_ORDER.
  5. Defina el script PL/SQL para calcular, recopilar y almacenar en buffer, y publique las métricas personalizadas en el servicio OCI Monitoring.
  6. Programe y ejecute scripts de los pasos 4 y 5.
  7. Observe las métricas personalizadas publicadas en la consola de Oracle Cloud.

En un caso de uso de producción, tiene su propia aplicación para rellenar los datos y actualizaciones reales. Por lo tanto, las etapas 3 y 4 no serán necesarias en este caso.

Pasos

  1. Cree un grupo dinámico para la instancia de Oracle Autonomous Transaction Processing y autorícelo para publicar métricas en el servicio Oracle Cloud Infrastructure (OCI) Monitoring con la política.

    1. Cree un grupo dinámico denominado adb_dg para la instancia (o instancias) de Oracle Autonomous Transaction Processing con la regla:

      ALL {resource.type = 'autonomousdatabase', resource.compartment.id = '<compartment OCID for your ADB instance>'}

      También puede seleccionar una única instancia de Oracle Autonomous Transaction Processing en lugar de todas las instancias del compartimento:

      ALL {resource.type = 'autonomousdatabase', resource.id = '<OCID for your ATP instance>'}

      Grupo dinámico para Oracle Autonomous Database

    2. Cree una política de Oracle Cloud Infrastructure Identity and Access Management (IAM) para autorizar al grupo dinámico adb_dg para publicar métricas en el servicio OCI Monitoring con una política denominada adb_dg_policy y con reglas de política Allow dynamic-group adb_dg to read metrics in compartment <Your Oracle Autonomous Transaction Processing compartment OCID>.

      Ahora, el servicio Oracle Autonomous Transaction Processing (que se trata con la definición del grupo dinámico adb_dg) está autorizado a publicar métricas en el mismo compartimento.

      No tiene ningún usuario de base de datos de Oracle Autonomous Transaction Processing autorizado para publicar métricas en el servicio OCI Monitoring sí. PL/SQL que se ejecuta en Oracle Autonomous Transaction Processing todavía no puede publicar ninguna métrica en el servicio OCI Monitoring. Esto se realizará en el paso 3c.

  2. Cree un nuevo usuario o esquema de base de datos con los privilegios necesarios en la instancia de Oracle Autonomous Transaction Processing o actualice un usuario o esquema de base de datos existente con los privilegios necesarios.

    1. Cree un usuario o esquema de base de datos denominado ECOMMERCE_USER en la instancia de Oracle Autonomous Transaction Processing. Puede crearlo como usuario ADMIN para cada instancia de Oracle Autonomous Transaction Processing. Puede omitir este paso si decide utilizar un usuario existente.

      CREATE USER ECOMMERCE_USER IDENTIFIED BY "Password of your choice for this User";
      

      Nota: Ahora haremos referencia al usuario (o esquema) como ECOMMERCE_USER y el resto de los pasos seguirán siendo los mismos, tanto si utiliza un usuario existente como si se ha creado recientemente.

    2. Otorgue los privilegios necesarios relacionados con Oracle Database a ECOMMERCE_USER.

      GRANT  CREATE TABLE, ALTER ANY INDEX, CREATE PROCEDURE, CREATE JOB, 
             SELECT ANY TABLE, EXECUTE ANY PROCEDURE, 
             UPDATE ANY TABLE, CREATE SESSION,
             UNLIMITED TABLESPACE, CONNECT, RESOURCE TO ECOMMERCE_USER;
      GRANT  SELECT ON "SYS"."V_$PDBS" TO ECOMMERCE_USER;
      GRANT  EXECUTE ON "C##CLOUD$SERVICE"."DBMS_CLOUD" to ECOMMERCE_USER;
      GRANT  SELECT ON SYS.DBA_JOBS_RUNNING TO ECOMMERCE_USER;
      
    3. Active las credenciales de Oracle Database para el principal de recursos de Oracle Cloud y proporcione su acceso a db-user ECOMMERCE_USER. Conecta el grupo dinámico adb_dg creado en el paso 1 al usuario de la base de datos ECOMMERCE_USER, lo que otorga al usuario la autorización para publicar métricas en el servicio de supervisión de OCI. Para obtener más información, consulte Uso del principal de recursos para acceder a los recursos de Oracle Cloud Infrastructure.

      EXEC DBMS_CLOUD_ADMIN.ENABLE_RESOURCE_PRINCIPAL(username => 'ECOMMERCE_USER');
      
    4. (Opcional) Verifique las operaciones que ha completado en el paso anterior.

      Nota: Una vez que la credencial de Oracle Database para el principal de recurso de Oracle Cloud está activada, siempre es propiedad del usuario ADMIN para Oracle Autonomous Database. Puede verificar esto:

      SELECT OWNER, CREDENTIAL_NAME FROM DBA_CREDENTIALS WHERE CREDENTIAL_NAME = 'OCI$RESOURCE_PRINCIPAL'  AND OWNER =  'ADMIN';
      
      -- To check if any other user, here ECOMMERCE_USER has access DB credential(hence to OCI Resource Principal), you have to check *DBA_TAB_PRIVS* view, as follows.
      SELECT * from DBA_TAB_PRIVS WHERE DBA_TAB_PRIVS.GRANTEE='ECOMMERCE_USER';
      
  3. Cree una tabla de datos de ejemplo denominada SHOPPING_ORDER para mostrar el cálculo de métricas en una tabla de base de datos.

    El esquema de tabla es autoexplicativo, pero tenga en cuenta la columna STATUS:

     DROP TABLE SHOPPING_ORDER;
     CREATE TABLE SHOPPING_ORDER (
         ID                NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY
         PRIMARY KEY,
         CREATED_DATE      TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP,
         DETAILS           VARCHAR2(1000) DEFAULT NULL,
         LAST_UPDATED_DATE TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP,
         STATUS            VARCHAR2(30 CHAR),
         TOTAL_CHARGES     FLOAT DEFAULT 0.0,
         CUSTOMER_ID       NUMBER(19)
     )
         PARTITION BY LIST ( STATUS ) 
         (   PARTITION ACCEPTED VALUES ( 'ACCEPTED' ),
             PARTITION PAYMENT_REJECTED VALUES ( 'PAYMENT_REJECTED' ),
             PARTITION SHIPPED VALUES ( 'SHIPPED' ),
             PARTITION ABORTED VALUES ( 'ABORTED' ),
             PARTITION OUT_FOR_DELIVERY VALUES ( 'OUT_FOR_DELIVERY' ),
             PARTITION ORDER_DROPPED_NO_INVENTORY VALUES ( 'ORDER_DROPPED_NO_INVENTORY' ),
             PARTITION PROCESSED VALUES ( 'PROCESSED' ),
             PARTITION NOT_FULLFILLED VALUES ( 'NOT_FULFILLED' )
         );
     /
    
     -- we move rows from one partition to another, hence we enable row movement for this partioned table
     ALTER TABLE SHOPPING_ORDER ENABLE ROW MOVEMENT;
    

    Cada orden de compra puede tener cualquiera de los ocho valores de estado durante su vida útil: [ACCEPTED, PAYMENT_REJECTED, SHIPPED, ABORTED, OUT_FOR_DELIVERY, ORDER_DROPPED_NO_INVENTORY, PROCESSED, NOT_FULFILLED].

  4. Lea el siguiente script PL/SQL; rellena los datos de la tabla SHOPPING_ORDER. Ejecútelo en el cliente de Oracle Database que desee.

    El script agregará primero el número TOTAL_ROWS_IN_SHOPPING_ORDER de filas a la tabla SHOPPING_ORDER con datos de orden generados aleatoriamente. A continuación, actualizará los datos, cambiando los valores STATUS de cada fila SHOPPING_ORDER aleatoriamente.

    CREATE OR REPLACE PROCEDURE POPULATE_DATA_FEED IS
        ARR_STATUS_RANDOM_INDEX      INTEGER;
        CUSTOMER_ID_RANDOM           INTEGER;
        TYPE STATUS_ARRAY IS VARRAY(8) OF VARCHAR2(30);
        ARRAY STATUS_ARRAY := STATUS_ARRAY('ACCEPTED', 'PAYMENT_REJECTED',
                                        'SHIPPED', 'ABORTED', 'OUT_FOR_DELIVERY',
                                        'ORDER_DROPPED_NO_INVENTORY', 
                                        'PROCESSED', 'NOT_FULFILLED');
        TOTAL_ROWS_IN_SHOPPING_ORDER INTEGER := 15000;
        TYPE ROWID_NT IS TABLE OF ROWID;
        ROWIDS                       ROWID_NT;
    BEGIN     
        -- starting from scratch just be idempotent and have predictable execution time for this stored procedure
        -- deleting existing rows is optional 
        DELETE SHOPPING_ORDER;
    
        -- insert data
        FOR COUNTER IN 1..TOTAL_ROWS_IN_SHOPPING_ORDER LOOP
            ARR_STATUS_RANDOM_INDEX := TRUNC(DBMS_RANDOM.VALUE(LOW => 1, HIGH => 9));
            CUSTOMER_ID_RANDOM := TRUNC(DBMS_RANDOM.VALUE(LOW => 1, HIGH => 8000));
            INSERT INTO SHOPPING_ORDER (STATUS,CUSTOMER_ID) VALUES (ARRAY(ARR_STATUS_RANDOM_INDEX),CUSTOMER_ID_RANDOM);
            COMMIT;          
        END LOOP;
    
        DBMS_OUTPUT.PUT_LINE('DONE WITH INITIAL DATA LOAD');
    
        -- keep on updating the same data
        FOR COUNTER IN 1..8000 LOOP        
    
                --Get the rowids
            SELECT R BULK COLLECT INTO ROWIDS FROM (SELECT ROWID R FROM SHOPPING_ORDER SAMPLE ( 5 ) ORDER BY DBMS_RANDOM.VALUE) RNDM
            WHERE ROWNUM < TOTAL_ROWS_IN_SHOPPING_ORDER + 1;
    
                --update the table
            ARR_STATUS_RANDOM_INDEX := TRUNC(DBMS_RANDOM.VALUE(LOW => 1, HIGH => 9));
    
            FOR I IN 1..ROWIDS.COUNT LOOP
                UPDATE SHOPPING_ORDER SET STATUS = ARRAY(ARR_STATUS_RANDOM_INDEX) WHERE ROWID = ROWIDS(I);
                COMMIT;
            END LOOP;    
            --sleep in-between if you want to run script for longer duration
            --DBMS_SESSION.SLEEP(ROUND(dbms_random.value(low => 1, high => 2)));          
        END LOOP;
    
        DBMS_OUTPUT.PUT_LINE('DONE WITH POPULATE_DATA_FEED');
        EXECUTE IMMEDIATE 'ANALYZE TABLE SHOPPING_ORDER COMPUTE STATISTICS';
    END;
    /
    
  5. Vamos a profundizar en las ventajas reales de este tutorial: el script que calcula las métricas personalizadas y las publica en el servicio OCI Monitoring. Ejecútelo en el cliente de base de datos Oracle que desee. El script es idempotente para asegurarse de que puede reproducirlo en varias ejecuciones. Ahora, analice la escritura piecemeal.

    1. Cree la tabla SHOPPING_ORDER_METRICS_TABLE y utilícela para recopilar y almacenar en buffer las métricas calculadas.

      Asegúrese de que las tablas de datos están optimizadas para las consultas que ejecutan el cálculo de métricas. No desea que estas consultas pongan demasiada carga en la base de datos y perturben los casos de uso de producción.

      DECLARE
          COUNT_VAR NUMBER := 0;
      BEGIN
          SELECT COUNT(*) INTO COUNT_VAR FROM ALL_TABLES WHERE TABLE_NAME = 'SHOPPING_ORDER_METRICS_TABLE';
      
          IF COUNT_VAR > 0 THEN
              DBMS_OUTPUT.PUT_LINE('TABLE EXISTS ALREADY!');
          ELSE
              -- table doesn't exist
              EXECUTE IMMEDIATE 'CREATE TABLE SHOPPING_ORDER_METRICS_TABLE(
                                  ID                 NUMBER         GENERATED BY DEFAULT ON NULL AS IDENTITY PRIMARY KEY,
                                  CREATED_DATE       TIMESTAMP(6)   DEFAULT CURRENT_TIMESTAMP,
                                  STATUS             VARCHAR2(30 CHAR),
                                  COUNT              NUMBER)';
          END IF;
      
      END;
      /
      
    2. Cree un procedimiento almacenado que calcule la métrica: Recuento del número de órdenes por valores de estado, en la instancia de tiempo de esta recopilación de métricas.

      A continuación, el procedimiento almacenado almacena en buffer las métricas calculadas en la tabla de buffers SHOPPING_ORDER_METRICS_TABLE que ha creado en el paso anterior. Buffer para asegurarse de que puede intentar volver a publicar las métricas en el futuro si hay una interrupción temporal al publicarlas en el servicio OCI Monitoring.

      CREATE OR REPLACE PROCEDURE COMPUTE_AND_BUFFER_METRICS IS
      BEGIN    
          -- compute simple metric for getting count order by order-status 
          -- and store in buffer table SHOPPING_ORDER_METRICS_TABLE
          INSERT INTO SHOPPING_ORDER_METRICS_TABLE (STATUS, COUNT, CREATED_DATE) 
          SELECT STATUS, COUNT(*), SYSTIMESTAMP AT TIME ZONE 'UTC' FROM SHOPPING_ORDER SO GROUP BY SO.STATUS;
      
          -- we buffer at most 1000 metric points, please configure as per your needs
          DELETE FROM SHOPPING_ORDER_METRICS_TABLE SOMT WHERE SOMT.ID NOT IN
              (SELECT ID FROM SHOPPING_ORDER_METRICS_TABLE ORDER BY CREATED_DATE FETCH FIRST 1000 ROWS ONLY);
      
          COMMIT;    
          DBMS_OUTPUT.PUT_LINE('compute and buffering done @ ' || TO_CHAR(SYSTIMESTAMP));
      END;
      /
      

      Para limitar el tamaño de la tabla de buffers, córtela si su tamaño supera las 1.000 filas.

    3. Utilice la función PL/SQL PREPARE_JSON_OBJECT_FROM_METRIC_ROWS que convierte las métricas almacenadas en buffer de SHOPPING_ORDER_METRICS_TABLE en objetos JSON que espera la API PostMetricsData en su solicitud.

      Nota:

      • Esta función convierte el número BATCH_SIZE_FOR_EACH_POST de los puntos de datos de métricas más recientes de SHOPPING_ORDER_METRICS_TABLE en OCI_METADATA_JSON_OBJ JSON_OBJECT_T.
      • OCI_METADATA_JSON_OBJ es una variable del tipo de dato JSON incorporado PL/SQL JSON_OBJECT_T. Hemos creado OCI_METADATA_JSON_OBJ con la misma estructura JSON que se describe en PostMetricDataDetails, cuerpo de solicitud para la API PostMetricsData.
       CREATE OR REPLACE FUNCTION GET_METRIC_DATA_DETAILS_JSON_OBJ (
           IN_ORDER_STATUS         IN VARCHAR2,
           IN_METRIC_CMPT_ID       IN VARCHAR2,
           IN_ADB_NAME             IN VARCHAR2,
           IN_METRIC_VALUE         IN NUMBER,
           IN_TS_METRIC_COLLECTION IN VARCHAR2
       ) RETURN JSON_OBJECT_T IS
           METRIC_DATA_DETAILS JSON_OBJECT_T;
           MDD_METADATA        JSON_OBJECT_T;
           MDD_DIMENSIONS      JSON_OBJECT_T;
           ARR_MDD_DATAPOINT   JSON_ARRAY_T;
           MDD_DATAPOINT       JSON_OBJECT_T;
       BEGIN
           MDD_METADATA := JSON_OBJECT_T();
           MDD_METADATA.PUT('unit', 'row_count'); -- metric unit is arbitrary, as per choice of developer
      
           MDD_DIMENSIONS := JSON_OBJECT_T();
           MDD_DIMENSIONS.PUT('dbname', IN_ADB_NAME);
           MDD_DIMENSIONS.PUT('schema_name', SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA'));
           MDD_DIMENSIONS.PUT('table_name', 'SHOPPING_ORDER');
           MDD_DIMENSIONS.PUT('status_enum', IN_ORDER_STATUS);
           MDD_DATAPOINT := JSON_OBJECT_T();
           MDD_DATAPOINT.PUT('timestamp', IN_TS_METRIC_COLLECTION); --timestamp value RFC3339 compliant
           MDD_DATAPOINT.PUT('value', IN_METRIC_VALUE);
           MDD_DATAPOINT.PUT('count', 1);
           ARR_MDD_DATAPOINT := JSON_ARRAY_T();
           ARR_MDD_DATAPOINT.APPEND(MDD_DATAPOINT);
           METRIC_DATA_DETAILS := JSON_OBJECT_T();
           METRIC_DATA_DETAILS.PUT('datapoints', ARR_MDD_DATAPOINT);
           METRIC_DATA_DETAILS.PUT('metadata', MDD_METADATA);
           METRIC_DATA_DETAILS.PUT('dimensions', MDD_DIMENSIONS);
      
           -- namespace, resourceGroup and name for the custom metric are arbitrary values, as per choice of developer
           METRIC_DATA_DETAILS.PUT('namespace', 'custom_metrics_from_adb');
           METRIC_DATA_DETAILS.PUT('resourceGroup', 'ecommerece_adb');
           METRIC_DATA_DETAILS.PUT('name', 'customer_orders_submitted');
      
           -- since compartment OCID is fetched using ADB metadata, our custom metrics will land up in same compartment as our ADB
           METRIC_DATA_DETAILS.PUT('compartmentId', IN_METRIC_CMPT_ID);
           RETURN METRIC_DATA_DETAILS;
       END;
       /
      
       CREATE OR REPLACE FUNCTION PREPARE_JSON_OBJECT_FROM_METRIC_ROWS (
           OCI_METADATA_JSON_OBJ JSON_OBJECT_T, BATCH_SIZE_FOR_EACH_POST NUMBER
       ) RETURN JSON_OBJECT_T IS
           OCI_POST_METRICS_BODY_JSON_OBJ JSON_OBJECT_T;
           ARR_METRIC_DATA                JSON_ARRAY_T;
           METRIC_DATA_DETAILS            JSON_OBJECT_T;
       BEGIN
           -- prepare JSON body for postmetrics api..
           -- for details please refer https://docs.oracle.com/en-us/iaas/api/#/en/monitoring/20180401/datatypes/PostMetricDataDetails
           ARR_METRIC_DATA := JSON_ARRAY_T();
      
           -- PostMetrics api has soft limit of 50 unique metric stream per call, hence we cap it at 50. 
           -- For Production usecase where every metric data point is important, we can use chunking
           FOR METRIC_ROW IN (SELECT * FROM SHOPPING_ORDER_METRICS_TABLE 
                               ORDER BY CREATED_DATE DESC FETCH FIRST BATCH_SIZE_FOR_EACH_POST ROWS ONLY) LOOP
      
               --DBMS_OUTPUT.PUT_LINE('inside for loop ' || METRIC_ROW.STATUS );
      
               METRIC_DATA_DETAILS := GET_METRIC_DATA_DETAILS_JSON_OBJ(
                                   METRIC_ROW.STATUS,
                                   OCI_METADATA_JSON_OBJ.GET_STRING('COMPARTMENT_OCID'), 
                                   OCI_METADATA_JSON_OBJ.GET_STRING('DATABASE_NAME'), 
                                   METRIC_ROW.COUNT, 
                                   TO_CHAR(METRIC_ROW.CREATED_DATE, 'yyyy-mm-dd"T"hh24:mi:ss.ff3"Z"'));
               --DBMS_OUTPUT.PUT_LINE('METRIC_DATA_DETAILS '|| METRIC_DATA_DETAILS.to_clob);
               ARR_METRIC_DATA.APPEND(METRIC_DATA_DETAILS);
      
           END LOOP;
           DBMS_OUTPUT.PUT_LINE('done with for loop ');
           OCI_POST_METRICS_BODY_JSON_OBJ := JSON_OBJECT_T();
           OCI_POST_METRICS_BODY_JSON_OBJ.PUT('metricData', ARR_METRIC_DATA);
      
           RETURN OCI_POST_METRICS_BODY_JSON_OBJ;
       END;
       /
      
    4. Utilice el código PL/SQL para publicar estas métricas convertidas en el servicio OCI Monitoring mediante la API PostMetricsData.

      Nota: Esto se consigue con la función PL/SQL denominada POST_METRICS_DATA_TO_OCI y el procedimiento almacenado PUBLISH_BUFFERED_METRICS_TO_OCI.

      
       CREATE OR REPLACE FUNCTION POST_METRICS_DATA_TO_OCI(OCI_POST_METRICS_BODY_JSON_OBJ JSON_OBJECT_T, ADB_REGION VARCHAR2) 
       RETURN NUMBER 
       IS
           RETRY_COUNT                    INTEGER := 0;
           MAX_RETRIES                    INTEGER := 3;
           RESP                           DBMS_CLOUD_TYPES.RESP;
           EXCEPTION_POSTING_METRICS      EXCEPTION;
           SLEEP_IN_SECONDS               INTEGER := 5;
       BEGIN
           FOR RETRY_COUNT in 1..MAX_RETRIES  LOOP
                   -- invoking REST endpoint for OCI Monitoring API
                   -- for details please refer https://docs.oracle.com/en-us/iaas/api/#/en/monitoring/20180401/MetricData/PostMetricData
               RESP := DBMS_CLOUD.SEND_REQUEST(CREDENTIAL_NAME => 'OCI$RESOURCE_PRINCIPAL', 
                                               URI => 'https://telemetry-ingestion.'|| ADB_REGION|| '.oraclecloud.com/20180401/metrics', 
                                               METHOD =>DBMS_CLOUD.METHOD_POST, 
                                               BODY => UTL_RAW.CAST_TO_RAW(OCI_POST_METRICS_BODY_JSON_OBJ.TO_STRING));
      
               IF DBMS_CLOUD.GET_RESPONSE_STATUS_CODE(RESP) = 200 THEN    -- when it is 200 from OCI Metrics API, all good
                   DBMS_OUTPUT.PUT_LINE('POSTED METRICS SUCCESSFULLY TO OCI MONIOTRING');
                   RETURN 200;
               ELSIF DBMS_CLOUD.GET_RESPONSE_STATUS_CODE(RESP) = 429 THEN -- 429 is caused by throttling
                   IF RETRY_COUNT < MAX_RETRIES THEN
                       -- increase sleep time for each retry, doing exponential backoff
                       DBMS_SESSION.SLEEP(POWER(SLEEP_IN_SECONDS, RETRY_COUNT+1));
                       DBMS_OUTPUT.PUT_LINE('RETRYING THE POSTMETRICS API CALL');
                   ELSE
                       DBMS_OUTPUT.PUT_LINE('ABANDONING POSTMETRICS CALLS, AFTER 3 RETRIES, CAUSED BY THROTTLING, WILL BERETRIED IN NEXT SCHEDULED RUN');
                       RETURN 429;
                   END IF;
               ELSE -- for any other http status code....1. log error, 2. raise exception and then quit posting metrics, as it is most probably a persistent error 
                       DBMS_OUTPUT.PUT_LINE('IRRECOVERABLE ERROR HAPPENED WHEN POSTING METRICS TO OCI MONITORING, PLEASE SEE CONSOLE FOR ERRORS');
                       -- Response Body in TEXT format
                       DBMS_OUTPUT.put_line('Body: ' || '------------' || CHR(10) || DBMS_CLOUD.get_response_text(resp) || CHR(10));
                       -- Response Headers in JSON format
                       DBMS_OUTPUT.put_line('Headers: ' || CHR(10) || '------------' || CHR(10) || DBMS_CLOUD.get_response_headers(resp).to_clob || CHR(10));
                       -- Response Status Code
                       DBMS_OUTPUT.put_line('Status Code: ' || CHR(10) || '------------' || CHR(10) || DBMS_CLOUD.get_response_status_code(resp));
                       RETURN 500;
               END IF;
      
           END LOOP;
       END;
       /
      
       CREATE OR REPLACE PROCEDURE PUBLISH_BUFFERED_METRICS_TO_OCI IS
           OCI_METADATA_JSON_RESULT       VARCHAR2(1000);
           OCI_METADATA_JSON_OBJ          JSON_OBJECT_T;
           ADB_REGION                     VARCHAR2(25);
           OCI_POST_METRICS_BODY_JSON_OBJ JSON_OBJECT_T;
           TYPE ID_ARRAY IS VARRAY(50) OF NUMBER;
           ARRAY                          ID_ARRAY;
           TOTAL_METRICS_STREAM_CNT       NUMBER;
           HTTP_CODE                      NUMBER;
           BATCH_SIZE_FOR_EACH_POST       NUMBER:=8; -- not more than 50! as per PostMetricsData API docs
       BEGIN
           -- get the meta-data for this ADB Instance like its OCI compartmentId, region and DBName etc; as JSON in oci_metadata_json_result
           SELECT CLOUD_IDENTITY INTO OCI_METADATA_JSON_RESULT FROM V$PDBS; 
           -- dbms_output.put_line(oci_metadata_json_result);
      
           -- convert the JSON string into PLSQL JSON native JSON datatype json_object_t variable named oci_metadata_json_result
           OCI_METADATA_JSON_OBJ := JSON_OBJECT_T.PARSE(OCI_METADATA_JSON_RESULT);
      
      
           WHILE(TRUE) LOOP
               SELECT COUNT(*) INTO TOTAL_METRICS_STREAM_CNT FROM SHOPPING_ORDER_METRICS_TABLE;
               IF(TOTAL_METRICS_STREAM_CNT < BATCH_SIZE_FOR_EACH_POST) THEN
                   DBMS_OUTPUT.PUT_LINE('Only ' || TOTAL_METRICS_STREAM_CNT || ' metrics datapoints buffered(less than batch size' || BATCH_SIZE_FOR_EACH_POST || '), hence waiting for buffer to fill up');
                   EXIT;
               END IF;   
      
               OCI_POST_METRICS_BODY_JSON_OBJ := PREPARE_JSON_OBJECT_FROM_METRIC_ROWS(OCI_METADATA_JSON_OBJ, BATCH_SIZE_FOR_EACH_POST);
               ADB_REGION := OCI_METADATA_JSON_OBJ.GET_STRING('REGION');
      
               HTTP_CODE := POST_METRICS_DATA_TO_OCI(OCI_POST_METRICS_BODY_JSON_OBJ, ADB_REGION);
      
               IF(HTTP_CODE = 200) THEN
                   DBMS_OUTPUT.PUT_LINE('Deleting the published metrics');
                   DELETE FROM SHOPPING_ORDER_METRICS_TABLE WHERE ID IN 
                                       (SELECT ID FROM SHOPPING_ORDER_METRICS_TABLE 
                                       ORDER BY CREATED_DATE DESC FETCH FIRST 50 ROWS ONLY);
               END IF;    
      
               COMMIT;    
      
               -- PostMetricData API has TPS rate limit of 50, just for safety  
               -- Hence sleep for atleast seconds => (1/50) to avoid throttling
               -- DBMS_SESSION.SLEEP(seconds => (1/50));                                  
           END LOOP;
       END;
       /
      

      La función POST_METRICS_DATA_TO_OCI llama a la API PostMetricsData. Al igual que con todas las API de Oracle Cloud, necesita la autorización adecuada de OCI IAM para llamarlo. Transfiere lo siguiente, con el parámetro con nombre credential_name => 'OCI$RESOURCE_PRINCIPAL'.

      La credencial de base de datos OCI$RESOURCE_PRINCIPAL está enlazada al grupo dinámico adb_dg que ha creado en el paso 2 y el usuario ECOMMERCE_USER del paso 3 ya tiene acceso.

      Por lo tanto, mediante cadena de confianza, este script PL/SQL ejecutado por ECOMMERCE_USER tiene autorización para publicar las métricas personalizadas en el servicio de supervisión de OCI.

      RESP := DBMS_CLOUD.SEND_REQUEST(CREDENTIAL_NAME => 'OCI$RESOURCE_PRINCIPAL', 
                                              URI => 'https://telemetry-ingestion.'|| ADB_REGION|| '.oraclecloud.com/20180401/metrics', 
                                              METHOD =>DBMS_CLOUD.METHOD_POST, 
                                              BODY => UTL_RAW.CAST_TO_RAW(OCI_POST_METRICS_BODY_JSON_OBJ.TO_STRING));
      

      dbms_cloud.send_request es un procedimiento PL/SQL almacenado incorporado que llama a cualquier punto final de reposo, preinstalado con cada Oracle Autonomous Database. Aquí se utiliza para llamar a la API de REST del servicio OCI Monitoring.

      El procedimiento almacenado PUBLISH_BUFFERED_METRICS_TO_OCI publica todas las métricas almacenadas en buffer en el servicio OCI Monitoring mediante todas las funciones y procedimientos que hemos tratado hasta ahora. Para realizar el rendimiento, crea lotes de tamaño BATCH_SIZE_FOR_EACH_POST de puntos de datos de métricas para cada llamada de API PostMetricsData.

  6. Programe y ejecute scripts de los pasos 4 y 5. En los pasos 4 y 5, definió funciones y procedimientos almacenados en Oracle Database, pero aún no los ha ejecutado.

    1. Ejecute el script del paso 4 para rellenar los datos de la tabla SHOPPING_ORDER. El script se ejecutará durante aproximadamente 15 minutos en la instancia de procesamiento de transacciones de Oracle Autonomouse con 1 OCPU y 1 TB de almacenamiento.

      -- we schedule the data feed to run immediately, asynchronously and only once!
      BEGIN
           DBMS_SCHEDULER.CREATE_JOB(
                                   JOB_NAME => 'POPULATE_DATA_FEED_JOB', 
                                   JOB_TYPE => 'STORED_PROCEDURE', 
                                   JOB_ACTION => 'POPULATE_DATA_FEED',
                                   ENABLED => TRUE, 
                                   AUTO_DROP => TRUE, -- drop job after 1 run.
                                   COMMENTS => 'ONE-TIME JOB');
       END;
       /
      
       -- just for our information
       SELECT STATUS,count(*) FROM SHOPPING_ORDER GROUP BY STATUS; 
      
    2. Lo único que queda es la ejecución periódica del script PL/SQL del paso 5: cálculo y publicación en el servicio OCI Monitoring.

      Lo hacemos de la siguiente manera con el procedimiento almacenado incorporado PL/SQL DBMS_SCHEDULER.CREATE_JOB.

      Crea Oracle Database SCHEDULED_JOB con una duración de 20 minutos (1.200 segundos). Realiza el cálculo de métricas personalizadas y lo publica cada minuto.

      Para un caso de uso de producción, configúrelo según sus necesidades.

      BEGIN
          DBMS_SCHEDULER.CREATE_JOB(
                                  JOB_NAME => 'POST_METRICS_TO_OCI_JOB', 
                                  JOB_TYPE   => 'PLSQL_BLOCK',
                                  JOB_ACTION => 'BEGIN 
                                                  ECOMMERCE_USER.COMPUTE_AND_BUFFER_METRICS(); 
                                                  ECOMMERCE_USER.PUBLISH_BUFFERED_METRICS_TO_OCI();
                                                 END;',
                                  START_DATE => SYSTIMESTAMP,                        -- start the first run immediately
                                  REPEAT_INTERVAL => 'FREQ=SECONDLY;INTERVAL=60',    -- run this PLSQL_BLOCK every 60th second 
                                  END_DATE => SYSTIMESTAMP + INTERVAL '1200' SECOND, -- this schedule is only active
                                  AUTO_DROP => TRUE,                                 -- delete the schedule after 1200 seconds, effectively after its last run
                                  ENABLED => TRUE,                                   -- enable this schedule as soon as it is created
                                  COMMENTS => 'JOB TO POST DB METRICS TO OCI MONITORING SERVICE, RUNS EVERY 10TH SECOND');
      END;
      /   
      
  7. Explore las métricas personalizadas publicadas en la consola de Oracle Cloud.

    1. En el menú de navegación, haga clic en Explorador de métricas.

      Vaya al explorador de métricas en la consola de Oracle Cloud

    2. En Explorador de métricas, seleccione el espacio de nombres como custom_metrics_from_adb, resourceGroup como ecommerece_adb y el nombre de métrica como customer_orders_submitted que haya definido para las métricas personalizadas.

      Todos los metadatos y dimensiones definidos para las métricas personalizadas están disponibles.

      Puede crear consultas MQL para analizar estas métricas según sus necesidades y el caso de uso. A continuación, puede que desee configurar las alarmas de Oracle Cloud en el flujo de métricas para alertar al equipo operativo.

      Esto automatiza el bucle de observación para las métricas de Oracle Autonomous Database que elija.

      Explore las métricas personalizadas que ha publicado

Conclusión

Ha aprendido a emitir métricas personalizadas de Oracle Autonomous Database al servicio de control de Oracle Cloud Infrastructure (OCI) con scripts PL/SQL simples mediante el SDK de OCI para PL/SQL. Oracle Database es una "fuente de verdad" para muchos de los flujos de trabajo empresariales, por lo que se trata de una funcionalidad muy potente.

Las métricas personalizadas son ciudadanos de primera clase del servicio OCI Monitoring, al igual que las métricas nativas. Puede analizarlos con el mismo potente lenguaje de consulta de métricas y configurar alarmas en ellos para notificarle cuando se produzca algún evento de interés o problema.

Esto le proporciona la vista 'Panel único de vidrio' definitiva para todas sus métricas, ya sea el servicio OCI generado o las métricas personalizadas generadas por las aplicaciones y las bases de datos.

Agradecimientos

Más recursos de aprendizaje

Explore otras prácticas en docs.oracle.com/learn o acceda a contenido de aprendizaje más gratuito en el canal YouTube de Oracle Learning. Además, visite education.oracle.com/learning-explorer para convertirse en un explorador de formación de Oracle.

Para obtener documentación sobre los productos, visite Oracle Help Center.