Skip to content

Commit e8d567a

Browse files
johnoliverCopilot
andcommitted
Add targeted profiling support
Add role- and instance-targeted profile collection, backward-compatible Service Profiler protocol negotiation, and settings moniker correlation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent d73069f commit e8d567a

32 files changed

Lines changed: 1910 additions & 80 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@ build/
1111
# VSCode
1212
/.vscode/
1313
bin/
14+
15+
/docs/adr/targettedProfiling/targettedProfiling_goal.md

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
### Enhancements
66

7+
* Add Java agent support for ServiceProfiler targeted collection plans by cloud role or
8+
role-qualified instance
9+
710
* Add continuous profiling (`enableContinuousProfiling`, `continuousProfilingMaxAgeSeconds`) which
811
keeps a single JFR recording running in a circular buffer so profile requests dump the most recent
912
window of data immediately

agent/agent-profiler/agent-alerting-api/src/main/java/com/microsoft/applicationinsights/alerting/alert/AlertBreach.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.microsoft.applicationinsights.alerting.config.AlertMetricType;
1111
import java.io.IOException;
1212
import java.util.UUID;
13+
import javax.annotation.Nullable;
1314

1415
/** Represents a breach of an alert threshold. */
1516
@AutoValue
@@ -68,6 +69,9 @@ public AlertBreach setProfileId(String profileId) {
6869
return this;
6970
}
7071

72+
@Nullable
73+
public abstract String getSettingsMoniker();
74+
7175
public abstract Builder toBuilder();
7276

7377
public static AlertBreach.Builder builder() {
@@ -88,6 +92,9 @@ public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
8892
jsonWriter.writeDoubleField("cpuMetric", cpuMetric);
8993
jsonWriter.writeDoubleField("memoryUsage", memoryUsage);
9094
jsonWriter.writeStringField("profileId", profileId);
95+
if (getSettingsMoniker() != null) {
96+
jsonWriter.writeStringField("settingsMoniker", getSettingsMoniker());
97+
}
9198
jsonWriter.writeEndObject();
9299
return jsonWriter;
93100
}
@@ -113,6 +120,8 @@ public abstract static class Builder implements JsonSerializable<Builder> {
113120

114121
public abstract Builder setProfileId(String profileId);
115122

123+
public abstract Builder setSettingsMoniker(@Nullable String settingsMoniker);
124+
116125
public abstract AlertBreach build();
117126

118127
@Override

agent/agent-profiler/agent-alerting-api/src/main/java/com/microsoft/applicationinsights/alerting/config/AlertingConfiguration.java

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.google.auto.value.AutoValue;
77
import java.time.Instant;
88
import java.util.List;
9+
import javax.annotation.Nullable;
910

1011
/** Contains the overall configuration of the entire alerting subsystem. */
1112
@AutoValue
@@ -17,24 +18,46 @@ public static AlertingConfiguration create(
1718
DefaultConfiguration defaultConfiguration,
1819
CollectionPlanConfiguration collectionPlanConfiguration,
1920
List<AlertConfiguration> requestAlertConfiguration) {
21+
return create(
22+
cpuAlert,
23+
memoryAlert,
24+
defaultConfiguration,
25+
collectionPlanConfiguration,
26+
requestAlertConfiguration,
27+
null);
28+
}
29+
30+
public static AlertingConfiguration create(
31+
AlertConfiguration cpuAlert,
32+
AlertConfiguration memoryAlert,
33+
DefaultConfiguration defaultConfiguration,
34+
CollectionPlanConfiguration collectionPlanConfiguration,
35+
List<AlertConfiguration> requestAlertConfiguration,
36+
@Nullable TargetedCollectionPlanConfiguration targetedCollectionPlanConfiguration) {
2037
return new AutoValue_AlertingConfiguration(
2138
cpuAlert,
2239
memoryAlert,
2340
defaultConfiguration,
2441
collectionPlanConfiguration,
25-
requestAlertConfiguration);
42+
requestAlertConfiguration,
43+
targetedCollectionPlanConfiguration);
2644
}
2745

