You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
common-smartgears/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java

116 lines
4.8 KiB
Java

package org.gcube.smartgears.handlers.application.request;
import static org.gcube.smartgears.Constants.called_method_header;
import javax.xml.bind.annotation.XmlRootElement;
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;
import org.gcube.common.authorization.library.provider.AuthorizationProvider;
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.smartgears.Constants;
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;
import org.gcube.smartgears.utils.InnerMethodName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@XmlRootElement(name = Constants.request_accounting)
public class RequestAccounting extends RequestHandler {
private static Logger log = LoggerFactory.getLogger(RequestAccounting.class);
private static ThreadLocal<Long> startCallThreadLocal = new ThreadLocal<Long>();
@Override
public String getName() {
return Constants.request_accounting;
}
@Override
public void handleRequest(RequestEvent e) {
ApplicationContext context = e.context();
String calledMethod = e.request().getHeader(called_method_header);
if (calledMethod==null){
calledMethod = e.request().getRequestURI().substring(e.request().getContextPath().length());
if (calledMethod.isEmpty())
calledMethod = "/";
}
InnerMethodName.instance.set(calledMethod);
String caller = AuthorizationProvider.instance.get()!=null? AuthorizationProvider.instance.get().getClient().getId(): "UNKNOWN";
startCallThreadLocal.set(System.currentTimeMillis());
log.info("REQUEST START ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} ",
context.configuration().name(),context.configuration().serviceClass(), InnerMethodName.instance.get(),
caller, e.request().getRemoteHost(), ScopeProvider.instance.get());
}
@Override
public void handleResponse(ResponseEvent e) {
ApplicationContext context = e.context();
boolean resetScope = false;
if (ScopeProvider.instance.get()==null && SecurityTokenProvider.instance.get()==null){
String infrastructure = e.context().container().configuration().infrastructure();
ScopeProvider.instance.set("/"+infrastructure);
resetScope = true;
}
String caller = AuthorizationProvider.instance.get()!=null? AuthorizationProvider.instance.get().getClient().getId(): "UNKNOWN";
String callerQualifier = AuthorizationProvider.instance.get()!=null? AuthorizationProvider.instance.get().getTokenQualifier(): "UNKNOWN";
//retieves caller Ip when there is a proxy
String callerIp = e.request().getHeader("x-forwarded-for");
if(callerIp==null)
callerIp=e.request().getRemoteHost();
generateAccounting(caller,callerQualifier,callerIp==null?"UNKNOWN":callerIp , context);
log.info("REQUEST SERVED ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} FINISHED IN {} millis",
context.configuration().name(),context.configuration().serviceClass(), InnerMethodName.instance.get(),
caller, callerIp, ScopeProvider.instance.get(), System.currentTimeMillis()-startCallThreadLocal.get());
startCallThreadLocal.remove();
InnerMethodName.instance.reset();
if (resetScope)
ScopeProvider.instance.reset();
}
void generateAccounting(String caller, String callerQualifier, String remoteHost, ApplicationContext context){
AccountingPersistenceFactory.setFallbackLocation(context.container().persistence().location());
AccountingPersistence persistence = AccountingPersistenceFactory.getPersistence();
ServiceUsageRecord serviceUsageRecord = new ServiceUsageRecord();
try{
serviceUsageRecord.setConsumerId(caller);
serviceUsageRecord.setCallerQualifier(callerQualifier);
serviceUsageRecord.setScope(ScopeProvider.instance.get());
serviceUsageRecord.setServiceClass(context.configuration().serviceClass());
serviceUsageRecord.setServiceName(context.configuration().name());
serviceUsageRecord.setHost(context.container().configuration().hostname()+":"+context.container().configuration().port());
serviceUsageRecord.setCalledMethod(InnerMethodName.instance.get());
serviceUsageRecord.setCallerHost(remoteHost);
serviceUsageRecord.setOperationResult(OperationResult.SUCCESS);
serviceUsageRecord.setDuration(System.currentTimeMillis()-startCallThreadLocal.get());
persistence.account(serviceUsageRecord);
}catch(Exception ex){
log.warn("invalid record passed to accounting ",ex);
}
}
@Override
public String toString() {
return getName();
}
}