【Azure API 管理】在APIM 中添加 log-to-eventhub 策略,把 Request Body 信息全部記錄在Event Hub中

問題描述

根據(jù)文檔 https://docs.azure.cn/zh-cn/api-management/api-management-howto-log-event-hubs , 可以將Azure API Management中的請求記錄到Azure 事件中心。文檔中有詳細的步驟描述。但是在對于如何創(chuàng)建APIM的Logger, 如何在API中配置策略描述非常不清楚,所以本文就補充如何創(chuàng)建Logger及在APIM的API中添加log-to-eventhub 策略。

前提條件

操作步驟

1) 創(chuàng)建APIM Logger

示例

PUT https://management.chinacloudapi.cn/subscriptions/<your subscription id>/resourceGroups/<group name>/providers/Microsoft.ApiManagement/service/<your apim name>/loggers/<loggerideh01>?api-version=2020-12-01

注:替換<>中的內(nèi)容為自己的相應(yīng)資源信息,同時也定義loggers的名稱。

這里的Endpoint為中國區(qū)Azure的Endpoint: https://management.chinacloudapi.cn/, 如果需要Global Azure,則為:https://management.azure.com/

Authorization

兩種方式任選其一:

  1. Azure Active Directory OAuth2 Flow : https://www.cnblogs.com/lulight/p/14279338.html
  2. 似乎用瀏覽器打開Azure APIM的門戶,通過F12--開發(fā)者選項中的 Network, 查看其中對API的請求,復(fù)制其中的Authorization 值


    No alt text provided for this image

Body

{
 "properties": {
   "loggerType": "azureEventHub",
   "description": "adding a new logger",
   "credentials": {
     "name": "<your event hub name>",
     "connectionString": "Endpoint=sb://<your event hub namespace>.servicebus.chinacloudapi.cn/;SharedAccessKeyName=xxxxxxxxxxxxxxxxx;SharedAccessKey=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
   }
 }
}

Response - 201 Created

{
   "id": "/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/xxxx-rg/providers/Microsoft.ApiManagement/service/xxxx/loggers/loggerideh01",
   "type": "Microsoft.ApiManagement/service/loggers",
   "name": "loggerideh01",
   "properties": {
       "loggerType": "azureEventHub",
       "description": "adding a new logger",
       "credentials": {
           "name": "xxxxxxxxxxxx",
           "connectionString": "{{Logger-Credentials--xxxxxxxxxxxx}}"
       },
       "isBuffered": true,
       "resourceId": null
   }
}

演示動畫

No alt text provided for this image

2) 添加 log-to-eventhub 策略

  1. 瀏覽到自己的 APIM 實例。
  2. 選擇“API”選項卡。
  3. 選擇要將策略添加到的 API。
  4. 選擇“所有操作”。
  5. 選擇屏幕頂部的“設(shè)計”選項卡。
  6. 在“入站或出站處理”窗口中,單擊三角形(鉛筆旁邊)。
  7. 選擇“代碼編輯器”。 有關(guān)詳細信息,請參閱如何設(shè)置或編輯策略
  8. 將光標放在 inbound 或 outbound 策略部分中。
  9. 在右側(cè)窗口中,選擇“高級策略” > “記錄到 EventHub”。 這會插入 log-to-eventhub 策略語句模板。


    No alt text provided for this image

注: Log-to-eventhub 中的logger-id由上面第一步創(chuàng)建。 Request Body的信息一定要進行格式轉(zhuǎn)換。所以需要使用 ** context.Request.Body.As<string>() **

<policies>
   <inbound>
       <base />
       <log-to-eventhub logger-id="loggerideh01">@{
       return new JObject(
           new JProperty("EventTime", DateTime.UtcNow.ToString()),
           new JProperty("ServiceName", context.Deployment.ServiceName),
           new JProperty("RequestId", context.RequestId),
           new JProperty("RequestBody1", context.Request.Body.As<string>()),
           new JProperty("OperationName", context.Operation.Name)
       ).ToString();
   }</log-to-eventhub>
   </inbound>
   <backend>
       <base />
   </backend>
   <outbound>
       <base />
       <log-to-eventhub logger-id="loggerideh01">@{
       return new JObject(
           new JProperty("EventTime", DateTime.UtcNow.ToString()),
           new JProperty("ServiceName", context.Deployment.ServiceName),
           new JProperty("RequestId", context.RequestId),
           new JProperty("RequestBody2", context.Response.Body.As<string>()),
           new JProperty("OperationName", context.Operation.Name)
       ).ToString();
   }</log-to-eventhub>
   </outbound>
   <on-error>
       <base />
   </on-error>
