Nota:

Pubblica le metriche personalizzate da Oracle Autonomous Database utilizzando il servizio Oracle Cloud Infrastructure Monitoring

Introduzione

Oracle Autonomous Database sta rivoluzionando il modo in cui i dati vengono gestiti con l'introduzione del primo database autonomo al mondo. Oracle Autonomous Database promuove le applicazioni aziendali strategiche per le aziende, in tutto il mondo, come fonte di dati principale.

Oracle Autonomous Database offre numerose metriche di servizio correlate al database pronti all'uso, grazie alla sua profonda integrazione con il servizio di monitoraggio di Oracle Cloud Infrastructure (OCI). Detto questo, molti dei nostri clienti innovativi vogliono portare avanti il loro percorso di osservabilità. Questi clienti desiderano raccogliere, pubblicare e analizzare le proprie metriche sui dati dell'applicazione memorizzati in Oracle Autonomous Database. Chiamiamo queste metriche personalizzate e sono le metriche che le applicazioni possono raccogliere e pubblicare sul servizio di monitoraggio OCI tramite una semplice API REST fornita dall'SDK OCI.

Questa esercitazione descrive quanto sia facile pubblicare metriche personalizzate da Oracle Autonomous Database con pochi script PL/SQL e con pochi clic nella console di Oracle Cloud.

Questa esercitazione utilizza uno schema di database degli ordini di acquisto di e-commerce come esempio per mostrare come calcolare e raccogliere le metriche sui dati. Verrà descritto come calcolare periodicamente una metrica che rappresenta il conteggio per ogni stato dell'ordine (riempito, accettato, rifiutato e così via) per ogni ordine ricevuto dall'applicazione di e-commerce. Infine, pubblicherà queste metriche personalizzate nel servizio di monitoraggio di Oracle Cloud.

Prerequisiti

  1. Accesso a un livello gratuito o a un account a pagamento di Oracle Cloud.
  2. Qualsiasi tipo di istanza di Oracle Autonomous Database, condivisa o dedicata.

    Nota: per questa esercitazione, utilizzi Oracle Autonomous Database per un'istanza di Oracle Autonomous Transaction Processing con appena 1 OCPU e 1 TB di storage nell'infrastruttura condivisa. Puoi crearlo utilizzando un account di livello gratuito Oracle Cloud.

  3. Familiarità PL/SQL di base.
  4. Conoscenza della console di Oracle Cloud.
  5. È possibile utilizzare qualsiasi client Oracle Database come SQL Developer o SQL*Plus. Se hai familiarità con Oracle Autonomous Transaction Processing, consulta la sezione relativa alla connessione a un Autonomous Database. Per Oracle Autonomous Transaction Processing, vedere SQL Developer Web, disponibile nella pagina della console di Oracle Cloud per Oracle Autonomous Transaction Processing. Quando si utilizza SQL Developer Web, non è necessario Oracle Wallet.
  6. Accesso utente ADMIN all'istanza di Oracle Autonomous Transaction Processing.
  7. Familiarità di base con i concetti di Oracle Cloud quali servizio di monitoraggio OCI, PostMetricData API per la pubblicazione di metriche personalizzate e gruppi dinamici e principi delle risorse.

Panoramica soluzione

Avremo uno script PL/SQL semplice distribuito nella nostra istanza di Oracle Autonomous Database, la cui esecuzione è pianificata periodicamente per calcolare, raccogliere e pubblicare le metriche personalizzate nel servizio di monitoraggio OCI.

Inoltre, l'istanza di Oracle Autonomous Database può avere un endpoint privato o pubblico. La comunicazione tra Oracle Autonomous Database e il servizio di monitoraggio OCI avviene sulla rete Oracle Cloud, che è ultraveloce e ad alta disponibilità. Non è necessario impostare un gateway di servizi.

In questa esercitazione verranno trattati tutti gli elementi necessari per conoscere fino a quando non sarà necessario ottenere le metriche personalizzate da Oracle Autonomous Database al servizio di monitoraggio OCI.

