Skip to content

Commit

Permalink
some refactoring adding properties collection for webapps
Browse files Browse the repository at this point in the history
  • Loading branch information
dhaval24 committed Mar 29, 2018
1 parent 1a0fa4e commit edef438
Show file tree
Hide file tree
Showing 7 changed files with 247 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,24 @@

import com.microsoft.applicationinsights.internal.logger.InternalLogger;
import com.microsoft.applicationinsights.internal.util.PropertyHelper;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable;
import org.apache.commons.lang3.exception.ExceptionUtils;

public class BaseDefaultHeartbeatPropertyProvider implements HeartBeatDefaultPayloadProviderInterface {

private final List<String> defaultFields;
private final Set<String> defaultFields;

private UUID uniqueProcessId;

private final String name = "Base";

public BaseDefaultHeartbeatPropertyProvider() {
defaultFields = new ArrayList<>();
defaultFields = new HashSet<>();
initializeDefaultFields(defaultFields);
}

Expand All @@ -27,18 +28,13 @@ public String getName() {
return this.name;
}

@Override
public boolean isKeyword(String keyword) {
return containsIgnoreCase(keyword, defaultFields);
}

@Override
public Callable<Boolean> setDefaultPayload(final List<String> disableFields,
final HeartBeatProviderInterface provider) {
return new Callable<Boolean>() {

volatile boolean hasSetValues = false;
volatile List<String> enabledProperties = except(defaultFields, disableFields);
volatile Set<String> enabledProperties = MiscUtils.except(defaultFields, disableFields);
@Override
public Boolean call() {
for (String fieldName : enabledProperties) {
Expand All @@ -60,6 +56,9 @@ public Boolean call() {
provider.addHeartBeatProperty(fieldName, getProcessSessionId(), true);
hasSetValues = true;
break;
default:
InternalLogger.INSTANCE.trace("Encountered unknown default property");
break;
}
}
catch (Exception e) {
Expand All @@ -69,59 +68,20 @@ public Boolean call() {
}
return hasSetValues;
}

private List<String> except(List<String> list1, List<String> list2) {
try {
if (list1 == null || list2 == null) throw new IllegalArgumentException("Input is null");
List<String> union = new ArrayList<>(list1);
union.addAll(list2);
List<String> intersection = new ArrayList<>(list1);
intersection.retainAll(list2);
union.removeAll(intersection);
return union;
}
catch (Exception e) {
InternalLogger.INSTANCE.warn("stack trace is %s", ExceptionUtils.getStackTrace(e));
}
finally{
if (list1 != null) return list1;
return list2;
}
}
};
}

private void initializeDefaultFields(List<String> defaultFields) {
private void initializeDefaultFields(Set<String> defaultFields) {

if (defaultFields == null) {
defaultFields = new ArrayList<>();
defaultFields = new HashSet<>();
}
defaultFields.add("jdkVersion");
defaultFields.add("sdk-version");
defaultFields.add("osType");
defaultFields.add("processSessionId");
}

private boolean containsIgnoreCase(String keyword, List<String> inputList) {
try {
if (keyword == null) throw new IllegalArgumentException("Keyword to compare is null");
if (inputList == null) throw new IllegalArgumentException("List to compare is null");
for (String key : inputList) {
if (key.equalsIgnoreCase(keyword)) return true;
}
return false;
}
catch (Exception e) {
InternalLogger.INSTANCE.warn("exception while comparision, stack trace is %s",
ExceptionUtils.getStackTrace(e));
}
finally{
//return true so we don't add property when comparison exception
return true;
}

}

private String getJdkVersion() {
return System.getProperty("java.version");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ public interface HeartBeatDefaultPayloadProviderInterface {

String getName();

boolean isKeyword(String keyword);

Callable<Boolean> setDefaultPayload(List<String> disableFields, HeartBeatProviderInterface provider);

}
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,35 @@
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class HeartBeatModule implements TelemetryModule {

private final HeartBeatProviderInterface heartBeatProviderInterface;

private Lock lock = new ReentrantLock();

private boolean isEnabled = false;

public HeartBeatModule(Map<String, String> properties) {

heartBeatProviderInterface = new HeartBeatProvider();

if (properties != null) {
for (Map.Entry<String, String> entry : properties.entrySet()) {
switch (entry.getKey()) {
case "HeartBeatInterval":
try {
setHeartBeatInterval(Long.valueOf(entry.getValue()));
break;
} catch (Exception e) {
//add log
}
case "isHeartBeatEnabled":
try {
setHeartBeatEnabled(Boolean.parseBoolean(entry.getValue()));
break;
}
catch (Exception e) {
//log
Expand All @@ -34,6 +44,7 @@ public HeartBeatModule(Map<String, String> properties) {
try {
List<String> excludedHeartBeatPropertiesProviderList = parseStringToList(entry.getValue());
setExcludedHeartBeatPropertiesProvider(excludedHeartBeatPropertiesProviderList);
break;
}
catch (Exception e) {
//log
Expand All @@ -42,15 +53,17 @@ public HeartBeatModule(Map<String, String> properties) {
try {
List<String> excludedHeartBeatPropertiesList = parseStringToList(entry.getValue());
setExcludedHeartBeatProperties(excludedHeartBeatPropertiesList);
break;
}
catch (Exception e) {
//log
}
default:
break;
}
}
}

heartBeatProviderInterface = new HeartBeatProvider();
}

public long getHeartBeatInterval() {
Expand Down Expand Up @@ -88,7 +101,18 @@ public void setHeartBeatEnabled(boolean heartBeatEnabled) {

@Override
public void initialize(TelemetryConfiguration configuration) {
InternalLogger.INSTANCE.info("heartbeat is enabled");
lock.lock();
try {
if (!isEnabled) {
this.heartBeatProviderInterface.initialize(configuration);
InternalLogger.INSTANCE.info("heartbeat is enabled");
}
isEnabled = true;
}
finally{
lock.lock();

This comment has been minimized.

Copy link
@gavlyukovskiy

gavlyukovskiy Mar 29, 2018

Contributor

@dhaval24 I think here should be unlock()

This comment has been minimized.

Copy link
@dhaval24

dhaval24 Mar 29, 2018

Author Contributor

@gavlyukovskiy thanks for catching. Yeah will correct it. Still pending to write test cases though :)

}

}

private List<String> parseStringToList(String value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@

import com.microsoft.applicationinsights.TelemetryClient;
import com.microsoft.applicationinsights.TelemetryConfiguration;
import com.microsoft.applicationinsights.agent.internal.common.StringUtils;
import com.microsoft.applicationinsights.internal.logger.InternalLogger;
import com.microsoft.applicationinsights.internal.shutdown.Stoppable;
import com.microsoft.applicationinsights.telemetry.MetricTelemetry;
import com.microsoft.applicationinsights.telemetry.Telemetry;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;

public class HeartBeatProvider implements HeartBeatProviderInterface, Stoppable {
Expand All @@ -37,6 +42,8 @@ public class HeartBeatProvider implements HeartBeatProviderInterface, Stoppable

private volatile boolean isEnabled;

private Lock lock = new ReentrantLock();

public HeartBeatProvider() {
this.interval = HeartBeatProviderInterface.DEFAULT_HEARTBEAT_INTERVAL;
this.heartbeatProperties = new ConcurrentHashMap<>();
Expand All @@ -61,11 +68,19 @@ public void initialize(TelemetryConfiguration configuration) {
this.telemetryClient = new TelemetryClient(configuration);
}

executorService.submit(HeartbeatDefaultPayload.populateDefaultPayload(getExcludedHeartBeatProperties(),
getExcludedHeartBeatPropertyProviders(), this));
// try {
executorService.submit(HeartbeatDefaultPayload.populateDefaultPayload(getExcludedHeartBeatProperties(),
getExcludedHeartBeatPropertyProviders(), this));
// }
// catch (InterruptedException e) {
//
// }
// catch (ExecutionException e) {
//
// }

if (isEnabled) {
scheduledExecutorService.schedule(heartBeatPulse(), interval, TimeUnit.SECONDS);
scheduledExecutorService.scheduleAtFixedRate(heartBeatPulse(), interval, interval, TimeUnit.SECONDS);
}

}
Expand All @@ -75,14 +90,15 @@ public boolean addHeartBeatProperty(String propertyName, String propertyValue,
boolean isHealthy) {

boolean isAdded= false;
if (!StringUtils.isNullOrEmpty(propertyName) && !HeartbeatDefaultPayload.isDefaultKeyword(propertyName)) {
if (!StringUtils.isEmpty(propertyName)) {
try {
if (!heartbeatProperties.containsKey(propertyName)) {
HeartBeatPropertyPayload payload = new HeartBeatPropertyPayload();
payload.setHealthy(isHealthy);
payload.setPayloadValue(propertyValue);
heartbeatProperties.put(propertyName, payload);
isAdded = true;
InternalLogger.INSTANCE.trace("added heartbeat property");
}
} catch (Exception e) {
InternalLogger.INSTANCE.warn("Failed to add the property %s value %s, stack trace is : %s," ,
Expand All @@ -100,7 +116,7 @@ public boolean setHeartBeatProperty(String propertyName, String propertyValue,
boolean isHealthy) {

boolean setResult = false;
if (!StringUtils.isNullOrEmpty(propertyName) && !HeartbeatDefaultPayload.isDefaultKeyword(propertyName)) {
if (!StringUtils.isEmpty(propertyName)) {
try {
if (heartbeatProperties.containsKey(propertyName)) {
HeartBeatPropertyPayload payload = new HeartBeatPropertyPayload();
Expand Down Expand Up @@ -182,11 +198,50 @@ public void stop(long timeout, TimeUnit timeUnit) {
}
}

private void send() {

lock.lock();
try {
MetricTelemetry telemetry = (MetricTelemetry)gatherData();
telemetry.getContext().getOperation().setSyntheticSource(HEARTBEAT_SYNTHETIC_METRIC_NAME);
telemetryClient.trackMetric(telemetry);
InternalLogger.INSTANCE.trace("sent heart beat");
}
finally{
lock.unlock();
}
}

private Telemetry gatherData() {

MetricTelemetry heartbeat = new MetricTelemetry(HEARTBEAT_SYNTHETIC_METRIC_NAME, 0.0);
Map<String, String> property = heartbeat.getProperties();
for (Map.Entry<String, HeartBeatPropertyPayload> entry : heartbeatProperties.entrySet()) {
property.put(entry.getKey(), entry.getValue().getPayloadValue());
double currentValue = heartbeat.getValue();
currentValue += entry.getValue().isHealthy() ? 0 : 1;
heartbeat.setValue(currentValue);
++heartbeatsSent;
}
return heartbeat;
}

private Runnable heartBeatPulse() {
return new Runnable() {
@Override
public void run() {

if (isEnabled) {

try {
send();
}
catch (Exception e) {
InternalLogger.INSTANCE.warn("Error occured while sending heartbeat");
}
}
else {
InternalLogger.INSTANCE.info("Heartbeat is disabled");
}
}
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,7 @@ public class HeartbeatDefaultPayload {

static {
defaultPayloadProviders.add(new BaseDefaultHeartbeatPropertyProvider());
}

public static boolean isDefaultKeyword(String keyword) {
for (HeartBeatDefaultPayloadProviderInterface payloadProvider : defaultPayloadProviders) {
if (payloadProvider.isKeyword(keyword)) {
return true;
}
}
return false;
defaultPayloadProviders.add(new WebAppsDefaultHeartbeatProvider());
}

public static Callable<Boolean> populateDefaultPayload(final List<String> disabledFields, final List<String>
Expand Down
Loading

0 comments on commit edef438

Please sign in to comment.