Skip to content

Commit

Permalink
Add BWC layer
Browse files Browse the repository at this point in the history
  • Loading branch information
danielmitterdorfer committed May 7, 2024
1 parent 9a8ba58 commit 885015b
Show file tree
Hide file tree
Showing 11 changed files with 395 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public void testGetStackTracesUnfiltered() throws Exception {
null,
null,
null,
null,
null
);
GetFlamegraphResponse response = client().execute(GetFlamegraphAction.INSTANCE, request).get();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public void testGetStackTracesUnfiltered() throws Exception {
null,
null,
null,
null,
null
);
request.setAdjustSampleCount(true);
Expand Down Expand Up @@ -72,6 +73,7 @@ public void testGetStackTracesGroupedByServiceName() throws Exception {
null,
null,
null,
null,
null
);
request.setAdjustSampleCount(true);
Expand Down Expand Up @@ -116,11 +118,12 @@ public void testGetStackTracesGroupedByInvalidField() {
null,
null,
null,
null,
null
);
request.setAdjustSampleCount(true);
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, client().execute(GetStackTracesAction.INSTANCE, request));
assertEquals("Requested custom event aggregation field [service.names] but only [service.name] is supported.", e.getMessage());
assertEquals("Requested custom event aggregation fields [service.names] but only [service.name] is supported.", e.getMessage());
}

public void testGetStackTracesFromAPMWithMatchNoDownsampling() throws Exception {
Expand All @@ -142,6 +145,7 @@ public void testGetStackTracesFromAPMWithMatchNoDownsampling() throws Exception
null,
null,
null,
null,
null
);
GetStackTracesResponse response = client().execute(GetStackTracesAction.INSTANCE, request).get();
Expand Down Expand Up @@ -187,6 +191,7 @@ public void testGetStackTracesFromAPMWithMatchAndDownsampling() throws Exception
null,
null,
null,
null,
null
);
// ensures consistent results in the random sampler aggregation that is used internally
Expand Down Expand Up @@ -237,6 +242,7 @@ public void testGetStackTracesFromAPMNoMatch() throws Exception {
null,
null,
null,
null,
null
);
GetStackTracesResponse response = client().execute(GetStackTracesAction.INSTANCE, request).get();
Expand All @@ -259,6 +265,7 @@ public void testGetStackTracesFromAPMIndexNotAvailable() throws Exception {
null,
null,
null,
null,
null
);
GetStackTracesResponse response = client().execute(GetStackTracesAction.INSTANCE, request).get();
Expand All @@ -281,6 +288,7 @@ public void testGetStackTracesFromAPMStackTraceFieldNotAvailable() throws Except
null,
null,
null,
null,
null
);
GetStackTracesResponse response = client().execute(GetStackTracesAction.INSTANCE, request).get();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public void testGetTopNFunctionsUnfiltered() throws Exception {
null,
null,
null,
null,
null
);
request.setAdjustSampleCount(true);
Expand All @@ -46,6 +47,7 @@ public void testGetTopNFunctionsGroupedByServiceName() throws Exception {
null,
null,
null,
null,
null
);
request.setAdjustSampleCount(true);
Expand Down Expand Up @@ -73,6 +75,7 @@ public void testGetTopNFunctionsFromAPM() throws Exception {
null,
null,
null,
null,
null
);
GetTopNFunctionsResponse response = client().execute(GetTopNFunctionsAction.INSTANCE, request).get();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import org.elasticsearch.action.support.TransportAction;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.core.UpdateForV9;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.tasks.CancellableTask;
import org.elasticsearch.tasks.Task;
Expand Down Expand Up @@ -42,7 +43,9 @@ public class GetStackTracesRequest extends ActionRequest implements IndicesReque
public static final ParseField LIMIT_FIELD = new ParseField("limit");
public static final ParseField INDICES_FIELD = new ParseField("indices");
public static final ParseField STACKTRACE_IDS_FIELD = new ParseField("stacktrace_ids_field");
@UpdateForV9 // Remove this BWC layer and allow only AGGREGATION_FIELDS
public static final ParseField AGGREGATION_FIELD = new ParseField("aggregation_field");
public static final ParseField AGGREGATION_FIELDS = new ParseField("aggregation_fields");
public static final ParseField REQUESTED_DURATION_FIELD = new ParseField("requested_duration");
public static final ParseField AWS_COST_FACTOR_FIELD = new ParseField("aws_cost_factor");
public static final ParseField AZURE_COST_FACTOR_FIELD = new ParseField("azure_cost_factor");
Expand All @@ -59,7 +62,9 @@ public class GetStackTracesRequest extends ActionRequest implements IndicesReque
private String[] indices;
private boolean userProvidedIndices;
private String stackTraceIdsField;
@UpdateForV9 // Remove this BWC layer and allow only aggregationFields
private String aggregationField;
private String[] aggregationFields;
private Double requestedDuration;
private Double awsCostFactor;
private Double azureCostFactor;
Expand All @@ -78,7 +83,7 @@ public class GetStackTracesRequest extends ActionRequest implements IndicesReque
private Integer shardSeed;