28-
public boolean hasAnEnabledTrigger() {
46+
public boolean hasAnEnabledTrigger(
47+
@Nullable String roleName, @Nullable String roleInstance, Instant now) {
48+
CollectionPlanConfiguration collectionPlan = getCollectionPlanConfiguration();
2949
boolean manualProfileEnabled =
30-
getCollectionPlanConfiguration().isSingle()
31-
&& getCollectionPlanConfiguration().getMode()
32-
== CollectionPlanConfiguration.EngineMode.immediate
33-
&& Instant.now().isBefore(getCollectionPlanConfiguration().getExpiration());
34-
35-
return getCpuAlert().isEnabled() || manualProfileEnabled || getMemoryAlert().isEnabled();
36-
// Sampling not enabled yet
37-
// getDefaultConfiguration().getSamplingEnabled();
50+
collectionPlan.isSingle()
51+
&& collectionPlan.getMode() == CollectionPlanConfiguration.EngineMode.immediate
52+
&& now.isBefore(collectionPlan.getExpiration());
53+
54+
TargetedCollectionPlanConfiguration targetedPlan = getTargetedCollectionPlanConfiguration();
55+
boolean onDemandProfileEnabled =
56+
targetedPlan == null
57+
? manualProfileEnabled
58+
: targetedPlan.isActionable(roleName, roleInstance, now);
59+
60+
return getCpuAlert().isEnabled() || onDemandProfileEnabled || getMemoryAlert().isEnabled();
3861
}
3962

4063
public boolean hasRequestAlertConfiguration() {
@@ -55,4 +78,7 @@ public boolean hasRequestAlertConfiguration() {
5578

5679
// Alert configuration for SPAN telemetry
5780
public abstract List<AlertConfiguration> getRequestAlertConfiguration();
81+
82+
@Nullable
83+
public abstract TargetedCollectionPlanConfiguration getTargetedCollectionPlanConfiguration();
5884
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.microsoft.applicationinsights.alerting.config;
5+
6+
import com.google.auto.value.AutoValue;
7+
import javax.annotation.Nullable;
8+
9+
@AutoValue
10+
public abstract class AlertingSubsystemConfiguration {
11+
12+
public static AlertingSubsystemConfiguration create(
13+
@Nullable String roleName,
14+
@Nullable String roleInstance,
15+
AlertingProfileFileTriggerConfiguration profileFileTriggerConfiguration) {
16+
return new AutoValue_AlertingSubsystemConfiguration(
17+
roleName, roleInstance, profileFileTriggerConfiguration);
18+
}
19+
20+
@Nullable
21+
public abstract String getRoleName();
22+
23+
@Nullable
24+
public abstract String getRoleInstance();
25+
26+
public abstract AlertingProfileFileTriggerConfiguration getProfileFileTriggerConfiguration();
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.microsoft.applicationinsights.alerting.config;
5+
6+
import com.google.auto.value.AutoValue;
7+
import java.time.Instant;
8+
import java.util.ArrayList;
9+
import java.util.Collections;
10+
import java.util.List;
11+
import javax.annotation.Nullable;
12+
13+
@AutoValue
14+
public abstract class TargetedCollectionPlanConfiguration {
15+
16+
public static TargetedCollectionPlanConfiguration create(
17+
@Nullable List<String> roles,
18+
@Nullable List<TargetedInstanceConfiguration> instances,
19+
int immediateProfilingDurationSeconds,
20+
@Nullable Instant expiration,
21+
@Nullable String settingsMoniker) {
22+
return new AutoValue_TargetedCollectionPlanConfiguration(
23+
immutableCopy(roles),
24+
immutableCopy(instances),
25+
immediateProfilingDurationSeconds,
26+
expiration,
27+
settingsMoniker);
28+
}
29+
30+
@Nullable
31+
public abstract List<String> getRoles();
32+
33+
@Nullable
34+
public abstract List<TargetedInstanceConfiguration> getInstances();
35+
36+
public abstract int getImmediateProfilingDurationSeconds();
37+
38+
@Nullable
39+
public abstract Instant getExpiration();
40+
41+
@Nullable
42+
public abstract String getSettingsMoniker();
43+
44+
public boolean isValid() {
45+
List<String> roles = getRoles();
46+
List<TargetedInstanceConfiguration> instances = getInstances();
47+
if ((roles == null) == (instances == null)
48+
|| getImmediateProfilingDurationSeconds() < 1
49+
|| getImmediateProfilingDurationSeconds() > 360
50+
|| getExpiration() == null
51+
|| isBlank(getSettingsMoniker())) {
52+
return false;
53+
}
54+
55+
if (roles != null) {
56+
if (roles.isEmpty()) {
57+
return false;
58+
}
59+
for (String role : roles) {
60+
if (isBlank(role)) {
61+
return false;
62+
}
63+
}
64+
return true;
65+
}
66+
67+
if (instances.isEmpty()) {
68+
return false;
69+
}
70+
for (TargetedInstanceConfiguration instance : instances) {
71+
if (instance == null || isBlank(instance.getRole()) || isBlank(instance.getName())) {
72+
return false;
73+
}
74+
}
75+
return true;
76+
}
77+
78+
public boolean isSelected(@Nullable String roleName, @Nullable String roleInstance) {
79+
if (!isValid() || isBlank(roleName)) {
80+
return false;
81+
}
82+
83+
List<String> roles = getRoles();
84+
if (roles != null) {
85+
for (String role : roles) {
86+
if (equalsNormalized(role, roleName)) {
87+
return true;
88+
}
89+
}
90+
return false;
91+
}
92+
93+
List<TargetedInstanceConfiguration> instances = getInstances();
94+
if (isBlank(roleInstance) || instances == null) {
95+
return false;
96+
}
97+
for (TargetedInstanceConfiguration instance : instances) {
98+
if (instance != null
99+
&& equalsNormalized(instance.getRole(), roleName)
100+
&& equalsNormalized(instance.getName(), roleInstance)) {
101+
return true;
102+
}
103+
}
104+
return false;
105+
}
106+
107+
public boolean isActionable(
108+
@Nullable String roleName, @Nullable String roleInstance, Instant now) {
109+
Instant expiration = getExpiration();
110+
return expiration != null && now.isBefore(expiration) && isSelected(roleName, roleInstance);
111+
}
112+
113+
@Nullable
114+
private static <T> List<T> immutableCopy(@Nullable List<T> values) {
115+
return values == null ? null : Collections.unmodifiableList(new ArrayList<>(values));
116+
}
117+
118+
private static boolean equalsNormalized(@Nullable String left, @Nullable String right) {
119+
return left != null && right != null && left.trim().equalsIgnoreCase(right.trim());
120+
}
121+
122+
private static boolean isBlank(@Nullable String value) {
123+
return value == null || value.trim().isEmpty();
124+
}
125+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
package com.microsoft.applicationinsights.alerting.config;
5+
6+
import com.google.auto.value.AutoValue;
7+
import javax.annotation.Nullable;
8+
9+
@AutoValue
10+
public abstract class TargetedInstanceConfiguration {
11+
12+
public static TargetedInstanceConfiguration create(@Nullable String role, @Nullable String name) {
13+
return new AutoValue_TargetedInstanceConfiguration(role, name);
14+
}
15+
16+
@Nullable
17+
public abstract String getRole();
18+
19+
@Nullable
20+
public abstract String getName();
21+
}

0 commit comments

Comments
 (0)