Caution: the service for writing logs to the AuditLogger
is not available publicly. The audit logging functionality is only documented below for transparency, but most likely not usable in your situation as of today.
Disclaimer: This blog post is only applicable for the SAP Cloud SDK version of at most 2.19.2. It has not been updated to version 3.0.0 or later. Specifically, CloudLoggerFactory
has been removed - we recommend to use the LoggerFactory
from plain SLF4J instead.
package com.sap.cloud.sdk.tutorial;
import com.google.gson.Gson;
import org.slf4j.Logger;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import com.sap.cloud.sdk.cloudplatform.auditlog.AccessedAttribute;
import com.sap.cloud.sdk.cloudplatform.auditlog.AuditLogger;
import com.sap.cloud.sdk.cloudplatform.logging.CloudLoggerFactory;
import com.sap.cloud.sdk.odatav2.connectivity.ODataException;
import com.sap.cloud.sdk.s4hana.datamodel.odata.namespaces.businesspartner.BusinessPartner;
import com.sap.cloud.sdk.s4hana.datamodel.odata.services.DefaultBusinessPartnerService;
@WebServlet("/businesspartners")
public class BusinessPartnerServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final Logger logger = CloudLoggerFactory.getLogger(BusinessPartnerServlet.class);
@Override
protected void doGet(final HttpServletRequest request, final HttpServletResponse response)
throws ServletException, IOException {
String businessPartnerId = request.getParameter("id");
// 1. Create AccessedAttribute Object for more insights on operation attempt of an attribute
AccessedAttribute attemptAttributes = new AccessedAttribute(
"BusinessPartner.CreationDate",
AccessedAttribute.Operation.READ
);
// 2. Log AccessedAttribute Object
AuditLogger.logDataReadAttempt(
businessPartnerId,
null,
Collections.singleton(attemptAttributes),
"Attempt to SELECT business partner"
);
try {
final BusinessPartner businessPartner =
new DefaultBusinessPartnerService()
.getBusinessPartnerByKey(businessPartnerId)
.select(BusinessPartner.BUSINESS_PARTNER,
BusinessPartner.LAST_NAME,
BusinessPartner.FIRST_NAME,
BusinessPartner.IS_MALE,
BusinessPartner.IS_FEMALE,
BusinessPartner.CREATION_DATE)
.execute();
response.setContentType("application/json");
response.getWriter().write(new Gson().toJson(businessPartner));
// 3. Create AccessedAttribute Object to log output of operation of an attribute
AccessedAttribute auditableValueAccessedAttribute = new AccessedAttribute(
"BusinessPartner.CreationDate",
AccessedAttribute.Operation.READ,
"Creation date of business partner",
businessPartner.getCreationDate(),
null,
true
);
// 4a. Log AccessedAttribute Object
AuditLogger.logDataRead(
businessPartner.getBusinessPartner(),
businessPartner.getLastName(),
Collections.singleton(auditableValueAccessedAttribute),
"Succeeded to SELECT business partner",
null
);
} catch (final ODataException e) {
logger.error(e.getMessage(), e);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().write(e.getMessage());
AccessedAttribute failedAttemptAttributes = new AccessedAttribute(
"BusinessPartner.CreationDate",
AccessedAttribute.Operation.READ,
"Creation date of business partner",
null,
null,
false
);
// 4b. Log AccessedAttribute Object
AuditLogger.logDataRead(
businessPartnerId,
null,
Collections.singleton(failedAttemptAttributes),
"Failed to SELECT business partner",
e
);
}
}
}
As the names suggest those should typically be used to log security relevant events, changes to configuration data, read or change access to sensitive personal data or any other project-specific event requirements. You will find method pairs consisting of two flavours: plain and ending with "Attempt" or "Beginning". With the plain method, you document the actual outcome of an operation, whether successful or not. The latter can be used to document the operations’ starting point as suggested in our code example; its usage, however, is optional.
cf create-service auditlog standard my-auditlog
) and bind your application to the audit log service.package com.sap.cloud.sdk.tutorial;
import com.google.gson.Gson;
import org.slf4j.Logger;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import com.sap.cloud.sdk.cloudplatform.logging.CloudLoggerFactory;
import com.sap.cloud.sdk.odatav2.connectivity.ODataException;
import com.sap.cloud.sdk.s4hana.datamodel.odata.helper.Order;
import com.sap.cloud.sdk.s4hana.datamodel.odata.namespaces.businesspartner.BusinessPartner;
import com.sap.cloud.sdk.s4hana.datamodel.odata.services.DefaultBusinessPartnerService;
@WebServlet("/businesspartners")
public class BusinessPartnerServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
// 1. Get logger for our servlet
private static final Logger logger = CloudLoggerFactory.getLogger(BusinessPartnerServlet.class);
private static final String CATEGORY_PERSON = "1";
@Override
protected void doGet(final HttpServletRequest request, final HttpServletResponse response)
throws ServletException, IOException {
//2. Log event providing INFO level, info is moderate
logger.info("Attempt to SELECT business partners");
try {
final List<BusinessPartner> businessPartners =
new DefaultBusinessPartnerService()
.getAllBusinessPartner()
.select(BusinessPartner.BUSINESS_PARTNER,
BusinessPartner.LAST_NAME,
BusinessPartner.FIRST_NAME,
BusinessPartner.IS_MALE,
BusinessPartner.IS_FEMALE,
BusinessPartner.CREATION_DATE)
.filter(BusinessPartner.BUSINESS_PARTNER_CATEGORY.eq(CATEGORY_PERSON))
.orderBy(BusinessPartner.LAST_NAME, Order.ASC)
.execute();
response.setContentType("application/json");
response.getWriter().write(new Gson().toJson(businessPartners));
// 3a. Log event including basic information providing INFO level
logger.info("Succeeded to SELECT {} business partners", businessPartners.size());
} catch (final ODataException e) {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().write(e.getMessage());
// 3b. Log event including exception providing ERROR level
logger.error("Failed to SELECT business partners", e);
}
}
}
ERROR > WARN > INFO > DEBUG > TRACE
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
21 | |
16 | |
13 | |
13 | |
10 | |
10 | |
7 | |
7 | |
7 | |
7 |