Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

### Enhancements

* Add Java agent support for ServiceProfiler targeted collection plans by cloud role or
role-qualified instance

* Add continuous profiling (`enableContinuousProfiling`, `continuousProfilingMaxAgeSeconds`) which
keeps a single JFR recording running in a circular buffer so profile requests dump the most recent
window of data immediately
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.google.auto.value.AutoValue;
import java.time.Instant;
import java.util.List;
import javax.annotation.Nullable;

/** Contains the overall configuration of the entire alerting subsystem. */
@AutoValue
Expand All @@ -17,24 +18,46 @@ public static AlertingConfiguration create(
DefaultConfiguration defaultConfiguration,
CollectionPlanConfiguration collectionPlanConfiguration,
List<AlertConfiguration> requestAlertConfiguration) {
return create(
cpuAlert,
memoryAlert,
defaultConfiguration,
collectionPlanConfiguration,
requestAlertConfiguration,
null);
}

public static AlertingConfiguration create(
AlertConfiguration cpuAlert,
AlertConfiguration memoryAlert,
DefaultConfiguration defaultConfiguration,
CollectionPlanConfiguration collectionPlanConfiguration,
List<AlertConfiguration> requestAlertConfiguration,
@Nullable TargetedCollectionPlanConfiguration targetedCollectionPlanConfiguration) {
return new AutoValue_AlertingConfiguration(
cpuAlert,
memoryAlert,
defaultConfiguration,
collectionPlanConfiguration,
requestAlertConfiguration);
requestAlertConfiguration,
targetedCollectionPlanConfiguration);
}

public boolean hasAnEnabledTrigger() {
public boolean hasAnEnabledTrigger(
@Nullable String roleName, @Nullable String roleInstance, Instant now) {
CollectionPlanConfiguration collectionPlan = getCollectionPlanConfiguration();
boolean manualProfileEnabled =
getCollectionPlanConfiguration().isSingle()
&& getCollectionPlanConfiguration().getMode()
== CollectionPlanConfiguration.EngineMode.immediate
&& Instant.now().isBefore(getCollectionPlanConfiguration().getExpiration());

return getCpuAlert().isEnabled() || manualProfileEnabled || getMemoryAlert().isEnabled();
// Sampling not enabled yet
// getDefaultConfiguration().getSamplingEnabled();
collectionPlan.isSingle()
&& collectionPlan.getMode() == CollectionPlanConfiguration.EngineMode.immediate
&& now.isBefore(collectionPlan.getExpiration());

TargetedCollectionPlanConfiguration targetedPlan = getTargetedCollectionPlanConfiguration();
boolean onDemandProfileEnabled =
targetedPlan == null
? manualProfileEnabled
: targetedPlan.isActionable(roleName, roleInstance, now);

return getCpuAlert().isEnabled() || onDemandProfileEnabled || getMemoryAlert().isEnabled();
}

public boolean hasRequestAlertConfiguration() {
Expand All @@ -55,4 +78,7 @@ public boolean hasRequestAlertConfiguration() {

// Alert configuration for SPAN telemetry
public abstract List<AlertConfiguration> getRequestAlertConfiguration();

@Nullable
public abstract TargetedCollectionPlanConfiguration getTargetedCollectionPlanConfiguration();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.microsoft.applicationinsights.alerting.config;

import com.google.auto.value.AutoValue;
import javax.annotation.Nullable;

@AutoValue
public abstract class AlertingSubsystemConfiguration {

public static AlertingSubsystemConfiguration create(
@Nullable String roleName,
@Nullable String roleInstance,
AlertingProfileFileTriggerConfiguration profileFileTriggerConfiguration) {
return new AutoValue_AlertingSubsystemConfiguration(
roleName, roleInstance, profileFileTriggerConfiguration);
}

@Nullable
public abstract String getRoleName();

@Nullable
public abstract String getRoleInstance();

public abstract AlertingProfileFileTriggerConfiguration getProfileFileTriggerConfiguration();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.microsoft.applicationinsights.alerting.config;

import com.google.auto.value.AutoValue;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;

@AutoValue
public abstract class TargetedCollectionPlanConfiguration {

public static TargetedCollectionPlanConfiguration create(
@Nullable List<String> roles,
@Nullable List<TargetedInstanceConfiguration> instances,
int immediateProfilingDurationSeconds,
@Nullable Instant expiration,
@Nullable String settingsMoniker) {
return new AutoValue_TargetedCollectionPlanConfiguration(
immutableCopy(roles),
immutableCopy(instances),
immediateProfilingDurationSeconds,
expiration,
settingsMoniker);
}

@Nullable
public abstract List<String> getRoles();

@Nullable
public abstract List<TargetedInstanceConfiguration> getInstances();

public abstract int getImmediateProfilingDurationSeconds();

@Nullable
public abstract Instant getExpiration();

@Nullable
public abstract String getSettingsMoniker();

public boolean isValid() {
List<String> roles = getRoles();
List<TargetedInstanceConfiguration> instances = getInstances();
if ((roles == null) == (instances == null)
|| getImmediateProfilingDurationSeconds() < 1
|| getImmediateProfilingDurationSeconds() > 360
|| getExpiration() == null
|| isBlank(getSettingsMoniker())) {
return false;
}

if (roles != null) {
if (roles.isEmpty()) {
return false;
}
for (String role : roles) {
if (isBlank(role)) {
return false;
}
}
return true;
}

if (instances.isEmpty()) {
return false;
}
for (TargetedInstanceConfiguration instance : instances) {
if (instance == null || isBlank(instance.getRole()) || isBlank(instance.getName())) {
return false;
}
}
return true;
}

public boolean isSelected(@Nullable String roleName, @Nullable String roleInstance) {
if (!isValid() || isBlank(roleName)) {
return false;
}

List<String> roles = getRoles();
if (roles != null) {
for (String role : roles) {
if (equalsNormalized(role, roleName)) {
return true;
}
}
return false;
}

List<TargetedInstanceConfiguration> instances = getInstances();
if (isBlank(roleInstance) || instances == null) {
return false;
}
for (TargetedInstanceConfiguration instance : instances) {
if (instance != null
&& equalsNormalized(instance.getRole(), roleName)
&& equalsNormalized(instance.getName(), roleInstance)) {
return true;
}
}
return false;
}

public boolean isActionable(
@Nullable String roleName, @Nullable String roleInstance, Instant now) {
Instant expiration = getExpiration();
return expiration != null && now.isBefore(expiration) && isSelected(roleName, roleInstance);
}

@Nullable
private static <T> List<T> immutableCopy(@Nullable List<T> values) {
return values == null ? null : Collections.unmodifiableList(new ArrayList<>(values));
}

private static boolean equalsNormalized(@Nullable String left, @Nullable String right) {
return left != null && right != null && left.trim().equalsIgnoreCase(right.trim());
}

private static boolean isBlank(@Nullable String value) {
return value == null || value.trim().isEmpty();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.microsoft.applicationinsights.alerting.config;

import com.google.auto.value.AutoValue;
import javax.annotation.Nullable;

@AutoValue
public abstract class TargetedInstanceConfiguration {

public static TargetedInstanceConfiguration create(@Nullable String role, @Nullable String name) {
return new AutoValue_TargetedInstanceConfiguration(role, name);
}

@Nullable
public abstract String getRole();

@Nullable
public abstract String getName();
}
Loading