SAP APIM Logging in Splunk

Estimated read time 24 min read
Introduction

SAP API Management often requires centralized transaction logging to support monitoring, troubleshooting, and operational analysis across API flows. While working with SAP APIM, I found it difficult to consistently monitor request and response errors and track client IP addresses, especially when issues had to be investigated across multiple policies and runtime stages. On one implementation, this became a recurring support problem because we could see that requests were failing, but we could not quickly tell whether the failure happened during API key validation, target processing, or response handling. That experience led me to implement a centralized logging pattern with Splunk. In this scenario, the goal was to capture key request and response details, including validation failures, response status, and performance metrics, without introducing significant runtime overhead. This post describes a reusable integration pattern using KVM-based configuration, asynchronous service callout, and PreFlow/PostFlow logging so that structured API logging can be implemented in SAP APIM for improved observability.

Integration Pattern for SAP APIM and Splunk

This approach was chosen to keep the logging design secure, reusable, and lightweight. Splunk endpoint details and authentication values are externalized in KVM so they can be maintained without changing policy code. Logging is separated across PreFlow and PostFlow to capture both early validation failures and end-to-end response details, while asynchronous service callouts help minimize runtime impact on the API transaction.

How to integrate Splunk with SAP APIM?
Prerequisites

Splunk URL: https://{{HostName}}:{{Port}}/services/collector/event
Authorization header: Splunk {{Token}}
Data format: JSON{
“index”: “test_sap”,
“host”: “cpidev”,
“sourcetype”: “sap:api:events”,
“source”: “API00XX”,
“event”: {
“message”: “Event Data/Structure Here”
}
}

Solution Overview

The implementation uses SAP APIM policies and JavaScript to build a structured log payload and forward it to Splunk. PreFlow handles authentication-related failures before the request reaches the backend, while PostFlow captures response status, payload details, and timing metrics after target processing. This separation is useful because it ensures that both failed and completed transactions can be logged based on configured conditions. It also gives the team flexibility to log only exceptions or all traffic, depending on operational needs and expected log volume.

Policy Steps: PreFlow
KVM: SplunkDetails (Connection Settings)

This policy reads the Splunk connection details from a Key Value Map, including the URL, resource path, host, index, source type, and proxy-specific success logging flag. KVM is used here to externalize configuration so that endpoint changes can be handled without modifying policy definitions or JavaScript logic. If any required KVM entry is missing at runtime, the downstream service callout may fail or produce incomplete log events, so these values should be validated carefully in each environment.

<KeyValueMapOperations mapIdentifier=”SplunkDetails” async=”true” continueOnError=”false” enabled=”true”
xmlns=”http://www.sap.com/apimgmt”>
<!– PUT stores the key value pair mentioned inside the element –>
<Get assignTo=”private.splunkURL”>
<Key>
<Parameter>splunkURL</Parameter>
</Key>
</Get>
<Get assignTo=”private.splunkResourcePath”>
<Key>
<Parameter>splunkResourcePath</Parameter>
</Key>
</Get>
<Get assignTo=”private.splunkHost”>
<Key>
<Parameter>splunkHost</Parameter>
</Key>
</Get>
<Get assignTo=”private.splunkIndex”>
<Key>
<Parameter>splunkIndex</Parameter>
</Key>
</Get>
<Get assignTo=”private.splunkSourceType”>
<Key>
<Parameter>splunkSourceType</Parameter>
</Key>
</Get>
<Get assignTo=”private.sendSucessToSplunk”>
<Key>
<Parameter ref=”apiproxy.name” />
</Key>
</Get>
<!– the scope of the key value map. Valid values are environment, organization, apiproxy and policy –>
</KeyValueMapOperations>

KVM: Passwords (Token)

This policy retrieves the Splunk token from a secure Key Value Map entry. Storing the token outside the policy definition helps reduce hardcoding of credentials and makes token rotation easier to manage. If the token is invalid or missing, the call to Splunk will not be authorized, so this is one of the first places to check during troubleshooting.

<KeyValueMapOperations mapIdentifier=”Passwords” async=”true” continueOnError=”false” enabled=”true”
xmlns=”http://www.sap.com/apimgmt”>
<!– PUT stores the key value pair mentioned inside the element –>
<Get assignTo=”private.splunkToken”>
<Key>
<Parameter>SPLUNKLOGGING_TOKEN</Parameter>
</Key>
</Get>
<!– the scope of the key value map. Valid values are environment, organization, apiproxy and policy –>
</KeyValueMapOperations>