Panoramica

  1. Crea un gruppo dinamico per la tua istanza Oracle Autonomous Transaction Processing e lo autorizza a inviare le metriche al servizio di monitoraggio di Oracle Cloud Infrastructure (OCI) mediante un criterio.
  2. Creare un nuovo utente o schema di database con i privilegi necessari nell'istanza di Oracle Autonomous Transaction Processing o aggiornare l'utente o lo schema di database esistente con i privilegi necessari.
  3. Crea una tabella denominata SHOPPING_ORDER per memorizzare i dati per la nostra applicazione di e-commerce di esempio (le metriche personalizzate vengono calcolate sugli ordini dei clienti memorizzati in questa tabella).
  4. Definire lo script PL/SQL per popolare i dati casuali per gli ordini cliente nella tabella SHOPPING_ORDER.
  5. Definire lo script PL/SQL per calcolare, raccogliere e buffer e pubblicare le metriche personalizzate nel servizio di monitoraggio OCI.
  6. Pianificare ed eseguire gli script dai passi 4 e 5.
  7. Osservare le metriche personalizzate pubblicate nella console di Oracle Cloud.

In un caso d'uso di produzione, si dispone di una propria applicazione per popolare i dati e gli aggiornamenti reali. Pertanto, i passi 3 e 4 non saranno necessari in questo caso.

