Observação:

Publique métricas personalizadas do Oracle Autonomous Database usando o serviço Oracle Cloud Infrastructure Monitoring

Introdução

O Oracle Autonomous Database está revolucionando como os dados são gerenciados com a introdução do primeiro banco de dados "autônomo" do mundo. O Oracle Autonomous Database está capacitando aplicativos comerciais críticos de empresas de todo o mundo, como sua principal fonte de dados.

O Oracle Autonomous Database oferece muitas métricas de serviço relacionadas ao banco de dados importantes prontas para uso, graças a sua integração profunda com o serviço de Monitoramento do Oracle Cloud Infrastructure (OCI). Dito isto, muitos dos nossos clientes inovadores querem dar um passo à sua jornada de observabilidade. Esses clientes querem coletar, publicar e analisar suas próprias métricas sobre os dados dos aplicativos armazenados no Oracle Autonomous Database. Chamamos essas métricas personalizadas e elas são as métricas que os aplicativos podem coletar e postar no serviço OCI Monitoring por uma API REST simples fornecida pelo OCI SDK.

Este tutorial mostra a facilidade com que você pode publicar métricas personalizadas do seu Oracle Autonomous Database com apenas alguns scripts PL/SQL e alguns cliques na Console do Oracle Cloud.

Este tutorial usa um esquema de banco de dados de ordens de compra de eCommerce como exemplo para mostrar como você pode calcular e coletar métricas de dados. Você verá como calcular periodicamente uma métrica que representa a contagem de cada status do pedido (preenchido, aceito, rejeitado etc.) para cada pedido recebido pelo aplicativo de ecommerce. E, por fim, você publicará essas métricas personalizadas no Oracle Cloud Monitoring Service.

Pré-requisitos

  1. Acesso a uma camada grátis ou conta paga do Oracle Cloud.
  2. Qualquer tipo de instância do Oracle Autonomous Database, compartilhada ou dedicada.

    Observação: Para este tutorial, você usa um Oracle Autonomous Database para uma instância do Oracle Autonomous Transaction Processing com apenas 1 OCPU e 1 TB de armazenamento em infraestrutura compartilhada. Você pode criar isso usando uma conta na camada gratuita do Oracle Cloud.

  3. Familiaridade básica com PL/SQL.
  4. Familiaridade da Console do Oracle Cloud.
  5. É possível usar qualquer um dos clientes do Oracle Database, como SQL Developer ou SQL*Plus. Se você for iniciante no Oracle Autonomous Transaction Processing, consulte Conexão com um Autonomous Database. Para o Oracle Autonomous Transaction Processing, consulte SQL Developer Web, disponível na página Console do Oracle Cloud para o Oracle Autonomous Transaction Processing. Não há necessidade do Oracle Wallet ao usar o SQL Developer Web.
  6. Acesso do usuário ADMIN à sua instância do Oracle Autonomous Transaction Processing.
  7. Familiaridade básica com conceitos do Oracle Cloud, como o serviço OCI Monitoring, PostMetricData API para publicar métricas personalizadas e grupos dinâmicos e princípios de recursos.

Visão Geral da Solução

Teremos um script PL/SQL simples implantado em nossa instância do Oracle Autonomous Database, que é programado para ser executado periodicamente para calcular, coletar e postar as métricas personalizadas no serviço de Monitoramento do OCI.

Além disso, a instância do Oracle Autonomous Database pode ter um ponto final privado ou público. A comunicação entre o Oracle Autonomous Database e o serviço de Monitoramento do OCI ocorre na rede do Oracle Cloud, que é ultrarrápida e altamente disponível. Não há necessidade de configurar um gateway de serviço.

Neste tutorial, abrangeremos tudo o que você precisa saber até que precise obter as métricas personalizadas do Oracle Autonomous Database para o serviço de Monitoramento do OCI.