JavaScript

This JavaScript policy constructs the structured log payload for authentication failures detected in PreFlow. It captures request metadata such as API key, product name, proxy name, environment, client IP address, timestamps, request details, and the validation fault name. This step is important because authentication failures occur before the backend is invoked, so if they are not logged in PreFlow, they may be missed entirely in transaction monitoring.

var logdata = {
apiKey: context.getVariable(“request.header.APIKey”),
productName: context.getVariable(“apiproduct.name”),
proxyName: context.getVariable(“apiproxy.name”),
environmentName: context.getVariable(“environment.name”),
IpAddress: context.getVariable(“client.ip”),
currentSystemTime: context.getVariable(“system.time”),
currentSystemTimeStamp: context.getVariable(“system.timestamp”),
requestReceivedStartTime: context.getVariable(“client.received.start.time”),
requestReceivedStartTimeStamp: context.getVariable(“client.received.start.timestamp”),
requestReceivedEndTime: context.getVariable(“client.received.end.time”),
requestReceivedEndtTimeStamp: context.getVariable(“client.received.end.timestamp”),
responseCode: “401”,
messageId: context.getVariable(“messageid”),
requestURI: context.getVariable(“request.uri”),
requestVerb: context.getVariable(“request.verb”),
requestContent: context.getVariable(“request.content”),
responseMessage: context.getVariable(“oauthV2.VAK-ValidateAPIKey.fault.name”)
}
context.setVariable(“sapapim.logmessage”, JSON.stringify(logdata));

Note : Regarding the variables use the reference SAP Help Link variable-references

Service Callout

This service callout sends the PreFlow log payload to the Splunk HTTP Event Collector endpoint. It is configured asynchronously so that the logging call does not unnecessarily delay the client-facing transaction. The condition should be set so that it runs only when API key or OAuth validation fails; otherwise, Splunk will receive unnecessary events and the logs will become noisy.

Condition: Use oauthV2.VAK-ValidateAPIKey.failed is true for source-side API key authentication. If OAuth-based authentication is used, replace this with oauthV2.failed is true. This condition ensures that only requests with authentication failures are sent to Splunk, which helps keep the logs focused on exception scenarios.

<ServiceCallout async=”true” continueOnError=”true” enabled=”true” xmlns=”http://www.sap.com/apimgmt”>
<Request>
<Set>
<Headers>
<Header name=”Content-Type”>application/json</Header>
<Header name=”Authorization”>Splunk {private.splunkToken}</Header>
</Headers>
<Payload contentType=”application/json” variablePrefix=”#” variableSuffix=”@”>{
“time”: #client.received.start.timestamp@,
“index”: “#private.splunkIndex@”,
“host”: “#private.splunkHost@”,
“sourcetype”: “#private.splunkSourceType@”,
“source”: “#apiproxy.name@”,
“event”: {
“Message”: #sapapim.logmessage@
}
}</Payload>
<Verb>POST</Verb>
</Set>
</Request>
<Timeout>30000</Timeout>
<HTTPTargetConnection>
<URL>https://{private.splunkURL}/{private.splunkResourcePath}</URL>
</HTTPTargetConnection>
</ServiceCallout>

Raise Fault

This policy returns a controlled error response to the client when authentication fails. It ensures that the consumer receives a consistent 401 Unauthorized response rather than an inconsistent backend or policy error. This is useful not only for client handling, but also because it keeps the error path predictable while the failure is logged separately to Splunk.

Condition: Use oauthV2.VAK-ValidateAPIKey.failed is true for source-side API key authentication. If OAuth-based authentication is used instead, replace this with oauthV2.failed is true and update the error reference in the policy to oauthV2.OA-VerifyAccessToken.fault.name.

This condition determines whether the exception flow should be triggered when authentication fails. It ensures that only failed authentication requests are handled by the fault policy, which helps maintain consistent error handling and supports accurate logging for monitoring and troubleshooting.

