ノート:
- このチュートリアルではOracle Cloudにアクセスする必要があります。無料アカウントに登録するには、Oracle Cloud Infrastructure Free Tierの使用を開始するを参照してください。
- Oracle Cloud Infrastructureの資格証明、テナンシおよびコンパートメントに例の値を使用します。演習を完了するときは、これらの値をクラウド環境に固有の値に置き換えます。
Oracle Cloud Infrastructure Monitoringサービスを使用して、Oracle Autonomous Databaseからカスタム・メトリックを公開
イントロダクション
Oracle Autonomous Databaseは、世界初の自動稼働データベースを導入して、データを管理する方法に革命をもたらしています。Oracle Autonomous Databaseは、世界中の企業の重要なビジネス・アプリケーションを主要なデータ・ソースとして活かしています。
Oracle Autonomous Databaseは、Oracle Cloud Infrastructure (OCI) Monitoringサービスとの緊密な統合により、数多くの重要なデータベース関連のサービス・メトリックをデフォルトで提供しています。それは、多くの革新的な顧客は、彼らの可観測性を一歩進めたいと考えています。これらの顧客は、Oracle Autonomous Databaseに格納されているアプリケーション・データに関する独自のメトリックを収集、公開および分析する必要があります。これらのカスタム・メトリックと呼びますが、これは、アプリケーションがOCI SDKによって提供される単純なREST APIによってOCIモニタリング・サービスに収集および投稿できるメトリックです。
このチュートリアルでは、いくつかのPL/SQLスクリプトのみを使用し、Oracle Cloudコンソールで数回クリックするだけで、Oracle Autonomous Databaseからカスタム・メトリックを簡単に公開する方法を説明します。
このチュートリアルでは、eコマース・ショッピング・オーダー・データベース・スキーマを使用して、データのメトリックを計算および収集する方法を紹介します。eコマース・アプリケーションが受信した各オーダーについて、各オーダー・ステータス(履行済、受入済、拒否済など)の数を表すメトリックを定期的に計算する方法が表示されます。最後に、これらのカスタム・メトリックをOracle Cloud Monitoring Serviceに公開します。
前提条件
- Oracle Cloud無料の層または有料アカウントにアクセスします。
-
共有または専用のいずれかのタイプのOracle Autonomous Databaseインスタンス。
ノート:このチュートリアルでは、共有インフラストラクチャ上で1 OCPUと1TBのストレージのみを使用するOracle Autonomous Transaction ProcessingインスタンスにOracle Autonomous Databaseを使用します。これは、Oracle Cloud無料の層アカウントを使用して作成できます。
- PL/SQLに関する基本的な知識。
- Oracle Cloudコンソールの精通。
- SQL DeveloperやSQL*Plusなどの任意のOracle Databaseクライアントを使用できます。Oracle Autonomous Transaction Processingを初めて使用する場合は、Autonomous Databaseへの接続を参照してください。Oracle Autonomous Transaction Processingについては、Oracle Autonomous Transaction ProcessingのOracle Cloudコンソール・ページから入手できるSQL Developer Webを参照してください。SQL Developer Webを使用する場合、Oracle Walletは不要です。
- Oracle Autonomous Transaction Processingインスタンスへの
ADMINユーザー・アクセス。 - OCIモニタリング・サービス、カスタム・メトリックを公開するためのPostMetricData API、動的グループおよびリソース原則などのOracle Cloudの概念をよく理解します。
ソリューション一覧

