2016-11-25 15:42:29 +01:00
|
|
|
package org.gcube.smartgears.handlers.application.request;
|
|
|
|
|
|
|
|
import org.gcube.accounting.datamodel.UsageRecord.OperationResult;
|
|
|
|
import org.gcube.accounting.datamodel.usagerecords.ServiceUsageRecord;
|
|
|
|
import org.gcube.accounting.persistence.AccountingPersistence;
|
|
|
|
import org.gcube.accounting.persistence.AccountingPersistenceFactory;
|
2022-05-30 18:29:46 +02:00
|
|
|
import org.gcube.common.security.providers.SecretManagerProvider;
|
2016-11-25 15:42:29 +01:00
|
|
|
import org.gcube.smartgears.Constants;
|
2022-02-07 09:44:31 +01:00
|
|
|
import org.gcube.smartgears.configuration.Mode;
|
2016-11-25 15:42:29 +01:00
|
|
|
import org.gcube.smartgears.context.application.ApplicationContext;
|
|
|
|
import org.gcube.smartgears.handlers.application.RequestEvent;
|
|
|
|
import org.gcube.smartgears.handlers.application.RequestHandler;
|
|
|
|
import org.gcube.smartgears.handlers.application.ResponseEvent;
|
2017-07-28 12:09:32 +02:00
|
|
|
import org.gcube.smartgears.utils.InnerMethodName;
|
2016-11-25 15:42:29 +01:00
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
|
|
|
public class RequestAccounting extends RequestHandler {
|
|
|
|
|
|
|
|
private static Logger log = LoggerFactory.getLogger(RequestAccounting.class);
|
|
|
|
|
2023-02-01 17:18:13 +01:00
|
|
|
private static ThreadLocal<Long> startCallThreadLocal = new ThreadLocal<Long>();
|
2022-05-23 17:15:46 +02:00
|
|
|
|
2022-06-15 17:44:52 +02:00
|
|
|
private static final String UNKNOWN = "Unknown";
|
2022-05-23 17:15:46 +02:00
|
|
|
|
2016-11-25 15:42:29 +01:00
|
|
|
@Override
|
|
|
|
public String getName() {
|
|
|
|
return Constants.request_accounting;
|
|
|
|
}
|
2022-05-23 17:15:46 +02:00
|
|
|
|
2016-11-25 15:42:29 +01:00
|
|
|
@Override
|
|
|
|
public void handleRequest(RequestEvent e) {
|
2022-05-30 18:29:46 +02:00
|
|
|
ApplicationContext appContext = e.context();
|
2022-05-23 17:15:46 +02:00
|
|
|
|
2022-05-30 18:29:46 +02:00
|
|
|
String context = getContext(appContext);
|
2022-07-20 17:31:20 +02:00
|
|
|
|
2023-02-01 17:18:13 +01:00
|
|
|
if (InnerMethodName.instance.get() == null) {
|
2022-07-20 17:31:20 +02:00
|
|
|
String calledMethod = e.request().getRequestURI().substring(e.request().getContextPath().length());
|
|
|
|
if (calledMethod.isEmpty())
|
|
|
|
calledMethod = "/";
|
2023-02-01 17:18:13 +01:00
|
|
|
calledMethod = e.request().getMethod() + " " + calledMethod;
|
2022-07-20 17:31:20 +02:00
|
|
|
InnerMethodName.instance.set(calledMethod);
|
|
|
|
}
|
|
|
|
|
2023-02-01 17:18:13 +01:00
|
|
|
String caller = SecretManagerProvider.instance.get() != null
|
|
|
|
? SecretManagerProvider.instance.get().getOwner().getId()
|
|
|
|
: UNKNOWN;
|
2016-11-25 15:42:29 +01:00
|
|
|
startCallThreadLocal.set(System.currentTimeMillis());
|
2022-05-23 17:15:46 +02:00
|
|
|
|
2023-02-01 17:18:13 +01:00
|
|
|
log.info("REQUEST START ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} ", appContext.configuration().name(),
|
2023-03-31 14:16:23 +02:00
|
|
|
appContext.configuration().group(), InnerMethodName.instance.get(), caller,
|
2023-02-01 17:18:13 +01:00
|
|
|
e.request().getRemoteHost(), context);
|
2022-05-23 17:15:46 +02:00
|
|
|
|
2016-11-25 15:42:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void handleResponse(ResponseEvent e) {
|
2022-05-30 18:29:46 +02:00
|
|
|
ApplicationContext appContext = e.context();
|
2022-05-23 17:15:46 +02:00
|
|
|
|
|
|
|
try {
|
2022-07-20 17:31:20 +02:00
|
|
|
|
2022-05-30 18:29:46 +02:00
|
|
|
String context = getContext(appContext);
|
2022-05-23 17:15:46 +02:00
|
|
|
|
2023-02-01 17:18:13 +01:00
|
|
|
String caller = SecretManagerProvider.instance.get() != null
|
|
|
|
? SecretManagerProvider.instance.get().getOwner().getId()
|
|
|
|
: UNKNOWN;
|
2022-06-15 17:44:52 +02:00
|
|
|
String callerQualifier = UNKNOWN;
|
2023-02-01 17:18:13 +01:00
|
|
|
// retieves caller Ip when there is a proxy
|
2022-05-23 17:15:46 +02:00
|
|
|
String callerIp = e.request().getHeader("x-forwarded-for");
|
2023-02-01 17:18:13 +01:00
|
|
|
if (callerIp == null)
|
|
|
|
callerIp = e.request().getRemoteHost();
|
|
|
|
|
|
|
|
boolean success = e.response().getStatus() < 400;
|
|
|
|
|
|
|
|
if (appContext.container().configuration().mode() != Mode.offline)
|
|
|
|
generateAccounting(caller, callerQualifier, callerIp == null ? UNKNOWN : callerIp, success, context,
|
|
|
|
appContext);
|
|
|
|
|
|
|
|
long durationInMillis = System.currentTimeMillis() - startCallThreadLocal.get();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Metrics.globalRegistry.timer("smartgears.requests",
|
|
|
|
* "response",Integer.toString(e.response().getStatus()) , "context", context,
|
|
|
|
* "result", success?"SUCCEDED":"FAILED", "caller-ip", callerIp,
|
|
|
|
* "caller-username", caller, "service-class",
|
|
|
|
* appContext.configuration().serviceClass(), "service-name",
|
|
|
|
* appContext.configuration().name(), "method",
|
|
|
|
* InnerMethodName.instance.get()).record(durationInMillis,
|
|
|
|
* TimeUnit.MILLISECONDS);
|
|
|
|
*/
|
2022-05-30 18:29:46 +02:00
|
|
|
|
2023-02-01 17:18:13 +01:00
|
|
|
log.info("REQUEST SERVED ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} {}(CODE {}) IN {} millis",
|
2023-03-31 14:16:23 +02:00
|
|
|
appContext.configuration().name(), appContext.configuration().group(),
|
2023-02-01 17:18:13 +01:00
|
|
|
InnerMethodName.instance.get(), caller, callerIp, context, success ? "SUCCEDED" : "FAILED",
|
|
|
|
e.response().getStatus(), durationInMillis);
|
2022-07-20 17:31:20 +02:00
|
|
|
|
2023-02-01 17:18:13 +01:00
|
|
|
} catch (Exception e1) {
|
|
|
|
log.error("error on accounting", e);
|
2022-05-23 17:15:46 +02:00
|
|
|
throw e1;
|
2022-07-20 17:31:20 +02:00
|
|
|
} finally {
|
|
|
|
startCallThreadLocal.remove();
|
|
|
|
InnerMethodName.instance.reset();
|
2016-11-30 17:27:21 +01:00
|
|
|
}
|
2022-05-23 17:15:46 +02:00
|
|
|
|
2016-11-25 15:42:29 +01:00
|
|
|
}
|
|
|
|
|
2023-02-01 17:18:13 +01:00
|
|
|
void generateAccounting(String caller, String callerQualifier, String remoteHost, boolean success,
|
|
|
|
String gcubeContext, ApplicationContext appContext) {
|
|
|
|
AccountingPersistenceFactory
|
|
|
|
.setFallbackLocation(appContext.container().configuration().accountingFallbackLocation());
|
2016-11-25 15:42:29 +01:00
|
|
|
AccountingPersistence persistence = AccountingPersistenceFactory.getPersistence();
|
|
|
|
ServiceUsageRecord serviceUsageRecord = new ServiceUsageRecord();
|
2023-02-01 17:18:13 +01:00
|
|
|
try {
|
2022-05-23 17:15:46 +02:00
|
|
|
|
2016-11-25 15:42:29 +01:00
|
|
|
serviceUsageRecord.setConsumerId(caller);
|
|
|
|
serviceUsageRecord.setCallerQualifier(callerQualifier);
|
2022-05-30 18:29:46 +02:00
|
|
|
serviceUsageRecord.setScope(gcubeContext);
|
2023-03-31 14:16:23 +02:00
|
|
|
serviceUsageRecord.setServiceClass(appContext.configuration().group());
|
2022-05-30 18:29:46 +02:00
|
|
|
serviceUsageRecord.setServiceName(appContext.configuration().name());
|
2022-05-23 17:15:46 +02:00
|
|
|
|
2023-02-01 17:18:13 +01:00
|
|
|
serviceUsageRecord.setHost(appContext.container().configuration().hostname() + ":"
|
|
|
|
+ appContext.container().configuration().port());
|
2017-07-28 12:09:32 +02:00
|
|
|
serviceUsageRecord.setCalledMethod(InnerMethodName.instance.get());
|
2016-11-25 15:42:29 +01:00
|
|
|
serviceUsageRecord.setCallerHost(remoteHost);
|
2023-02-01 17:18:13 +01:00
|
|
|
serviceUsageRecord.setOperationResult(success ? OperationResult.SUCCESS : OperationResult.FAILED);
|
|
|
|
serviceUsageRecord.setDuration(System.currentTimeMillis() - startCallThreadLocal.get());
|
2016-11-25 15:42:29 +01:00
|
|
|
persistence.account(serviceUsageRecord);
|
2022-05-23 17:15:46 +02:00
|
|
|
|
2023-02-01 17:18:13 +01:00
|
|
|
} catch (Exception ex) {
|
|
|
|
log.warn("invalid record passed to accounting ", ex);
|
2016-11-25 15:42:29 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-30 18:29:46 +02:00
|
|
|
private String getContext(ApplicationContext appContext) {
|
|
|
|
String infrastructure = appContext.container().configuration().infrastructure();
|
2023-02-01 17:18:13 +01:00
|
|
|
String context = "/" + infrastructure;
|
2022-05-30 18:29:46 +02:00
|
|
|
if (SecretManagerProvider.instance.get() != null)
|
|
|
|
context = SecretManagerProvider.instance.get().getContext();
|
|
|
|
return context;
|
|
|
|
}
|
2022-07-20 17:31:20 +02:00
|
|
|
|
2016-11-30 17:27:21 +01:00
|
|
|
@Override
|
|
|
|
public String toString() {
|
|
|
|
return getName();
|
|
|
|
}
|
|
|
|
|
2016-11-25 15:42:29 +01:00
|
|
|
}
|