<!– can be used to create custom messages in case of an error condition –>
<RaiseFault async=”true” continueOnError=”false” enabled=”true” xmlns=”http://www.sap.com/apimgmt”>
<!– Defines the response message returned to the requesting client –>
<FaultResponse>
<Set>
<!– Sets or overwrites HTTP headers in the respone message –>
<Headers />
<Payload contentType=”application/json”>
{

“Error”: “{oauthV2.VAK-ValidateAPIKey.fault.name}”

}
</Payload>
<StatusCode>401</StatusCode>
<!– sets the reason phrase of the response –>
<ReasonPhrase>Unauthorized</ReasonPhrase>
</Set>
</FaultResponse>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</RaiseFault>

Policy Steps: PostFlow
JavaScript

This JavaScript policy prepares the structured log payload after target processing is completed. In addition to request and response details, it captures timing information such as target response time and overall API response time, which makes the logs useful for both troubleshooting and performance analysis. This policy also reads the success logging flag so that the proxy can be configured to send only failures or both failures and successful transactions.

var sendSuccessToSplunk = context.getVariable(“private.sendSucessToSplunk”);
var logdata = {
apiKey: context.getVariable(“request.header.APIKey”),
productName: context.getVariable(“apiproduct.name”),
proxyName: context.getVariable(“apiproxy.name”),
environmentName: context.getVariable(“environment.name”),
IpAddress: context.getVariable(“client.ip”),
currentSystemTime: context.getVariable(“system.time”),
currentSystemTimeStamp: context.getVariable(“system.timestamp”),
requestReceivedStartTime: context.getVariable(“client.received.start.time”),
requestReceivedStartTimeStamp: context.getVariable(“client.received.start.timestamp”),
requestReceivedEndTime: context.getVariable(“client.received.end.time”),
requestReceivedEndtTimeStamp: context.getVariable(“client.received.end.timestamp”),
targetResponseTime: context.getVariable(“target.received.end.timestamp”) – context.getVariable(“target.sent.start.timestamp”),
apiResponseTime: context.getVariable(“system.timestamp”) – context.getVariable(“client.received.end.timestamp”),
targetResponseEndTime: context.getVariable(“target.received.end.time”),
messageStatusCode: context.getVariable(“message.status.code”),
messageId: context.getVariable(“messageid”),
requestContent: context.getVariable(“request.content”),
requestURI: context.getVariable(“request.uri”),
requestVerb: context.getVariable(“request.verb”),
requestURL: context.getVariable(“request.url”),
responseMessage: context.getVariable(“response.content”),
sendSuccessToSplunk: context.getVariable(“private.sendSucessToSplunk”)
}
context.setVariable(“sapapim.logmessage”, JSON.stringify(logdata));

Service Callout

This service callout sends the PostFlow event to Splunk after the response is generated. The condition allows logging for 4xx and 5xx responses by default, and it can also log successful responses when the proxy-specific KVM setting is enabled. This design gives good operational flexibility, because teams that want lower log volume can capture only failures, while teams that need fuller observability can enable success logging.

Condition: Use ((message.status.code =| 4 or message.status.code =| 5) and private.sendSucessToSplunk is false) or private.sendSucessToSplunk is true.

This condition determines whether the transaction should be forwarded to Splunk after response processing. If success logging is disabled, only error responses in the 4xx or 5xx range are sent to Splunk. If success logging is enabled, both successful and failed transactions are logged.

The ProxyName entry in the SplunkDetails KVM controls this behavior. If the value is true, Splunk receives both success and failure messages. If the value is false, only failure messages are sent, which helps reduce log volume while still preserving visibility into exception scenarios.

<ServiceCallout async=”true” continueOnError=”true” enabled=”true” xmlns=”http://www.sap.com/apimgmt”>
<Request>
<Set>
<Headers>
<Header name=”Content-Type”>application/json</Header>
<Header name=”Authorization”>Splunk {private.splunkToken}</Header>
</Headers>
<Payload contentType=”application/json” variablePrefix=”#” variableSuffix=”@”>{
“time”: #client.received.start.timestamp@,
“index”: “#private.splunkIndex@”,
“host”: “#private.splunkHost@”,
“sourcetype”: “#private.splunkSourceType@”,
“source”: “#apiproxy.name@”,
“event”: {
“Message”: #sapapim.logmessage@
}
}</Payload>
<Verb>POST</Verb>
</Set>
</Request>
<Timeout>30000</Timeout>
<HTTPTargetConnection>
<URL>https://{private.splunkURL}/{private.splunkResourcePath}</URL>
</HTTPTargetConnection>
</ServiceCallout>

