(Erik Knizat) REPO-2853 Move the Heartbeat class to Community and cleanup legacy code

* Move HeartBeat bean definitions to new hearbeat-context.xml
* Removed bean definition for the EnterpriseHBDataCollector.java
* Refactored code based on code review
* Added real data collection to CommunityHBDataCollector.java
This commit is contained in:
Ancuta Morarasu
2017-09-12 01:37:22 +03:00
parent 37464d825c
commit ca14f06392
6 changed files with 293 additions and 29 deletions

View File

@@ -25,35 +25,292 @@
*/
package org.alfresco.heartbeat;
import org.alfresco.repo.descriptor.DescriptorDAO;
import org.alfresco.repo.dictionary.CustomModelsInfo;
import org.alfresco.repo.transaction.RetryingTransactionHelper;
import org.alfresco.repo.usage.RepoUsageComponent;
import org.alfresco.service.cmr.admin.RepoUsage;
import org.alfresco.service.cmr.dictionary.CustomModelService;
import org.alfresco.service.cmr.repository.HBDataCollectorService;
import org.alfresco.service.cmr.security.AuthorityService;
import org.alfresco.service.cmr.security.AuthorityType;
import org.alfresco.service.descriptor.Descriptor;
import org.alfresco.service.license.LicenseException;
import org.alfresco.service.transaction.TransactionService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.extensions.surf.util.Base64;
import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.*;
public class CommunityHBDataCollector extends HBBaseDataCollector {
/** The logger. */
private static final Log logger = LogFactory.getLog(CommunityHBDataCollector.class);
/**
* The parameters that we expect to remain static throughout the lifetime of the repository. There is no need to
* continuously update these.
*/
private Map<String, Object> staticParameters;
public CommunityHBDataCollector (HBDataCollectorService dataCollectorService)
{
super(dataCollectorService);
/** The transaction service. */
private TransactionService transactionService;
/** DAO for current repository descriptor. */
private DescriptorDAO currentRepoDescriptorDAO;
/** DAO for current descriptor. */
private DescriptorDAO serverDescriptorDAO;
/** The authority service. */
private AuthorityService authorityService;
private RepoUsageComponent repoUsageComponent;
/** Provides information about custom models */
private CustomModelService customModelService;
public void setCurrentRepoDescriptorDAO(DescriptorDAO currentRepoDescriptorDAO) {
this.currentRepoDescriptorDAO = currentRepoDescriptorDAO;
}
public void setServerDescriptorDAO(DescriptorDAO serverDescriptorDAO) {
this.serverDescriptorDAO = serverDescriptorDAO;
}
public void setAuthorityService(AuthorityService authorityService) {
this.authorityService = authorityService;
}
public void setRepoUsageComponent(RepoUsageComponent repoUsageComponent) {
this.repoUsageComponent = repoUsageComponent;
}
public void setTransactionService(TransactionService transactionService) {
this.transactionService = transactionService;
}
public void setCustomModelService(CustomModelService customModelService) {
this.customModelService = customModelService;
}
@Override
public List<HBData> collectData()
{
String timeStamp = new SimpleDateFormat("YYYY-MM-dd'T'HH:mm:ss.sss'Z'").format(new Date());
List<HBData> collectedData = new LinkedList<>();
// Collect some data
HBData data = new HBData("Community_sys_id","Community_collector_id","Community_collector_v", timeStamp);
RetryingTransactionHelper.RetryingTransactionCallback<Void> initCallback = new RetryingTransactionHelper.RetryingTransactionCallback<Void>()
{
@Override
public Void execute() throws Throwable
{
lazyInit();
return null;
}
};
transactionService.getRetryingTransactionHelper().doInTransaction(initCallback, true);
return Arrays.asList(data);
// collect repository info data
logger.debug("Preparing repository info data...");
Map<String, Object> infoValues = new HashMap<String, Object>();
infoValues.put("repoName", this.staticParameters.get("repoName"));
infoValues.put("edition", this.staticParameters.get("edition"));
infoValues.put("versionMajor", this.staticParameters.get("versionMajor"));
infoValues.put("versionMinor", this.staticParameters.get("versionMinor"));
infoValues.put("schema", this.staticParameters.get("schema"));
HBData infoData = new HBData(
this.currentRepoDescriptorDAO.getDescriptor().getId(),
"acs.repository.info",
"1.0",
timeStamp,
infoValues);
collectedData.add(infoData);
// collect repository usage (system) data
logger.debug("Preparing repository usage (system) data...");
Runtime runtime = Runtime.getRuntime();
Map<String, Object> systemUsageValues = new HashMap<String, Object>();
systemUsageValues.put("memFree", runtime.freeMemory());
systemUsageValues.put("memMax", runtime.maxMemory());
systemUsageValues.put("memTotal", runtime.totalMemory());
HBData systemUsageData = new HBData(
this.currentRepoDescriptorDAO.getDescriptor().getId(),
"acs.repository.usage.system",
"1.0",
timeStamp,
systemUsageValues);
collectedData.add(systemUsageData);
// collect repository usage (model) data
logger.debug("Preparing repository usage (model) data...");
final CustomModelsInfo customModelsInfo = transactionService.getRetryingTransactionHelper().doInTransaction(
new RetryingTransactionHelper.RetryingTransactionCallback<CustomModelsInfo>()
{
public CustomModelsInfo execute()
{
return customModelService.getCustomModelsInfo();
}
}, true);
Map<String, Object> modelUsageValues = new HashMap<String, Object>();
modelUsageValues.put("numOfActiveModels", new Integer(customModelsInfo.getNumberOfActiveModels()));
modelUsageValues.put("numOfActiveTypes", new Integer(customModelsInfo.getNumberOfActiveTypes()));
modelUsageValues.put("numOfActiveAspects", new Integer(customModelsInfo.getNumberOfActiveAspects()));
HBData modelUsageData = new HBData(
this.currentRepoDescriptorDAO.getDescriptor().getId(),
"acs.repository.usage.model",
"1.0",
timeStamp,
modelUsageValues);
collectedData.add(modelUsageData);
// collect repository license data
logger.debug("Preparing repository license data...");
String licenseKey = transactionService.getRetryingTransactionHelper().doInTransaction(
new RetryingTransactionHelper.RetryingTransactionCallback<String>()
{
public String execute()
{
try
{
byte[] licenseKey = currentRepoDescriptorDAO.getLicenseKey();
return licenseKey == null ? null : org.springframework.extensions.surf.util.Base64.encodeBytes(licenseKey, Base64.DONT_BREAK_LINES);
}
catch (LicenseException e)
{
// Swallow Licence Exception Here
// Don't log error: It'll be reported later and the logging fails
return null;
}
}
}, true);
Map<String, Object> licenseValues = new HashMap<String, Object>();
if (licenseKey != null)
{
licenseValues.put("licenseKey", licenseKey);
}
Long licenseMaxUsers = repoUsageComponent.getRestrictions().getUsers();
if (licenseMaxUsers != null)
{
licenseValues.put("licenseMaxUsers", licenseMaxUsers);
}
HBData licenseData = new HBData(
this.currentRepoDescriptorDAO.getDescriptor().getId(),
"acs.repository.license",
"1.0",
timeStamp,
licenseValues);
collectedData.add(licenseData);
return collectedData;
}
/**
* Initializes static parameters on first invocation. Avoid doing it on construction due to bootstrap dependencies
* (e.g. patch service must have run)
*
* @throws GeneralSecurityException
* @throws IOException
*/
private synchronized void lazyInit() throws GeneralSecurityException, IOException
{
if (this.staticParameters == null)
{
this.staticParameters = new TreeMap<String, Object>();
// Load up the static parameters
final String ip = getLocalIps();
this.staticParameters.put("ip", ip);
final String uid;
final Descriptor currentRepoDescriptor = this.currentRepoDescriptorDAO.getDescriptor();
if (currentRepoDescriptor != null)
{
uid = currentRepoDescriptor.getId();
this.staticParameters.put("uid", uid);
}
else
{
uid = "Unknown";
}
final Descriptor serverDescriptor = this.serverDescriptorDAO.getDescriptor();
this.staticParameters.put("repoName", serverDescriptor.getName());
this.staticParameters.put("edition", serverDescriptor.getEdition());
this.staticParameters.put("versionMajor", serverDescriptor.getVersionMajor());
this.staticParameters.put("versionMinor", serverDescriptor.getVersionMinor());
this.staticParameters.put("schema", new Integer(serverDescriptor.getSchema()));
this.staticParameters.put("numUsers", new Integer(this.authorityService.getAllAuthoritiesInZone(
AuthorityService.ZONE_APP_DEFAULT, AuthorityType.USER).size()));
this.staticParameters.put("numGroups", new Integer(this.authorityService.getAllAuthoritiesInZone(
AuthorityService.ZONE_APP_DEFAULT, AuthorityType.GROUP).size()));
if(repoUsageComponent != null)
{
RepoUsage usage = repoUsageComponent.getUsage();
if (usage.getUsers() != null)
{
this.staticParameters.put("licenseUsers", new Long((usage.getUsers())));
}
}
}
}
/**
* Attempts to get all the local IP addresses of this machine in order to distinguish it from other nodes in the
* same network. The machine may use a static IP address in conjunction with a loopback adapter (e.g. to support
* Oracle on Windows), so the IP of the default network interface may not be enough to uniquely identify this
* machine.
*
* @return the local IP addresses, separated by the '/' character
*/
private String getLocalIps()
{
final StringBuilder ip = new StringBuilder(1024);
boolean first = true;
try
{
final Enumeration<NetworkInterface> i = NetworkInterface.getNetworkInterfaces();
while (i.hasMoreElements())
{
final NetworkInterface n = i.nextElement();
final Enumeration<InetAddress> j = n.getInetAddresses();
while (j.hasMoreElements())
{
InetAddress a = j.nextElement();
if (a.isLoopbackAddress())
{
continue;
}
if (first)
{
first = false;
}
else
{
ip.append('/');
}
ip.append(a.getHostAddress());
}
}
}
catch (final Exception e)
{
// Ignore
}
return first ? "127.0.0.1" : ip.toString();
}
}

View File

@@ -33,17 +33,12 @@ public abstract class HBBaseDataCollector
{
private HBDataCollectorService hbDataCollectorService;
public HBBaseDataCollector( HBDataCollectorService dataCollectorService ) {
this.hbDataCollectorService = dataCollectorService;
this.register(); // I'v moved the registering here assuming every collector will do the same?
}
public void register()
{
hbDataCollectorService.registerCollector(this);
}
public void setHBDataCollectorService(HBDataCollectorService hbDataCollectorService)
public void setHbDataCollectorService(HBDataCollectorService hbDataCollectorService)
{
this.hbDataCollectorService = hbDataCollectorService;
}

View File

@@ -307,7 +307,6 @@ public class DescriptorServiceImpl extends AbstractLifecycleBean
}
// Load heart-beat special service (even if disabled at the moment)
//heartBeat = constructSpecialService("org.alfresco.enterprise.heartbeat.HeartBeat");
heartBeat = constructSpecialService("org.alfresco.heartbeat.HeartBeat");
// Now listen for future license changes

View File

@@ -52,4 +52,5 @@
<import resource="classpath*:alfresco/dbscripts/*-context.xml" />
<import resource="classpath*:alfresco/enterprise/authorization-context.xml" />
<import resource="classpath*:alfresco/enterprise/enterprise-usage-services-context.xml" />
<import resource="classpath:alfresco/heartbeat-context.xml"/>
</beans>

View File

@@ -287,19 +287,6 @@
<property name="repoUsageComponent" ref="repoUsageComponent"/>
</bean>
<!-- HeartBeat data collector service -->
<bean id="hbDataCollectorService" class="org.alfresco.heartbeat.HBDataCollectorServiceImpl">
</bean>
<!-- HeartBeat community data collector -->
<bean id="hbCommunityDataCollector" class="org.alfresco.heartbeat.CommunityHBDataCollector" depends-on="hbDataCollectorService">
<constructor-arg ref = "hbDataCollectorService"/>
</bean>
<!-- Bootstrap MT (multi-tenancy) if applicable -->
<bean id="multiTenantBootstrap" class="org.alfresco.repo.tenant.MultiTenantBootstrap" >
<property name="tenantAdminService" ref="tenantAdminService"/>

View File

@@ -0,0 +1,25 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>
<beans>
<!-- HeartBeat data collector service -->
<bean id="hbDataCollectorService" class="org.alfresco.heartbeat.HBDataCollectorServiceImpl">
</bean>
<!-- HeartBeat abstract data collector -->
<bean id="hbBaseDataCollector" class="org.alfresco.heartbeat.HBBaseDataCollector" abstract="true">
<property name="hbDataCollectorService" ref="hbDataCollectorService"/>
</bean>
<!-- HeartBeat community data collector -->
<bean id="hbCommunityDataCollector" class="org.alfresco.heartbeat.CommunityHBDataCollector" parent="hbBaseDataCollector" init-method="register">
<property name="currentRepoDescriptorDAO" ref="currentRepoDescriptorDAO"/>
<property name="serverDescriptorDAO" ref="serverDescriptorDAO"/>
<property name="authorityService" ref="authorityService"/>
<property name="repoUsageComponent" ref="repoUsageComponent"/>
<property name="transactionService" ref="transactionService"/>
<property name="customModelService" ref="customModelService"/>
</bean>
</beans>