Visão Geral

  1. Crie um grupo dinâmico para sua instância do Oracle Autonomous Transaction Processing e autorize-o a publicar métricas no serviço de Monitoramento do Oracle Cloud Infrastructure (OCI) com uma política.
  2. Crie um novo usuário ou esquema de banco de dados com os privilégios necessários na sua instância do Oracle Autonomous Transaction Processing ou atualize o usuário ou esquema de banco de dados existente com os privilégios necessários.
  3. Crie uma tabela chamada SHOPPING_ORDER para armazenar dados do nosso aplicativo de ecommerce de exemplo (você calcula métricas personalizadas nos pedidos de clientes armazenados nessa tabela).
  4. Defina o script PL/SQL para preencher dados aleatórios de ordens de cliente na tabela SHOPPING_ORDER.
  5. Defina o script PL/SQL para calcular, coletar e armazenar no buffer e publicar as métricas personalizadas no serviço OCI Monitoring.
  6. Programe e execute scripts das etapas 4 e 5.
  7. Observe as métricas personalizadas publicadas no Oracle Cloud Console.

Em um caso de uso de produção, você tem seu próprio aplicativo para preencher os dados e as atualizações do mundo real. Assim, as etapas 3 e 4 não serão necessárias neste caso.

Etapas

  1. Crie um grupo dinâmico para sua instância do Oracle Autonomous Transaction Processing e autorize-o a publicar métricas no serviço de Monitoramento do Oracle Cloud Infrastructure (OCI) com a política.

    1. Crie um grupo dinâmico chamado adb_dg para sua instância (ou instâncias) do Oracle Autonomous Transaction Processing, com a regra:

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

      Como alternativa, você pode selecionar uma única instância do Oracle Autonomous Transaction Processing, em vez de todas as instâncias do compartimento:

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

      Grupo dinâmico para o Oracle Autonomous Database

    2. Crie uma política do Oracle Cloud Infrastructure Identity and Access Management (IAM) para autorizar o grupo dinâmico adb_dg a publicar métricas no serviço OCI Monitoring com uma política chamada adb_dg_policy e com regras de política Allow dynamic-group adb_dg to read metrics in compartment <Your Oracle Autonomous Transaction Processing compartment OCID>.

      Agora o seu serviço Oracle Autonomous Transaction Processing (coberto pela definição do seu grupo dinâmico adb_dg) está autorizado a publicar métricas no mesmo compartimento.

      Você não tem usuários de banco de dados do Oracle Autonomous Transaction Processing autorizados a publicar métricas no serviço OCI Monitoring sim. A PL/SQL executada no Oracle Autonomous Transaction Processing ainda não consegue postar nenhuma métrica no serviço de Monitoramento do OCI. Você fará isso na Etapa 3c.

  2. Crie um novo usuário ou esquema de banco de dados com os privilégios necessários na sua instância do Oracle Autonomous Transaction Processing ou atualize um usuário ou esquema de banco de dados existente com os privilégios necessários.

    1. Crie um usuário ou esquema de banco de dados chamado ECOMMERCE_USER em sua instância do Oracle Autonomous Transaction Processing. Você pode criar isso como um usuário ADMIN para cada instância do Oracle Autonomous Transaction Processing. Você poderá ignorar essa etapa se optar por usar um usuário existente.

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

      Observação: Agora vamos fazer referência ao usuário (ou esquema) pois ECOMMERCE_USER e o restante das etapas permanece o mesmo, quer você use um usuário existente ou um usuário recém-criado.

    2. Conceda privilégios obrigatórios relacionados ao Oracle Database ao 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. Ative as credenciais do Oracle Database para o Principal do Recurso do Oracle Cloud e dê seu acesso ao usuário db ECOMMERCE_USER. Isso conecta o grupo dinâmico adb_dg criado na etapa 1 ao usuário do banco de dados ECOMMERCE_USER, dando ao usuário a autorização para publicar métricas no serviço OCI Monitoring. Para obter mais informações, consulte Usar Principal de Recurso para Acessar Recursos do Oracle Cloud Infrastructure.

      EXEC DBMS_CLOUD_ADMIN.ENABLE_RESOURCE_PRINCIPAL(username => 'ECOMMERCE_USER');
      
    4. (Opcional) Verifique as operações concluídas na etapa anterior.

      Observação: Quando a credencial do Oracle Database para o Principal do Recurso do Oracle Cloud estiver ativada, ela sempre pertencerá ao usuário ADMIN para o Oracle Autonomous Database. Você pode verificar isso:

      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. Crie uma tabela de dados de exemplo chamada SHOPPING_ORDER para mostrar o cálculo de métricas em uma tabela de banco de dados.

    O esquema da tabela é autoexplicativo, mas observe a coluna 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 ordem de compra pode ter qualquer um dos oito valores de status durante sua vida útil: [ACCEPTED, PAYMENT_REJECTED, SHIPPED, ABORTED, OUT_FOR_DELIVERY, ORDER_DROPPED_NO_INVENTORY, PROCESSED, NOT_FULFILLED].

  4. Leia o script PL/SQL a seguir; ele preenche dados na tabela SHOPPING_ORDER. Execute-o no cliente Oracle Database de sua escolha.

    O script primeiro adicionará o número TOTAL_ROWS_IN_SHOPPING_ORDER de linhas à tabela SHOPPING_ORDER com dados de ordem gerados aleatoriamente. Em seguida, ele atualizará os dados, alterando aleatoriamente os valores de STATUS de cada linha SHOPPING_ORDER.

    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 mergulhar no básico real deste tutorial: o script que calcula as métricas personalizadas e as publica no serviço de Monitoramento do OCI. Execute-o no cliente do Oracle Datbase de sua escolha. O script é idempotente para garantir que você pode jogar com ele em várias execuções. Agora, analise o script fragmentado.

    1. Crie a tabela SHOPPING_ORDER_METRICS_TABLE e use-a para coletar e armazenar em buffer métricas calculadas.

      Certifique-se de que suas tabelas de dados sejam otimizadas para consultas que executam o cálculo de métricas. Você não deseja que essas consultas sobrecarregem muito seu banco de dados, incomodando seus casos de uso de produção.

      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. Crie um procedimento armazenado que calcule a métrica: Contagem do número de ordens por valores de status, na instância de momento dessa coleta de métricas.

      O procedimento armazenado em seguida coloca em buffer as métricas calculadas na tabela de buffer SHOPPING_ORDER_METRICS_TABLE que você criou na etapa anterior. Buffer para certificar-se de que você possa tentar publicar as métricas novamente no futuro se houver uma interrupção temporária ao publicá-las no serviço de Monitoramento do 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;
      /
      

      Para limitar o tamanho da tabela de buffer, corte-a se seu tamanho exceder 1.000 linhas.

    3. Use a função PL/SQL PREPARE_JSON_OBJECT_FROM_METRIC_ROWS que converte métricas armazenadas em buffer de SHOPPING_ORDER_METRICS_TABLE em objetos JSON que a API PostMetricsData espera em sua solicitação.

      Observação:

      • Essa função converte o número BATCH_SIZE_FOR_EACH_POST dos pontos de dados de métricas mais recentes de SHOPPING_ORDER_METRICS_TABLE em OCI_METADATA_JSON_OBJ JSON_OBJECT_T.
      • OCI_METADATA_JSON_OBJ é uma variável do tipo de dados JSON incorporado PL/SQL JSON_OBJECT_T. Construímos OCI_METADATA_JSON_OBJ com a mesma estrutura JSON, conforme descrito em PostMetricDataDetails, o corpo da solicitação da 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. Use o código PL/SQL para publicar essas métricas convertidas no serviço OCI Monitoring usando a API PostMetricsData.

      Observação: Conseguimos isso com a função PL/SQL denominada POST_METRICS_DATA_TO_OCI e o procedimento armazenado 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;
       /
      

      A função POST_METRICS_DATA_TO_OCI chama a API PostMetricsData. Como acontece com cada API do Oracle Cloud, você precisa de autorização adequada do OCI IAM para chamá-la. Você passa o mesmo que a seguir, com o parâmetro nomeado credential_name => 'OCI$RESOURCE_PRINCIPAL'.

      A credencial de banco de dados OCI$RESOURCE_PRINCIPAL está vinculada ao grupo dinâmico adb_dg que você criou na etapa 2 e o usuário ECOMMERCE_USER da etapa 3 já tem acesso.

      Assim, por cadeia de confiança, este script PL/SQL executado por ECOMMERCE_USER tem autorização para postar as métricas personalizadas no serviço de Monitoramento do 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 é um procedimento armazenado PL/SQL incorporado que chama qualquer ponto final rest, pré-instalado com cada Oracle Autonomous Database. Aqui a usamos para chamar a API REST do serviço de Monitoramento do OCI.

      O procedimento armazenado PUBLISH_BUFFERED_METRICS_TO_OCI publica todas as métricas armazenadas no buffer para o serviço OCI Monitoring usando todas as funções e procedimentos discutidos até o momento. Para ser executado, ele cria lotes do tamanho BATCH_SIZE_FOR_EACH_POST de pontos de dados de métrica para cada chamada de API PostMetricsData.

  6. Programe e execute scripts das etapas 4 e 5. Nas etapas 4 e 5, você definiu procedimentos e funções armazenados no Oracle Database, mas ainda não os executou.

    1. Execute o script na etapa 4 para preencher os dados na tabela SHOPPING_ORDER. O script será executado por aproximadamente 15 minutos na instância do Oracle Autonomouse Transaction Processing com 1 OCPU e 1 TB de armazenamento.

      -- 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. O único restante é a execução periódica do script PL/SQL na etapa 5: computação e publicação no serviço OCI Monitoring.

      Fazemos da seguinte forma com o procedimento armazenado incorporado PL/SQL DBMS_SCHEDULER.CREATE_JOB.

      Ele cria o Oracle Database SCHEDULED_JOB com duração de 20 minutos (1.200 segundos). Ele faz computação de métricas personalizadas e as publica a cada minuto.

      Para um caso de uso de produção, configure-o de acordo com suas necessidades.

      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 as métricas personalizadas publicadas na Console do Oracle Cloud.

    1. No menu de navegação, clique em Explorador de Métricas.

      Vá para o Metrics Explorer na Console do Oracle Cloud

    2. No Explorador de Métricas, selecione o namespace como custom_metrics_from_adb, resourceGroup como ecommerece_adb e o nome da métrica como customer_orders_submitted que você definiu para métricas personalizadas.

      Todos os metadados e dimensões definidos para as métricas personalizadas estão disponíveis.

      Você pode construir consultas MQL para analisar essas métricas de acordo com suas necessidades e caso de uso. Em seguida, talvez você queira configurar Alarms do Oracle Cloud no fluxo de métricas para alertar sua equipe operacional.

      Isso automatiza o loop de observabilidade das métricas do Oracle Autonomous Database à sua escolha.

      Explore as métricas personalizadas publicadas

Conclusão

Você aprendeu a emitir métricas personalizadas do Oracle Autonomous Database para o serviço de Monitoramento do Oracle Cloud Infrastructure (OCI) com scripts PL/SQL simples usando o OCI SDK para PL/SQL. O Oracle Database é uma "fonte de verdade" para muitos dos fluxos de trabalho de negócios, então essa é uma funcionalidade muito poderosa.

Métricas personalizadas são cidadãos de primeira classe do serviço de Monitoramento de OCI, juntamente com métricas nativas. Você pode analisá-los com a mesma Linguagem de Consulta de Métricas avançada e configurar Alarms para notificá-lo sempre que ocorrer qualquer evento de interesse ou problema.

Isso dá a você a última exibição de 'Painel Único de Vidro' para todas as suas métricas, seja ela gerada pelo Serviço OCI ou métricas personalizadas geradas por seus aplicativos e bancos de dados.

Agradecimentos

Mais Recursos de Aprendizagem

Explore outros laboratórios em docs.oracle.com/learn ou acesse mais conteúdo de aprendizado gratuito no canal YouTube do Oracle Learning. Além disso, visite education.oracle.com/learning-explorer para se tornar um Oracle Learning Explorer.

Para obter a documentação do produto, visite o Oracle Help Center.