</policies>

3) 連接到Event Hub,查看 Request Body 信息

下載zip包,解壓后在里面找到文件名為:ServiceBusExplorer.exe。 雙擊即可運行


No alt text provided for this image

在下面的字符串框中輸入Event Hub Namespace的連接字符串。點擊Save/ OK后,即可連接到Event Hub中。


No alt text provided for this image

進入保存日志的Event Hub中,找到合適的分區(qū)數(shù),點擊“Create Partitions Listener ”, 然后再彈出的頁面中點擊 “Strat”按鈕,就可以收到Event Hub中所存儲的消息


No alt text provided for this image

附錄一:如何在APIM的Policy set-variable 中為參數(shù)在進行格式轉(zhuǎn)換時候進行驗證是否為null呢?避免Expression evaluation failed.

使用C#的問號表達式 (condition == null ? value1 :value2)

在APIM中,如果在測試階段,出現(xiàn)Expression evaluation failed錯誤,可以在Test 的Trace中進行查看,了解真實的錯誤信息。如:

{
               "source": "log-to-eventhub",
               "timestamp": "2021-12-01T03:25:33.7362765Z",
               "elapsed": "00:00:00.0007502",
               "data": {
                   "messages": [
                       {
                           "message": "Expression evaluation failed.",
                           "expression": "\n        return new JObject(\n            new JProperty(\"EventTime\", DateTime.UtcNow.ToString()),\n            new JProperty(\"ServiceName\", context.Deployment.ServiceName),\n            new JProperty(\"RequestId\", context.RequestId),\n            new JProperty(\"RequestIp\", context.Request.Body),\n            new JProperty(\"OperationName\", context.Operation.Name)\n        ).ToString();\n    ",
                           "details": "Could not determine JSON object type for type Microsoft.WindowsAzure.ApiManagement.Proxy.Gateway.MessageBody.\r\n   at Newtonsoft.Json.Linq.JValue.GetValueType(Nullable`1 current, Object value)\r\n   at Newtonsoft.Json.Linq.JContainer.CreateFromContent(Object content)\r\n   at Newtonsoft.Json.Linq.JProperty..ctor(String name, Object content)"
                       },
                       "Expression evaluation failed. Could not determine JSON object type for type Microsoft.WindowsAzure.ApiManagement.Proxy.Gateway.MessageBody.\r\n   at Newtonsoft.Json.Linq.JValue.GetValueType(Nullable`1 current, Object value)\r\n   at Newtonsoft.Json.Linq.JContainer.CreateFromContent(Object content)\r\n   at Newtonsoft.Json.Linq.JProperty..ctor(String name, Object content)",
                       "Could not determine JSON object type for type Microsoft.WindowsAzure.ApiManagement.Proxy.Gateway.MessageBody."
                   ]
               }
           }

為了避免這樣的情況,在格式轉(zhuǎn)換時候,最好對其進行 null 檢測,當時 null的時候就可以改變其值的或者賦值為“”。

  • <set-variable name="testvalue" value="@(context.Variables["tokenvalue"]==null?context.Request.Headers.GetValueOrDefault("User-Agent","empty"):"")" />*

  • <set-variable name="requestbody" value="@(context.Request.Body==null?"no body":context.Request.Body.As<string>())" />*

參考資料

如何在 Azure API 管理中將事件記錄到 Azure 事件中心 : https://docs.azure.cn/zh-cn/api-management/api-management-howto-log-event-hubs#configure-log-to-eventhub-policies

Logger - Create Or Update : https://docs.microsoft.com/zh-cn/rest/api/apimanagement/2020-12-01/logger/create-or-update#apimanagementcreateehlogger

創(chuàng)建 Azure 事件中心:https://docs.azure.cn/zh-cn/event-hubs/event-hubs-create

下載 Service Bus Explorer查看事件中心消息:https://github.com/paolosalvatori/ServiceBusExplorer/releases

當在復(fù)雜的環(huán)境中面臨問題,格物之道需:濁而靜之徐清,安以動之徐生。 云中,恰是如此!

分類: 【Azure API 管理】

標簽: APIM, 事件中心 Azure Event Hub, Azure API 管理中將事件記錄到 Azure 事件中心, context.Request.Body.As(), log-to-eventhub

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容