Migrate profiler code from jackson json to azure json (#3896)

Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>
This commit is contained in:
Helen 2024-11-10 10:58:44 -08:00 коммит произвёл GitHub
Родитель 3ba19119d4
Коммит 439cd29729
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
36 изменённых файлов: 1289 добавлений и 569 удалений

Просмотреть файл

@ -8,8 +8,7 @@ if (project.properties.containsKey("publish-diagnostics")) {
}
dependencies {
compileOnly("com.fasterxml.jackson.core:jackson-annotations")
compileOnly("com.fasterxml.jackson.core:jackson-databind")
compileOnly("com.azure:azure-json")
compileOnly("com.google.auto.value:auto-value-annotations")
annotationProcessor("com.google.auto.value:auto-value")
}

Просмотреть файл

@ -3,75 +3,208 @@
package com.microsoft.applicationinsights.alerting.aiconfig;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.azure.json.JsonReader;
import com.azure.json.JsonSerializable;
import com.azure.json.JsonToken;
import com.azure.json.JsonWriter;
import java.io.IOException;
public class AlertingConfig {
public enum RequestFilterType {
@JsonProperty("name-regex")
NAME_REGEX
}
public static class RequestFilter {
public final RequestFilterType type;
public final String value;
public static class RequestFilter implements JsonSerializable<RequestFilter> {
public RequestFilterType type;
public String value;
@JsonCreator
public RequestFilter(
@JsonProperty("type") RequestFilterType type, @JsonProperty("value") String value) {
public RequestFilterType getType() {
return type;
}
public RequestFilter setType(RequestFilterType type) {
this.type = type;
return this;
}
public String getValue() {
return value;
}
public RequestFilter setValue(String value) {
this.value = value;
return this;
}
@Override
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
jsonWriter.writeStartObject();
if (type != null) {
jsonWriter.writeStringField("type", type.name());
}
jsonWriter.writeStringField("value", value);
jsonWriter.writeEndObject();
return jsonWriter;
}
public static RequestFilter fromJson(JsonReader jsonReader) throws IOException {
return jsonReader.readObject(
reader -> {
RequestFilter deserializedRequestFilter = new RequestFilter();
while (reader.nextToken() != JsonToken.END_OBJECT) {
reader.nextToken();
String fieldName = reader.getFieldName();
if ("type".equals(fieldName)) {
deserializedRequestFilter.setType(RequestFilterType.valueOf(reader.getString()));
} else if ("value".equals(fieldName)) {
deserializedRequestFilter.setValue(reader.getString());
} else {
reader.skipChildren();
}
}
return deserializedRequestFilter;
});
}
}
public static class RequestAggregationConfig {
public static class RequestAggregationConfig
implements JsonSerializable<RequestAggregationConfig> {
// Threshold in ms over which a span will consider to be a breach
// Used by the breach ratio aggregation
public final int thresholdMillis;
public int thresholdMillis;
// Minimum number of samples that must have been collected in order for the aggregation to
// produce data. Avoids volatile aggregation output on small sample sizes.
public final int minimumSamples;
public int minimumSamples;
@JsonCreator
public RequestAggregationConfig(
@JsonProperty("thresholdMillis") int thresholdMillis,
@JsonProperty("minimumSamples") int minimumSamples) {
public int getThresholdMillis() {
return thresholdMillis;
}
public RequestAggregationConfig setThresholdMillis(int thresholdMillis) {
this.thresholdMillis = thresholdMillis;
return this;
}
public int getMinimumSamples() {
return minimumSamples;
}
public RequestAggregationConfig setMinimumSamples(int minimumSamples) {
this.minimumSamples = minimumSamples;
return this;
}
@Override
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
jsonWriter.writeStartObject();
jsonWriter.writeIntField("thresholdMillis", thresholdMillis);
jsonWriter.writeIntField("minimumSamples", minimumSamples);
jsonWriter.writeEndObject();
return jsonWriter;
}
public static RequestAggregationConfig fromJson(JsonReader jsonReader) throws IOException {
return jsonReader.readObject(
reader -> {
RequestAggregationConfig deserializedRequestAggregationConfig =
new RequestAggregationConfig();
while (reader.nextToken() != JsonToken.END_OBJECT) {
reader.nextToken();
String fieldName = reader.getFieldName();
if ("thresholdMillis".equals(fieldName)) {
deserializedRequestAggregationConfig.setThresholdMillis(jsonReader.getInt());
} else if ("minimumSamples".equals(fieldName)) {
deserializedRequestAggregationConfig.setMinimumSamples(jsonReader.getInt());
} else {
reader.skipChildren();
}
}
return deserializedRequestAggregationConfig;
});
}
}
public enum RequestAggregationType {
@JsonProperty("breach-ratio")
BREACH_RATIO
}
public static class RequestAggregation {
public final RequestAggregationType type;
public final long windowSizeMillis; // in ms
public final RequestAggregationConfig configuration;
public static class RequestAggregation implements JsonSerializable<RequestAggregation> {
public RequestAggregationType type;
public long windowSizeMillis; // in ms
public RequestAggregationConfig configuration;
@JsonCreator
public RequestAggregation(
@JsonProperty("type") RequestAggregationType type,
@JsonProperty("windowSizeMillis") long windowSizeMillis,
@JsonProperty("configuration") RequestAggregationConfig configuration) {
public RequestAggregationType getType() {
return type;
}
public RequestAggregation setType(RequestAggregationType type) {
this.type = type;
return this;
}
public long getWindowSizeMillis() {
return windowSizeMillis;
}
public RequestAggregation setWindowSizeMillis(long windowSizeMillis) {
this.windowSizeMillis = windowSizeMillis;
return this;
}
public RequestAggregationConfig getConfiguration() {
return configuration;
}
public RequestAggregation setConfiguration(RequestAggregationConfig configuration) {
this.configuration = configuration;
return this;
}
@Override
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
jsonWriter.writeStartObject();
if (type != null) {
jsonWriter.writeStringField("type", type.name());
}
jsonWriter.writeLongField("windowSizeMillis", windowSizeMillis);
jsonWriter.writeJsonField("configuration", configuration);
jsonWriter.writeEndObject();
return jsonWriter;
}
public static RequestAggregation fromJson(JsonReader jsonReader) throws IOException {
return jsonReader.readObject(
reader -> {
RequestAggregation deserializedRequestAggregation = new RequestAggregation();
while (reader.nextToken() != JsonToken.END_OBJECT) {
reader.nextToken();
String fieldName = reader.getFieldName();
if ("type".equals(fieldName)) {
deserializedRequestAggregation.setType(
RequestAggregationType.valueOf(reader.getString()));
} else if ("windowSizeMillis".equals(fieldName)) {
deserializedRequestAggregation.setWindowSizeMillis(jsonReader.getLong());
} else if ("configuration".equals(fieldName)) {
deserializedRequestAggregation.setConfiguration(
RequestAggregationConfig.fromJson(jsonReader));
} else {
reader.skipChildren();
}
}
return deserializedRequestAggregation;
});
}
}
public enum RequestTriggerThresholdType {
@JsonProperty("greater-than")
GREATER_THAN
}
public static class RequestTriggerThreshold {
public final RequestTriggerThresholdType type;
public static class RequestTriggerThreshold implements JsonSerializable<RequestTriggerThreshold> {
public RequestTriggerThresholdType type;
// Threshold value applied to the output of the aggregation
// i.e :
@ -80,65 +213,236 @@ public class AlertingConfig {
// - For a rolling average aggregation 0.75 will mean this will trigger if the average request
// processing time
// breaches 0.75ms
public final float value;
public float value;
@JsonCreator
public RequestTriggerThreshold(
@JsonProperty("type") RequestTriggerThresholdType type,
@JsonProperty("value") float value) {
public RequestTriggerThresholdType getType() {
return type;
}
public RequestTriggerThreshold setType(RequestTriggerThresholdType type) {
this.type = type;
return this;
}
public float getValue() {
return value;
}
public RequestTriggerThreshold setValue(float value) {
this.value = value;
return this;
}
@Override
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
jsonWriter.writeStartObject();
if (type != null) {
jsonWriter.writeStringField("type", type.name());
}
jsonWriter.writeFloatField("value", value);
jsonWriter.writeEndObject();
return jsonWriter;
}
public static RequestTriggerThreshold fromJson(JsonReader jsonReader) throws IOException {
return jsonReader.readObject(
reader -> {
RequestTriggerThreshold deserializedRequestTriggerThreshold =
new RequestTriggerThreshold();
while (reader.nextToken() != JsonToken.END_OBJECT) {
reader.nextToken();
String fieldName = reader.getFieldName();
if ("type".equals(fieldName)) {
deserializedRequestTriggerThreshold.setType(
RequestTriggerThresholdType.valueOf(reader.getString()));
} else if ("value".equals(fieldName)) {
deserializedRequestTriggerThreshold.setValue(reader.getFloat());
} else {
reader.skipChildren();
}
}
return deserializedRequestTriggerThreshold;
});
}
}
public enum RequestTriggerThrottlingType {
@JsonProperty("fixed-duration-cooldown")
FIXED_DURATION_COOLDOWN
}
public static class RequestTriggerThrottling {
public final RequestTriggerThrottlingType type;
public final long value; // in seconds
public static class RequestTriggerThrottling
implements JsonSerializable<RequestTriggerThrottling> {
public RequestTriggerThrottlingType type;
public long value; // in seconds
@JsonCreator
public RequestTriggerThrottling(
@JsonProperty("type") RequestTriggerThrottlingType type,
@JsonProperty("value") long value) {
public RequestTriggerThrottlingType getType() {
return type;
}
public RequestTriggerThrottling setType(RequestTriggerThrottlingType type) {
this.type = type;
return this;
}
public long getValue() {
return value;
}
public RequestTriggerThrottling setValue(long value) {
this.value = value;
return this;
}
@Override
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
jsonWriter.writeStartObject();
if (type != null) {
jsonWriter.writeStringField("type", type.name());
}
jsonWriter.writeLongField("value", value);
jsonWriter.writeEndObject();
return jsonWriter;
}
public static RequestTriggerThrottling fromJson(JsonReader jsonReader) throws IOException {
return jsonReader.readObject(
reader -> {
RequestTriggerThrottling deserializedRequestTriggerThrottling =
new RequestTriggerThrottling();
while (reader.nextToken() != JsonToken.END_OBJECT) {
reader.nextToken();
String fieldName = reader.getFieldName();
if ("type".equals(fieldName)) {
deserializedRequestTriggerThrottling.setType(
RequestTriggerThrottlingType.valueOf(reader.getString()));
} else if ("value".equals(fieldName)) {
deserializedRequestTriggerThrottling.setValue(reader.getLong());
} else {
reader.skipChildren();
}
}
return deserializedRequestTriggerThrottling;
});
}
}
public enum RequestTriggerType {
@JsonProperty("latency")
LATENCY
}
public static class RequestTrigger {
public final String name;
public final RequestTriggerType type;
public final RequestFilter filter;
public final RequestAggregation aggregation;
public final RequestTriggerThreshold threshold;
public final RequestTriggerThrottling throttling;
public final long profileDuration;
public static class RequestTrigger implements JsonSerializable<RequestTrigger> {
public String name;
public RequestTriggerType type;
public RequestFilter filter;
public RequestAggregation aggregation;
public RequestTriggerThreshold threshold;
public RequestTriggerThrottling throttling;
public long profileDuration;
@JsonCreator
public RequestTrigger(
@JsonProperty("name") String name,
@JsonProperty("type") RequestTriggerType type,
@JsonProperty("filter") RequestFilter filter,
@JsonProperty("aggregation") RequestAggregation aggregation,
@JsonProperty("threshold") RequestTriggerThreshold threshold,
@JsonProperty("throttling") RequestTriggerThrottling throttling,
@JsonProperty("profileDuration") long profileDuration) {
public String getName() {
return name;
}
public RequestTrigger setName(String name) {
this.name = name;
return this;
}
public RequestTriggerType getType() {
return type;
}
public RequestTrigger setType(RequestTriggerType type) {
this.type = type;
return this;
}
public RequestFilter getFilter() {
return filter;
}
public RequestTrigger setFilter(RequestFilter filter) {
this.filter = filter;
return this;
}
public RequestAggregation getAggregation() {
return aggregation;
}
public RequestTrigger setAggregation(RequestAggregation aggregation) {
this.aggregation = aggregation;
return this;
}
public RequestTriggerThreshold getThreshold() {
return threshold;
}
public RequestTrigger setThreshold(RequestTriggerThreshold threshold) {
this.threshold = threshold;
return this;
}
public RequestTriggerThrottling getThrottling() {
return throttling;
}
public RequestTrigger setThrottling(RequestTriggerThrottling throttling) {
this.throttling = throttling;
return this;
}
public long getProfileDuration() {
return profileDuration;
}
public RequestTrigger setProfileDuration(long profileDuration) {
this.profileDuration = profileDuration;
return this;
}
@Override
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
jsonWriter.writeStartObject();
jsonWriter.writeStringField("name", name);
jsonWriter.writeStringField("type", type.name());
jsonWriter.writeJsonField("filter", filter);
jsonWriter.writeJsonField("aggregation", aggregation);
jsonWriter.writeJsonField("threshold", threshold);
jsonWriter.writeJsonField("throttling", throttling);
jsonWriter.writeLongField("profileDuration", profileDuration);
jsonWriter.writeEndObject();
return jsonWriter;
}
public static RequestTrigger fromJson(JsonReader jsonReader) throws IOException {
return jsonReader.readObject(
reader -> {
RequestTrigger deserializedRequestTrigger = new RequestTrigger();
while (reader.nextToken() != JsonToken.END_OBJECT) {
reader.nextToken();
String fieldName = reader.getFieldName();
if ("name".equals(fieldName)) {
deserializedRequestTrigger.setName(reader.getString());
} else if ("type".equals(fieldName)) {
deserializedRequestTrigger.setType(RequestTriggerType.valueOf(reader.getString()));
} else if ("filter".equals(fieldName)) {
deserializedRequestTrigger.setFilter(RequestFilter.fromJson(reader));
} else if ("aggregation".equals(fieldName)) {
deserializedRequestTrigger.setAggregation(RequestAggregation.fromJson(reader));
} else if ("threshold".equals(fieldName)) {
deserializedRequestTrigger.setThreshold(RequestTriggerThreshold.fromJson(reader));
} else if ("throttling".equals(fieldName)) {
deserializedRequestTrigger.setThrottling(RequestTriggerThrottling.fromJson(reader));
} else if ("profileDuration".equals(fieldName)) {
deserializedRequestTrigger.setProfileDuration(reader.getLong());
} else {
reader.skipChildren();
}
}
return deserializedRequestTrigger;
});
}
}

Просмотреть файл

@ -3,45 +3,71 @@
package com.microsoft.applicationinsights.alerting.alert;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.azure.json.JsonSerializable;
import com.azure.json.JsonWriter;
import com.google.auto.value.AutoValue;
import com.microsoft.applicationinsights.alerting.config.AlertConfiguration;
import com.microsoft.applicationinsights.alerting.config.AlertMetricType;
import java.io.IOException;
import java.util.UUID;
/** Represents a breach of an alert threshold. */
@AutoValue
@JsonSerialize(as = AlertBreach.class)
@JsonDeserialize(builder = AlertBreach.Builder.class)
@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class AlertBreach {
public abstract class AlertBreach implements JsonSerializable<AlertBreach> {
private AlertMetricType type;
private double alertValue;
private AlertConfiguration alertConfiguration;
private double cpuMetric;
private double memoryUsage;
private String profileId = UUID.randomUUID().toString();
@JsonProperty("type")
public abstract AlertMetricType getType();
public AlertBreach setType(AlertMetricType type) {
this.type = type;
return this;
}
// Value of the telemetry at the time of the breach
@JsonProperty("alertValue")
public abstract double getAlertValue();
@JsonProperty("alertConfiguration")
public AlertBreach setAlertValue(double alertValue) {
this.alertValue = alertValue;
return this;
}
public abstract AlertConfiguration getAlertConfiguration();
public AlertBreach setAlertConfiguration(AlertConfiguration alertConfiguration) {
this.alertConfiguration = alertConfiguration;
return this;
}
// CPU usage at the time of the breach
@JsonProperty(value = "cpuMetric")
public abstract double getCpuMetric();
public AlertBreach setCpuMetric(double cpuMetric) {
this.cpuMetric = cpuMetric;
return this;
}
// MEMORY usage at the time of the breach
@JsonProperty(value = "memoryUsage")
public abstract double getMemoryUsage();
public AlertBreach setMemoryUsage(double memoryUsage) {
this.memoryUsage = memoryUsage;
return this;
}
// Unique ID for profile/breach
@JsonProperty("profileId")
public abstract String getProfileId();
public AlertBreach setProfileId(String profileId) {
this.profileId = profileId;
return this;
}
public abstract Builder toBuilder();
public static AlertBreach.Builder builder() {
@ -51,33 +77,57 @@ public abstract class AlertBreach {
.setProfileId(UUID.randomUUID().toString());
}
@AutoValue.Builder
@JsonIgnoreProperties(ignoreUnknown = true)
public abstract static class Builder {
@JsonCreator
public static Builder builder() {
return AlertBreach.builder();
@Override
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
jsonWriter.writeStartObject();
if (type != null) {
jsonWriter.writeStringField("type", type.name());
}
jsonWriter.writeDoubleField("alertValue", alertValue);
jsonWriter.writeJsonField("alertConfiguration", alertConfiguration);
jsonWriter.writeDoubleField("cpuMetric", cpuMetric);
jsonWriter.writeDoubleField("memoryUsage", memoryUsage);
jsonWriter.writeStringField("profileId", profileId);
jsonWriter.writeEndObject();
return jsonWriter;
}
@AutoValue.Builder
public abstract static class Builder implements JsonSerializable<Builder> {
private AlertMetricType type;
private double alertValue;
private AlertConfiguration alertConfiguration;
private double cpuMetric;
private double memoryUsage;
private final String profileId = UUID.randomUUID().toString();
@JsonProperty("type")
public abstract Builder setType(AlertMetricType type);
@JsonProperty("alertValue")
public abstract Builder setAlertValue(double alertValue);
@JsonProperty("alertConfiguration")
public abstract Builder setAlertConfiguration(AlertConfiguration alertConfiguration);
@JsonProperty(value = "cpuMetric")
public abstract Builder setCpuMetric(double cpuMetric);
@JsonProperty(value = "memoryUsage")
public abstract Builder setMemoryUsage(double memoryUsage);
@JsonProperty("profileId")
public abstract Builder setProfileId(String profileId);
public abstract AlertBreach build();
@Override
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
jsonWriter.writeStartObject();
if (type != null) {
jsonWriter.writeStringField("type", type.name());
}
jsonWriter.writeDoubleField("alertValue", alertValue);
jsonWriter.writeJsonField("alertConfiguration", alertConfiguration);
jsonWriter.writeDoubleField("cpuMetric", cpuMetric);
jsonWriter.writeDoubleField("memoryUsage", memoryUsage);
jsonWriter.writeStringField("profileId", profileId);
jsonWriter.writeEndObject();
return jsonWriter;
}
}
}

Просмотреть файл

@ -3,39 +3,82 @@
package com.microsoft.applicationinsights.alerting.config;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.azure.json.JsonSerializable;
import com.azure.json.JsonWriter;
import com.google.auto.value.AutoValue;
import com.microsoft.applicationinsights.alerting.aiconfig.AlertingConfig;
import java.io.IOException;
import javax.annotation.Nullable;
/** Alert configuration for a given telemetry type. */
@AutoValue
@JsonSerialize(as = AlertConfiguration.class)
@JsonDeserialize(builder = AlertConfiguration.Builder.class)
public abstract class AlertConfiguration {
public abstract class AlertConfiguration implements JsonSerializable<AlertConfiguration> {
protected AlertMetricType type;
protected boolean enabled;
protected float threshold;
protected int profileDurationSeconds;
protected int cooldownSeconds;
protected AlertingConfig.RequestTrigger requestTrigger;
@JsonProperty("type")
public abstract AlertMetricType getType();
@JsonProperty("enabled")
public AlertConfiguration setType(AlertMetricType type) {
this.type = type;
return this;
}
public abstract boolean isEnabled();
@JsonProperty("threshold")
public AlertConfiguration setEnabled(boolean enabled) {
this.enabled = enabled;
return this;
}
public abstract float getThreshold();
@JsonProperty("profileDuration")
public AlertConfiguration setThreshold(float threshold) {
this.threshold = threshold;
return this;
}
public abstract int getProfileDurationSeconds();
@JsonProperty("cooldown")
public AlertConfiguration setProfileDurationSeconds(int profileDurationSeconds) {
this.profileDurationSeconds = profileDurationSeconds;
return this;
}
public abstract int getCooldownSeconds();
public AlertConfiguration setCooldownSeconds(int cooldownSeconds) {
this.cooldownSeconds = cooldownSeconds;
return this;
}
@Nullable
@JsonProperty("requestTrigger")
public abstract AlertingConfig.RequestTrigger getRequestTrigger();
public AlertConfiguration setRequestTrigger(AlertingConfig.RequestTrigger requestTrigger) {
this.requestTrigger = requestTrigger;
return this;
}
@Override
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
jsonWriter.writeStartObject();
if (type != null) {
jsonWriter.writeStringField("type", type.name());
}
jsonWriter.writeBooleanField("enabled", enabled);
jsonWriter.writeFloatField("threshold", threshold);
jsonWriter.writeIntField("profileDurationSeconds", profileDurationSeconds);
jsonWriter.writeIntField("cooldownSeconds", cooldownSeconds);
jsonWriter.writeJsonField("requestTrigger", requestTrigger);
jsonWriter.writeEndObject();
return jsonWriter;
}
public static Builder builder() {
// TODO (trask) which of these is really required?
return new AutoValue_AlertConfiguration.Builder()
@ -46,31 +89,42 @@ public abstract class AlertConfiguration {
}
@AutoValue.Builder
public abstract static class Builder {
@JsonCreator
public static Builder builder() {
return AlertConfiguration.builder();
}
public abstract static class Builder implements JsonSerializable<Builder> {
private AlertMetricType type;
private boolean enabled;
private float threshold;
private int profileDurationSeconds;
private int cooldownSeconds;
private AlertingConfig.RequestTrigger requestTrigger;
@JsonProperty("enabled")
public abstract Builder setEnabled(boolean enabled);
@JsonProperty("threshold")
public abstract Builder setThreshold(float threshold);
@JsonProperty("profileDuration")
public abstract Builder setProfileDurationSeconds(int profileDurationSeconds);
@JsonProperty("cooldown")
public abstract Builder setCooldownSeconds(int cooldownSeconds);
@JsonProperty("type")
public abstract Builder setType(AlertMetricType type);
@JsonProperty("requestTrigger")
public abstract Builder setRequestTrigger(
@Nullable AlertingConfig.RequestTrigger requestTrigger);
public abstract AlertConfiguration build();
@Override
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
jsonWriter.writeStartObject();
if (type != null) {
jsonWriter.writeStringField("type", type.name());
}
jsonWriter.writeBooleanField("enabled", enabled);
jsonWriter.writeFloatField("threshold", threshold);
jsonWriter.writeIntField("profileDurationSeconds", profileDurationSeconds);
jsonWriter.writeIntField("cooldownSeconds", cooldownSeconds);
jsonWriter.writeJsonField("requestTrigger", requestTrigger);
jsonWriter.writeEndObject();
return jsonWriter;
}
}
}

Просмотреть файл

@ -8,5 +8,5 @@ public enum AlertMetricType {
MEMORY,
PERIODIC,
MANUAL,
REQUEST
REQUEST;
}

Просмотреть файл

@ -8,6 +8,7 @@ dependencies {
implementation(project(":agent:agent-profiler:agent-alerting-api"))
implementation("org.slf4j:slf4j-api")
implementation("com.azure:azure-json")
testImplementation("org.junit.jupiter:junit-jupiter")
testImplementation("org.assertj:assertj-core")

Просмотреть файл

@ -1,6 +1,7 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
com.azure:azure-json:1.3.0=runtimeClasspath
com.azure:azure-sdk-bom:1.2.29=runtimeClasspath
com.fasterxml.jackson:jackson-bom:2.18.1=runtimeClasspath
io.netty:netty-bom:4.1.114.Final=runtimeClasspath

Просмотреть файл

@ -9,9 +9,7 @@ if (project.properties.containsKey("publish-diagnostics")) {
dependencies {
compileOnly("org.gradle.jfr.polyfill:jfr-polyfill:1.0.2")
compileOnly("com.fasterxml.jackson.core:jackson-annotations")
compileOnly("com.azure:azure-json")
compileOnly("com.google.auto.service:auto-service")
annotationProcessor("com.google.auto.service:auto-service")
}

Просмотреть файл

@ -3,6 +3,11 @@
package com.microsoft.applicationinsights.diagnostics.jfr;
import com.azure.json.JsonReader;
import com.azure.json.JsonSerializable;
import com.azure.json.JsonToken;
import com.azure.json.JsonWriter;
import java.io.IOException;
import jdk.jfr.Category;
import jdk.jfr.Description;
import jdk.jfr.Event;
@ -16,17 +21,46 @@ import jdk.jfr.StackTrace;
@Category("Diagnostic")
@Description("AlertBreach")
@StackTrace(false)
public class AlertBreachJfrEvent extends Event {
public class AlertBreachJfrEvent extends Event implements JsonSerializable<AlertBreachJfrEvent> {
public static final String NAME = "com.microsoft.applicationinsights.diagnostics.jfr.AlertBreach";
private final String alertBreach;
private String alertBreach;
public AlertBreachJfrEvent(String alertBreach) {
this.alertBreach = alertBreach;
}
public AlertBreachJfrEvent() {}
public String getAlertBreach() {
return alertBreach;
}
public AlertBreachJfrEvent setAlertBreach(String alertBreach) {
this.alertBreach = alertBreach;
return this;
}
/** Serialize a AlertBreachJfrEvent to a JSON writer */
@Override
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
jsonWriter.writeStartObject();
jsonWriter.writeStringField("alertBreach", alertBreach);
jsonWriter.writeEndObject();
return jsonWriter;
}
/** Deserialize a AlertBreachJfrEvent from a JSON reader */
public static AlertBreachJfrEvent fromJson(JsonReader jsonReader) throws IOException {
return jsonReader.readObject(
reader -> {
AlertBreachJfrEvent event = new AlertBreachJfrEvent();
while (reader.nextToken() != JsonToken.END_OBJECT) {
String fieldName = reader.getFieldName();
reader.nextToken();
if ("alertBreach".equals(fieldName)) {
event.setAlertBreach(reader.getString());
}
}
return event;
});
}
}

Просмотреть файл

@ -3,8 +3,11 @@
package com.microsoft.applicationinsights.diagnostics.jfr;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.azure.json.JsonReader;
import com.azure.json.JsonSerializable;
import com.azure.json.JsonToken;
import com.azure.json.JsonWriter;
import java.io.IOException;
import jdk.jfr.Category;
import jdk.jfr.Description;
import jdk.jfr.Event;
@ -20,63 +23,107 @@ import jdk.jfr.StackTrace;
@Description("CGroupData")
@StackTrace(false)
@Period("beginChunk")
public class CGroupData extends Event {
public class CGroupData extends Event implements JsonSerializable<CGroupData> {
public static final String NAME = "com.microsoft.applicationinsights.diagnostics.jfr.CGroupData";
public static final int CGROUP_DATA_ABSENT = -2;
public static final int CGROUP_DATA_ABSENT = -2; // No CGroup data was found for this value
// Limit of the kernel memory
private final long kmemLimit; // /sys/fs/cgroup/memory/memory.kmem.limit_in_bytes
private long kmemLimit; // /sys/fs/cgroup/memory/memory.kmem.limit_in_bytes
// Limit of the containers memory
private final long memoryLimit; // /sys/fs/cgroup/memory/memory.limit_in_bytes
private long memoryLimit; // /sys/fs/cgroup/memory/memory.limit_in_bytes
// Soft memory limit (enforced over the long term)
private final long memorySoftLimit; // /sys/fs/cgroup/memory/memory.soft_limit_in_bytes
private long memorySoftLimit; // /sys/fs/cgroup/memory/memory.soft_limit_in_bytes
// CPU usage limit
private final long cpuLimit; // /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us
private long cpuLimit; // /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us
// CPU usage period
private final long cpuPeriod; // /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us
@JsonCreator
public CGroupData(
@JsonProperty(value = "kmemLimit") long kmemLimit,
@JsonProperty(value = "memoryLimit") long memoryLimit,
@JsonProperty(value = "memorySoftLimit") long memorySoftLimit,
@JsonProperty(value = "cpuLimit") long cpuLimit,
@JsonProperty(value = "cpuPeriod", required = false) Long cpuPeriod) {
this.kmemLimit = kmemLimit;
this.memoryLimit = memoryLimit;
this.memorySoftLimit = memorySoftLimit;
this.cpuLimit = cpuLimit;
if (cpuPeriod == null) {
// No CGroup data was found for this value
this.cpuPeriod = CGROUP_DATA_ABSENT;
} else {
this.cpuPeriod = cpuPeriod;
}
}
private long cpuPeriod = CGROUP_DATA_ABSENT; // /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us
public long getKmemLimit() {
return kmemLimit;
}
public CGroupData setKmemLimit(long kmemLimit) {
this.kmemLimit = kmemLimit;
return this;
}
public long getMemoryLimit() {
return memoryLimit;
}
public CGroupData setMemoryLimit(long memoryLimit) {
this.memoryLimit = memoryLimit;
return this;
}
public long getMemorySoftLimit() {
return memorySoftLimit;
}
public CGroupData setMemorySoftLimit(long memorySoftLimit) {
this.memorySoftLimit = memorySoftLimit;
return this;
}
public long getCpuLimit() {
return cpuLimit;
}
public CGroupData setCpuLimit(long cpuLimit) {
this.cpuLimit = cpuLimit;
return this;
}
public long getCpuPeriod() {
return cpuPeriod;
}
public CGroupData setCpuPeriod(long cpuPeriod) {
this.cpuPeriod = cpuPeriod;
return this;
}
@Override
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
return jsonWriter
.writeStartObject()
.writeLongField("kmemLimit", kmemLimit)
.writeLongField("memoryLimit", memoryLimit)
.writeLongField("memorySoftLimit", memorySoftLimit)
.writeLongField("cpuLimit", cpuLimit)
.writeLongField("cpuPeriod", cpuPeriod)
.writeEndObject();
}
public static CGroupData fromJson(JsonReader jsonReader) throws IOException {
return jsonReader.readObject(
reader -> {
CGroupData deserializedValue = new CGroupData();
while (reader.nextToken() != JsonToken.END_OBJECT) {
String fieldName = reader.getFieldName();
reader.nextToken();
if ("kmemLimit".equals(fieldName)) {
deserializedValue.setKmemLimit(reader.getLong());
} else if ("memoryLimit".equals(fieldName)) {
deserializedValue.setMemoryLimit(reader.getLong());
} else if ("memorySoftLimit".equals(fieldName)) {
deserializedValue.setMemorySoftLimit(reader.getLong());
} else if ("cpuLimit".equals(fieldName)) {
deserializedValue.setCpuLimit(reader.getLong());
} else if ("cpuPeriod".equals(fieldName)) {
deserializedValue.setCpuPeriod(reader.getLong());
} else {
reader.skipChildren();
}
}
return deserializedValue;
});
}
}

Просмотреть файл

@ -3,6 +3,11 @@
package com.microsoft.applicationinsights.diagnostics.jfr;
import com.azure.json.JsonReader;
import com.azure.json.JsonSerializable;
import com.azure.json.JsonToken;
import com.azure.json.JsonWriter;
import java.io.IOException;
import jdk.jfr.Category;
import jdk.jfr.Description;
import jdk.jfr.Event;
@ -18,23 +23,58 @@ import jdk.jfr.StackTrace;
@Description("MachineStats")
@StackTrace(false)
@Period("beginChunk")
public class MachineStats extends Event {
public class MachineStats extends Event implements JsonSerializable<MachineStats> {
public static final String NAME =
"com.microsoft.applicationinsights.diagnostics.jfr.MachineStats";
private final double contextSwitchesPerMs;
private double contextSwitchesPerMs;
private final int coreCount;
public MachineStats(double contextSwitchesPerMs, int coreCount) {
this.contextSwitchesPerMs = contextSwitchesPerMs;
this.coreCount = coreCount;
}
private int coreCount;
public double getContextSwitchesPerMs() {
return contextSwitchesPerMs;
}
public MachineStats setContextSwitchesPerMs(double contextSwitchesPerMs) {
this.contextSwitchesPerMs = contextSwitchesPerMs;
return this;
}
public int getCoreCount() {
return coreCount;
}
public MachineStats setCoreCount(int coreCount) {
this.coreCount = coreCount;
return this;
}
@Override
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
return jsonWriter
.writeStartObject()
.writeDoubleField("contextSwitchesPerMs", contextSwitchesPerMs)
.writeIntField("coreCount", coreCount)
.writeEndObject();
}
public static MachineStats fromJson(JsonReader jsonReader) throws IOException {
return jsonReader.readObject(
reader -> {
MachineStats deserializedValue = new MachineStats();
while (reader.nextToken() != JsonToken.END_OBJECT) {
String fieldName = reader.getFieldName();
reader.nextToken();
if ("contextSwitchesPerMs".equals(fieldName)) {
deserializedValue.setContextSwitchesPerMs(reader.getDouble());
} else if ("coreCount".equals(fieldName)) {
deserializedValue.setCoreCount(reader.getInt());
} else {
reader.skipChildren();
}
}
return deserializedValue;
});
}
}

Просмотреть файл

@ -3,7 +3,11 @@
package com.microsoft.applicationinsights.diagnostics.jfr;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.azure.json.JsonReader;
import com.azure.json.JsonSerializable;
import com.azure.json.JsonToken;
import com.azure.json.JsonWriter;
import java.io.IOException;
import java.util.List;
import java.util.StringJoiner;
import jdk.jfr.Category;
@ -21,44 +25,76 @@ import jdk.jfr.StackTrace;
@Description("Telemetry")
@StackTrace(false)
@Period("100 ms")
public class Telemetry extends Event {
public class Telemetry extends Event implements JsonSerializable<Telemetry> {
public static final String NAME = "com.microsoft.applicationinsights.diagnostics.jfr.Telemetry";
public static final int LATEST_VERSION = 3;
private static final int LATEST_VERSION = 3;
public final int version;
public final String telemetry;
@JsonCreator
public Telemetry(Integer version, String telemetry) {
if (version == null) {
this.version = 1;
} else {
this.version = version;
}
this.telemetry = telemetry;
}
public Telemetry(String telemetry) {
this.telemetry = telemetry;
this.version = LATEST_VERSION;
}
public Telemetry(List<Double> telemetry) {
StringJoiner joiner = new StringJoiner(",");
telemetry.forEach(
it -> {
if (it == null) {
joiner.add("null");
} else {
joiner.add(Double.toString(it));
}
});
this.telemetry = joiner.toString();
this.version = LATEST_VERSION;
}
private int version = 1;
private String telemetry;
public int getVersion() {
return version;
}
public Telemetry setVersion(int version) {
this.version = version;
return this;
}
public String getTelemetry() {
return telemetry;
}
@SuppressWarnings("unchecked")
public Telemetry setTelemetry(Object telemetry) {
if (telemetry instanceof List) {
StringJoiner joiner = new StringJoiner(",");
((List<Double>) telemetry)
.forEach(
it -> {
if (it == null) {
joiner.add("null");
} else {
joiner.add(Double.toString(it));
}
});
this.telemetry = joiner.toString();
this.version = LATEST_VERSION;
} else if (telemetry instanceof String) {
this.telemetry = (String) telemetry;
this.version = LATEST_VERSION;
}
return this;
}
@Override
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
return jsonWriter
.writeStartObject()
.writeIntField("version", version)
.writeStringField("telemetry", telemetry)
.writeEndObject();
}
public static Telemetry fromJson(JsonReader jsonReader) throws IOException {
return jsonReader.readObject(
reader -> {
Telemetry deserializedValue = new Telemetry();
while (reader.nextToken() != JsonToken.END_OBJECT) {
String fieldName = reader.getFieldName();
reader.nextToken();
if ("version".equals(fieldName)) {
deserializedValue.setVersion(reader.getInt());
} else if ("telemetry".equals(fieldName)) {
deserializedValue.setTelemetry(reader.getString());
} else {
reader.skipChildren();
}
}
return deserializedValue;
});
}
}

Просмотреть файл

@ -1,19 +0,0 @@
plugins {
id("ai.java-conventions")
}
// Allows publishing this library to the local host ONLY if -Ppublish-diagnostics is provided
if (project.properties.containsKey("publish-diagnostics")) {
apply(plugin = "ai.publish-conventions")
}
dependencies {
implementation(project(":agent:agent-profiler:agent-alerting-api"))
compileOnly("org.slf4j:slf4j-api")
compileOnly("com.fasterxml.jackson.core:jackson-annotations")
compileOnly("com.fasterxml.jackson.core:jackson-databind")
compileOnly("com.google.auto.service:auto-service")
annotationProcessor("com.google.auto.service:auto-service")
}

Просмотреть файл

@ -1,13 +0,0 @@
# This is a Gradle generated file for dependency locking.
# Manual edits can break the build and are not advised.
# This file is expected to be part of source control.
com.azure:azure-sdk-bom:1.2.29=runtimeClasspath
com.fasterxml.jackson:jackson-bom:2.18.1=runtimeClasspath
io.netty:netty-bom:4.1.114.Final=runtimeClasspath
io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom-alpha:2.9.0-alpha=runtimeClasspath
io.opentelemetry.instrumentation:opentelemetry-instrumentation-bom:2.9.0=runtimeClasspath
io.opentelemetry:opentelemetry-bom-alpha:1.43.0-alpha=runtimeClasspath
io.opentelemetry:opentelemetry-bom:1.43.0=runtimeClasspath
org.junit:junit-bom:5.11.3=runtimeClasspath
org.testcontainers:testcontainers-bom:1.20.3=runtimeClasspath
empty=

Просмотреть файл

@ -1,22 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package com.microsoft.applicationinsights.diagnostics.collection.json;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.microsoft.applicationinsights.alerting.aiconfig.AlertingConfig;
public class AlertApiModule extends SimpleModule {
public AlertApiModule() {
addEnumConfig(AlertingConfig.RequestFilterType.class);
addEnumConfig(AlertingConfig.RequestAggregationType.class);
addEnumConfig(AlertingConfig.RequestTriggerThresholdType.class);
addEnumConfig(AlertingConfig.RequestTriggerThrottlingType.class);
addEnumConfig(AlertingConfig.RequestAggregationType.class);
}
private <T extends Enum<T>> void addEnumConfig(Class<T> clazz) {
addSerializer(clazz, new LowerCaseEnumSerializers.LowerCaseEnumSerializer<>());
addDeserializer(clazz, new LowerCaseEnumSerializers.LowerCaseEnumDeSerializer<>(clazz));
}
}

Просмотреть файл

@ -1,41 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package com.microsoft.applicationinsights.diagnostics.collection.json;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.util.Locale;
public class LowerCaseEnumSerializers {
private LowerCaseEnumSerializers() {}
public static class LowerCaseEnumSerializer<T extends Enum<T>> extends JsonSerializer<T> {
@Override
public void serialize(T value, JsonGenerator gen, SerializerProvider serializers)
throws IOException {
gen.writeString(value.name().toLowerCase(Locale.ROOT).replace("_", "-"));
}
}
public static class LowerCaseEnumDeSerializer<T extends Enum<T>> extends JsonDeserializer<T> {
private final Class<T> clazz;
public LowerCaseEnumDeSerializer(Class<T> clazz) {
this.clazz = clazz;
}
@Override
public T deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
return Enum.valueOf(
clazz, p.getValueAsString().toUpperCase(Locale.ROOT).replaceAll("-", "_"));
}
}
}

Просмотреть файл

@ -8,15 +8,13 @@ if (project.properties.containsKey("publish-diagnostics")) {
}
dependencies {
implementation(project(":agent:agent-profiler:agent-diagnostics-serialization"))
implementation(project(":agent:agent-profiler:agent-alerting-api"))
implementation(project(":agent:agent-profiler:agent-diagnostics-api"))
implementation(project(":agent:agent-profiler:agent-diagnostics-jfr"))
compileOnly("org.slf4j:slf4j-api")
compileOnly("com.fasterxml.jackson.core:jackson-annotations")
compileOnly("com.fasterxml.jackson.core:jackson-databind")
compileOnly("org.gradle.jfr.polyfill:jfr-polyfill:1.0.2")
compileOnly("com.azure:azure-json")
compileOnly("com.google.auto.service:auto-service")
annotationProcessor("com.google.auto.service:auto-service")

Просмотреть файл

@ -3,16 +3,17 @@
package com.microsoft.applicationinsights.diagnostics.appinsights;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.azure.json.JsonProviders;
import com.azure.json.JsonWriter;
import com.microsoft.applicationinsights.alerting.alert.AlertBreach;
import com.microsoft.applicationinsights.diagnostics.DiagnosisResult;
import com.microsoft.applicationinsights.diagnostics.DiagnosticEngine;
import com.microsoft.applicationinsights.diagnostics.collection.json.AlertApiModule;
import com.microsoft.applicationinsights.diagnostics.jfr.AlertBreachJfrEvent;
import com.microsoft.applicationinsights.diagnostics.jfr.CodeOptimizerDiagnosticsJfrInit;
import com.microsoft.applicationinsights.diagnostics.jfr.MachineStats;
import com.microsoft.applicationinsights.diagnostics.jfr.SystemStatsProvider;
import java.io.IOException;
import java.io.StringWriter;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
@ -30,14 +31,12 @@ public class CodeOptimizerDiagnosticEngineJfr implements DiagnosticEngine {
LoggerFactory.getLogger(CodeOptimizerDiagnosticEngineJfr.class);
public static final int SEMAPHORE_TIMEOUT_IN_SEC = 10;
public static final long TIME_BEFORE_END_OF_PROFILE_TO_EMIT_EVENT = 10L;
private final ObjectMapper mapper;
private final ScheduledExecutorService executorService;
private final Semaphore semaphore = new Semaphore(1, false);
private int thisPid;
public CodeOptimizerDiagnosticEngineJfr(ScheduledExecutorService executorService) {
this.executorService = executorService;
this.mapper = new ObjectMapper().registerModule(new AlertApiModule());
}
@Override
@ -133,7 +132,7 @@ public class CodeOptimizerDiagnosticEngineJfr implements DiagnosticEngine {
TimeUnit.SECONDS);
}
private void emitInfo(AlertBreach alert) {
private static void emitInfo(AlertBreach alert) {
LOGGER.debug("Emitting Code Optimizer Diagnostic Event");
emitAlertBreachJfrEvent(alert);
CodeOptimizerDiagnosticsJfrInit.emitCGroupData();
@ -145,13 +144,14 @@ public class CodeOptimizerDiagnosticEngineJfr implements DiagnosticEngine {
machineStats.commit();
}
private void emitAlertBreachJfrEvent(AlertBreach alert) {
try {
String serializedBreach = mapper.writeValueAsString(alert);
AlertBreachJfrEvent event = new AlertBreachJfrEvent(serializedBreach);
private static void emitAlertBreachJfrEvent(AlertBreach alert) {
try (StringWriter stringWriter = new StringWriter();
JsonWriter writer = JsonProviders.createWriter(stringWriter)) {
alert.toJson(writer).flush();
AlertBreachJfrEvent event = new AlertBreachJfrEvent().setAlertBreach(stringWriter.toString());
event.commit();
LOGGER.debug("Emitted Code Optimizer Diagnostic Event");
} catch (JsonProcessingException e) {
} catch (IOException e) {
LOGGER.error("Failed to create breach JFR event", e);
}
}

Просмотреть файл

@ -3,9 +3,10 @@
package com.microsoft.applicationinsights.diagnostics.collection.jvm;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.azure.json.JsonSerializable;
import com.azure.json.JsonWriter;
import com.microsoft.applicationinsights.diagnostics.collection.libos.process.ProcessInfo;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -18,13 +19,13 @@ import javax.annotation.Nullable;
/**
* Represents information about a running process. Also attempts to redact any sensitive arguments.
*/
public class ProcessData implements ProcessInfo {
public class ProcessData implements ProcessInfo, JsonSerializable<ProcessData> {
private final String name;
private final int pid;
private final String uid;
private String name;
private int pid;
private String uid = UUID.randomUUID().toString();
@Nullable private final Map<String, String> metaData;
@Nullable private Map<String, String> metaData;
private static final List<String> SENSITIVE_PROPERTIES_ARGS =
Arrays.asList(
@ -68,49 +69,81 @@ public class ProcessData implements ProcessInfo {
return name;
}
public ProcessData() {}
public ProcessData(String name, int pid) {
this(name, pid, UUID.randomUUID().toString());
setName(name).setPid(pid);
}
public ProcessData(String name, int pid, Map<String, String> metaData) {
this(name, pid, UUID.randomUUID().toString(), metaData);
setName(name).setPid(pid).setMetaData(metaData);
}
public ProcessData(String name, int pid, String uid) {
this(name, pid, uid, null);
setName(name).setPid(pid).setUid(uid);
}
public ProcessData(String name) {
this(sanetiseArg(name), -1, UUID.randomUUID().toString(), null);
setName(name).setPid(-1);
}
public ProcessData(ProcessInfo clone) {
this(
(clone == null ? "Unknown" : clone.getName()),
(clone == null ? -1 : clone.getPid()),
(clone == null ? UUID.randomUUID().toString() : clone.getUid()),
(clone == null ? null : clone.getMetaData()));
setName(clone == null ? "Unknown" : clone.getName())
.setPid(clone == null ? -1 : clone.getPid())
.setUid(clone == null ? UUID.randomUUID().toString() : clone.getUid())
.setMetaData(clone == null ? null : clone.getMetaData());
}
@JsonCreator
public ProcessData(
@JsonProperty("name") String name,
@JsonProperty("pid") int pid,
@Nullable @JsonProperty("uid") String uid,
@Nullable @JsonProperty("metaData") Map<String, String> metaData) {
this.name = sanetiseArg(name);
this.pid = pid;
if (uid == null) {
this.uid = UUID.randomUUID().toString();
} else {
this.uid = uid;
}
@Override
public String getName() {
return name;
}
if (metaData != null) {
this.metaData = Collections.unmodifiableMap(metaData);
} else {
this.metaData = null;
}
public ProcessData setName(String name) {
this.name = sanetiseArg(name);
return this;
}
@Override
public int getPid() {
return pid;
}
public ProcessData setPid(int pid) {
this.pid = pid;
return this;
}
@Override
public String getUid() {
return uid;
}
public ProcessData setUid(String uid) {
this.uid = uid;
return this;
}
@Override
@Nullable
public Map<String, String> getMetaData() {
return metaData;
}
public ProcessData setMetaData(@Nullable Map<String, String> metaData) {
this.metaData = metaData != null ? Collections.unmodifiableMap(metaData) : null;
return this;
}
@Override
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
jsonWriter.writeStartObject();
jsonWriter.writeStringField("name", name);
jsonWriter.writeIntField("pid", pid);
jsonWriter.writeStringField("uid", uid);
jsonWriter.writeMapField("metaData", metaData, JsonWriter::writeString);
jsonWriter.writeEndObject();
return jsonWriter;
}
// @ExistsForTesting
@ -127,21 +160,6 @@ public class ProcessData implements ProcessInfo {
return new ProcessData(name, pid, uid);
}
@Override
public String getName() {
return name;
}
@Override
public int getPid() {
return pid;
}
@Override
public String getUid() {
return uid;
}
@Override
public int compareTo(ProcessInfo o) {
return COMPARATOR.compare(this, o);
@ -178,10 +196,4 @@ public class ProcessData implements ProcessInfo {
}
return pid == other.pid;
}
@Override
@Nullable
public Map<String, String> getMetaData() {
return metaData;
}
}

Просмотреть файл

@ -3,45 +3,64 @@
package com.microsoft.applicationinsights.diagnostics.collection.libos.hardware;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.azure.json.JsonSerializable;
import com.azure.json.JsonWriter;
import java.io.IOException;
public class MemoryInfo {
public class MemoryInfo implements JsonSerializable<MemoryInfo> {
private final long totalInKb;
private long totalInKb;
private final long freeInKb;
private long freeInKb;
private final long virtualMemoryTotalInKb;
private long virtualMemoryTotalInKb;
private final long virtualMemoryUsedInKb;
@JsonCreator
public MemoryInfo(
@JsonProperty("totalInKB") long totalInKb,
@JsonProperty("freeInKB") long freeInKb,
@JsonProperty("virtualMemoryTotalInKB") long virtualMemoryTotalInKb,
@JsonProperty("virtualMemoryUsedInKB") long virtualMemoryUsedInKb) {
this.totalInKb = totalInKb;
this.freeInKb = freeInKb;
this.virtualMemoryTotalInKb = virtualMemoryTotalInKb;
this.virtualMemoryUsedInKb = virtualMemoryUsedInKb;
}
private long virtualMemoryUsedInKb;
public long getTotalInKb() {
return totalInKb;
}
public MemoryInfo setTotalInKb(long totalInKb) {
this.totalInKb = totalInKb;
return this;
}
public long getFreeInKb() {
return freeInKb;
}
public MemoryInfo setFreeInKb(long freeInKb) {
this.freeInKb = freeInKb;
return this;
}
public long getVirtualMemoryTotalInKb() {
return virtualMemoryTotalInKb;
}
public MemoryInfo setVirtualMemoryTotalInKb(long virtualMemoryTotalInKb) {
this.virtualMemoryTotalInKb = virtualMemoryTotalInKb;
return this;
}
public long getVirtualMemoryUsedInKb() {
return virtualMemoryUsedInKb;
}
public MemoryInfo setVirtualMemoryUsedInKb(long virtualMemoryUsedInKb) {
this.virtualMemoryUsedInKb = virtualMemoryUsedInKb;
return this;
}
@Override
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
jsonWriter.writeStartObject();
jsonWriter.writeLongField("totalInKb", totalInKb);
jsonWriter.writeLongField("freeInKb", freeInKb);
jsonWriter.writeLongField("virtualMemoryTotalInKb", virtualMemoryTotalInKb);
jsonWriter.writeLongField("virtualMemoryUsedInKb", virtualMemoryUsedInKb);
jsonWriter.writeEndObject();
return jsonWriter;
}
}

Просмотреть файл

@ -16,7 +16,12 @@ public class LinuxMemoryInfoReader extends TwoStepProcReader implements MemoryIn
private int freeInKbIndex = -1;
private int virtualMemoryTotalInKbIndex = -1;
private int virtualMemoryUsedInKbIndex = -1;
private MemoryInfo memoryInfo = new MemoryInfo(-1, -1, -1, -1);
private MemoryInfo memoryInfo =
new MemoryInfo()
.setTotalInKb(-1)
.setFreeInKb(-1)
.setVirtualMemoryTotalInKb(-1)
.setVirtualMemoryUsedInKb(-1);
public LinuxMemoryInfoReader() {
super(new File(MEMINFO));
@ -46,7 +51,11 @@ public class LinuxMemoryInfoReader extends TwoStepProcReader implements MemoryIn
long virtualMemoryTotalInKb = readMemoryNumber(lines[virtualMemoryTotalInKbIndex]);
long virtualMemoryUsedInKb = readMemoryNumber(lines[virtualMemoryUsedInKbIndex]);
return new MemoryInfo(totalInKb, freeInKb, virtualMemoryTotalInKb, virtualMemoryUsedInKb);
return new MemoryInfo()
.setTotalInKb(totalInKb)
.setFreeInKb(freeInKb)
.setVirtualMemoryTotalInKb(virtualMemoryTotalInKb)
.setVirtualMemoryUsedInKb(virtualMemoryUsedInKb);
}
private static long readMemoryNumber(String line) {

Просмотреть файл

@ -17,7 +17,11 @@ public class NoOpMemoryInfoReader implements MemoryInfoReader {
@Override
public MemoryInfo getMemoryInfo() {
return new MemoryInfo(-1, -1, -1, -1);
return new MemoryInfo()
.setTotalInKb(-1)
.setFreeInKb(-1)
.setVirtualMemoryTotalInKb(-1)
.setVirtualMemoryUsedInKb(-1);
}
@Override

Просмотреть файл

@ -3,16 +3,8 @@
package com.microsoft.applicationinsights.diagnostics.collection.libos.process;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import java.util.Map;
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type",
visible = true)
@JsonIgnoreProperties(ignoreUnknown = true)
public interface ProcessInfo extends Comparable<ProcessInfo> {
String getName();

Просмотреть файл

@ -38,7 +38,7 @@ public class CodeOptimizerDiagnosticsJfrInit {
List<Double> telemetry = statsReader.readTelemetry();
if (telemetry != null && telemetry.size() > 0) {
new Telemetry(telemetry).commit();
new Telemetry().setTelemetry(telemetry).commit();
} else {
logFailure("No telemetry data present", null, telemetryFailureLogCount);
}

Просмотреть файл

@ -36,7 +36,6 @@ import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import javax.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -74,10 +73,12 @@ public class SystemStatsProvider {
}
}
@SuppressWarnings("unchecked")
private static <T> T getSingleton(Class<T> clazz) {
return (T) singletons.get(clazz).get();
}
@SuppressWarnings("unchecked")
private static <T> T getSingleton(Class<T> clazz, Supplier<T> supplier) {
AtomicReference<T> current = (AtomicReference<T>) singletons.get(clazz);
@ -110,12 +111,14 @@ public class SystemStatsProvider {
() -> {
try {
CGroupDataReader reader = buildCGroupDataReader();
return new CGroupData(
reader.getKmemLimit(),
reader.getMemoryLimit(),
reader.getMemorySoftLimit(),
reader.getCpuLimit(),
reader.getCpuPeriod());
CGroupData data = new CGroupData();
return data.setKmemLimit(reader.getKmemLimit())
.setMemoryLimit(reader.getMemoryLimit())
.setMemorySoftLimit(reader.getMemorySoftLimit())
.setCpuLimit(reader.getCpuLimit())
.setCpuPeriod(reader.getCpuPeriod());
} catch (RuntimeException | OperatingSystemInteractionException e) {
LOGGER.warn("No CGroup data present");
return null;
@ -127,9 +130,9 @@ public class SystemStatsProvider {
return getSingleton(
MachineStats.class,
() ->
new MachineStats(
getCalibration().getContextSwitchingRate(),
new RuntimeCoreCounter().getCoreCount()));
new MachineStats()
.setContextSwitchesPerMs(getCalibration().getContextSwitchingRate())
.setCoreCount(new RuntimeCoreCounter().getCoreCount()));
}
private static Calibration getCalibration() {
@ -170,7 +173,6 @@ public class SystemStatsProvider {
}
}
@Nullable
@SuppressWarnings("checkstyle:AbbreviationAsWordInName")
private static ProcessDumper getProcessDumper() {
ThisPidSupplier pidSupplier = getSingleton(ThisPidSupplier.class);

Просмотреть файл

@ -3,73 +3,202 @@
package com.microsoft.applicationinsights.agent.internal.profiler.config;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.azure.json.JsonReader;
import com.azure.json.JsonSerializable;
import com.azure.json.JsonToken;
import com.azure.json.JsonWriter;
import com.fasterxml.jackson.databind.util.StdDateFormat;
import com.google.auto.value.AutoValue;
import com.microsoft.applicationinsights.agent.internal.profiler.util.TimestampContract;
import com.microsoft.applicationinsights.alerting.aiconfig.AlertingConfig;
import java.io.IOException;
import java.text.ParseException;
import java.util.Date;
import java.util.List;
import javax.annotation.Nullable;
@AutoValue
public abstract class ProfilerConfiguration {
public class ProfilerConfiguration implements JsonSerializable<ProfilerConfiguration> {
public static final Date DEFAULT_DATE;
// TODO find an alternative to com.fasterxml.jackson.databind.util.StdDateFormat
private static final StdDateFormat STD_DATE_FORMAT;
static {
STD_DATE_FORMAT = new StdDateFormat();
Date defaultDate;
try {
defaultDate = new StdDateFormat().parse("0001-01-01T00:00:00+00:00");
defaultDate = STD_DATE_FORMAT.parse("0001-01-01T00:00:00+00:00");
} catch (ParseException e) {
// will not happen
defaultDate = null;
}
DEFAULT_DATE = defaultDate;
}
@JsonCreator
public static ProfilerConfiguration create(
@JsonProperty("lastModified") Date lastModified,
@JsonProperty("enabled") boolean enabled,
@JsonProperty("collectionPlan") String collectionPlan,
@JsonProperty("cpuTriggerConfiguration") String cpuTriggerConfiguration,
@JsonProperty("memoryTriggerConfiguration") String memoryTriggerConfiguration,
@JsonProperty("defaultConfiguration") String defaultConfiguration,
@JsonProperty("requestTriggerConfiguration")
List<AlertingConfig.RequestTrigger> requestTriggerConfiguration) {
return new AutoValue_ProfilerConfiguration(
lastModified,
enabled,
collectionPlan,
cpuTriggerConfiguration,
memoryTriggerConfiguration,
defaultConfiguration,
requestTriggerConfiguration);
}
private String id;
private Date lastModified;
private Date enabledLastModified;
private boolean enabled;
private String collectionPlan;
private String cpuTriggerConfiguration;
private String memoryTriggerConfiguration;
private String defaultConfiguration;
private List<AlertingConfig.RequestTrigger> requestTriggerConfiguration;
public boolean hasBeenConfigured() {
return getLastModified().compareTo(DEFAULT_DATE) != 0;
}
public abstract Date getLastModified();
public String id() {
return id;
}
public abstract boolean isEnabled();
public ProfilerConfiguration setId(String id) {
this.id = id;
return this;
}
public Date getLastModified() {
return lastModified;
}
public ProfilerConfiguration setLastModified(Date lastModified) {
this.lastModified = lastModified;
return this;
}
public Date getEnabledLastModified() {
return enabledLastModified;
}
public ProfilerConfiguration setEnabledLastModified(Date enabledLastModified) {
this.enabledLastModified = enabledLastModified;
return this;
}
public boolean isEnabled() {
return enabled;
}
public ProfilerConfiguration setEnabled(boolean enabled) {
this.enabled = enabled;
return this;
}
@Nullable
public abstract String getCollectionPlan();
public String getCollectionPlan() {
return collectionPlan;
}
public ProfilerConfiguration setCollectionPlan(String collectionPlan) {
this.collectionPlan = collectionPlan;
return this;
}
@Nullable
public abstract String getCpuTriggerConfiguration();
public String getCpuTriggerConfiguration() {
return cpuTriggerConfiguration;
}
public ProfilerConfiguration setCpuTriggerConfiguration(String cpuTriggerConfiguration) {
this.cpuTriggerConfiguration = cpuTriggerConfiguration;
return this;
}
@Nullable
public abstract String getMemoryTriggerConfiguration();
public String getMemoryTriggerConfiguration() {
return memoryTriggerConfiguration;
}
public ProfilerConfiguration setMemoryTriggerConfiguration(String memoryTriggerConfiguration) {
this.memoryTriggerConfiguration = memoryTriggerConfiguration;
return this;
}
@Nullable
public abstract String getDefaultConfiguration();
public String getDefaultConfiguration() {
return defaultConfiguration;
}
public ProfilerConfiguration setDefaultConfiguration(String defaultConfiguration) {
this.defaultConfiguration = defaultConfiguration;
return this;
}
@Nullable
public abstract List<AlertingConfig.RequestTrigger> getRequestTriggerConfiguration();
public List<AlertingConfig.RequestTrigger> getRequestTriggerConfiguration() {
return requestTriggerConfiguration;
}
public ProfilerConfiguration setRequestTriggerConfiguration(
List<AlertingConfig.RequestTrigger> requestTriggerConfiguration) {
this.requestTriggerConfiguration = requestTriggerConfiguration;
return this;
}
@Override
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
jsonWriter.writeStartObject();
jsonWriter.writeStringField("id", id);
jsonWriter.writeStringField("lastModified", STD_DATE_FORMAT.format(lastModified));
jsonWriter.writeStringField(
"enabledLastModified", TimestampContract.timestampToString(enabledLastModified));
jsonWriter.writeBooleanField("enabled", enabled);
jsonWriter.writeStringField("collectionPlan", collectionPlan);
jsonWriter.writeStringField("cpuTriggerConfiguration", cpuTriggerConfiguration);
jsonWriter.writeStringField("memoryTriggerConfiguration", memoryTriggerConfiguration);
jsonWriter.writeStringField("defaultConfiguration", defaultConfiguration);
jsonWriter.writeStartArray("requestTriggerConfiguration");
for (AlertingConfig.RequestTrigger trigger : requestTriggerConfiguration) {
trigger.toJson(jsonWriter);
}
jsonWriter.writeEndArray();
jsonWriter.writeEndObject();
return jsonWriter;
}
public static ProfilerConfiguration fromJson(JsonReader jsonReader) throws IOException {
return jsonReader.readObject(
reader -> {
ProfilerConfiguration deserializedProfilerConfiguration = new ProfilerConfiguration();
while (reader.nextToken() != JsonToken.END_OBJECT) {
reader.nextToken();
String fieldName = reader.getFieldName();
if ("id".equals(fieldName)) {
String id = reader.getString();
deserializedProfilerConfiguration.setId(id);
} else if ("lastModified".equals(fieldName)) {
String lastModified = reader.getString();
try {
deserializedProfilerConfiguration.setLastModified(
new StdDateFormat().parse(lastModified));
} catch (ParseException ignored) {
deserializedProfilerConfiguration.setLastModified(DEFAULT_DATE);
}
} else if ("enabledLastModified".equals(fieldName)) {
String enabledLastModified = reader.getString();
try {
deserializedProfilerConfiguration.setEnabledLastModified(
STD_DATE_FORMAT.parse(enabledLastModified));
} catch (ParseException ignored) {
deserializedProfilerConfiguration.setEnabledLastModified(DEFAULT_DATE);
}
} else if ("enabled".equals(fieldName)) {
deserializedProfilerConfiguration.setEnabled(reader.getBoolean());
} else if ("collectionPlan".equals(fieldName)) {
deserializedProfilerConfiguration.setCollectionPlan(reader.getString());
} else if ("cpuTriggerConfiguration".equals(fieldName)) {
deserializedProfilerConfiguration.setCpuTriggerConfiguration(reader.getString());
} else if ("memoryTriggerConfiguration".equals(fieldName)) {
deserializedProfilerConfiguration.setMemoryTriggerConfiguration(reader.getString());
} else if ("defaultConfiguration".equals(fieldName)) {
deserializedProfilerConfiguration.setDefaultConfiguration(reader.getString());
} else if ("requestTriggerConfiguration".equals(fieldName)) {
deserializedProfilerConfiguration.setRequestTriggerConfiguration(
reader.readArray(AlertingConfig.RequestTrigger::fromJson));
} else {
reader.skipChildren();
}
}
return deserializedProfilerConfiguration;
});
}
}

Просмотреть файл

@ -3,29 +3,87 @@
package com.microsoft.applicationinsights.agent.internal.profiler.service;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.auto.value.AutoValue;
import com.azure.json.JsonReader;
import com.azure.json.JsonSerializable;
import com.azure.json.JsonToken;
import com.azure.json.JsonWriter;
import java.io.IOException;
/** Result of uploading an artifact to service profiler. */
@AutoValue
public abstract class ArtifactAcceptedResponse {
public class ArtifactAcceptedResponse implements JsonSerializable<ArtifactAcceptedResponse> {
@JsonCreator
public static ArtifactAcceptedResponse create(
@JsonProperty("acceptedTime") String acceptedTime,
@JsonProperty("blobUri") String blobUri,
@JsonProperty("correlationId") String correlationId,
@JsonProperty("stampId") String stampId) {
private String acceptedTime;
private String stampId;
private String correlationId;
private String blobUri;
return new AutoValue_ArtifactAcceptedResponse(acceptedTime, stampId, correlationId, blobUri);
public String getAcceptedTime() {
return acceptedTime;
}
public abstract String getAcceptedTime();
public ArtifactAcceptedResponse setAcceptedTime(String acceptedTime) {
this.acceptedTime = acceptedTime;
return this;
}
public abstract String getStampId();
public String getStampId() {
return stampId;
}
public abstract String getCorrelationId();
public ArtifactAcceptedResponse setStampId(String stampId) {
this.stampId = stampId;
return this;
}
public abstract String getBlobUri();
public String getCorrelationId() {
return correlationId;
}
public ArtifactAcceptedResponse setCorrelationId(String correlationId) {
this.correlationId = correlationId;
return this;
}
public String getBlobUri() {
return blobUri;
}
public ArtifactAcceptedResponse setBlobUri(String blobUri) {
this.blobUri = blobUri;
return this;
}
@Override
public JsonWriter toJson(JsonWriter jsonWriter) throws IOException {
jsonWriter.writeStartObject();
jsonWriter.writeStringField("acceptedTime", acceptedTime);
jsonWriter.writeStringField("stampId", stampId);
jsonWriter.writeStringField("correlationId", correlationId);
jsonWriter.writeStringField("blobUri", blobUri);
jsonWriter.writeEndObject();
return jsonWriter;
}
public static ArtifactAcceptedResponse fromJson(JsonReader jsonReader) throws IOException {
return jsonReader.readObject(
reader -> {
ArtifactAcceptedResponse deserializedArtifactAcceptedResponse =
new ArtifactAcceptedResponse();
while (reader.nextToken() != JsonToken.END_OBJECT) {
String fieldName = reader.getFieldName();
if ("acceptedTime".equals(fieldName)) {
deserializedArtifactAcceptedResponse.setAcceptedTime(reader.getString());
} else if ("stampId".equals(fieldName)) {
deserializedArtifactAcceptedResponse.setStampId(reader.getString());
} else if ("correlationId".equals(fieldName)) {
deserializedArtifactAcceptedResponse.setCorrelationId(reader.getString());
} else if ("blobUri".equals(fieldName)) {
deserializedArtifactAcceptedResponse.setBlobUri(reader.getString());
} else {
reader.skipChildren();
}
}
return deserializedArtifactAcceptedResponse;
});
}
}

Просмотреть файл

@ -8,8 +8,8 @@ import com.azure.core.http.HttpMethod;
import com.azure.core.http.HttpPipeline;
import com.azure.core.http.HttpRequest;
import com.azure.core.http.HttpResponse;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.azure.json.JsonProviders;
import com.azure.json.JsonReader;
import com.microsoft.applicationinsights.agent.internal.profiler.config.ProfilerConfiguration;
import com.microsoft.applicationinsights.agent.internal.profiler.util.TimestampContract;
import java.io.IOException;
@ -27,9 +27,6 @@ public class ServiceProfilerClient {
private static final Logger logger = LoggerFactory.getLogger(ServiceProfilerClient.class);
private static final ObjectMapper mapper =
new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
private static final String PROFILER_API_PREFIX = "api/profileragent/v4";
private static final String INSTRUMENTATION_KEY_PARAMETER = "iKey";
@ -108,9 +105,8 @@ public class ServiceProfilerClient {
// this shouldn't happen, the mono should complete with a response or a failure
return Mono.error(new AssertionError("response body mono returned empty"));
}
try {
ArtifactAcceptedResponse data =
mapper.readValue(json, ArtifactAcceptedResponse.class);
try (JsonReader reader = JsonProviders.createReader(json)) {
ArtifactAcceptedResponse data = ArtifactAcceptedResponse.fromJson(reader);
if (data == null) {
return Mono.error(new IllegalStateException("Failed to deserialize response"));
}
@ -165,8 +161,8 @@ public class ServiceProfilerClient {
.getBodyAsString()
.flatMap(
body -> {
try {
return Mono.just(mapper.readValue(body, ProfilerConfiguration.class));
try (JsonReader jsonReader = JsonProviders.createReader(body)) {
return Mono.just(ProfilerConfiguration.fromJson(jsonReader));
} catch (IOException e) {
return Mono.error(e);
}

Просмотреть файл

@ -70,40 +70,45 @@ class RequestAlertPipelineBuilder {
AlertingConfig.RequestTriggerType.valueOf(configuration.type.name());
AlertingConfig.RequestFilter filter =
new AlertingConfig.RequestFilter(
AlertingConfig.RequestFilterType.valueOf(configuration.filter.type.name()),
configuration.filter.value);
new AlertingConfig.RequestFilter()
.setType(AlertingConfig.RequestFilterType.valueOf(configuration.filter.type.name()))
.setValue(configuration.filter.value);
AlertingConfig.RequestAggregationConfig requestAggregationConfig =
new AlertingConfig.RequestAggregationConfig(
configuration.aggregation.configuration.thresholdMillis,
configuration.aggregation.configuration.minimumSamples);
new AlertingConfig.RequestAggregationConfig()
.setThresholdMillis(configuration.aggregation.configuration.thresholdMillis)
.setMinimumSamples(configuration.aggregation.configuration.minimumSamples);
AlertingConfig.RequestAggregation aggregation =
new AlertingConfig.RequestAggregation(
AlertingConfig.RequestAggregationType.valueOf(configuration.aggregation.type.name()),
configuration.aggregation.windowSizeMillis,
requestAggregationConfig);
new AlertingConfig.RequestAggregation()
.setType(
AlertingConfig.RequestAggregationType.valueOf(
configuration.aggregation.type.name()))
.setWindowSizeMillis(configuration.aggregation.windowSizeMillis)
.setConfiguration(requestAggregationConfig);
AlertingConfig.RequestTriggerThreshold requestTriggerThreshold =
new AlertingConfig.RequestTriggerThreshold(
AlertingConfig.RequestTriggerThresholdType.valueOf(configuration.threshold.type.name()),
configuration.threshold.value);
new AlertingConfig.RequestTriggerThreshold()
.setType(
AlertingConfig.RequestTriggerThresholdType.valueOf(
configuration.threshold.type.name()))
.setValue(configuration.threshold.value);
AlertingConfig.RequestTriggerThrottling throttling =
new AlertingConfig.RequestTriggerThrottling(
AlertingConfig.RequestTriggerThrottlingType.valueOf(
configuration.throttling.type.name()),
configuration.throttling.value);
new AlertingConfig.RequestTriggerThrottling()
.setType(
AlertingConfig.RequestTriggerThrottlingType.valueOf(
configuration.throttling.type.name()))
.setValue(configuration.throttling.value);
return new AlertingConfig.RequestTrigger(
configuration.name,
type,
filter,
aggregation,
requestTriggerThreshold,
throttling,
configuration.profileDuration);
return new AlertingConfig.RequestTrigger()
.setName(configuration.name)
.setType(type)
.setFilter(filter)
.setAggregation(aggregation)
.setThreshold(requestTriggerThreshold)
.setThrottling(throttling)
.setProfileDuration(configuration.profileDuration);
}
@Nullable

Просмотреть файл

@ -22,7 +22,7 @@ import java.util.regex.Pattern;
*/
public final class TimestampContract {
// Cant use ISO_INSTANT as it does not pad the nanos to 7 figures
private static final DateTimeFormatter FORMATTER =
public static final DateTimeFormatter FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.nX", Locale.ROOT);
private static final Pattern TIMESTAMP_PATTERN = Pattern.compile(".*\\.([0-9]+)Z$");

Просмотреть файл

@ -166,28 +166,28 @@ public class ProfilingInitializerTest {
@NotNull
private static ProfilerConfiguration unconfiguredState() {
return ProfilerConfiguration.create(
ProfilerConfiguration.DEFAULT_DATE,
true,
"",
"--cpu-threshold 80 --cpu-trigger-profilingDuration 120 --cpu-trigger-cooldown 14400 --cpu-trigger-enabled true",
"--memory-threshold 80 --memory-trigger-profilingDuration 120 --memory-trigger-cooldown 14400 --memory-trigger-enabled true",
null,
null);
return new ProfilerConfiguration()
.setLastModified(ProfilerConfiguration.DEFAULT_DATE)
.setEnabled(true)
.setCollectionPlan("")
.setCpuTriggerConfiguration(
"--cpu-threshold 80 --cpu-trigger-profilingDuration 120 --cpu-trigger-cooldown 14400 --cpu-trigger-enabled true")
.setMemoryTriggerConfiguration(
"--memory-threshold 80 --memory-trigger-profilingDuration 120 --memory-trigger-cooldown 14400 --memory-trigger-enabled true");
}
@NotNull
private static ProfilerConfiguration userConfiguredTriggersState(boolean triggersEnabled) {
return ProfilerConfiguration.create(
new Date(Instant.now().toEpochMilli()),
true,
"",
"--cpu-threshold 80 --cpu-trigger-profilingDuration 120 --cpu-trigger-cooldown 14400 --cpu-trigger-enabled "
+ triggersEnabled,
"--memory-threshold 80 --memory-trigger-profilingDuration 120 --memory-trigger-cooldown 14400 --memory-trigger-enabled "
+ triggersEnabled,
null,
null);
return new ProfilerConfiguration()
.setLastModified(new Date(Instant.now().toEpochMilli()))
.setEnabled(true)
.setCollectionPlan("")
.setCpuTriggerConfiguration(
"--cpu-threshold 80 --cpu-trigger-profilingDuration 120 --cpu-trigger-cooldown 14400 --cpu-trigger-enabled "
+ triggersEnabled)
.setMemoryTriggerConfiguration(
"--memory-threshold 80 --memory-trigger-profilingDuration 120 --memory-trigger-cooldown 14400 --memory-trigger-enabled "
+ triggersEnabled);
}
@NotNull
@ -200,18 +200,19 @@ public class ProfilingInitializerTest {
expiration = Instant.now().plus(100, ChronoUnit.SECONDS);
}
return ProfilerConfiguration.create(
new Date(Instant.now().minus(10, ChronoUnit.SECONDS).toEpochMilli()),
true,
"--single --mode immediate --immediate-profiling-duration 120 --expiration "
+ toBinaryDate(expiration)
+ " --settings-moniker a-settings-moniker",
"--cpu-threshold 80 --cpu-trigger-profilingDuration 120 --cpu-trigger-cooldown 14400 --cpu-trigger-enabled "
+ triggersEnabled,
"--memory-threshold 80 --memory-trigger-profilingDuration 120 --memory-trigger-cooldown 14400 --memory-trigger-enabled "
+ triggersEnabled,
null,
null);
return new ProfilerConfiguration()
.setLastModified(new Date(Instant.now().minus(10, ChronoUnit.SECONDS).toEpochMilli()))
.setEnabled(true)
.setCollectionPlan(
"--single --mode immediate --immediate-profiling-duration 120 --expiration "
+ toBinaryDate(expiration)
+ " --settings-moniker a-settings-moniker")
.setCpuTriggerConfiguration(
"--cpu-threshold 80 --cpu-trigger-profilingDuration 120 --cpu-trigger-cooldown 14400 --cpu-trigger-enabled "
+ triggersEnabled)
.setMemoryTriggerConfiguration(
"--memory-threshold 80 --memory-trigger-profilingDuration 120 --memory-trigger-cooldown 14400 --memory-trigger-enabled "
+ triggersEnabled);
}
@SuppressWarnings("DirectInvocationOnMock")

Просмотреть файл

@ -11,7 +11,7 @@ import com.azure.core.http.HttpPipeline;
import com.azure.core.http.HttpPipelineBuilder;
import com.azure.core.test.TestBase;
import com.azure.core.test.TestMode;
import com.fasterxml.jackson.core.JsonParseException;
import com.azure.json.implementation.jackson.core.JsonParseException;
import com.microsoft.applicationinsights.agent.internal.profiler.service.ServiceProfilerClient;
import java.io.IOException;
import java.net.MalformedURLException;

Просмотреть файл

@ -78,20 +78,31 @@ class AlertConfigParserTest {
@Test
void requestTriggerIsBuilt() {
AlertingConfig.RequestTrigger requestTrigger =
new AlertingConfig.RequestTrigger(
"test",
AlertingConfig.RequestTriggerType.LATENCY,
new AlertingConfig.RequestFilter(
AlertingConfig.RequestFilterType.NAME_REGEX, "/api/users/.*"),
new AlertingConfig.RequestAggregation(
AlertingConfig.RequestAggregationType.BREACH_RATIO,
7000,
new AlertingConfig.RequestAggregationConfig(10000, 10)),
new AlertingConfig.RequestTriggerThreshold(
AlertingConfig.RequestTriggerThresholdType.GREATER_THAN, 0.75f),
new AlertingConfig.RequestTriggerThrottling(
AlertingConfig.RequestTriggerThrottlingType.FIXED_DURATION_COOLDOWN, 1800),
10);
new AlertingConfig.RequestTrigger()
.setName("test")
.setType(AlertingConfig.RequestTriggerType.LATENCY)
.setFilter(
new AlertingConfig.RequestFilter()
.setType(AlertingConfig.RequestFilterType.NAME_REGEX)
.setValue("/api/users/.*"))
.setAggregation(
new AlertingConfig.RequestAggregation()
.setType(AlertingConfig.RequestAggregationType.BREACH_RATIO)
.setWindowSizeMillis(7000)
.setConfiguration(
new AlertingConfig.RequestAggregationConfig()
.setThresholdMillis(10000)
.setMinimumSamples(10)))
.setThreshold(
new AlertingConfig.RequestTriggerThreshold()
.setType(AlertingConfig.RequestTriggerThresholdType.GREATER_THAN)
.setValue(0.75f))
.setThrottling(
new AlertingConfig.RequestTriggerThrottling()
.setType(AlertingConfig.RequestTriggerThrottlingType.FIXED_DURATION_COOLDOWN)
.setValue(1800))
.setProfileDuration(10);
List<AlertingConfig.RequestTrigger> requestTriggers = new ArrayList<>();
requestTriggers.add(requestTrigger);

Просмотреть файл

@ -3,12 +3,14 @@
package com.microsoft.applicationinsights.agent.internal.profiler.triggers;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.azure.json.JsonProviders;
import com.azure.json.JsonReader;
import com.azure.json.JsonWriter;
import com.microsoft.applicationinsights.agent.internal.configuration.Configuration;
import com.microsoft.applicationinsights.agent.internal.profiler.testutil.TestTimeSource;
import com.microsoft.applicationinsights.alerting.aiconfig.AlertingConfig;
import java.io.IOException;
import java.io.StringWriter;
import java.time.Instant;
import java.util.List;
import java.util.stream.Collectors;
@ -21,24 +23,47 @@ import org.junit.jupiter.api.TestFactory;
public class RequestAlertPipelineBuilderTest {
@Test
public void configurationIsCorrectlyDuplicated() throws JsonProcessingException {
Configuration.RequestTrigger triggerConfig = new Configuration.RequestTrigger();
triggerConfig.filter.type = Configuration.RequestFilterType.NAME_REGEX;
triggerConfig.filter.value = "foo.*";
triggerConfig.threshold.value = 0.75f;
public void configurationIsCorrectlyDuplicated() throws IOException {
Configuration.RequestTrigger expectedRequestTrigger = new Configuration.RequestTrigger();
expectedRequestTrigger.filter.type = Configuration.RequestFilterType.NAME_REGEX;
expectedRequestTrigger.filter.value = "foo.*";
expectedRequestTrigger.threshold.value = 0.75f;
TestTimeSource timeSource = new TestTimeSource();
timeSource.setNow(Instant.EPOCH);
AlertingConfig.RequestTrigger config =
RequestAlertPipelineBuilder.buildRequestTriggerConfiguration(triggerConfig);
RequestAlertPipelineBuilder.buildRequestTriggerConfiguration(expectedRequestTrigger);
ObjectMapper mapper = new ObjectMapper();
String configurationStr = mapper.writeValueAsString(triggerConfig);
String alertingConfigStr = mapper.writeValueAsString(config);
;
String alertingConfigStr;
try (StringWriter stringWriter = new StringWriter();
JsonWriter writer = JsonProviders.createWriter(stringWriter)) {
config.toJson(writer).flush();
alertingConfigStr = stringWriter.toString();
}
AlertingConfig.RequestTrigger actualAlertingConfig;
try (JsonReader reader = JsonProviders.createReader(alertingConfigStr)) {
actualAlertingConfig = AlertingConfig.RequestTrigger.fromJson(reader);
}
Assertions.assertEquals(configurationStr, alertingConfigStr);
Assertions.assertEquals(expectedRequestTrigger.name, actualAlertingConfig.name);
Assertions.assertEquals(expectedRequestTrigger.type.name(), actualAlertingConfig.type.name());
Assertions.assertEquals(
expectedRequestTrigger.filter.type.name(), actualAlertingConfig.filter.type.name());
Assertions.assertEquals(expectedRequestTrigger.filter.value, actualAlertingConfig.filter.value);
Assertions.assertEquals(
expectedRequestTrigger.aggregation.type.name(),
actualAlertingConfig.aggregation.type.name());
Assertions.assertEquals(
expectedRequestTrigger.threshold.type.name(), actualAlertingConfig.threshold.type.name());
Assertions.assertEquals(
expectedRequestTrigger.threshold.value, actualAlertingConfig.threshold.value);
Assertions.assertEquals(
expectedRequestTrigger.throttling.type.name(), actualAlertingConfig.throttling.type.name());
Assertions.assertEquals(
expectedRequestTrigger.throttling.value, actualAlertingConfig.throttling.value);
Assertions.assertEquals(
expectedRequestTrigger.profileDuration, actualAlertingConfig.profileDuration);
}
@TestFactory
@ -52,28 +77,15 @@ public class RequestAlertPipelineBuilderTest {
DynamicTest.dynamicTest(
file,
() -> {
ObjectMapper mapper = new ObjectMapper();
JsonNode array =
mapper
.readTree(
RequestAlertPipelineBuilderTest.class
.getClassLoader()
.getResourceAsStream(file))
.get("preview")
.get("profiler")
.withArray("requestTriggerEndpoints");
array.forEach(
config -> {
try {
AlertingConfig.RequestTrigger alertingConfig =
mapper.readValue(
config.toPrettyString(), AlertingConfig.RequestTrigger.class);
Assertions.assertNotNull(alertingConfig);
} catch (JsonProcessingException e) {
Assertions.fail(e);
}
});
try (JsonReader reader =
JsonProviders.createReader(
RequestAlertPipelineBuilderTest.class
.getClassLoader()
.getResourceAsStream(file))) {
AlertingConfig.RequestTrigger alertingConfig =
AlertingConfig.RequestTrigger.fromJson(reader);
Assertions.assertNotNull(alertingConfig);
}
}))
.collect(Collectors.toList());
}

Просмотреть файл

@ -60,4 +60,8 @@
<Class name="com.microsoft.applicationinsights.extensibility.context.ContextTagKeys"/>
<Bug pattern="SING_SINGLETON_GETTER_NOT_SYNCHRONIZED"/> <!-- inner class use default encoding can be ignored -->
</Match>
<Match>
<Class name="com.microsoft.applicationinsights.agent.internal.profiler.config.ProfilerConfiguration"/>
<Bug pattern="STCAL_INVOKE_ON_STATIC_DATE_FORMAT_INSTANCE"/> <!-- inner class use default encoding can be ignored -->
</Match>
</FindBugsFilter>

Просмотреть файл

@ -33,7 +33,6 @@ include(":agent:agent-gc-monitor:gc-monitor-core")
include(":agent:agent-gc-monitor:gc-monitor-tests")
include(":agent:agent-profiler:agent-diagnostics-jfr")
include(":agent:agent-profiler:agent-diagnostics-serialization")
include(":agent:agent-profiler:agent-alerting-api")
include(":agent:agent-profiler:agent-diagnostics-api")
include(":agent:agent-profiler:agent-diagnostics")