Oracle Autonomous Databaseインスタンスにデプロイされた単純なPL/SQLスクリプトがあります。これは、OCIモニタリング・サービスでカスタム・メトリックの計算、収集および転記を定期的に実行するようにスケジュールされています。
また、Oracle Autonomous Databaseインスタンスにプライベートまたはパブリック・エンドポイントを含めることもできます。Oracle Autonomous DatabaseとOCI Monitoringサービス間の通信は、超高速で高可用性を備えたOracle Cloudネットワークで行われます。サービス・ゲートウェイを設定する必要はありません。
このチュートリアルでは、Oracle Autonomous DatabaseからOCIモニタリング・サービスにカスタム・メトリックを取得するまで、知っておく必要があるすべてのことを説明します。
概要
- Oracle Autonomous Transaction Processingインスタンスの動的グループを作成し、ポリシーを使用してメトリックをOracle Cloud Infrastructure (OCI)モニタリング・サービスにポストすることを認可します。
- Oracle Autonomous Transaction Processingインスタンスで必要な権限を持つ新規データベース・ユーザーまたはスキーマを作成するか、必要な権限を持つ既存のデータベース・ユーザーまたはスキーマを更新します。
- サンプルのeコマース・アプリケーションのデータを格納する
SHOPPING_ORDERという名前の表を作成します(この表に格納されている顧客オーダーのカスタム・メトリックを計算します)。 - 顧客オーダーのランダム・データを
SHOPPING_ORDER表に移入するためのPL/SQLスクリプトを定義します。 - PL/SQLスクリプトを定義して、OCIモニタリング・サービスでカスタム・メトリックを計算、収集および転記します。
- ステップ4および5からスクリプトをスケジュールおよび実行します。
- Oracle Cloudコンソールで公開されているカスタム・メトリックを確認します。
本番のユース・ケースでは、実際のデータと更新を移入するための独自のアプリケーションがあります。したがって、この場合、ステップ3および4は必要ありません。
ステップ
-
Oracle Autonomous Transaction Processingインスタンスの動的グループを作成し、ポリシーを使用してメトリックをOracle Cloud Infrastructure (OCI)モニタリング・サービスにポストすることを認可します。
-
ルールを使用して、Oracle Autonomous Transaction Processingインスタンス(またはインスタンス)に対して
adb_dgという名前の動的グループを作成します。ALL {resource.type = 'autonomousdatabase', resource.compartment.id = '<compartment OCID for your ADB instance>'}または、コンパートメント内のすべてのインスタンスではなく、単一のOracle Autonomous Transaction Processingインスタンスを選択することもできます:
ALL {resource.type = 'autonomousdatabase', resource.id = '<OCID for your ATP instance>'}
-
Oracle Cloud Infrastructure Identity and Access Management (IAM)ポリシーを作成して、動的グループ
adb_dgを認可し、adb_dg_policyという名前のポリシーおよびポリシー・ルールAllow dynamic-group adb_dg to read metrics in compartment <Your Oracle Autonomous Transaction Processing compartment OCID>を使用してOCIモニタリング・サービスにメトリックを投稿します。
これで、Oracle Autonomous Transaction Processingサービス(動的グループ
adb_dgの定義でカバーされる)は、同じコンパートメントにメトリックを投稿する権限になりました。OCIモニタリング・サービスにメトリックを公開する権限を持つOracle Autonomous Transaction Processingデータベース・ユーザーがいません。はい。Oracle Autonomous Transaction Processingで実行されているPL/SQLでは、メトリックをOCIモニタリング・サービスに投稿できません。手順3cで行います。
-
-
Oracle Autonomous Transaction Processingインスタンスで必要な権限を持つ新規データベース・ユーザーまたはスキーマを作成するか、必要な権限を持つ既存のデータベース・ユーザーまたはスキーマを更新します。
-
Oracle Autonomous Transaction Processingインスタンスに、
ECOMMERCE_USERという名前のデータベース・ユーザーまたはスキーマを作成します。これは、すべてのOracle Autonomous Transaction ProcessingインスタンスのADMINユーザーとして作成できます。既存のユーザーを使用する場合は、このステップをスキップできます。CREATE USER ECOMMERCE_USER IDENTIFIED BY "Password of your choice for this User";ノート:ここで、ユーザー(またはスキーマ)を
ECOMMERCE_USERとして参照し、残りのステップは同じままです(既存のユーザーを使用するか、新しく作成したユーザーを使用するか)。 -
必要なOracle Database関連の権限を
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; -
Oracle Cloudリソース・プリンシパルのOracle Database資格証明を有効にして、そのアクセスをdb-user
ECOMMERCE_USERに付与します。これにより、ステップ1で作成した動的グループadb_dgがデータベース・ユーザーECOMMERCE_USERに接続され、ユーザーがメトリックをOCIモニタリング・サービスにポストする認可が付与されます。詳細は、リソース・プリンシパルを使用したOracle Cloud Infrastructureリソースへのアクセスを参照してください。EXEC DBMS_CLOUD_ADMIN.ENABLE_RESOURCE_PRINCIPAL(username => 'ECOMMERCE_USER'); -
(オプション)前のステップで完了した操作を確認します。
ノート: Oracle Cloudリソース・プリンシパルのOracle Database資格証明を有効にすると、常にOracle Autonomous DatabaseのADMINユーザーによって所有されます。確認方法:
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';
-
-
データベース表のメトリックの計算を示す
SHOPPING_ORDERというサンプル・データ表を作成します。表スキーマはわかりやすいですが、
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;各ショッピング・オーダーは、その存続期間中に8つのステータス値のいずれかを持つことができます:
[ACCEPTED, PAYMENT_REJECTED, SHIPPED, ABORTED, OUT_FOR_DELIVERY, ORDER_DROPPED_NO_INVENTORY, PROCESSED, NOT_FULFILLED]。 -
次のPL/SQLスクリプトを読み、
SHOPPING_ORDER表にデータを移入します。任意のOracle Databaseクライアントで実行します。このスクリプトは、最初に
TOTAL_ROWS_IN_SHOPPING_ORDER行数をランダムに生成された順序データとともにSHOPPING_ORDER表に追加します。次に、各SHOPPING_ORDER行のSTATUS値をランダムに変更して、データを更新します。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; / -
このチュートリアル(カスタム・メトリックを計算してOCIモニタリング・サービスにパブリッシュするスクリプト)の実際について説明します。任意のOracle Datbaseクライアントで実行します。スクリプトは、複数の実行で再生できることを確認するためにべき等です。次に、スクリプト部分を分析します。
-
SHOPPING_ORDER_METRICS_TABLE表を作成し、これを使用して、計算されたメトリックを収集およびバッファします。メトリック計算を実行する問合せに対してデータ表が最適化されていることを確認します。これらの問合せは、データベースに負荷がかかりすぎないようにし、本番のユースケースを妨げます。
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; / -
メトリックを計算するストアド・プロシージャを作成します: ステータス値別のオーダー数のカウント、このメトリック・コレクションのインスタンス。
次に、ストアド・プロシージャは、前のステップで作成したバッファ表
SHOPPING_ORDER_METRICS_TABLEの計算済メトリックをバッファします。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; /バッファ・テーブルのサイズを制限するには、サイズが1,000行を超える場合はトリムします。
-
バッファ・メトリックを
SHOPPING_ORDER_METRICS_TABLEからPostMetricsData APIが要求で想定するJSONオブジェクトに変換するPL/SQLファンクションPREPARE_JSON_OBJECT_FROM_METRIC_ROWSを使用します。ノート:
- この関数は、最新のメトリック・データ・ポイントの
BATCH_SIZE_FOR_EACH_POST数をSHOPPING_ORDER_METRICS_TABLEからOCI_METADATA_JSON_OBJ JSON_OBJECT_Tに変換します。 OCI_METADATA_JSON_OBJは、PL/SQLの組込みJSONデータ型JSON_OBJECT_Tの変数です。PostMetricsData APIのリクエスト本文であるPostMetricDataDetailsと同じJSON構造を持つOCI_METADATA_JSON_OBJを構築しました。
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; / - この関数は、最新のメトリック・データ・ポイントの
-
PL/SQLコードを使用して、PostMetricsData APIを使用してこれらの変換済メトリックをOCIモニタリング・サービスに公開します。
ノート:これは、PL/SQLファンクション
POST_METRICS_DATA_TO_OCIおよびストアド・プロシージャ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; /関数
POST_METRICS_DATA_TO_OCIは、PostMetricsData APIを起動します。すべてのOracle Cloud APIと同様に、呼び出すには、適切なOCI IAM認可が必要です。次のように、名前付きパラメータcredential_name => 'OCI$RESOURCE_PRINCIPAL'を使用して渡します。データベース資格証明
OCI$RESOURCE_PRINCIPALは、ステップ2で作成した動的グループadb_dgにリンクされ、ステップ3のECOMMERCE_USERユーザーはすでにアクセスできます。そのため、信頼チェーンによって、
ECOMMERCE_USERによって実行されるこのPL/SQLスクリプトには、カスタム・メトリックを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は、すべてのOracle Autonomous Databaseとともに事前インストールされた任意のレスト・エンドポイントを起動する組込みのPL/SQLストアド・プロシージャです。ここでは、これを使用してOCIモニタリング・サービスのREST APIを起動します。ストアド・プロシージャ
PUBLISH_BUFFERED_METRICS_TO_OCIは、これまでに説明したすべての関数とプロシージャを使用して、すべてのバッファ・メトリックをOCIモニタリング・サービスにポストします。実行するには、PostMetricsData APIの起動ごとに、メトリック・データ・ポイントのサイズBATCH_SIZE_FOR_EACH_POSTのバッチを作成します。
-
-
ステップ4および5からスクリプトをスケジュールおよび実行します。ステップ4および5では、ストアド・プロシージャおよびストアド・ファンクションをOracle Databaseに定義しましたが、まだ実行していません。
-
ステップ4からスクリプトを実行して、
SHOPPING_ORDER表にデータを移入します。このスクリプトは、1 OCPUおよび1TBのストレージでOracle Autonomouse Transaction Processingインスタンスで約15分間実行されます。-- 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; -
残っているのは、ステップ5:計算および公開からOCIモニタリング・サービスへのPL/SQLスクリプトの定期的な実行のみです。
次のように、PL/SQL組込みストアド・プロシージャ
DBMS_SCHEDULER.CREATE_JOBを使用して実行します。20分(1,200秒)の間続くOracle Database
SCHEDULED_JOBが作成されます。カスタム・メトリックが計算され、毎分公開されます。本番ユース・ケースの場合は、必要に応じて構成します。
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; /
-
-
Oracle Cloudコンソールで公開されているカスタム・メトリックを確認します。
-
ナビゲーション・メニューから、「メトリック・エクスプローラ」をクリックします。

