Refs #11230: Retrieve Accounting Regex rules through Service Endpoint
Task-Url: https://support.d4science.org/issues/11230 git-svn-id: https://svn.d4science.research-infrastructures.eu/gcube/trunk/accounting/accounting-lib@164461 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
parent
d88b374b04
commit
12f3c4eca8
|
@ -0,0 +1,120 @@
|
||||||
|
package org.gcube.accounting.aggregator;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.gcube.accounting.datamodel.validations.validators.RegexReplace;
|
||||||
|
import org.gcube.accounting.persistence.AccountingPersistenceConfiguration;
|
||||||
|
import org.gcube.documentstore.persistence.ExecutorUtils;
|
||||||
|
import org.gcube.documentstore.records.DSMapper;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JavaType;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
public class RegexRulesAggregator implements Runnable {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(RegexRulesAggregator.class);
|
||||||
|
|
||||||
|
protected TimeUnit timeUnit = TimeUnit.MINUTES;
|
||||||
|
protected long delay = TimeUnit.MINUTES.toMinutes(15);
|
||||||
|
|
||||||
|
protected static final String DELAY = "delay";
|
||||||
|
protected static final String TIME_UNIT = "timeUnit";
|
||||||
|
protected static final String JSON_ARRAY_CALLED_METHOD_RULES = "jsonArrayCalledMethodRules";
|
||||||
|
|
||||||
|
protected ScheduledFuture<?> rulesReloader;
|
||||||
|
|
||||||
|
protected List<RegexReplace> regexReplaceList;
|
||||||
|
|
||||||
|
protected AccountingPersistenceConfiguration accountingPersistenceConfiguration;
|
||||||
|
|
||||||
|
protected static RegexRulesAggregator instance;
|
||||||
|
|
||||||
|
public synchronized static RegexRulesAggregator getInstance() {
|
||||||
|
if(instance==null) {
|
||||||
|
instance = new RegexRulesAggregator();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected RegexRulesAggregator() {
|
||||||
|
regexReplaceList = new ArrayList<>();
|
||||||
|
readConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<RegexReplace> getRegexReplacelist() {
|
||||||
|
return regexReplaceList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegexReplace addRegexReplace(String serviceClass, String serviceName, String regex, String replace) {
|
||||||
|
RegexReplace regexReplace = new RegexReplace(serviceClass, serviceName, regex, replace);
|
||||||
|
return addRegexReplace(regexReplace);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegexReplace addRegexReplace(RegexReplace regexReplace) {
|
||||||
|
synchronized(regexReplaceList) {
|
||||||
|
regexReplaceList.add(regexReplace);
|
||||||
|
}
|
||||||
|
return regexReplace;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected ScheduledFuture<?> reloadAggregatorRules;
|
||||||
|
|
||||||
|
public void readConfiguration() {
|
||||||
|
try {
|
||||||
|
accountingPersistenceConfiguration = new AccountingPersistenceConfiguration(this.getClass());
|
||||||
|
|
||||||
|
try {
|
||||||
|
String delayString = accountingPersistenceConfiguration.getProperty(DELAY);
|
||||||
|
delay = Long.parseLong(delayString);
|
||||||
|
|
||||||
|
String timeUnitString = accountingPersistenceConfiguration.getProperty(TIME_UNIT);
|
||||||
|
timeUnit = TimeUnit.valueOf(timeUnitString.toUpperCase());
|
||||||
|
}catch (Exception e) {
|
||||||
|
logger.warn("Unable to retrieve regex reload delay. Goign to use last known delay {} {}", delay, timeUnit.name().toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
String rulesString = accountingPersistenceConfiguration.getProperty(JSON_ARRAY_CALLED_METHOD_RULES);
|
||||||
|
ObjectMapper mapper = DSMapper.getObjectMapper();
|
||||||
|
JavaType type = mapper.getTypeFactory().constructCollectionType(List.class, RegexReplace.class);
|
||||||
|
List<RegexReplace> rules = mapper.readValue(rulesString, type);
|
||||||
|
synchronized(regexReplaceList) {
|
||||||
|
regexReplaceList = rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch(Exception e) {
|
||||||
|
logger.error("Unable to properly load RegexRules", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
readConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() {
|
||||||
|
if(reloadAggregatorRules == null) {
|
||||||
|
reloadAggregatorRules = ExecutorUtils.scheduler.scheduleAtFixedRate(this, delay, delay, timeUnit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop rule reloader. Use only if you really know what you do.
|
||||||
|
*/
|
||||||
|
public void stop() {
|
||||||
|
if(reloadAggregatorRules != null) {
|
||||||
|
try {
|
||||||
|
reloadAggregatorRules.cancel(true);
|
||||||
|
reloadAggregatorRules = null;
|
||||||
|
}catch (Throwable t) {
|
||||||
|
logger.error("Unable to properly stop {} reloader", this.getClass().getSimpleName(), t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
package org.gcube.accounting.datamodel.validations.validators;
|
package org.gcube.accounting.datamodel.validations.validators;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
|
||||||
|
import org.gcube.accounting.aggregator.RegexRulesAggregator;
|
||||||
import org.gcube.accounting.datamodel.basetypes.AbstractServiceUsageRecord;
|
import org.gcube.accounting.datamodel.basetypes.AbstractServiceUsageRecord;
|
||||||
import org.gcube.documentstore.exception.InvalidValueException;
|
import org.gcube.documentstore.exception.InvalidValueException;
|
||||||
import org.gcube.documentstore.records.Record;
|
import org.gcube.documentstore.records.Record;
|
||||||
|
@ -19,25 +19,19 @@ public class CalledMethodRegexReplaceValidator implements FieldAction {
|
||||||
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(CalledMethodRegexReplaceValidator.class);
|
private static Logger logger = LoggerFactory.getLogger(CalledMethodRegexReplaceValidator.class);
|
||||||
|
|
||||||
protected static final List<RegexReplace> regexReplaceList;
|
@Deprecated
|
||||||
|
|
||||||
public static List<RegexReplace> getRegexReplacelist() {
|
public static List<RegexReplace> getRegexReplacelist() {
|
||||||
return regexReplaceList;
|
return RegexRulesAggregator.getInstance().getRegexReplacelist();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public static RegexReplace addRegexReplace(String serviceClass, String serviceName, String regex, String replace) {
|
public static RegexReplace addRegexReplace(String serviceClass, String serviceName, String regex, String replace) {
|
||||||
RegexReplace regexReplace = new RegexReplace(serviceClass, serviceName, regex, replace);
|
return RegexRulesAggregator.getInstance().addRegexReplace(serviceClass, serviceName, regex, replace);
|
||||||
regexReplaceList.add(regexReplace);
|
|
||||||
return regexReplace;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public static RegexReplace addRegexReplace(RegexReplace regexReplace) {
|
public static RegexReplace addRegexReplace(RegexReplace regexReplace) {
|
||||||
regexReplaceList.add(regexReplace);
|
return RegexRulesAggregator.getInstance().addRegexReplace(regexReplace);
|
||||||
return regexReplace;
|
|
||||||
}
|
|
||||||
|
|
||||||
static {
|
|
||||||
regexReplaceList = new ArrayList<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,21 +4,22 @@ import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class RegexReplace {
|
public class RegexReplace {
|
||||||
|
|
||||||
protected final String serviceClass;
|
protected String serviceClass;
|
||||||
protected final String serviceName;
|
protected String serviceName;
|
||||||
|
|
||||||
protected final String regex;
|
protected String regex;
|
||||||
protected final Pattern regexPattern;
|
protected Pattern regexPattern;
|
||||||
|
|
||||||
protected final String replace;
|
protected String replace;
|
||||||
|
|
||||||
|
protected RegexReplace() {}
|
||||||
|
|
||||||
public RegexReplace(String serviceClass, String serviceName, String regex, String replace) {
|
public RegexReplace(String serviceClass, String serviceName, String regex, String replace) {
|
||||||
super();
|
super();
|
||||||
this.serviceClass = serviceClass;
|
this.serviceClass = serviceClass;
|
||||||
this.serviceName = serviceName;
|
this.serviceName = serviceName;
|
||||||
this.regex = regex;
|
|
||||||
this.regexPattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
|
|
||||||
this.replace = replace;
|
this.replace = replace;
|
||||||
|
setRegex(regex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getServiceClass() {
|
public String getServiceClass() {
|
||||||
|
@ -29,6 +30,11 @@ public class RegexReplace {
|
||||||
return serviceName;
|
return serviceName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void setRegex(String regex) {
|
||||||
|
this.regex = regex;
|
||||||
|
this.regexPattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
|
||||||
|
}
|
||||||
|
|
||||||
public String getRegex() {
|
public String getRegex() {
|
||||||
return regex;
|
return regex;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,6 @@ import org.gcube.common.resources.gcore.ServiceEndpoint;
|
||||||
import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint;
|
import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint;
|
||||||
import org.gcube.common.resources.gcore.ServiceEndpoint.Property;
|
import org.gcube.common.resources.gcore.ServiceEndpoint.Property;
|
||||||
import org.gcube.common.resources.gcore.utils.Group;
|
import org.gcube.common.resources.gcore.utils.Group;
|
||||||
import org.gcube.documentstore.persistence.PersistenceBackend;
|
|
||||||
import org.gcube.documentstore.persistence.PersistenceBackendConfiguration;
|
import org.gcube.documentstore.persistence.PersistenceBackendConfiguration;
|
||||||
import org.gcube.resources.discovery.client.api.DiscoveryClient;
|
import org.gcube.resources.discovery.client.api.DiscoveryClient;
|
||||||
import org.gcube.resources.discovery.client.queries.api.SimpleQuery;
|
import org.gcube.resources.discovery.client.queries.api.SimpleQuery;
|
||||||
|
@ -37,13 +36,13 @@ public class AccountingPersistenceConfiguration extends PersistenceBackendConfig
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public AccountingPersistenceConfiguration(Class<? extends PersistenceBackend> clz) throws Exception {
|
public AccountingPersistenceConfiguration(Class<?> clz) throws Exception {
|
||||||
super(clz);
|
super();
|
||||||
ServiceEndpoint serviceEndpoint = getServiceEndpoint(SERVICE_ENDPOINT_CATEGORY, SERVICE_ENDPOINT_NAME, clz);
|
ServiceEndpoint serviceEndpoint = getServiceEndpoint(SERVICE_ENDPOINT_CATEGORY, SERVICE_ENDPOINT_NAME, clz);
|
||||||
setValues(serviceEndpoint, clz);
|
setValues(serviceEndpoint, clz);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ServiceEndpoint getServiceEndpoint(String serviceEndpointCategory, String serviceEndpointName, Class<? extends PersistenceBackend> clz){
|
protected ServiceEndpoint getServiceEndpoint(String serviceEndpointCategory, String serviceEndpointName, Class<?> clz){
|
||||||
SimpleQuery query = ICFactory.queryFor(ServiceEndpoint.class);
|
SimpleQuery query = ICFactory.queryFor(ServiceEndpoint.class);
|
||||||
query.addCondition(String.format("$resource/Profile/Category/text() eq '%s'", serviceEndpointCategory));
|
query.addCondition(String.format("$resource/Profile/Category/text() eq '%s'", serviceEndpointCategory));
|
||||||
query.addCondition(String.format("$resource/Profile/Name/text() eq '%s'", serviceEndpointName));
|
query.addCondition(String.format("$resource/Profile/Name/text() eq '%s'", serviceEndpointName));
|
||||||
|
@ -71,7 +70,7 @@ public class AccountingPersistenceConfiguration extends PersistenceBackendConfig
|
||||||
return StringEncrypter.getEncrypter().decrypt(encrypted);
|
return StringEncrypter.getEncrypter().decrypt(encrypted);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setValues(ServiceEndpoint serviceEndpoint, Class<? extends PersistenceBackend> clz) throws Exception{
|
protected void setValues(ServiceEndpoint serviceEndpoint, Class<?> clz) throws Exception{
|
||||||
Group<AccessPoint> accessPoints = serviceEndpoint.profile().accessPoints();
|
Group<AccessPoint> accessPoints = serviceEndpoint.profile().accessPoints();
|
||||||
for(AccessPoint accessPoint : accessPoints){
|
for(AccessPoint accessPoint : accessPoints){
|
||||||
if(accessPoint.name().compareTo(clz.getSimpleName())==0){
|
if(accessPoint.name().compareTo(clz.getSimpleName())==0){
|
||||||
|
|
|
@ -20,6 +20,7 @@ public class UsageRecordTest {
|
||||||
Assert.assertEquals(0, usageRecord.compareTo(ur));
|
Assert.assertEquals(0, usageRecord.compareTo(ur));
|
||||||
Assert.assertEquals(0, ur.compareTo(usageRecord));
|
Assert.assertEquals(0, ur.compareTo(usageRecord));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@Test
|
@Test
|
||||||
public void testCompareToEqualsObject() throws Exception {
|
public void testCompareToEqualsObject() throws Exception {
|
||||||
|
|
|
@ -8,10 +8,10 @@ import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.gcube.accounting.aggregator.RegexRulesAggregator;
|
||||||
import org.gcube.accounting.datamodel.UsageRecord;
|
import org.gcube.accounting.datamodel.UsageRecord;
|
||||||
import org.gcube.accounting.datamodel.aggregation.AggregatedServiceUsageRecord;
|
import org.gcube.accounting.datamodel.aggregation.AggregatedServiceUsageRecord;
|
||||||
import org.gcube.accounting.datamodel.basetypes.AbstractServiceUsageRecord;
|
import org.gcube.accounting.datamodel.basetypes.AbstractServiceUsageRecord;
|
||||||
import org.gcube.accounting.datamodel.validations.validators.CalledMethodRegexReplaceValidator;
|
|
||||||
import org.gcube.accounting.datamodel.validations.validators.RegexReplace;
|
import org.gcube.accounting.datamodel.validations.validators.RegexReplace;
|
||||||
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
|
import org.gcube.common.authorization.library.provider.SecurityTokenProvider;
|
||||||
import org.gcube.common.scope.api.ScopeProvider;
|
import org.gcube.common.scope.api.ScopeProvider;
|
||||||
|
@ -152,8 +152,9 @@ public class ServiceUsageRecordTest extends ScopedTest {
|
||||||
+ "\"operationResult\":\"SUCCESS\""
|
+ "\"operationResult\":\"SUCCESS\""
|
||||||
+"}";
|
+"}";
|
||||||
|
|
||||||
|
|
||||||
String goodReplace = "/delete/{collection-id}/{item-id}";
|
String goodReplace = "/delete/{collection-id}/{item-id}";
|
||||||
|
|
||||||
|
/*
|
||||||
RegexReplace regexReplace = new RegexReplace("Index", "FullTextIndexNode",
|
RegexReplace regexReplace = new RegexReplace("Index", "FullTextIndexNode",
|
||||||
"/delete/[^\\t\\n\\r\\f\\v]+/[^\\t\\n\\r\\f\\v]+", goodReplace);
|
"/delete/[^\\t\\n\\r\\f\\v]+/[^\\t\\n\\r\\f\\v]+", goodReplace);
|
||||||
CalledMethodRegexReplaceValidator.addRegexReplace(regexReplace);
|
CalledMethodRegexReplaceValidator.addRegexReplace(regexReplace);
|
||||||
|
@ -167,9 +168,18 @@ public class ServiceUsageRecordTest extends ScopedTest {
|
||||||
regexReplace = new RegexReplace("InformationSystem", "resource-registry",
|
regexReplace = new RegexReplace("InformationSystem", "resource-registry",
|
||||||
"/access/instance/EService/[^\\t\\n\\r\\f\\v]+", replace);
|
"/access/instance/EService/[^\\t\\n\\r\\f\\v]+", replace);
|
||||||
CalledMethodRegexReplaceValidator.addRegexReplace(regexReplace);
|
CalledMethodRegexReplaceValidator.addRegexReplace(regexReplace);
|
||||||
|
*/
|
||||||
|
|
||||||
UsageRecord usageRecord = DSMapper.unmarshal(AggregatedServiceUsageRecord.class, usageRecordString);
|
UsageRecord usageRecord = DSMapper.unmarshal(AggregatedServiceUsageRecord.class, usageRecordString);
|
||||||
logger.debug("{}", usageRecord);
|
logger.debug("{}", usageRecord);
|
||||||
|
|
||||||
|
RegexRulesAggregator regexRulesAggregator = RegexRulesAggregator.getInstance();
|
||||||
|
List<RegexReplace> list = regexRulesAggregator.getRegexReplacelist();
|
||||||
|
for(RegexReplace regexReplace : list) {
|
||||||
|
logger.debug("{} {} {} {}", regexReplace.getServiceClass(), regexReplace.getServiceName(), regexReplace.getRegex(), regexReplace.getReplace());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
AggregatedServiceUsageRecord aggregatedServiceUsageRecord = new AggregatedServiceUsageRecord(usageRecord.getResourceProperties());
|
AggregatedServiceUsageRecord aggregatedServiceUsageRecord = new AggregatedServiceUsageRecord(usageRecord.getResourceProperties());
|
||||||
logger.debug("{}", aggregatedServiceUsageRecord);
|
logger.debug("{}", aggregatedServiceUsageRecord);
|
||||||
|
|
||||||
|
@ -202,12 +212,13 @@ public class ServiceUsageRecordTest extends ScopedTest {
|
||||||
+ "\"operationResult\":\"SUCCESS\""
|
+ "\"operationResult\":\"SUCCESS\""
|
||||||
+ "}";
|
+ "}";
|
||||||
|
|
||||||
|
|
||||||
String replace = "/delete/{collection-id}/{item-id}";
|
String replace = "/delete/{collection-id}/{item-id}";
|
||||||
|
/*
|
||||||
RegexReplace regexReplace = new RegexReplace("Index", "FullTextIndexNode",
|
RegexReplace regexReplace = new RegexReplace("Index", "FullTextIndexNode",
|
||||||
"/delete/[^\\t\\n\\r\\f\\v]+/[^\\t\\n\\r\\f\\v]+", replace);
|
"/delete/[^\\t\\n\\r\\f\\v]+/[^\\t\\n\\r\\f\\v]+", replace);
|
||||||
CalledMethodRegexReplaceValidator.addRegexReplace(regexReplace);
|
CalledMethodRegexReplaceValidator.addRegexReplace(regexReplace);
|
||||||
|
*/
|
||||||
|
RegexRulesAggregator.getInstance();
|
||||||
|
|
||||||
UsageRecord usageRecord = DSMapper.unmarshal(AggregatedServiceUsageRecord.class, usageRecordString);
|
UsageRecord usageRecord = DSMapper.unmarshal(AggregatedServiceUsageRecord.class, usageRecordString);
|
||||||
logger.debug("{}", usageRecord);
|
logger.debug("{}", usageRecord);
|
||||||
|
@ -245,10 +256,12 @@ public class ServiceUsageRecordTest extends ScopedTest {
|
||||||
+ "}";
|
+ "}";
|
||||||
|
|
||||||
String replace = "GET /access/instance/Configuration/{id}";
|
String replace = "GET /access/instance/Configuration/{id}";
|
||||||
|
/*
|
||||||
RegexReplace regexReplace = new RegexReplace("InformationSystem", "resource-registry",
|
RegexReplace regexReplace = new RegexReplace("InformationSystem", "resource-registry",
|
||||||
"/access/instance/Configuration/[^\\t\\n\\r\\f\\v]+", replace);
|
"/access/instance/Configuration/[^\\t\\n\\r\\f\\v]+", replace);
|
||||||
CalledMethodRegexReplaceValidator.addRegexReplace(regexReplace);
|
CalledMethodRegexReplaceValidator.addRegexReplace(regexReplace);
|
||||||
|
*/
|
||||||
|
RegexRulesAggregator.getInstance();
|
||||||
|
|
||||||
UsageRecord usageRecord = DSMapper.unmarshal(AggregatedServiceUsageRecord.class, usageRecordString);
|
UsageRecord usageRecord = DSMapper.unmarshal(AggregatedServiceUsageRecord.class, usageRecordString);
|
||||||
logger.debug("{}", usageRecord);
|
logger.debug("{}", usageRecord);
|
||||||
|
@ -287,10 +300,12 @@ public class ServiceUsageRecordTest extends ScopedTest {
|
||||||
+ "}";
|
+ "}";
|
||||||
|
|
||||||
String replace = "GET /access/instance/EService/{id}";
|
String replace = "GET /access/instance/EService/{id}";
|
||||||
|
/*
|
||||||
RegexReplace regexReplace = new RegexReplace("InformationSystem", "resource-registry",
|
RegexReplace regexReplace = new RegexReplace("InformationSystem", "resource-registry",
|
||||||
"/access/instance/EService/[^\\t\\n\\r\\f\\v]+", replace);
|
"/access/instance/EService/[^\\t\\n\\r\\f\\v]+", replace);
|
||||||
CalledMethodRegexReplaceValidator.addRegexReplace(regexReplace);
|
CalledMethodRegexReplaceValidator.addRegexReplace(regexReplace);
|
||||||
|
*/
|
||||||
|
RegexRulesAggregator.getInstance();
|
||||||
|
|
||||||
UsageRecord usageRecord = DSMapper.unmarshal(AggregatedServiceUsageRecord.class, usageRecordString);
|
UsageRecord usageRecord = DSMapper.unmarshal(AggregatedServiceUsageRecord.class, usageRecordString);
|
||||||
logger.debug("{}", usageRecord);
|
logger.debug("{}", usageRecord);
|
||||||
|
|
Loading…
Reference in New Issue