Raise Fault

This policy raises a fault for error responses returned from the target system. It preserves the backend status code and response content so that consumers receive a meaningful error while the same transaction is also available in Splunk for support analysis. Care should be taken when using this policy to ensure that sensitive backend payload content is not exposed to clients or written to logs without review.

Condition: Use (message.status.code =| 4 or message.status.code =| 5).

This condition checks whether the response belongs to an error category, specifically HTTP 4xx or 5xx status codes. It ensures that the policy is triggered only for error responses, which makes it useful for exception handling and error-specific logging.

<!– can be used to create custom messages in case of an error condition –>
<RaiseFault async=”true” continueOnError=”false” enabled=”true” xmlns=”http://www.sap.com/apimgmt”>
<!– Defines the response message returned to the requesting client –>
<FaultResponse>
<Set>
<!– Sets or overwrites HTTP headers in the respone message –>
<Headers />
<Payload contentType=”application/xml”>
{response.content}
</Payload>
<StatusCode>{target.response.status.code}</StatusCode>
<!– sets the reason phrase of the response –>
<!–<ReasonPhrase>Bad Request</ReasonPhrase>–>
</Set>
</FaultResponse>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</RaiseFault>

Logging Behavior

The design supports two logging modes. If success logging is enabled for a proxy, both successful and failed API transactions are sent to Splunk. If success logging is disabled, only error scenarios such as authentication failures and 4xx/5xx responses are logged, which helps reduce logging volume while still preserving operational visibility for exceptions.

Conclusion

This solution enables SAP APIM transaction logging to Splunk for better monitoring of API errors, responses, and performance. By using KVM for secure configuration and logging key events in PreFlow and PostFlow, it gives the integration team flexible control over whether to capture only errors or all transactions in Splunk.

Limitations 

One limitation of this approach is that the success payload cannot be logged when streaming is enabled. This should be considered during design if payload-level success logging is a monitoring requirement.

 

