Azure APIM入站策略为原始请求额外添加Body父属性问题
问题成因
- 额外出现的
body父节点和你写的set-body逻辑无关,是APIM对接EventHub的默认日志序列化规则导致的:- 如果你当前是用APIM内置的诊断日志功能(诊断设置中配置的日志导出到EventHub),该功能输出的日志有固定的系统schema,会自动把你修改后的请求体嵌套在
body字段下,无法通过调整入站set-body去掉这层包装。 - 如果你是自定义策略转发请求到EventHub,出现这层包装是因为你把
set-body处理后的结构化请求体传给EventHub发送逻辑时,逻辑默认将整个请求体作为body属性的值做了二次JSON封装,没有直接透传你生成的原始JSON字符串。
- 如果你当前是用APIM内置的诊断日志功能(诊断设置中配置的日志导出到EventHub),该功能输出的日志有固定的系统schema,会自动把你修改后的请求体嵌套在
- Splunk端看到的末尾缺失
}是多层嵌套后Splunk对EventHub消息的解析截断导致的,不是你的代码漏写括号。
修复方案
不要依赖入站set-body修改请求体的方式给EventHub传日志内容,改用<log-to-eventhub>策略直接构造要发送的原始JSON字符串,跳过系统默认的schema包装,步骤如下:
- 移除原有入站策略中构造
eventObject、返回包装后JSON的set-body逻辑(如果不需要修改转发给业务后端的请求体,可直接删掉该段set-body)。 - 在入站或出站策略中添加如下
<log-to-eventhub>配置,直接在策略内部完成字段处理和JSON构造:
<!-- 替换logger-id为你在APIM中配置的EventHub Logger的资源ID --> <log-to-eventhub logger-id="your-eventhub-logger-id">@{ var requestBody = context.Request.Body.As<JObject>(preserveContent: true); // 补全缺失的Timestamp字段 if (requestBody["Timestamp"] == null) { requestBody["Timestamp"] = DateTime.UtcNow; } // 移除空的StackTrace字段 if (string.IsNullOrEmpty((string)requestBody["StackTrace"])) { requestBody.Remove("StackTrace"); } // 构造符合Splunk要求的event结构 var eventObject = new JObject(); eventObject["event"] = requestBody; // 直接返回序列化后的字符串,不会额外加包装层 return eventObject.ToString(Newtonsoft.Json.Formatting.None); }</log-to-eventhub>
调整后发送到EventHub的消息体就是你期望的{"event":{...}}结构,Splunk消费后可以直接解析到正确的字段,不会出现多余的body父节点,也不会出现JSON截断问题。
如果你必须通过
set-body修改转发给EventHub REST API的请求体,需要严格按照EventHub REST API的事件格式构造请求,将你生成的eventObject序列化后的字符串赋值给事件结构的body字段,不要直接把eventObject作为整个请求体返回。
内容的提问来源于stack exchange,提问作者Jake Steele
相关产品推荐
相关产品推荐