Passi

  1. Crea un gruppo dinamico per la tua istanza Oracle Autonomous Transaction Processing e autorizza tale gruppo a inviare le metriche al servizio di monitoraggio OCI (Oracle Cloud Infrastructure) con il criterio.

    1. Creare un gruppo dinamico denominato adb_dg per l'istanza (o le istanze) di Oracle Autonomous Transaction Processing con la regola:

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

      In alternativa, puoi selezionare una singola istanza di Oracle Autonomous Transaction Processing anziché tutte le istanze del compartimento:

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

      Gruppo dinamico per Oracle Autonomous Database

    2. Crea un criterio IAM (Oracle Cloud Infrastructure Identity and Access Management) per autorizzare il gruppo dinamico adb_dg a inviare le metriche al servizio di monitoraggio OCI con un criterio denominato adb_dg_policy e con le regole dei criteri Allow dynamic-group adb_dg to read metrics in compartment <Your Oracle Autonomous Transaction Processing compartment OCID>.

      Ora il servizio Oracle Autonomous Transaction Processing (coperto dalla definizione del gruppo dinamico adb_dg) è autorizzato a registrare le metriche nello stesso compartimento.

      Non si dispone di utenti del database Oracle Autonomous Transaction Processing autorizzati a pubblicare le metriche nel servizio di monitoraggio OCI. PL/SQL in esecuzione su Oracle Autonomous Transaction Processing non può ancora inviare metriche al servizio di monitoraggio OCI. Lo farete al punto 3c.

  2. Creare un nuovo utente o schema di database con i privilegi necessari nell'istanza di Oracle Autonomous Transaction Processing o aggiornare un utente o uno schema di database esistente con i privilegi necessari.

    1. Creare un utente o uno schema di database denominato ECOMMERCE_USER nell'istanza di Oracle Autonomous Transaction Processing. È possibile crearla come utente ADMIN per ogni istanza di Oracle Autonomous Transaction Processing. È possibile saltare questo passo se si sceglie di utilizzare un utente esistente.

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

      Nota: ora fare riferimento all'utente (o allo schema) come ECOMMERCE_USER e il resto dei passi resterà invariato, sia che si utilizzi un utente esistente o un utente appena creato.

    2. Concedere i privilegi correlati a Oracle Database necessari 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. Abilitare le credenziali di Oracle Database per il principal delle risorse Oracle Cloud e fornire il relativo accesso all'utente DB ECOMMERCE_USER. Questo consente di connettere il gruppo dinamico adb_dg creato nel passo 1 all'utente del database ECOMMERCE_USER, concedendo all'utente l'autorizzazione per inviare le metriche al servizio di monitoraggio OCI. Per ulteriori informazioni, vedere Usa capitale risorsa per accedere alle risorse Oracle Cloud Infrastructure.

      EXEC DBMS_CLOUD_ADMIN.ENABLE_RESOURCE_PRINCIPAL(username => 'ECOMMERCE_USER');
      
    4. (Facoltativo) Verificare le operazioni completate nel passo precedente.

      Nota: una volta abilitata la credenziale Oracle Database per il principal delle risorse Oracle Cloud, è sempre di proprietà dell'utente ADMIN per Oracle Autonomous Database. È possibile verificare quanto riportato di seguito.

      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. Creare una tabella dati di esempio denominata SHOPPING_ORDER per mostrare il calcolo delle metriche in una tabella di database.

    Lo schema della tabella è di tipo "autoesplicativo", ma tenere presente la colonna 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;
    

    Ogni ordine di acquisto può avere uno qualsiasi degli otto valori di stato durante la sua vita: [ACCEPTED, PAYMENT_REJECTED, SHIPPED, ABORTED, OUT_FOR_DELIVERY, ORDER_DROPPED_NO_INVENTORY, PROCESSED, NOT_FULFILLED].

  4. Leggere lo script PL/SQL riportato di seguito. I dati vengono inseriti nella tabella SHOPPING_ORDER. Eseguirlo sul client Oracle Database di tua scelta.

    Lo script aggiungerà innanzitutto il numero TOTAL_ROWS_IN_SHOPPING_ORDER di righe alla tabella SHOPPING_ORDER con dati ordine generati casualmente. I dati verranno quindi aggiornati, modificando i valori STATUS di ogni riga SHOPPING_ORDER in modo casuale.

    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. Analizziamo il vero e proprio incrocio di questa esercitazione: lo script che calcola le metriche personalizzate e le pubblica nel servizio di monitoraggio OCI. Eseguirlo sul client Oracle Datbase di tua scelta. Lo script è idempotente per assicurarsi di poter giocare con esso in più esecuzioni. Ora, analizzare il frammento di script.

    1. Creare la tabella SHOPPING_ORDER_METRICS_TABLE e utilizzarla per raccogliere e inserire nel buffer le metriche calcolate.

      Assicurarsi che le tabelle dati siano ottimizzate per le query che eseguono il calcolo delle metriche. Non si desidera che queste query mettano troppo carico sul database, disturbando i casi d'uso di produzione.

      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. Creare una procedura memorizzata che calcola la metrica: Conteggio per numero di ordini in base ai valori di stato all'istanza temporale di questa raccolta di metriche.

      La procedura memorizzata esegue quindi il buffer delle metriche calcolate nella tabella buffer SHOPPING_ORDER_METRICS_TABLE creata nel passo precedente. Buffer per assicurarsi di poter provare a inviare di nuovo le metriche in futuro in caso di interruzione temporanea quando vengono pubblicate nel servizio di monitoraggio OCI.

      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;
      /
      

      Per limitare la dimensione della tabella buffer, modificarla se la dimensione supera 1.000 righe.

    3. Utilizzare la funzione PL/SQL PREPARE_JSON_OBJECT_FROM_METRIC_ROWS che converte le metriche nel buffer da SHOPPING_ORDER_METRICS_TABLE in oggetti JSON che l'interfaccia API PostMetricsData prevede nella propria richiesta.

      Nota:

      • Questa funzione converte il numero BATCH_SIZE_FOR_EACH_POST dei datapoint delle metriche più recenti da SHOPPING_ORDER_METRICS_TABLE in OCI_METADATA_JSON_OBJ JSON_OBJECT_T.
      • OCI_METADATA_JSON_OBJ è una variabile del tipo di dati JSON PL/SQL incorporato JSON_OBJECT_T. Abbiamo costruito il file OCI_METADATA_JSON_OBJ con la stessa struttura JSON descritta in PostMetricDataDetails, il corpo della richiesta dell'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. Utilizzare il codice PL/SQL per pubblicare queste metriche convertite nel servizio di monitoraggio OCI utilizzando l'API PostMetricsData.

      Nota: l'operazione viene eseguita con la funzione PL/SQL denominata POST_METRICS_DATA_TO_OCI e la procedura memorizzata 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 funzione POST_METRICS_DATA_TO_OCI richiama l'API PostMetricsData. Come ogni API Oracle Cloud, è necessaria l'autorizzazione IAM OCI appropriata per richiamarla. Si passa come segue, con il parametro denominato credential_name => 'OCI$RESOURCE_PRINCIPAL'.

      La credenziale di database OCI$RESOURCE_PRINCIPAL è collegata al gruppo dinamico adb_dg creato nel passo 2 e l'utente ECOMMERCE_USER del passo 3 dispone già dell'accesso.

      Pertanto, catena di attendibilità, questo script PL/SQL eseguito da ECOMMERCE_USER dispone dell'autorizzazione per inviare le metriche personalizzate al servizio di monitoraggio 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 è una procedura memorizzata PL/SQL incorporata che richiama qualsiasi endpoint di riposo, preinstallata con ogni Oracle Autonomous Database. Qui lo utilizziamo per richiamare l'API REST del servizio di monitoraggio OCI.

      La procedura memorizzata PUBLISH_BUFFERED_METRICS_TO_OCI invia al servizio di monitoraggio OCI tutte le metriche inserite nel buffer utilizzando tutte le funzioni e le procedure discusse finora. Per essere performante, crea batch di dimensioni BATCH_SIZE_FOR_EACH_POST dei datapoint delle metriche per ogni richiamo PostMetricsData API.

  6. Pianificare ed eseguire gli script dai passi 4 e 5. Nei passi 4 e 5 sono state definite procedure e funzioni memorizzate in Oracle Database ma non sono state ancora eseguite.

    1. Eseguire lo script dal passo 4 per popolare i dati nella tabella SHOPPING_ORDER. Lo script verrà eseguito per circa 15 minuti sull'istanza di Oracle Autonomouse Transaction Processing con 1 OCPU e 1 TB di storage.

      -- 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. L'unica cosa rimanente è l'esecuzione periodica dello script PL/SQL dal passo 5: calcolo e pubblicazione nel servizio di monitoraggio OCI.

      Lo facciamo come segue con la procedura integrata PL/SQL DBMS_SCHEDULER.CREATE_JOB.

      Crea Oracle Database SCHEDULED_JOB per 20 minuti (1.200 secondi). Esegue il calcolo personalizzato delle metriche e la pubblica ogni minuto.

      Per un caso d'uso di produzione, configurarlo in base alle proprie esigenze.

      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. Esplora le metriche personalizzate pubblicate nella console di Oracle Cloud.

    1. Nel menu di navigazione fare clic su Metrics Explorer.

      Vai a Metrics Explorer nella console di Oracle Cloud

    2. In Metrics Explorer selezionare lo spazio dei nomi come custom_metrics_from_adb, resourceGroup come ecommerece_adb e il nome della metrica come customer_orders_submitted impostato per le metriche personalizzate.

      Sono disponibili tutti i metadati e le dimensioni impostati per le metriche personalizzate.

      È possibile creare query MQL per analizzare queste metriche in base alle esigenze e al caso d'uso. Successivamente, potresti voler impostare gli armi di Oracle Cloud nel flusso delle metriche per avvisare il tuo team operativo.

      Ciò automatizza il loop di osservabilità per le metriche di Oracle Autonomous Database di tua scelta.

      Esplora le metriche personalizzate pubblicate

Conclusione

Hai appreso come emettere metriche personalizzate da Oracle Autonomous Database al servizio di monitoraggio di Oracle Cloud Infrastructure (OCI) con semplici script PL/SQL utilizzando l'SDK OCI per PL/SQL. Oracle Database è una "fonte di verità" per molti flussi di lavoro aziendali, quindi questa è una funzionalità molto potente.

Le metriche personalizzate sono cittadini di prim'ordine del servizio di monitoraggio OCI, al pari delle metriche native. È possibile analizzarli con lo stesso potente Metrics Query Language e impostare Alarms per avvisarli ogni volta che si verifica un evento di interesse o un problema.

In questo modo si ottiene la vista "Single Pane of Glass" definitiva per tutte le metriche, sia che si tratti di un servizio OCI generato o di metriche personalizzate generate dalle applicazioni e dai database.

Riconoscimenti

Altre risorse di apprendimento

Esplora altri laboratori su docs.oracle.com/learn o accedi a più contenuti di apprendimento gratuito sul canale Oracle Learning YouTube. Inoltre, visitare education.oracle.com/learning-explorer per diventare Oracle Learning Explorer.

Per la documentazione del prodotto, visitare il sito Oracle Help Center.