​ IntroductionSAP API Management often requires centralized transaction logging to support monitoring, troubleshooting, and operational analysis across API flows. While working with SAP APIM, I found it difficult to consistently monitor request and response errors and track client IP addresses, especially when issues had to be investigated across multiple policies and runtime stages. On one implementation, this became a recurring support problem because we could see that requests were failing, but we could not quickly tell whether the failure happened during API key validation, target processing, or response handling. That experience led me to implement a centralized logging pattern with Splunk. In this scenario, the goal was to capture key request and response details, including validation failures, response status, and performance metrics, without introducing significant runtime overhead. This post describes a reusable integration pattern using KVM-based configuration, asynchronous service callout, and PreFlow/PostFlow logging so that structured API logging can be implemented in SAP APIM for improved observability.Integration Pattern for SAP APIM and SplunkThis approach was chosen to keep the logging design secure, reusable, and lightweight. Splunk endpoint details and authentication values are externalized in KVM so they can be maintained without changing policy code. Logging is separated across PreFlow and PostFlow to capture both early validation failures and end-to-end response details, while asynchronous service callouts help minimize runtime impact on the API transaction.How to integrate Splunk with SAP APIM?PrerequisitesSplunk URL: https://{{HostName}}:{{Port}}/services/collector/event
Authorization header: Splunk {{Token}}
Data format: JSON{
“index”: “test_sap”,
“host”: “cpidev”,
“sourcetype”: “sap:api:events”,
“source”: “API00XX”,
“event”: {
“message”: “Event Data/Structure Here”
}
}Solution OverviewThe implementation uses SAP APIM policies and JavaScript to build a structured log payload and forward it to Splunk. PreFlow handles authentication-related failures before the request reaches the backend, while PostFlow captures response status, payload details, and timing metrics after target processing. This separation is useful because it ensures that both failed and completed transactions can be logged based on configured conditions. It also gives the team flexibility to log only exceptions or all traffic, depending on operational needs and expected log volume.Policy Steps: PreFlowKVM: SplunkDetails (Connection Settings)This policy reads the Splunk connection details from a Key Value Map, including the URL, resource path, host, index, source type, and proxy-specific success logging flag. KVM is used here to externalize configuration so that endpoint changes can be handled without modifying policy definitions or JavaScript logic. If any required KVM entry is missing at runtime, the downstream service callout may fail or produce incomplete log events, so these values should be validated carefully in each environment.<KeyValueMapOperations mapIdentifier=”SplunkDetails” async=”true” continueOnError=”false” enabled=”true”
xmlns=”http://www.sap.com/apimgmt”>
<!– PUT stores the key value pair mentioned inside the element –>
<Get assignTo=”private.splunkURL”>
<Key>
<Parameter>splunkURL</Parameter>
</Key>
</Get>
<Get assignTo=”private.splunkResourcePath”>
<Key>
<Parameter>splunkResourcePath</Parameter>
</Key>
</Get>
<Get assignTo=”private.splunkHost”>
<Key>
<Parameter>splunkHost</Parameter>
</Key>
</Get>
<Get assignTo=”private.splunkIndex”>
<Key>
<Parameter>splunkIndex</Parameter>
</Key>
</Get>
<Get assignTo=”private.splunkSourceType”>
<Key>
<Parameter>splunkSourceType</Parameter>
</Key>
</Get>
<Get assignTo=”private.sendSucessToSplunk”>
<Key>
<Parameter ref=”apiproxy.name” />
</Key>
</Get>
<!– the scope of the key value map. Valid values are environment, organization, apiproxy and policy –>
</KeyValueMapOperations>KVM: Passwords (Token)This policy retrieves the Splunk token from a secure Key Value Map entry. Storing the token outside the policy definition helps reduce hardcoding of credentials and makes token rotation easier to manage. If the token is invalid or missing, the call to Splunk will not be authorized, so this is one of the first places to check during troubleshooting.<KeyValueMapOperations mapIdentifier=”Passwords” async=”true” continueOnError=”false” enabled=”true”
xmlns=”http://www.sap.com/apimgmt”>
<!– PUT stores the key value pair mentioned inside the element –>
<Get assignTo=”private.splunkToken”>
<Key>
<Parameter>SPLUNKLOGGING_TOKEN</Parameter>
</Key>
</Get>
<!– the scope of the key value map. Valid values are environment, organization, apiproxy and policy –>
</KeyValueMapOperations>JavaScriptThis JavaScript policy constructs the structured log payload for authentication failures detected in PreFlow. It captures request metadata such as API key, product name, proxy name, environment, client IP address, timestamps, request details, and the validation fault name. This step is important because authentication failures occur before the backend is invoked, so if they are not logged in PreFlow, they may be missed entirely in transaction monitoring.var logdata = {
apiKey: context.getVariable(“request.header.APIKey”),
productName: context.getVariable(“apiproduct.name”),
proxyName: context.getVariable(“apiproxy.name”),
environmentName: context.getVariable(“environment.name”),
IpAddress: context.getVariable(“client.ip”),
currentSystemTime: context.getVariable(“system.time”),
currentSystemTimeStamp: context.getVariable(“system.timestamp”),
requestReceivedStartTime: context.getVariable(“client.received.start.time”),
requestReceivedStartTimeStamp: context.getVariable(“client.received.start.timestamp”),
requestReceivedEndTime: context.getVariable(“client.received.end.time”),
requestReceivedEndtTimeStamp: context.getVariable(“client.received.end.timestamp”),
responseCode: “401”,
messageId: context.getVariable(“messageid”),
requestURI: context.getVariable(“request.uri”),
requestVerb: context.getVariable(“request.verb”),
requestContent: context.getVariable(“request.content”),
responseMessage: context.getVariable(“oauthV2.VAK-ValidateAPIKey.fault.name”)
}
context.setVariable(“sapapim.logmessage”, JSON.stringify(logdata));Note : Regarding the variables use the reference SAP Help Link variable-referencesService CalloutThis service callout sends the PreFlow log payload to the Splunk HTTP Event Collector endpoint. It is configured asynchronously so that the logging call does not unnecessarily delay the client-facing transaction. The condition should be set so that it runs only when API key or OAuth validation fails; otherwise, Splunk will receive unnecessary events and the logs will become noisy.Condition: Use oauthV2.VAK-ValidateAPIKey.failed is true for source-side API key authentication. If OAuth-based authentication is used, replace this with oauthV2.failed is true. This condition ensures that only requests with authentication failures are sent to Splunk, which helps keep the logs focused on exception scenarios.<ServiceCallout async=”true” continueOnError=”true” enabled=”true” xmlns=”http://www.sap.com/apimgmt”>
<Request>
<Set>
<Headers>
<Header name=”Content-Type”>application/json</Header>
<Header name=”Authorization”>Splunk {private.splunkToken}</Header>
</Headers>
<Payload contentType=”application/json” variablePrefix=”#” variableSuffix=”@”>{
“time”: #client.received.start.timestamp@,
“index”: “#private.splunkIndex@”,
“host”: “#private.splunkHost@”,
“sourcetype”: “#private.splunkSourceType@”,
“source”: “#apiproxy.name@”,
“event”: {
“Message”: #sapapim.logmessage@
}
}</Payload>
<Verb>POST</Verb>
</Set>
</Request>
<Timeout>30000</Timeout>
<HTTPTargetConnection>
<URL>https://{private.splunkURL}/{private.splunkResourcePath}</URL>
</HTTPTargetConnection>
</ServiceCallout>Raise FaultThis policy returns a controlled error response to the client when authentication fails. It ensures that the consumer receives a consistent 401 Unauthorized response rather than an inconsistent backend or policy error. This is useful not only for client handling, but also because it keeps the error path predictable while the failure is logged separately to Splunk.Condition: Use oauthV2.VAK-ValidateAPIKey.failed is true for source-side API key authentication. If OAuth-based authentication is used instead, replace this with oauthV2.failed is true and update the error reference in the policy to oauthV2.OA-VerifyAccessToken.fault.name.This condition determines whether the exception flow should be triggered when authentication fails. It ensures that only failed authentication requests are handled by the fault policy, which helps maintain consistent error handling and supports accurate logging for monitoring and troubleshooting.<!– can be used to create custom messages in case of an error condition –>
<RaiseFault async=”true” continueOnError=”false” enabled=”true” xmlns=”http://www.sap.com/apimgmt”>
<!– Defines the response message returned to the requesting client –>
<FaultResponse>
<Set>
<!– Sets or overwrites HTTP headers in the respone message –>
<Headers />
<Payload contentType=”application/json”>
{

“Error”: “{oauthV2.VAK-ValidateAPIKey.fault.name}”

}
</Payload>
<StatusCode>401</StatusCode>
<!– sets the reason phrase of the response –>
<ReasonPhrase>Unauthorized</ReasonPhrase>
</Set>
</FaultResponse>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</RaiseFault>Policy Steps: PostFlowJavaScriptThis JavaScript policy prepares the structured log payload after target processing is completed. In addition to request and response details, it captures timing information such as target response time and overall API response time, which makes the logs useful for both troubleshooting and performance analysis. This policy also reads the success logging flag so that the proxy can be configured to send only failures or both failures and successful transactions.var sendSuccessToSplunk = context.getVariable(“private.sendSucessToSplunk”);
var logdata = {
apiKey: context.getVariable(“request.header.APIKey”),
productName: context.getVariable(“apiproduct.name”),
proxyName: context.getVariable(“apiproxy.name”),
environmentName: context.getVariable(“environment.name”),
IpAddress: context.getVariable(“client.ip”),
currentSystemTime: context.getVariable(“system.time”),
currentSystemTimeStamp: context.getVariable(“system.timestamp”),
requestReceivedStartTime: context.getVariable(“client.received.start.time”),
requestReceivedStartTimeStamp: context.getVariable(“client.received.start.timestamp”),
requestReceivedEndTime: context.getVariable(“client.received.end.time”),
requestReceivedEndtTimeStamp: context.getVariable(“client.received.end.timestamp”),
targetResponseTime: context.getVariable(“target.received.end.timestamp”) – context.getVariable(“target.sent.start.timestamp”),
apiResponseTime: context.getVariable(“system.timestamp”) – context.getVariable(“client.received.end.timestamp”),
targetResponseEndTime: context.getVariable(“target.received.end.time”),
messageStatusCode: context.getVariable(“message.status.code”),
messageId: context.getVariable(“messageid”),
requestContent: context.getVariable(“request.content”),
requestURI: context.getVariable(“request.uri”),
requestVerb: context.getVariable(“request.verb”),
requestURL: context.getVariable(“request.url”),
responseMessage: context.getVariable(“response.content”),
sendSuccessToSplunk: context.getVariable(“private.sendSucessToSplunk”)
}
context.setVariable(“sapapim.logmessage”, JSON.stringify(logdata));Service CalloutThis service callout sends the PostFlow event to Splunk after the response is generated. The condition allows logging for 4xx and 5xx responses by default, and it can also log successful responses when the proxy-specific KVM setting is enabled. This design gives good operational flexibility, because teams that want lower log volume can capture only failures, while teams that need fuller observability can enable success logging.Condition: Use ((message.status.code =| 4 or message.status.code =| 5) and private.sendSucessToSplunk is false) or private.sendSucessToSplunk is true.This condition determines whether the transaction should be forwarded to Splunk after response processing. If success logging is disabled, only error responses in the 4xx or 5xx range are sent to Splunk. If success logging is enabled, both successful and failed transactions are logged.The ProxyName entry in the SplunkDetails KVM controls this behavior. If the value is true, Splunk receives both success and failure messages. If the value is false, only failure messages are sent, which helps reduce log volume while still preserving visibility into exception scenarios.<ServiceCallout async=”true” continueOnError=”true” enabled=”true” xmlns=”http://www.sap.com/apimgmt”>
<Request>
<Set>
<Headers>
<Header name=”Content-Type”>application/json</Header>
<Header name=”Authorization”>Splunk {private.splunkToken}</Header>
</Headers>
<Payload contentType=”application/json” variablePrefix=”#” variableSuffix=”@”>{
“time”: #client.received.start.timestamp@,
“index”: “#private.splunkIndex@”,
“host”: “#private.splunkHost@”,
“sourcetype”: “#private.splunkSourceType@”,
“source”: “#apiproxy.name@”,
“event”: {
“Message”: #sapapim.logmessage@
}
}</Payload>
<Verb>POST</Verb>
</Set>
</Request>
<Timeout>30000</Timeout>
<HTTPTargetConnection>
<URL>https://{private.splunkURL}/{private.splunkResourcePath}</URL>
</HTTPTargetConnection>
</ServiceCallout>Raise FaultThis policy raises a fault for error responses returned from the target system. It preserves the backend status code and response content so that consumers receive a meaningful error while the same transaction is also available in Splunk for support analysis. Care should be taken when using this policy to ensure that sensitive backend payload content is not exposed to clients or written to logs without review.Condition: Use (message.status.code =| 4 or message.status.code =| 5).This condition checks whether the response belongs to an error category, specifically HTTP 4xx or 5xx status codes. It ensures that the policy is triggered only for error responses, which makes it useful for exception handling and error-specific logging.<!– can be used to create custom messages in case of an error condition –>
<RaiseFault async=”true” continueOnError=”false” enabled=”true” xmlns=”http://www.sap.com/apimgmt”>
<!– Defines the response message returned to the requesting client –>
<FaultResponse>
<Set>
<!– Sets or overwrites HTTP headers in the respone message –>
<Headers />
<Payload contentType=”application/xml”>
{response.content}
</Payload>
<StatusCode>{target.response.status.code}</StatusCode>
<!– sets the reason phrase of the response –>
<!–<ReasonPhrase>Bad Request</ReasonPhrase>–>
</Set>
</FaultResponse>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</RaiseFault>Logging BehaviorThe design supports two logging modes. If success logging is enabled for a proxy, both successful and failed API transactions are sent to Splunk. If success logging is disabled, only error scenarios such as authentication failures and 4xx/5xx responses are logged, which helps reduce logging volume while still preserving operational visibility for exceptions.ConclusionThis solution enables SAP APIM transaction logging to Splunk for better monitoring of API errors, responses, and performance. By using KVM for secure configuration and logging key events in PreFlow and PostFlow, it gives the integration team flexible control over whether to capture only errors or all transactions in Splunk.Limitations One limitation of this approach is that the success payload cannot be logged when streaming is enabled. This should be considered during design if payload-level success logging is a monitoring requirement.   Read More Technology Blog Posts by Members articles 

#SAP

#SAPTechnologyblog

You May Also Like

More From Author