パーサーの作成
パーサーを作成することで、ログ・ファイルからログ・エントリを抽出する方法と、ログ・エントリからフィールドを抽出する方法を定義します。
-
ナビゲーション・メニューを開き、「監視および管理」をクリックします。「ログ・アナリティクス」で、「管理」をクリックします。「管理の概要」ページが開きます。
-
管理リソースが、左側のナビゲーション・ペインの「リソース」の下にリストされます。「パーサー」をクリックします。
- 「パーサー」ページで、「作成」をクリックします。
- オプションから「正規表現タイプ」、「JSONタイプ」、「XMLタイプ」または「区切りタイプ」から選択します。
「パーサーの作成」ページが表示されます。
「正規表現タイプ」の場合、「パーサーの作成」ページがデフォルトでガイド付きモードで開きます。フィールドの選択後にログ・アナリティクスでログを解析する正規表現を生成する場合は、このモードで続行します。解析用の正規表現を記述する場合は、「拡張」モードに切り替えます。
Oracle定義パーサーをテンプレートとして使用して、パーサーを作成することもできます。「パーサー」ページでOracle定義パーサーを選択し、「複製」をクリックして、要件に従ってフィールドの値を変更します。
Oracle Logging Analyticsには、Java Hotspotダンプ・ログ、Linux、Siebel、PeopleSoftなどの複数のシステムなどのログ・ソース用の多くのOracle定義パーサーと、Oracle Database、Oracle WebLogic Server、Oracle Enterprise Manager Cloud Controlなどのエンティティ・タイプ用のものがあります。Oracle Logging Analyticsユーザー・インタフェース内から、サポートされているパーサーおよびログ・ソースの完全なリストにアクセスできます。
パーサーで他のアクションを実行するには、「パーサー」ページでパーサーの「作成タイプ」を選択し、「フィルタ」セクションで「パーサー・タイプ」を選択してパーサーの検索を絞り込みます。パーサーを識別したら、パーサーの行で「アクション」アイコンをクリックします:
-
詳細の表示: パーサー詳細ページが表示されます。パーサーの詳細を表示し、必要に応じて編集します。
-
編集: 「パーサーの編集」ダイアログ・ボックスが表示されます。ここでパーサーのプロパティを変更できます。
-
複製: 既存のパーサーの複製を作成する場合、これをクリックすると、その複製を変更してカスタマイズできます。
- エクスポート定義: Oracle Logging Analyticsを複数のリージョンで使用している場合、パーサー構成コンテンツをエクスポートして再インポートできます。これは、定義のコピーをOracle Logging Analyticsの外部に保存することもできます。構成コンテンツのインポートおよびエクスポートを参照してください。
-
削除: 古いパーサーまたは未使用のパーサーの一部を削除する必要がある場合があります。パーサーを削除するには、「エンティティの削除」ダイアログ・ボックスで確認します。パーサーを削除できるのは、依存ソースがない場合のみです。
トピック:
アクセシビリティ・ヒント: キーボードを使用してログからフィールド抽出のコンテンツを選択するには、ALT+arrowキーを使用します。
正規表現タイプ・パーサーの作成
デフォルトでは、「パーサーの作成」ページが「ガイド付き」モードで開きます。フィールドの選択後にログ・アナリティクスでログを解析する正規表現を生成する場合は、このモードで続行します。ガイド付きモードについては、 ビデオ: RegExパーサー・ビルダーの使用を参照してください。解析用の正規表現を記述する場合は、「拡張」モードに切り替えて、次のステップを続行します:
-
「名前」フィールドに、パーサー名を入力します。たとえば、
Custom Audit Logs
と入力します。 -
オプションで、識別しやすいようにパーサーに適切な説明を入力します。
-
「サンプルのログ・コンテンツ」フィールドで、次のように解析するログ・ファイルからコンテンツを貼り付けます:
Jun 20 2020 15:19:29 hostabc rpc.gssd: ERROR: can't open clnt5aa9: No such file or directory Jul 29 2020 11:26:28 hostabc kernel: FS-Cache: Loaded Jul 29 2020 11:26:28 hostxyz kernel: FS-Cache: Netfs 'nfs' registered for caching Aug 8 2020 03:20:01 slc08uvu rsyslogd-2068: could not load module '/lib64/rsyslog/lmnsd_gtls.so', rsyslog error -2078 [try http://www.rsyslog.com/e/2068 ] Aug 8 2020 03:20:36 0064:ff9b:0000:0000:0000:0000:1234:5678 rsyslogd-2066: could not load module '/lib64/rsyslog/lmnsd_gtls.so', dlopen: /lib64/rsyslog/lmnsd_gtls.so: cannot open shared object file: Too many open files [try http://www.rsyslog.com/e/2066 ] Sep 13 2020 03:36:06 hostnam sendmail: uAD3a6o5009542: from=root, size=263, class=0, nrcpts=1, msgid=<201611130336.uAD3a6o5009542@hostname.example.com>, relay=root@localhost Sep 13 2020 03:36:06 hostnam sendmail: uAD3a6o5009542: to=root, ctladdr=root (0/0), delay=00:00:00, xdelay=00:00:00, mailer=relay, pri=30263, relay=[127.0.0.1] [127.0.0.1], dsn=2.0.0, stat=Sent (uAD3a6KW009543 Message accepted for delivery) Sep 20 2020 08:11:03 hostnam sendmail: STARTTLS=client, relay=userv0022.example.com, version=TLSv1/SSLv3, verify=FAIL, cipher=DHE-RSA-AES256-GCM-SHA384, bits=256/256]]>
これは、エントリ4と5が複数の行にまたがっているため、複数行ログ・エントリです。
-
「正規表現の解析」フィールドに、フィールドを解析する正規表現を入力します。カッコの各ペアは、単一のフィールドに抽出する正規表現句を示します。
解析式は、各ログ・タイプに固有で、実際のログ・エントリのフォーマットごとに異なります。この例では、次を入力します:
(\w+)\s+(\d+)\s+(\d+)\s+(\d+):(\d+):(\d+)\s+([^\s]+)\s+([^:]+):\s+(.*)
ノート
-
コンテンツの前や後にスペースを含めないでください。
-
正規表現は、ログ・レコードの完全なテキストと一致する必要があります。
-
解析式に非表示文字が含まれている場合、「パーサーの作成」インタフェースによって警告メッセージが発行されます:
パーサー式に非表示の制御文字がいくつかあります。
このデフォルト・レスポンスを無効にするには、エラー・メッセージが表示されたら、「非表示の制御文字の表示」チェック・ボックスの選択を解除します。
解析式の作成についてさらに学習するには、サンプルの解析式を参照してください。
-
-
適切な「ログ・レコードのスパン」を選択します。
ログ・エントリは、単一行または複数行のどちらも可能です。複数行を選択した場合は、ログ・レコードの開始式を入力します。
新しいログ・エントリの開始を正しく識別するために必要な最小限のルールとなるように正規表現を定義する必要があります。この例では、開始式は次のようになります:(\w+)\s+(\d+)\s+(\d+)\s+
これは、新しい行がこのエントリ開始式と一致するテキストで始まるたびに、新しいログ・エントリの開始が発生することを示します。
オプションで、終了式も入力できます。「終了式」を使用して、ログ・レコードの終わりを示します。ログ・レコードが長期間にわたってファイルに書き込まれており、ログ・エントリ全体が確実に収集されるようにする場合は、終了正規表現を使用します。エージェントは、終了正規表現パターンが一致するまでログ・レコードの収集を待機します。終了式には、「エントリ開始式」のものと同じフォーマット・ルールが適用されます。
必要に応じて、「ファイル全体を単一ログ・エントリとして処理」チェック・ボックスを選択します。このオプションでは、ログ・ファイル全体を単一のログ・エントリとして解析および格納できます。これは、Java Hotspotダンプ・ログや、パッケージ・ログのRPMリストなどのログ・ソースの解析時に特に役立ちます。ログ・エントリに検索可能にするテキストが多数ある場合は、「このコンテンツにおけるRAWテキスト検索を有効化します」チェック・ボックスの選択を検討してください。このオプションによって、Raw Textフィールドでログ・レコードを検索できます。有効にすると、RAWテキストを含む元のログ・コンテンツを表示できます。
-
「フィールド」タブで、正規表現から取得された各値を格納する関連フィールドを選択します。
新しいフィールドを作成するには、アイコンをクリックします。「ユーザー定義フィールドの作成」ダイアログ・ボックスが開きます。「名前」、「データ型」、「説明」の値を入力し、ログに適用できる場合は「複数値フィールド」チェック・ボックスを使用します。入力する値の詳細は、フィールドの作成を参照してください。行の選択済フィールドを削除するには、アイコンをクリックします。
取得値ごとに、データを格納するフィールドを選択します。この例で最初に取得したフィールドは、次のように入力できます:
-
フィールド名: 月(短縮名)
-
フィールドのデータ型: STRING
-
フィールドの説明: ログ・エントリ時間の月(短縮名)の構成要素(Janなど)
-
フィールド式:
(\w{3})
前述のログの例では、次の順序でフィールドをマップします:
- 月(短縮名)
- 日
- 年(4桁)
- ホスト名(サーバー)
- サービス
- メッセージ
-
-
「ファンクション」タブで、「ファンクションの追加」をクリックして、オプションでログ・エントリを前処理するためのファンクションを追加します。ログ・エントリの前処理を参照してください。
-
「パーサー・テスト」タブをクリックして、新しく作成されたパーサーがログ・コンテンツから値を抽出する方法を表示します。
前に指定したサンプル・コンテンツのログ・エントリを表示できます。これを使用して、定義したパーサーが正常に機能するかどうかを確認します。
1つのログ・エントリで正規表現が失敗した場合、一致ステータスには、機能した式の部分が緑色で、失敗した部分が赤色で示されます。これにより、正規表現のどの部分を修正する必要があるかを識別できます。
パーサー・テストに失敗したイベントのリストおよび失敗の詳細を表示できます。また、正規表現のコストに関する知見を得ることができるステップ数も表示できます。この値は、できるだけ小さいことが理想的です。1000未満であれば許容できますが、よりコストのかかる正規表現が必要な場合もあります。正規表現のステップが多すぎると、エージェント・ホストでのCPU使用率が高くなり、ログの処理が遅くなる可能性があります。これにより、ログ・エクスプローラでのログ・エントリの使用が遅延します。正規表現のコストが高すぎる極端な例では、同じ収集期間に収集されたログ・エントリと他のすべてのエントリの解析がスキップされます。
「保存」をクリックして、作成した新しいパーサーを保存します。
パーサーの作成を中断するには、「取消」をクリックします。「取消」をクリックすると、「正規表現」タイプのパーサーの作成で進行中であった内容はすべて失われます。
TIMEDATE
マクロを使用した日時の解析
-
Oracle Logging Analyticsでは、
TIMEDATE
マクロを使用して、ログ・ファイル内の日時を解析することもできます。つまり、
TIMEDATE
式フォーマットを使用するログについては、前述の解析式を次のように記述する必要があります:{TIMEDATE}\s+([^\s]+)\s+([^:]+):\s+(.*)
この場合、エントリ開始式は
{TIMEDATE}\s+
です。 -
ログでログ・エントリに年が割り当てられていない場合、Oracle Logging Analyticsは、ホスト・タイムゾーンやファイルの最終変更時間などの使用可能な情報に基づいて年を識別しようとします。オンデマンド・アップロードでは、ユーザーは曖昧な日付を解決するための情報を提供できます。また、オンデマンド・アップロードまたは管理エージェントを使用してログを収集するときに、タイムゾーン・オーバーライド設定を使用できます。オンデマンドでのログのアップロードおよびホストからの継続的なログ収集の設定を参照してください。
-
単一のログ・レコードとして解析されるログ・ファイルのパーサーで日時が指定されていない場合、管理エージェントを使用したログの収集時には、ログ・ファイルの最終変更時間が考慮されます。収集中にログ・エントリの日時を確定できない場合、ログ・エントリは、そのログがOracle Logging Analyticsに収集された日時を使用して格納されます。
JSONタイプ・パーサーの作成
各ログ・エントリにコンテキスト/ヘッダー・ログ・データが含まれていない場合は、関連するヘッダー・ログ・データでログ・エントリをエンリッチできます。次のステップに従ってヘッダー詳細関数を指定することで、ログ・エントリを前処理し、ヘッダー情報でコンテンツをエンリッチできます。
-
まず、ヘッダー情報を取得するためにJSONパスを識別できるログ・コンテンツの例を指定して、ヘッダー・コンテンツ・パーサーを作成します。
-
ログ・エントリの残りの本文を解析する2番目のパーサーを定義します。
-
本文パーサーにヘッダー詳細ファンクション・インスタンスを追加し、ステップ1で定義したヘッダー・パーサーを選択します。
-
ステップ2で定義した本文パーサーをログ・ソースに追加し、ログ・ソースをエンティティに関連付けてログ収集を開始します。
JSONパーサーを作成するには:
-
「パーサー」フィールドに、パーサー名を入力します。たとえば、
Custom API Log
と入力します。 -
パーサー・タイプを「JSON」として選択します。
-
オプションで、識別しやすいようにパーサーに適切な説明を入力します。
-
「サンプルのログ・コンテンツ」フィールドで、次のように解析するログ・ファイルからコンテンツを貼り付けます:
{ "name": "helloapi", "hostname": "banana.local", "pid": 40442, "level": 30, "req": { "method": "GET", "url": "/hello?name=paul", "headers": { "user-agent": "curl/7.19.7 (universal-apple-darwin10.0) libcurl/7.19.7 OpenSSL/0.9.8r zlib/1/2/3", "host": "0.0.0.0:8080", "accept": "*/*" }, "remoteAddress": "127.0.0.1", "remotePort": 59834 }, "msg": "start", "time": "2012-03-28T17:39:44.880Z", "v": 0 }
サンプルのログ・コンテンツに基づいて、次の例のようにフィールドが選択され、「フィールド」タブに表示されます:
- 「フィールド」タブで、特定のJSONパスに対して、使用可能な定義済フィールドからフィールド名を選択します。
新しいフィールドを作成するには、アイコンをクリックします。「ユーザー定義フィールドの作成」ダイアログ・ボックスが開きます。「名前」、「データ型」、「説明」の値を入力し、ログに適用できる場合は「複数値フィールド」チェック・ボックスを使用します。入力する値の詳細は、フィールドの作成を参照してください。行の選択済フィールドを削除するには、アイコンをクリックします。
選択されるデフォルト・ルート・パスは、
$
です。JSONルート・パスを変更する場合は、「詳細オプション」セクションを展開して、メニューから「ログ・エントリJSONパス」を選択します。 - 「ファンクション」タブで、「ファンクションの追加」をクリックして、オプションでヘッダー・パーサー・ファンクションでログ・エントリを前処理するためのファンクションを追加します。ログ・エントリの前処理を参照してください。
- フィールドを選択したら、「パーサー・テスト」タブに移動して、一致ステータスおよびサンプルのログ・コンテンツから選択されたフィールドを表示します。
- 「保存」をクリックして、作成した新しいパーサーを保存します。
JSONタイプ・パーサーの作成を中断し、正規表現タイプのパーサーの作成に切り替えるには、「タイプ」で「正規表現」を選択します。
XMLタイプ・パーサーの作成
-
「パーサー」フィールドに、パーサー名を入力します。たとえば、
Custom Database Audit Log
と入力します。 -
パーサー・タイプを「XML」として選択します。
-
オプションで、識別しやすいようにパーサーに適切な説明を入力します。
-
「Example Log Content」フィールドで、次のExampleAのように解析するログ・ファイルからコンテンツを貼り付けます:
<AuditRecord><Audit_Type>1</Audit_Type><Session_ld>201073</Session_ld><Statementid>13</Statementid><Entryld>6</Entryld> <Extended_Timestamp>2016-09-09T01:26:07.832814Z</Extended_Timestamp><DB_User>SYSTEM</DB_User><OS_User>UserA</OS_User><Userhost>host1</Userhost> <OS_Process>25839</OS_Process><Terminal>pts/4</Terminal><Instance_Number>0</Instance_Number><Object_Schema>HR</Object_Schema> <Object_Name>EMPLOYEES</Object_Name><Action>17</Action> <Returncode>0</Returncode><Sen>§703187</Sen><AuthPrivileges>--------¥-----</AuthPrivileges> <Grantee>SUMON</Grantee> <Priv_Used>244</Priv_Used><DBID>2791516383</DBID><Sql_Text>GRANT SELECT ON hr.employees TO sumon</Sql_Text></AuditRecord>
サンプル・ログ・コンテンツに基づいて、Oracle Logging Analyticsは、ログ・レコードを表すXML要素のリストを自動的に識別します。
-
オプションで、「ネームスペースの無視」チェック・ボックスを有効にして、XMLパスのネームスペースを無視します。
-
オプションで、「位置認識の有効化」チェック・ボックスを有効にして、要素の配列の場合と同様に、XMLパスの下にある要素の複数の値を検出します。たとえば、次の例では、ログ・コンテンツExampleBです。
<ListOfTrackingFields> <TrackingField> <Name>NameA</Name> </TrackingField> <TrackingField> <Name>NameB</Name> </TrackingField> <TrackingField> <Name>NameC</Name> </TrackingField> <TrackingField> <Name>NameD</Name> </TrackingField> <TrackingField> <Name>NameE</Name> </TrackingField> </ListOfTrackingFields>
位置認識が有効になっていない場合は、XMLパス
/ListOfTrackingFields/TrackingField/Name
に制限され、Name
の最初の値のみが検出されます。位置認識を有効にすると、要素TrackingField
の下にあるName
の次の5つの値が検出されます。対応するすべてのXMLパスが構成されている場合は、NameA
、NameB
、NameC
、NameD
、NameE
。 -
「ログ・エントリXMLパス」メニューから、目的のログ・レコードに適したXML要素を選択します。前述のサンプルのログ・コンテンツExampleAでは、
/AuditRecord
を選択します。XMLパスの選択に基づいて、フィールドが選択され、「フィールド」タブに表示されます。前述のサンプルのログ・コンテンツでは、強調表示された要素がフィールドとして適格です。例のXMLパス
/AuditRecord
の場合、フィールドのXMLパスは、/AuditRecord/<highlighted_element>
になります(/AuditRecord/Audit_Type
など)。 -
「フィールド」タブで、特定のXMLパスに対して、使用可能な定義済フィールドからフィールド名を選択します。
新しいフィールドを作成するには、アイコンをクリックします。「ユーザー定義フィールドの作成」ダイアログ・ボックスが開きます。「名前」、「データ型」、「説明」の値を入力し、ログに適用できる場合は「複数値フィールド」チェック・ボックスを使用します。入力する値の詳細は、フィールドの作成を参照してください。行の選択済フィールドを削除するには、アイコンをクリックします。
-
フィールドを選択したら、「パーサー・テスト」タブに移動して、一致ステータスを表示します。
-
「保存」をクリックして、作成した新しいパーサーを保存します。
XMLタイプ・パーサーの作成を中断し、正規表現タイプのパーサーの作成に切り替えるには、「タイプ」で「正規表現」を選択します。
区切りタイプ・パーサーの作成
-
パーサーの名前を入力します。たとえば、
Comma Separated Custom App Log
と入力します。 -
オプションで、識別しやすいようにパーサーに適切な説明を入力します。
-
パーサー・タイプを「デリミタ付き」として選択します。
-
「デリミタ」で、「カンマ」、「セミコロン」、「スペース」または「タブ」などのフィールドを区切るためにログで使用するデリミタのタイプを選択します。リストされているオプションと異なる場合は、「その他」を選択し、指定したスペースにデリミタ文字を指定します。
次のログ・コンテンツの例を考えてみます。
helloapi,"host,local", 65427, 29, start, 2021-08-28T17:39:44.880Z
前述の例では、カンマ(
,
)はデリミタです。指定したデリミタ文字が、次に選択したクオリファイアと異なることを確認してください。
-
オプションで、ログ内のフィールドのテキストを折り返すために使用される修飾子を選択します。「二重見積」または「単一見積」を選択します。
テキスト・クオリファイアは、フィールド・データ内にデリミタが含まれている場合に使用されます。field1の値が
host,local
で、デリミタ文字(、)が含まれ、テキスト修飾子が使用されていないシナリオを考えてみます。デリミタ(local
)の後に発生するデータは、次のフィールドの値とみなされます。前のステップのログ・コンテンツの例では、二重引用符(
"
)が修飾子です。ノート
データ型文字列のフィールドの値については、修飾子の前後の空白文字も文字列の一部として考慮されます。文字列値が一致するように、修飾子がデリミタのすぐ横に配置されていることを確認します。たとえば、,"host,local",
では、最初のデリミタの後の空白文字が削除されます。また、最後のデリミタの前の空白文字が削除されます。したがって、後からパーサー・テスト結果に表示されるように、一致文字列フィールドの有効な値はhost,local
です。 -
オプションで、「ヘッダー」の下にログのヘッダー行を貼り付けます。このヘッダー行は、「フィールド」タブの「ヘッダー列」にマップできます。たとえば、
name, hostname, pid, level, msg, time
ヘッダーを指定すると、実際のログのヘッダーと完全に一致するログ行がフィルタで除外されます。
-
「サンプルのログ・コンテンツ」フィールドで、次のように解析するログ・ファイルからコンテンツを貼り付けます:
helloapi,"host,local", 65427, 29, start, 2021-08-28T17:39:44.880Z
サンプルのログ・コンテンツに基づいて、次の例のようにフィールドが選択され、「フィールド」タブに表示されます:
- 「フィールド」タブのヘッダー列で、使用可能な定義済フィールドからフィールド名を選択します。ただし、任意のヘッダー列のみを選択的にマップでき、すべてのヘッダー列のフィールドをマップする必要はありません。
新しいフィールドを作成するには、アイコンをクリックします。「ユーザー定義フィールドの作成」ダイアログ・ボックスが開きます。「名前」、「データ型」、「説明」の値を入力し、ログに適用できる場合は「複数値フィールド」チェック・ボックスを使用します。入力する値の詳細は、フィールドの作成を参照してください。行の選択済フィールドを削除するには、アイコンをクリックします。
- フィールドを選択したら、「パーサー・テスト」タブに移動して、一致ステータスおよびサンプルのログ・コンテンツから選択されたフィールドを表示します。
- 「パーサーの作成」をクリックして、作成した新しいパーサーを保存します。
区切りタイプのパーサーの作成を中止し、別のタイプのパーサーの作成に切り替えるには、「タイプ」でそれを選択します。
ベース・フィールドのパーサーへのマップ
元のログ・コンテンツが追加情報でラップされている場合は、元のログ・コンテンツを含むベース・フィールドをパーサーにマップし、その元のログ・レコードのフィールドを抽出できます。
元のログ・コンテンツが次のようになっているとします。
####<Feb 01, 2021 10:28:27 AM PST> <Info> <Diagnostics> <soaapps.example.com> <excstg_soa> <[ACTIVE] ExecuteThread: '34' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <kernel_version> <123456> <[severity-value:64] [rid: 0] [partition-id: 0] [partition-name: DOMAIN] > <BEA-320145> <Size based data retirement operation completed on archive HarvestedDataArchive. Retired 9,720 records in 11,242 ms.>
コネクタ・ハブを介してOCIロギングからOracle Logging Analyticsに同じログ・コンテンツが送信されると、JSONラッパーが元のログ・コンテンツに追加されます。例
{
"data": {
"Labels": "LogPath:/u01/APPLTOP/instance/wlslogs/FADomain/servers/ServiceServer_1/logs/ServiceServer_1.log;ServiceName:Host;ServiceType:Oracle_Host;LogSet:TEST_POD;HostName:examplehost.oraclecloud.com;IP:192.0.2.1;WLS:NA;Domain:NA;AppName:myApp;Customer:CompanyA, (U.S.) Corp;CustomerType:NonHypercare;PODType:TEST;PODSize:S0;DC:CDC;Version:11.13.20.10.0;",
"action": "ACTION",
"msg": "####<Feb 01, 2021 10:28:27 AM PST> <Info> <Diagnostics> <soaapps.example.com> <excstg_soa> <[ACTIVE] ExecuteThread: '34' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <kernel_version> <123456> <[severity-value:64] [rid: 0] [partition-id: 0] [partition-name: DOMAIN] > <BEA-320145> <Size based data retirement operation completed on archive HarvestedDataArchive. Retired 9,720 records in 11,242 ms.>"
},
"id": "123123123",
"oracle": {
"compartmentid": "ocid1.compartment.oc1..aaaaaaaauniqueID",
"ingestedtime": "2021-02-01T18:32:49.204Z",
"loggroupid": "ocid1.loggroup.oc1.iad.amaaaaaauniqueID",
"logid": "ocid1.log.oc1.iad.amaaaaaayuniqueID",
"tenantid": "ocid1.tenancy.oc1..aaaaaaaaetuniqueID"
},
"source": "FA-APPS",
"specversion": "1.0",
"time": "2021-02-01T11:48:43.091Z",
"type": "FA Unified Apps Logs"
}
前述の例では、元のログ・コンテンツがベース・フィールドmsg
に存在します。
前述の例では、ログ・コンテンツにJSONラッパーがあることに注意してください。ただし、元のログ・コンテンツとラッパーがサポートされているパーサー形式であり、ログがサポートされている任意の方法で収集されている場合でも、これらのステップを実行できます。
元のログ・コンテンツのフィールドを抽出するには、次のステップに従います。
-
元のログ・コンテンツのタイプに基づいて、元のログ・コンテンツから関連フィールドを取得するパーサーを識別または作成します。パーサーの作成を参照してください。
このパーサーは、次に作成するラッパー・パーサー内でマップされたパーサーとして使用されます。
-
ラッパー・コンテンツのタイプに基づいて、パーサーの作成のステップに従って、そのパーサーを作成します。
このパーサーは、後続のステップでラッパー・パーサーと呼ばれます。
-
ラッパー・パーサーの場合は、元のログ・コンテンツにラッパーがあるログ・コンテンツの例を指定します。
JSONパーサーの場合、選択したデフォルトのルート・パスは
$
です。JSONルート・パスを変更する場合は、「詳細オプション」セクションを展開して、メニューから「ログ・エントリJSONパス」を選択します。 -
元のログ・コンテンツを含むベース・フィールドに対応する「フィールド」タブで、「アクション」メニューをクリックし、「パーサーを介したフィールドのマップ」を選択します。パーサーを選択できるダイアログ・ボックスが開きます。
前述の例では、マップされたパーサーを追加する必要がある行は
$.data.msg
です。ラッパー・パーサーでは、マップされたパーサーに1つのベース・フィールドのみをマップできます。
-
「パーサーを介したフィールドのマップ」ダイアログ・ボックスで、ベース・フィールドのフィールドを抽出するパーサーを選択します。「フィールドのマップ」をクリックします。
「フィールド」タブに、ベース・フィールドが選択したマップ済パーサーおよび抽出されたフィールドのリストにマップされていることが表示されるようになりました。
選択したマップ済パーサーには、マップ済パーサーも含まれている可能性があります。Oracle Logging Analyticsでは、ネストされたマップ済パーサーの2つのレベルがサポートされます。たとえば、Wrapper-parserにはmapped-parser-1にはmapped-parser-2が含まれます。
-
残りのフィールドを選択したら、「パーサー・テスト」タブで、パーサー・テストを実行して、一致ステータスおよびサンプルのログ・コンテンツから選択されたフィールドを確認します。
ログ・エントリの前処理
Oracle Logging Analyticsには、ログ・エントリを前処理して結果のログ・エントリをエンリッチできる次のファンクションがあります:
パーサーの作成中にログ・エントリを前処理するには、「ファンクション」タブをクリックし、「ファンクションの追加」ボタンをクリックします。
表示される「ファンクションの追加」ダイアログ・ボックスで、ファンクションの名前を入力し、必要なファンクションを選択して、関連フィールドの値を指定します。
サンプルのログ・コンテンツにファンクションを適用した結果をテストするには、「テスト」をクリックします。比較結果が表示され、フィールド値の正確さを確認できます。
ヘッダー詳細ファンクション
このファンクションでは、ログ・ファイルのヘッダーのフィールドでログ・エントリをエンリッチできます。このファンクションは、ヘッダーとして本文のブロックが含まれ、その本文にエントリが含まれるログで特に役立ちます。
このファンクションは、ヘッダー・ログ・エントリのフィールドでログ本文の各エントリをエンリッチします。データベース・トレース・ファイルは、このようなログの例の1つです。
時間ベースの本文ログ・エントリをエンリッチするためのヘッダーおよび対応するフィールドを取得するには、パーサーの作成時に、「ファンクションの追加」ダイアログ・ボックスで対応する「ヘッダー・コンテンツ・パーサー」を選択します。
正規表現ヘッダー・コンテンツ・パーサーの例:
-
これらのタイプのログでは、ヘッダーは通常、ログ・ファイルの先頭部分のどこかに出現し、その後に他のエントリが続きます。次を参照してください:
Trace file /scratch/emga/DB1212/diag/rdbms/lxr1212/lxr1212_1/trace/lxr1212_1_ora_5071.trc Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP, Advanced Analytics and Real Application Testing options ORACLE_HOME = /scratch/emga/DB1212/dbh System name: Linux Node name: slc00drj Release: 2.6.18-308.4.1.0.1.el5xen Version: #1 SMP Tue Apr 17 16:41:30 EDT 2012 Machine: x86_64 VM name: Xen Version: 3.4 (PVM) Instance name: lxr1212_1 Redo thread mounted by this instance: 1 Oracle process number: 35 Unix process pid: 5071, image: oracle@slc00drj (TNS V1-V3) *** 2020-10-12 21:12:06.169 *** SESSION ID:(355.19953) 2020-10-12 21:12:06.169 *** CLIENT ID:() 2020-10-12 21:12:06.169 *** SERVICE NAME:(SYS$USERS) 2020-10-12 21:12:06.169 *** MODULE NAME:(sqlplus@slc00drj (TNS V1-V3)) 2020-10-12 21:12:06.169 *** CLIENT DRIVER:() 2020-10-12 21:12:06.169 *** ACTION NAME:() 2020-10-12 21:12:06.169 2020-10-12 21:12:06.169: [ GPNP]clsgpnp_dbmsGetItem_profile: [at clsgpnp_dbms.c:345] Result: (0) CLSGPNP_OK. (:GPNP00401:)got ASM-Profile.Mode='legacy' *** CLIENT DRIVER:(SQL*PLUS) 2020-10-12 21:12:06.290 SERVER COMPONENT id=UTLRP_BGN: timestamp=2020-10-12 21:12:06 *** 2020-10-12 21:12:10.078 SERVER COMPONENT id=UTLRP_END: timestamp=2020-10-12 21:12:10 *** 2020-10-12 21:12:39.209 KJHA:2phase clscrs_flag:840 instSid: KJHA:2phase ctx 2 clscrs_flag:840 instSid:lxr1212_1 KJHA:2phase clscrs_flag:840 dbname: KJHA:2phase ctx 2 clscrs_flag:840 dbname:lxr1212 KJHA:2phase WARNING!!! Instance:lxr1212_1 of kspins type:1 does not support 2 phase CRS *** 2020-10-12 21:12:39.222 Stopping background process SMCO *** 2020-10-12 21:12:40.220 ksimdel: READY status 5 *** 2020-10-12 21:12:47.628 ... KJHA:2phase WARNING!!! Instance:lxr1212_1 of kspins type:1 does not support 2 phase CRS
前述の例で、ヘッダー詳細ファンクションを使用すると、Oracle Logging Analyticsによって時間ベースの本文ログ・エントリがヘッダー・コンテンツのフィールドでエンリッチされます。
-
次のログの例を参照してください:
Server: prodsrv123 Application: OrderAppA 2020-08-01 23:02:43 INFO DataLifecycle Starting backup process 2020-08-01 23:02:43 ERROR OrderModule Order failed due to transaction timeout 2020-08-01 23:02:43 INFO DataLifecycle Backup process completed. Status=success 2020-08-01 23:02:43 WARN OrderModule Order completed with warnings: inventory on backorder
前述の例で、Oracle Logging Analyticsに取得する必要があるログ・エントリは4つです。サーバー名とアプリケーション名は、ログ・ファイルの先頭にのみ出現します。サーバー名とアプリケーション名を各ログ・エントリに含めるには:
-
サーバー・フィールドとアプリケーション・フィールドを解析するヘッダー用のパーサーを定義します:
Server:\s*(\S+).*?Application:\s*(\S+)
-
ログの残りの本文を解析する2番目のパーサーを定義します:
{TIMEDATE}\s(\S+)\s(\S+)\s(.*)
-
本文パーサーにヘッダー詳細ファンクション・インスタンスを追加し、ステップ1で定義したヘッダー・パーサーを選択します。
-
ステップ2で定義した本文パーサーをログ・ソースに追加し、ログ・ソースをエンティティに関連付けてログ収集を開始します。
これで、各エントリにサーバー名とアプリケーション名が追加された4つのログ・エントリを取得できます。
-
JSONヘッダー・コンテンツ・パーサーの例:
次に、ヘッダー詳細の様々なケースの例を示します。詳細ログ・エントリは、ヘッダー・ログ・エントリのフィールドにエンリッチされます。エンリッチされた詳細ログ・エントリの強調表示されたフィールドは、ヘッダー・ログ・エントリからコピーされたフィールドです。
-
JSON PATH: ヘッダー=
$
、詳細=$.data
{ "id" : "id_ERROR1", "data": { "id" : "id_data_ERROR1", "childblock0": { "src": "127.0.0.1" }, "childblocks": [ { "childblock": { "srchost1": "host1_ERROR1" } }, { "childblock": { "srchost2": "host2_ERROR1" } } ], "hdr": { "time_ms": "2021-05-21T04:27:18.89714589Z", "error": "hdr_ERROR1" } }, "compartmentName": "comp_name_ERROR1", "eventName": "GetBucket_ERROR1" }
抽出およびエンリッチされたログ・エントリ:
ヘッダー・ログ・エントリ:
{"id":"id_ERROR1","compartmentName":"comp_name_ERROR1","eventName":"GetBucket_ERROR1"}
詳細ログ・エントリ:
{"compartmentName":"comp_name_ERROR1","eventName":"GetBucket_ERROR1", "id": "id_data_ERROR1", "childblock0":{"src":"127.0.0.1"},"childblocks":[{"childblock":{"srchost1":"host1_ERROR1"}},{"childblock":{"srchost2":"host2_ERROR1"}}],"hdr":{"time_ms":"2021-05-21T04:27:18.89714589Z","error":"hdr_ERROR1"}}
id
フィールドは、ヘッダーと詳細の両方で使用できます。この場合、詳細のフィールドが選択されます。 -
JSON PATH: ヘッダー=
$.metadata
、詳細=$.datapoints[*]
この例では、最初のブロックにはヘッダーと詳細の両方がありますが、2番目のブロックには詳細ログ・エントリのみがあります。
{ "namespace":"oci_streaming", "resourceGroup":null, "name":"GetMessagesThroughput.Count1", "dimensions":{ "region":"phx1", "resourceId":"ocid1.stream.oc1.phx.1" }, "datapoints":[ { "timestamp":1652942170000, "value":1.1, "count":11 }, { "timestamp":1652942171001, "value":1.2, "count":12 } ], "metadata":{ "displayName":"Get Messages 1", "unit":"count1" } } { "namespace":"oci_streaming", "resourceGroup":null, "name":"GetMessagesThroughput.Count1", "dimensions":{ "region":"phx1", "resourceId":"ocid1.stream.oc1.phx.1" }, "datapoints":[ { "timestamp":1652942170002, "value":2.1, "count":21 }, { "timestamp":1652942171003, "value":3.2, "count":32 } ] }
抽出およびエンリッチされたログ・エントリ:
ヘッダー・ログ・エントリ:
{"displayName":"Get Messages 1","unit":"count1"}
詳細ログ・エントリ:
{"displayName":"Get Messages 1","unit":"count1", "timestamp":1652942170000,"value":1.1,"count":11}
詳細ログ・エントリ:
{"displayName":"Get Messages 1","unit":"count1", "timestamp":1652942171001,"value":1.2,"count":12}
詳細ログ・エントリ:
{"timestamp":1652942170002,"value":2.1,"count":21}
詳細ログ・エントリ:
{"timestamp":1652942171003,"value":3.2,"count":32}
-
JSON PATH: ヘッダー=
$.instanceHealths:[*]
、詳細=$.instanceHealths[*].instanceHealthChecks[*]
{ "reportType": "Health Status Report 1", "instanceHealths": [ { "instanceHealthChecks": [ { "HealthCheckName": "Check-A1", "Result": "Passed", "time": "2022-11-17T06:05:01Z" }, { "HealthCheckName": "Check-A2", "Result": "Passed", "time": "2022-11-17T06:05:01Z" } ], "Datacenter-A" : "Remote A" } ] }
抽出およびエンリッチされたログ・エントリ:
ヘッダー・ログ・エントリ:
{"Datacenter-A":"Remote A"}
詳細ログ・エントリ:
{"Datacenter-A":"Remote A", "HealthCheckName":"Check-A1","Result":"Passed","time":"2022-11-17T06:05:01Z"}
詳細ログ・エントリ:
{"Datacenter-A":"Remote A", "HealthCheckName":"Check-A2","Result":"Passed","time":"2022-11-17T06:05:01Z"}
-
JSON PATH: Header1 =
$.dimensions
, Header2 =$.metadata
, Details =$.datapoints[*]
この例では、2つの異なるヘッダーが適用されます。
{ "namespace":"oci_streaming", "resourceGroup":null, "name":"GetMessagesThroughput.Count1", "dimensions":{ "region":"phx1", "resourceId":"ocid1.stream.oc1.phx.1" }, "datapoints":[ { "timestamp":1652942170000, "value":1.1, "count":11 }, { "timestamp":1652942171001, "value":1.2, "count":12 } ], "metadata":{ "displayName":"Get Messages 1", "unit":"count1" } }
抽出およびエンリッチされたログ・エントリ:
Header1ログ・エントリ:
{"region":"phx1","resourceId":"ocid1.stream.oc1.phx.1"}
Header2ログ・エントリ:
{"displayName":"Get Messages 1","unit":"count1"}
詳細ログ・エントリ:
{"region":"phx1","resourceId":"ocid1.stream.oc1.phx.1", displayName":"Get Messages 1","unit":"count1", "timestamp":1652942170000,"value":1.1,"count":11}
詳細ログ・エントリ:
{"region":"phx1","resourceId":"ocid1.stream.oc1.phx.1", displayName":"Get Messages 1","unit":"count1", "timestamp":1652942171001,"value":1.2,"count":12}
-
JSON PATH: Header1 =
$.hdr1
, Header2 =$.hdr2
, Details =$.body
この場合、ヘッダー・ログ・エントリは、両方が同じブロック内にある場合、詳細ログ・エントリに関連付けられます。
{ "hdr1": { "module": "mod1", "error": "hdr1_error1" } } { "body": { "id": "data_id_ERROR2", "error": "body_ERROR2" } } { "hdr2": { "module": "mod3", "error": "hdr2_error3" } "body": { "id": "data_id_ERROR4", "error": "body_ERROR4" } }
抽出およびエンリッチされたログ・エントリ:
ヘッダー・ログ・エントリ:
{"id":"data_id_ERROR1","error":"hdr1_error1"}
詳細ログ・エントリ:
{"id":"data_id_ERROR2","error":"body_ERROR2"}
ヘッダー・ログ・エントリ:
{"module":"mod3","error":"hdr2_error3"}
詳細ログ・エントリ:
{"module":"mod3", "id":"data_id_ERROR4","error":"body_ERROR4"}
2番目の詳細ログ・エントリでは、ヘッダーと詳細で同じ要素が使用可能な場合、
error
の値が詳細から選択されることに注意してください。
検索/置換ファンクション
このファンクションでは、ログ行からテキストを抽出し、指定したパターンに基づいて条件付きでそのテキストを他のログ行に追加できます。たとえば、この機能を使用して、欠落しているタイムスタンプをMySQLの一般クエリー・ログとスロー・クエリー・ログに追加できます。
検索/置換ファンクションには、次の属性があります:
-
捕捉正規表現: すべてのログ行に一致した正規表現と、一致した正規表現の名前付きグループ・テキストが、置換式で使用するためにメモリーに保存されます。
-
捕捉式が行全体と一致する場合、置換式は後続のログ行に適用されません。これは、欠落している行を先頭に追加する場合に、同じ行を2回使用しないためです。
-
捕捉式に一致した行は、検出式では処理されません。そのため、検索/置換操作は同じログ行では実行できません。
-
名前が異なる複数のグループを指定できます。
-
-
検出正規表現: この正規表現は、ログ行の捕捉式の名前付きグループで一致するテキストに置き換えるテキストを指定します。
-
一致パターンはグループ化する必要があります。
-
検出式は、捕捉式に一致した行では実行されません。そのため、検索/置換操作は同じログ行では実行できません。
-
検出式には複数のグループを指定できます。各グループの一致テキストは、置換式によって作成されたテキストに置き換えられます。
-
-
置換正規表現: このカスタム表記は、検出式で検出されたグループを置き換えるテキストを示します。グループ名はカッコで囲む必要があります。
-
グループ名はカッコで囲む必要があります。
-
静的テキストを含めることができます。
-
置換式によって作成されたテキストは、検出式のすべてのグループの一致テキストを置き換えます。
-
フィールド「捕捉正規表現」、「検出正規表現」および「置換正規表現」の横にある「ヘルプ」アイコンをクリックすると、フィールドの説明、サンプル式、サンプル・コンテンツ、および実行されるアクションが表示されます。別の捕捉式を追加するには、「捕捉正規表現」で「式の追加」をクリックします。
例:
- この例の目的は、テキスト
# Time:
を含むログ行からタイムスタンプを取得し、タイムスタンプのない# User@Host
から始まるログ行に追加することです。次のログ・データを考えます:
# Time: 160201 1:55:58 # User@Host: root[root] @ localhost [] Id: 1 # Query_time: 0.001320 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 1 select @@version_comment limit 1; # User@Host: root[root] @ localhost [] Id: 2 # Query_time: 0.000138 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 2 SET timestamp=1454579783; SELECT DATABASE();
「捕捉正規表現」、「検出正規表現」および「置換正規表現」属性の値は次のようになります:
-
「捕捉正規表現」の値は、タイムスタンプのログ行と一致し、それをtimestrという名前でメモリーに保存するもので、
^(?<timestr>^# Time:.*)
です。 -
「検出正規表現」の値は、タイムスタンプのログ行を先頭に追加する必要がある行を検索するもので、
(^)# User@Host:.*
です。 -
「置換正規表現」の値は、タイムスタンプの欠落しているログ行の先頭を置き換えるもので、
(timestr)
です。
検索/置換ファンクションを追加した後、ログ行が次のように変更されます:
# Time: 160201 1:55:58 # User@Host: root[root] @ localhost [] Id: 1 # Query_time: 0.001320 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 1 select @@version_comment limit 1; # Time: 160201 1:55:58 # User@Host: root[root] @ localhost [] Id: 2 # Query_time: 0.000138 Lock_time: 0.000000 Rows_sent: 1 Rows_examined: 2 SET timestamp=1454579783; SELECT DATABASE();
前述の例の結果で、検索/置換ファンクションによって、ログの前処理中に検出された各ログ行の
User@host
エントリの前にタイムスタンプが挿入されていることがわかります。 -
-
この例の目的は、複数のパラメータを捕捉し、ログ・データの複数の場所で置換することです。
次のログ・データを考えます:
160203 21:23:54 Child process "proc1", owner foo, SUCCESS, parent init 160203 21:23:54 Child process "proc2" - 160203 21:23:54 Child process "proc3" -
前述のログ行では、2行目と3行目にユーザー・データが含まれていません。そのため、検索/置換ファンクションでは、ログの1行目から値を取得し、2行目と3行目の値を置き換える必要があります。
「捕捉正規表現」、「検出正規表現」および「置換正規表現」属性の値は次のようになります:
-
「捕捉正規表現」の値は、最初のログ行から
foo
およびinit
ユーザーの情報を取得し、それをパラメータuser1およびuser2を使用してメモリーに保存するもので、^.*?owner\s+(?<user1>\w+)\s*,\s*.*?parent\s+(?<user2>\w+).*
です。 -
「検出正規表現」の値は、ハイフン文字(
-
)を含む行を検索するもので、.*?(-).*
です。 -
「置換正規表現」の値は、
, owner (user1), UNKNOWN, parent (user2)
です。
検索/置換ファンクションを追加した後、ログ行が次のように変更されます:
160203 21:23:54 Child process "proc1", owner foo, SUCCESS, parent init 160203 21:23:54 Child process "proc2", owner foo, UNKNOWN, parent init 160203 21:23:54 Child process "proc3", owner foo, UNKNOWN, parent init
前述の例の結果で、検索/置換ファンクションによって、ログの前処理中に検出された各ログ行のハイフン文字(
-
)エントリのかわりに、user1およびuser2の情報が挿入されていることがわかります。 -
時間オフセット・ファンクション
一部のログ・レコードにはタイムスタンプがなく、一部には時間オフセットのみがあり、どちらもないものもあります。Oracle Logging Analyticsは、必要な情報を抽出し、各ログ・レコードにタイムスタンプを割り当てます。
次に、いくつかのシナリオと、時間オフセット・ファンクションを使用してタイムスタンプを割り当てるための対応する解決策を示します:
サンプルのログ・コンテンツ | シナリオ | 解決策 |
---|---|---|
|
ログ・ファイルには、最初のログにタイムスタンプがあり、その後にオフセットがあります。 |
最初のログ・レコードからタイムスタンプを取得し、時間オフセットで調整された後のログ・レコードに割り当てます。 |
|
ログ・ファイルには、最初のログに時間オフセットがあり、それより前にタイムスタンプ・ログはありません。 |
後のログ・レコードからタイムスタンプを取得し、時間オフセットで調整された前のログ・レコードに割り当てます。 中間にある時間オフセットがリセットされている場合(つまり、より少ない時間オフセットがログ・レコードに出現している場合)、前のログ・レコードのタイムスタンプを参照して修正します。 |
|
ログ・ファイルには、時間オフセットのみのログ・レコードがあり、タイムスタンプはありません。 |
ファイルの最終変更時間からのタイムスタンプ: すべてのログ・レコードを横断した後、ファイルの最終変更時間から計算済の時間オフセットを差し引くことで、タイムスタンプが計算されます。 ファイル名からのタイムスタンプ: UIでこのオプションを選択すると、タイムスタンプは、タイムスタンプ式によって指定されたフォーマットのファイル名から取得されます。 |
ログ・エントリの時間オフセットは、前に一致したタイムスタンプが基準になります。このドキュメントでは、このタイムスタンプをベース・タイムスタンプと呼びます。
パーサーの時間オフセット・ファンクションを使用して、ログ・レコードからタイムスタンプおよびタイムスタンプ・オフセットを抽出します。「ファンクションの追加」ダイアログ・ボックスで:
-
タイムスタンプを検索する場所: タイムスタンプを取得する場所を指定するには、「ファイル名」、「ファイルの最終変更時間」および「ログ・エントリ」から選択します。デフォルトでは、「ファイル名」が選択されます。
これを指定しない場合、タイムスタンプの検索は次の順序で実行されます:
- ログ・レコード全体を横断し、タイムスタンプ・パーサーとの一致を検索します(次のステップで指定します)。
- ファイルの最終変更時間をタイムスタンプとして取得します。
- ファイルの最終変更時間が使用できない場合は、システム時間をタイムスタンプとして選択します。
- ファイル名でタイムスタンプ式との一致を検索します(次のステップで指定します)。
-
タイムスタンプのソースの選択に基づいて、次の値を指定します:
- ステップ1で「ファイル名」を選択した場合:
タイムスタンプ式: 正規表現を指定して、ファイル名のタイムスタンプを検索します。デフォルトでは、
{TIMEDATE}
ディレクティブが使用されます。サンプル・ファイル名: 前述の設定のテストに使用できるサンプル・ログのファイル名を指定します。
-
ステップ1で「ファイルの最終変更時間」を選択した場合、「サンプル・ファイルの最終変更時間」を選択します。
-
ステップ1で「ログ・エントリ」を選択した場合、「タイムスタンプ・パーサー」メニューからパーサーを選択し、タイムスタンプ・フォーマットを指定します。
- ステップ1で「ファイル名」を選択した場合:
-
タイムスタンプ・オフセット式: 正規表現を指定して、秒およびミリ秒単位で時間オフセットを抽出し、タイムスタンプをログ・レコードに割り当てます。
sec
およびmsec
グループのみがサポートされます。たとえば、(?<sec>\d+)\.(?<msec>\d+)
。次のログ・レコードの例を考えます:
15.225 hostA debug services started
オフセット式の例では、ログ・レコードから
15
秒と225
ミリ秒が時間オフセットとして取得されます。 -
前のステップで選択が行われると、ログ・コンテンツが「サンプル・ログ」フィールドに表示されます。
「テスト」をクリックして、設定をテストします。
元のログ・コンテンツと、指定に基づいて計算された時間との比較が表示されます。
-
前述の時間オフセット・ファンクションを保存するには、「追加」をクリックします。