public GetStackTracesRequest() {
this(null, null, null, null, null, null, null, null, null, null, null, null, null);
this(null, null, null, null, null, null, null, null, null, null, null, null, null, null);
}

public GetStackTracesRequest(
Expand All @@ -90,6 +95,7 @@ public GetStackTracesRequest(
String[] indices,
String stackTraceIdsField,
String aggregationField,
String[] aggregationFields,
Double customCO2PerKWH,
Double customDatacenterPUE,
Double customPerCoreWattX86,
Expand All @@ -105,6 +111,7 @@ public GetStackTracesRequest(
this.userProvidedIndices = indices != null && indices.length > 0;
this.stackTraceIdsField = stackTraceIdsField;
this.aggregationField = aggregationField;
this.aggregationFields = aggregationFields;
this.customCO2PerKWH = customCO2PerKWH;
this.customDatacenterPUE = customDatacenterPUE;
this.customPerCoreWattX86 = customPerCoreWattX86;
Expand Down Expand Up @@ -181,6 +188,19 @@ public String getAggregationField() {
return aggregationField;
}

public String[] getAggregationFields() {
return aggregationField != null ? new String[] { aggregationField } : aggregationFields;
}

public boolean hasAggregationFields() {
String[] f = getAggregationFields();
return f != null && f.length > 0;
}

public boolean isLegacyAggregationField() {
return aggregationField != null;
}

public boolean isAdjustSampleCount() {
return Boolean.TRUE.equals(adjustSampleCount);
}
Expand Down Expand Up @@ -244,8 +264,10 @@ public void parseXContent(XContentParser parser) throws IOException {
}
} else if (token == XContentParser.Token.START_ARRAY) {
if (INDICES_FIELD.match(currentFieldName, parser.getDeprecationHandler())) {
this.indices = parseIndices(parser);
this.indices = parseToStringArray(parser, INDICES_FIELD);
this.userProvidedIndices = true;
} else if (AGGREGATION_FIELDS.match(currentFieldName, parser.getDeprecationHandler())) {
this.aggregationFields = parseToStringArray(parser, AGGREGATION_FIELDS);
} else {
throw new ParsingException(parser.getTokenLocation(), "Unexpected token " + token + " in [" + currentFieldName + "].");
}
Expand All @@ -260,12 +282,12 @@ public void parseXContent(XContentParser parser) throws IOException {
}
}

private String[] parseIndices(XContentParser parser) throws IOException {
private String[] parseToStringArray(XContentParser parser, ParseField parseField) throws IOException {
XContentParser.Token token;
List<String> indices = new ArrayList<>();
List<String> values = new ArrayList<>();
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
if (token == XContentParser.Token.VALUE_STRING) {
indices.add(parser.text());
values.add(parser.text());
} else {
throw new ParsingException(
parser.getTokenLocation(),
Expand All @@ -274,12 +296,12 @@ private String[] parseIndices(XContentParser parser) throws IOException {
+ "] but found ["
+ token
+ "] in ["
+ INDICES_FIELD.getPreferredName()
+ parseField.getPreferredName()
+ "]."
);
}
}
return indices.toArray(new String[0]);
return values.toArray(new String[0]);
}

@Override
Expand All @@ -300,6 +322,32 @@ public ActionRequestValidationException validate() {
);
}
}
if (aggregationField != null && aggregationFields != null) {
validationException = addValidationError(
"["
+ AGGREGATION_FIELD.getPreferredName()
+ "] must not be set when ["
+ AGGREGATION_FIELDS.getPreferredName()
+ "] is also set",
validationException
);

}
if (aggregationFields != null) {
// limit so we avoid an explosion of buckets
if (aggregationFields.length < 1 || aggregationFields.length > 2) {
validationException = addValidationError(
"["
+ AGGREGATION_FIELDS.getPreferredName()
+ "] must contain either one or two elements but contains ["
+ aggregationFields.length
+ "] elements.",
validationException
);
}

}

if (aggregationField != null && aggregationField.isBlank()) {
validationException = addValidationError(
"[" + AGGREGATION_FIELD.getPreferredName() + "] must be non-empty",
Expand Down Expand Up @@ -339,6 +387,7 @@ public String getDescription() {
appendField(sb, "indices", indices);
appendField(sb, "stacktrace_ids_field", stackTraceIdsField);
appendField(sb, "aggregation_field", aggregationField);
appendField(sb, "aggregation_fields", aggregationFields);
appendField(sb, "sample_size", sampleSize);
appendField(sb, "limit", limit);
appendField(sb, "requested_duration", requestedDuration);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,36 @@

package org.elasticsearch.xpack.profiling.action;

import org.elasticsearch.xcontent.ToXContentObject;
import org.elasticsearch.core.UpdateForV9;
import org.elasticsearch.xcontent.ToXContentFragment;
import org.elasticsearch.xcontent.XContentBuilder;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class SubGroup implements ToXContentObject {
public class SubGroup implements ToXContentFragment {
private final String name;
private Long count;
@UpdateForV9 // remove legacy XContent rendering
private final boolean renderLegacyXContent;
private final Map<String, SubGroup> subgroups;

public static SubGroup root(String name) {
return new SubGroup(name, null, new HashMap<>());
public static SubGroup root(String name, boolean renderLegacyXContent) {
return new SubGroup(name, null, renderLegacyXContent, new HashMap<>());
}

public SubGroup(String name, Long count, Map<String, SubGroup> subgroups) {
public SubGroup(String name, Long count, boolean renderLegacyXContent, Map<String, SubGroup> subgroups) {
this.name = name;
this.count = count;
this.renderLegacyXContent = renderLegacyXContent;
this.subgroups = subgroups;
}

public SubGroup addCount(String name, long count) {
if (this.subgroups.containsKey(name) == false) {
this.subgroups.put(name, new SubGroup(name, count, new HashMap<>()));
this.subgroups.put(name, new SubGroup(name, count, renderLegacyXContent, new HashMap<>()));
} else {
SubGroup s = this.subgroups.get(name);
s.count += count;
Expand All @@ -50,22 +54,32 @@ public SubGroup copy() {
for (Map.Entry<String, SubGroup> subGroup : subgroups.entrySet()) {
copy.put(subGroup.getKey(), subGroup.getValue().copy());
}
return new SubGroup(name, count, copy);
return new SubGroup(name, count, renderLegacyXContent, copy);
}

@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(name);
// only the root node has no count
if (count != null) {
builder.field("count", count);
}
if (subgroups != null && subgroups.isEmpty() == false) {
for (SubGroup subgroup : subgroups.values()) {
subgroup.toXContent(builder, params);
if (renderLegacyXContent) {
// This assumes that we only have one level of sub groups
if (subgroups != null && subgroups.isEmpty() == false) {
for (SubGroup subgroup : subgroups.values()) {
builder.field(subgroup.name, subgroup.count);
}
}
return builder;
} else {
builder.startObject(name);
// only the root node has no count
if (count != null) {
builder.field("count", count);
}
if (subgroups != null && subgroups.isEmpty() == false) {
for (SubGroup subgroup : subgroups.values()) {
subgroup.toXContent(builder, params);
}
}
return builder.endObject();
}
return builder.endObject();
}

@Override
Expand Down
Loading

0 comments on commit 885015b

Please sign in to comment.