Alachisoft.NCache.Sessions.CounterSession Maven / Gradle / Ivy
The newest version!
package Alachisoft.NCache.Sessions;
import Alachisoft.NCache.Common.DataStructures.SlidingIndex;
import Alachisoft.NCache.Common.Logger.ILogger;
import Alachisoft.NCache.DataModel.Counter;
import Alachisoft.NCache.DataModel.CounterData;
import Alachisoft.NCache.DataModel.MetricsDBSession;
import Alachisoft.NCache.DataModel.PublisherVersion;
import Alachisoft.NCache.MetricsAgents.MetricsAgentManager;
import com.alachisoft.ncache.common.caching.statistics.monitoring.CounterIDMap;
import com.alachisoft.ncache.common.monitoring.*;
import tangible.RefObject;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;
import java.util.function.Function;
public abstract class CounterSession {
// Private attributes
private MetricsDBSession metric;
protected long refTime = 0;
private int inMemoryInterval;
protected ILogger logger;
protected MetricsAgentManager metricsAgentManager;
// Protected attributes
protected boolean countersMetaPersisted;
protected SlidingIndex> countersIndex = null;
protected Map countersIDMap = new HashMap<>();
protected PublisherVersion publisherVersion = null;
protected long counterRefTime;
protected List counters = new ArrayList<>();
// Public properties
public MetricsDBSession getMetric() {
return metric;
}
public CounterIDMap getCounterIDMapCommon() {
return counterIDMapCommon;
}
public void setCounterIDMapCommon(CounterIDMap counterIDMapCommon) {
this.counterIDMapCommon = counterIDMapCommon;
}
private CounterIDMap counterIDMapCommon = new CounterIDMap();
public List countersMetadata = new ArrayList<>();
// Initialization
public CounterSession(String cacheConfigId) {
if (cacheConfigId == null || cacheConfigId.isEmpty())
sessionGuid = UUID.randomUUID().toString();
else
sessionGuid = cacheConfigId;
}
public void initializeCounters(int inMemoryInterval, ILogger logger, MetricsAgentManager metricsAgentManager) {
this.inMemoryInterval = inMemoryInterval;
countersIndex = new SlidingIndex<>(inMemoryInterval);
this.logger = logger;
this.metricsAgentManager = metricsAgentManager;
}
// Persistence
public void persistCounters() {
try {
synchronized (countersIndex) {
Iterator> iterator = countersIndex.GetCurrentData(new RefObject(new Long(0)), false);
while (iterator.hasNext()) {
MutableKeyValuePair entry = iterator.next();
if (entry.getValue()) {
CounterData counter = entry.getKey();
if (counterIDMapCommon != null && counter.getCounterMetadata() != null) {
String name = counterIDMapCommon.getCounterName(counter.getCounterId());
String counterName = getCounterNameWithLiteral(name, counter.getCounterMetadata().getCategory());
if (countersMetaPersisted) {
String counterInstanceName = getCounterInstanceName(counterName);
publishMetric(counterInstanceName, counter);
}
}
entry.setValue(false);
}
}
}
} catch (Exception e) {
logger.Error("MetricServer", e.toString());
}
}
public void createCounters() {
try {
synchronized (countersMetadata) {
if (!countersMetaPersisted) {
Iterator iterator = countersMetadata.iterator();
while (iterator.hasNext()) {
Counter current = iterator.next();
String counterName = getCounterNameWithLiteral(current.getName(), current.getCategory());
String counterInstanceName = getCounterInstanceName(counterName);
metricsAgentManager.initializeCounterInstance(counterInstanceName, counterName, current);
counters.add(counterInstanceName);
}
countersMetaPersisted = true;
}
}
} catch (Exception e) {
logger.Error("MetricServer", e.toString());
}
}
public void publishMetric(String instanceName, CounterData counterData) {
// Your implementation goes here
}
protected abstract List getParamsList();
/**
* This method receives counters metadata from the cache, client, or bridge and stores it in the session.
* Later, persistence is invoked to persist data to the database.
*
* @param counterMeta The CounterMetadataCollection to store.
*/
public void storeCountersMetadata(CounterMetadataCollection counterMeta) {
if (countersMetadata.isEmpty()) {
try {
synchronized (countersMetadata) {
getCounterIDMapCommon().assignAndAddCounters(counterMeta.getCounters());
if (counterMeta.getCategory() == Publisher.NCache) {
populateCacheCounters(counterMeta);
}
Iterator iterator = counterMeta.getCounters().iterator();
while (iterator.hasNext()) {
CounterMetadata current = iterator.next();
Counter counter = new Counter();
counter.setCategory(counterMeta.getCategory());
counter.setDescription(current.getDescription());
counter.setName(current.getName());
counter.setType(current.getType());
countersMetadata.add(counter);
}
}
} catch (Exception e) {
logger.Error("MetricServer", e.toString());
}
}
}
/**
* This method receives counters data from the cache, client, or bridge and stores it in the session.
* Later, persistence is invoked to persist data to the database.
*
* @param sessionId The session ID.
* @param counterData The CounterDataCollection to store.
*/
public void storeCountersData(String sessionId, CounterDataCollection counterData) {
List counterDatas = new ArrayList<>();
for (int iterator = 0; iterator < counterData.getValues().size(); iterator++) {
IntervalCounterDataCollection intervalData = counterData.getValues().get(iterator);
Date interval = intervalData.getTimestamp();
Iterator> iteratorMap = intervalData.getValues().entrySet().iterator();
while (iteratorMap.hasNext()) {
Map.Entry entry = iteratorMap.next();
short id = entry.getKey();
double value = entry.getValue();
CounterData data = new CounterData();
data.setData(value);
data.setCounterId(id);
data.setTimestamp(interval);
populateCounterMeta(data);
counterDatas.add(data);
}
// counterDatas contains the new counters data for the interval received
// Now accumulate these counters
addCountersDataToIndex(counterDatas, true);
counterDatas.clear();
}
}
public void populateCounterMeta(CounterData counterData) {
for (Counter item : countersMetadata) {
if (item.getName().equals(getCounterIDMapCommon().getCounterName(counterData.getCounterId()))) {
counterData.setCounterMetadata(item);
break;
}
}
}
public Map>> getInMemoryData(Collection counterIds, Date start, int limit) {
List inMemory = new ArrayList<>();
if (isInMemoryDataRequired(start, counterIds, inMemory)) {
List result = new ArrayList<>(inMemory);
List counters = getCountersMetadata();
Function groupByKeySelector = CounterData::getTimestamp;
Function> toDictionaryCriteria =
counterData -> {
String counterName = counters.stream()
.filter(meta -> meta.getId() == counterData.getCounterId())
.map(Counter::getName)
.findFirst()
.orElse(null);
return new AbstractMap.SimpleEntry<>(counterName, counterData.getData());
};
Map>> res =
result.stream()
.collect(Collectors.groupingBy(groupByKeySelector,
Collectors.mapping(toDictionaryCriteria, Collectors.toList())));
return res;
}
return null;
}
public List getCountersMetadata() {
if (countersMetadata == null || countersMetadata.isEmpty()) {
initializeCounterMetadata(publisherVersion.getVersion());
}
return countersMetadata;
}
protected void initializeCounterMetadata(String version) {
// Your implementation goes here
}
protected void initializeCounterMetadata(Collection countersMeta, Publisher publisher, String version) {
synchronized (countersMetadata) {
countersMetadata.clear();
countersIDMap.clear();
getCounterIDMapCommon().Clear();
countersMetadata.addAll(countersMeta);
List metadata = countersMetadata.stream()
.map(s -> {
CounterMetadata counter = new CounterMetadata();
counter.setCategory(s.getCategory());
counter.setDescription(s.getDescription());
counter.setName(s.getName());
counter.setType(s.getType());
return counter;
}).collect(Collectors.toList());
getCounterIDMapCommon().assignAndAddCounters(metadata);
Iterator enumerator = countersMeta.iterator();
while (enumerator.hasNext()) {
Counter current = enumerator.next();
short key = getCounterIDMapCommon().getCounterID(current.getName());
short value = current.getId();
if (!countersIDMap.containsKey(key)) {
countersIDMap.put(key, value);
}
}
}
}
protected void addCountersDataToIndex(List counterDatas, boolean persist) {
synchronized (countersIndex) {
for (int iterator = 0; iterator < counterDatas.size(); iterator++) {
MutableKeyValuePair entry = new MutableKeyValuePair<>();
entry.setKey(counterDatas.get(iterator));
entry.setValue(persist);
countersIndex.AddToIndex(entry);
}
}
}
private boolean isInMemoryDataRequired(Date start, Collection counterIds, List result) {
result = null;
synchronized (countersIndex) {
Instant currentTime = Instant.now();
Instant thresholdTime = currentTime.minusSeconds(inMemoryInterval);
if (thresholdTime.isAfter(Instant.now())) {
Iterator> counters = countersIndex.GetCurrentData();
result = new ArrayList<>();
while (counters.hasNext()) {
MutableKeyValuePair entry = counters.next();
if (entry.getValue()) {
CounterData data = entry.getKey();
if (start != null) {
if (data.getTimestamp().compareTo(start) >= 0 && counterIds.contains(data.getCounterId())) {
result.add(entry.getKey());
}
} else {
if (counterIds.contains(data.getCounterId())) {
result.add(entry.getKey());
}
}
}
}
if (result != null && result.size() > 0) {
return true;
}
}
}
return false;
}
private CounterMetadataCollection populateCacheCounters(CounterMetadataCollection counterMeta) {
counterMeta.getCounters().add(createCounter("configured_servers_count", "Total number of configured servers", CounterType.NumberOfItemCounter, Publisher.NCache));
counterMeta.getCounters().add(createCounter("total_cache_size", "Total size of the cache", CounterType.NumberOfItemCounter, Publisher.NCache));
return counterMeta;
}
private CounterMetadata createCounter(String counterName, String description, CounterType type, Publisher publisher) {
CounterMetadata counter = new CounterMetadata();
counter.setName(counterName);
counter.setDescription(description);
counter.setType(type);
counter.setCategory(publisher);
return counter;
}
private String getCounterLiteral(Publisher category, String name) {
String literal = "ncache_";
switch (category) {
case Bridge:
if (!name.toLowerCase().startsWith("bridge"))
literal += "bridge_";
break;
case BridgedCache:
literal += "bridgedcache_";
break;
case NCacheClient:
literal += "client_";
break;
case NCachePersistence:
literal = "persistence_";
break;
case NCacheLucene:
literal = "lucene_";
break;
case NCache:
if (name.toLowerCase().startsWith("bridge"))
literal += "caching_";
break;
}
return literal;
}
public String getCounterNameWithLiteral(String name, Publisher category) {
if (!name.contains(" ")) {
name = String.join(" ", name.chars().mapToObj(c -> Character.isUpperCase(c) ? " " + (char) c : String.valueOf((char) c)).toArray(String[]::new)).trim();
}
String literal = getCounterLiteral(category, name);
String counterName = literal + name
.replace(" ", "_")
.replace("#", "")
.replace("/", "_per_")
.replace("(", "")
.replace(")", "")
.replace("-", "_")
.replace("%", "percent")
.toLowerCase();
counterName = counterName.contains("__") ? counterName.replace("__", "_") : counterName;
return counterName;
}
protected String getCounterInstanceName(String counterName) {
return String.format("%s:%s", sessionGuid, counterName);
}
protected String sessionGuid = "";
// Dispose
public void dispose() {
synchronized (counters) {
for (String counterInstance : counters) {
metricsAgentManager.disposeCounterInstance(counterInstance, getParamsList());
}
}
}
}