Migrate profiler code from jackson json to azure json (#3896)
Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>
This commit is contained in:
Родитель
3ba19119d4
Коммит
439cd29729
|
@ -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")
|
||||
|
|
Загрузка…
Ссылка в новой задаче