-
「メトリック・エクスプローラ」で、ネームスペースを
custom_metrics_from_adb、resourceGroupをecommerece_adb、メトリック名をcustomer_orders_submittedとして選択し、カスタム・メトリックに設定します。カスタム・メトリックに設定したすべてのメタデータおよびディメンションを使用できます。
MQL問合せを作成して、ニーズおよびユース・ケースに従ってこれらのメトリックを分析できます。次に、メトリック・ストリームにOracle Cloudアラームを設定して、運用チームにアラートを通知できます。
これにより、選択したOracle Autonomous Databaseメトリックの可観測性ループが自動化されます。

-
まとめ
OCI SDK for PL/SQLを使用して、単純なPL/SQLスクリプトを使用してOracle Autonomous DatabaseからOracle Cloud Infrastructure (OCI) Monitoringサービスにカスタム・メトリックを生成する方法を学習しました。Oracle Databaseは多くのビジネス・ワークフローにとって「真のソース」であるため、これは非常に強力な機能です。
カスタム・メトリックは、ネイティブ・メトリックに匹敵するOCI Monitoringサービスの第一級市民です。それらを同じ強力なメトリック問合せ言語で分析し、それらに対してアラームを設定して、関心や問題が発生した場合に常に通知できます。
これにより、すべてのメトリックの最終的な「単一ペイン・オブ・グラス」ビュー(アプリケーションやデータベースで生成されたOCIサービスまたはカスタム・メトリックの生成)が提供されます。
謝辞
- 作成者 - Mayur Raleraskar、ソリューション・アーキテクト
その他の学習リソース
docs.oracle.com/learnの他のラボを調べるか、Oracle Learning YouTubeチャネルでさらに無料の学習コンテンツにアクセスします。さらに、education.oracle.com/learning-explorerにアクセスしてOracle Learning Explorerにします。
製品ドキュメントは、Oracleヘルプ・センターを参照してください。
Publish custom metrics from Oracle Autonomous Database using Oracle Cloud Infrastructure Monitoring service
F50481-01
November 2021
Copyright © 2021, Oracle and/or its affiliates.