Skip to content

Commit 3697588

Browse files
chore: Add support for dynamic expression in label application rules (#233)
1 parent a02e74f commit 3697588

File tree

6 files changed

+175
-2
lines changed

6 files changed

+175
-2
lines changed

hypertrace-graphql-labels-schema-api/src/main/java/org/hypertrace/graphql/label/schema/rule/Action.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public interface Action {
1414
String OPERATION_KEY = "operation";
1515
String STATIC_LABELS = "staticLabels";
1616
String DYNAMIC_LABEL_KEY_KEY = "dynamicLabelKey";
17+
String DYNAMIC_LABEL_EXPRESSION_KEY = "dynamicLabelExpression";
1718
String ACTION_TYPE_KEY = "type";
1819

1920
@GraphQLName(Operation.TYPE_NAME)
@@ -25,7 +26,8 @@ enum Operation {
2526
@GraphQLName(ActionType.TYPE_NAME)
2627
enum ActionType {
2728
STATIC_LABELS,
28-
DYNAMIC_LABEL_KEY;
29+
DYNAMIC_LABEL_KEY,
30+
DYNAMIC_LABEL_EXPRESSION;
2931
private static final String TYPE_NAME = "LabelApplicationActionType";
3032
}
3133

@@ -49,6 +51,11 @@ enum ActionType {
4951
@GraphQLName(DYNAMIC_LABEL_KEY_KEY)
5052
String dynamicLabelKey();
5153

54+
@GraphQLField
55+
@Nullable
56+
@GraphQLName(DYNAMIC_LABEL_EXPRESSION_KEY)
57+
DynamicLabelExpression dynamicLabelExpression();
58+
5259
@GraphQLField
5360
@GraphQLNonNull
5461
@GraphQLName(ACTION_TYPE_KEY)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package org.hypertrace.graphql.label.schema.rule;
2+
3+
import graphql.annotations.annotationTypes.GraphQLField;
4+
import graphql.annotations.annotationTypes.GraphQLName;
5+
import graphql.annotations.annotationTypes.GraphQLNonNull;
6+
import java.util.List;
7+
8+
@GraphQLName(DynamicLabelExpression.TYPE_NAME)
9+
public interface DynamicLabelExpression {
10+
String TYPE_NAME = "DynamicLabelExpression";
11+
12+
String LABEL_EXPRESSION_KEY = "labelExpression";
13+
String TOKEN_EXTRACTION_RULES_KEY = "tokenExtractionRules";
14+
15+
@GraphQLField
16+
@GraphQLName(LABEL_EXPRESSION_KEY)
17+
@GraphQLNonNull
18+
String labelExpression();
19+
20+
@GraphQLField
21+
@GraphQLNonNull
22+
@GraphQLName(TOKEN_EXTRACTION_RULES_KEY)
23+
List<TokenExtractionRule> tokenExtractionRules();
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package org.hypertrace.graphql.label.schema.rule;
2+
3+
import graphql.annotations.annotationTypes.GraphQLField;
4+
import graphql.annotations.annotationTypes.GraphQLName;
5+
import graphql.annotations.annotationTypes.GraphQLNonNull;
6+
import javax.annotation.Nullable;
7+
8+
@GraphQLName(TokenExtractionRule.TYPE_NAME)
9+
public interface TokenExtractionRule {
10+
String TYPE_NAME = "TokenExtractionRule";
11+
12+
String KEY_NAME = "key";
13+
String ALIAS_KEY = "alias";
14+
String REGEX_CAPTURE_KEY = "regexCapture";
15+
16+
@GraphQLField
17+
@GraphQLName(KEY_NAME)
18+
@GraphQLNonNull
19+
String key();
20+
21+
@GraphQLField
22+
@GraphQLName(ALIAS_KEY)
23+
@Nullable
24+
String alias();
25+
26+
@GraphQLField
27+
@GraphQLName(REGEX_CAPTURE_KEY)
28+
@Nullable
29+
String regexCapture();
30+
}

hypertrace-graphql-labels-schema-impl/src/main/java/org/hypertrace/graphql/label/dao/LabelApplicationRuleRequestConverter.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.hypertrace.label.application.rule.config.service.v1.DeleteLabelApplicationRuleRequest;
1313
import org.hypertrace.label.application.rule.config.service.v1.LabelApplicationRuleData;
1414
import org.hypertrace.label.application.rule.config.service.v1.LabelApplicationRuleData.Action;
15+
import org.hypertrace.label.application.rule.config.service.v1.LabelApplicationRuleData.Action.DynamicLabel.TokenExtractionRule;
1516
import org.hypertrace.label.application.rule.config.service.v1.LabelApplicationRuleData.CompositeCondition;
1617
import org.hypertrace.label.application.rule.config.service.v1.LabelApplicationRuleData.Condition;
1718
import org.hypertrace.label.application.rule.config.service.v1.LabelApplicationRuleData.LeafCondition;
@@ -82,11 +83,34 @@ private Action convertLabelAction(org.hypertrace.graphql.label.schema.rule.Actio
8283
.build();
8384
case DYNAMIC_LABEL_KEY:
8485
return actionBuilder.setDynamicLabelKey(action.dynamicLabelKey()).build();
86+
case DYNAMIC_LABEL_EXPRESSION:
87+
return actionBuilder
88+
.setDynamicLabelExpression(
89+
Action.DynamicLabel.newBuilder()
90+
.setLabelExpression(action.dynamicLabelExpression().labelExpression())
91+
.addAllTokenExtractionRules(
92+
convertTokenExtractionRules(
93+
action.dynamicLabelExpression().tokenExtractionRules())))
94+
.build();
8595
default:
8696
throw new IllegalArgumentException("Unsupported action value");
8797
}
8898
}
8999

100+
private List<TokenExtractionRule> convertTokenExtractionRules(
101+
List<org.hypertrace.graphql.label.schema.rule.TokenExtractionRule> tokenExtractionRules) {
102+
return tokenExtractionRules.stream()
103+
.map(
104+
rule -> {
105+
TokenExtractionRule.Builder builder =
106+
TokenExtractionRule.newBuilder().setKey(rule.key());
107+
Optional.ofNullable(rule.alias()).ifPresent(builder::setAlias);
108+
Optional.ofNullable(rule.regexCapture()).ifPresent(builder::setRegexCapture);
109+
return builder.build();
110+
})
111+
.collect(Collectors.toList());
112+
}
113+
90114
Condition convertConditionList(
91115
List<org.hypertrace.graphql.label.schema.rule.Condition> conditionList) {
92116
if (conditionList.size() == 1) {

hypertrace-graphql-labels-schema-impl/src/main/java/org/hypertrace/graphql/label/dao/LabelApplicationRuleResponseConverter.java

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@
1212
import lombok.extern.slf4j.Slf4j;
1313
import org.hypertrace.graphql.label.schema.rule.Action;
1414
import org.hypertrace.graphql.label.schema.rule.Condition;
15+
import org.hypertrace.graphql.label.schema.rule.DynamicLabelExpression;
1516
import org.hypertrace.graphql.label.schema.rule.LabelApplicationRule;
1617
import org.hypertrace.graphql.label.schema.rule.LabelApplicationRuleData;
1718
import org.hypertrace.graphql.label.schema.rule.LabelApplicationRuleResultSet;
1819
import org.hypertrace.graphql.label.schema.rule.LeafCondition;
1920
import org.hypertrace.graphql.label.schema.rule.StaticLabels;
2021
import org.hypertrace.graphql.label.schema.rule.StringCondition;
22+
import org.hypertrace.graphql.label.schema.rule.TokenExtractionRule;
2123
import org.hypertrace.graphql.label.schema.rule.UnaryCondition;
2224
import org.hypertrace.graphql.label.schema.rule.ValueCondition;
2325
import org.hypertrace.label.application.rule.config.service.v1.CreateLabelApplicationRuleResponse;
@@ -105,7 +107,7 @@ private Optional<Action> convertAction(
105107
return operation.map(
106108
op ->
107109
new ConvertedAction(
108-
entityTypes, op, staticLabels, null, Action.ActionType.STATIC_LABELS));
110+
entityTypes, op, staticLabels, null, null, Action.ActionType.STATIC_LABELS));
109111
case DYNAMIC_LABEL_KEY:
110112
return operation.map(
111113
op ->
@@ -114,7 +116,20 @@ private Optional<Action> convertAction(
114116
op,
115117
null,
116118
action.getDynamicLabelKey(),
119+
null,
117120
Action.ActionType.DYNAMIC_LABEL_KEY));
121+
case DYNAMIC_LABEL_EXPRESSION:
122+
DynamicLabelExpression dynamicLabelExpression =
123+
convertDynamicLabelExpression(action.getDynamicLabelExpression());
124+
return operation.map(
125+
op ->
126+
new ConvertedAction(
127+
entityTypes,
128+
op,
129+
null,
130+
null,
131+
dynamicLabelExpression,
132+
Action.ActionType.DYNAMIC_LABEL_EXPRESSION));
118133
default:
119134
log.error("Unrecognized Value type in Action {}", action.getValueCase().name());
120135
return Optional.empty();
@@ -128,6 +143,30 @@ private StaticLabels convertStaticLabels(
128143
return new ConvertedStaticLabels(staticLabels.getIdsList());
129144
}
130145

146+
private DynamicLabelExpression convertDynamicLabelExpression(
147+
org.hypertrace.label.application.rule.config.service.v1.LabelApplicationRuleData.Action
148+
.DynamicLabel
149+
dynamicLabel) {
150+
return new ConvertedDynamicLabelExpression(
151+
dynamicLabel.getLabelExpression(),
152+
convertTokenExtractionRules(dynamicLabel.getTokenExtractionRulesList()));
153+
}
154+
155+
private List<TokenExtractionRule> convertTokenExtractionRules(
156+
List<
157+
org.hypertrace.label.application.rule.config.service.v1.LabelApplicationRuleData
158+
.Action.DynamicLabel.TokenExtractionRule>
159+
tokenExtractionRules) {
160+
return tokenExtractionRules.stream()
161+
.map(
162+
rule ->
163+
new ConvertedTokenExtractionRule(
164+
rule.getKey(),
165+
rule.hasAlias() ? rule.getAlias() : null,
166+
rule.hasRegexCapture() ? rule.getRegexCapture() : null))
167+
.collect(Collectors.toList());
168+
}
169+
131170
private List<Condition> convertCondition(
132171
org.hypertrace.label.application.rule.config.service.v1.LabelApplicationRuleData.Condition
133172
condition) {
@@ -300,6 +339,7 @@ private static class ConvertedAction implements Action {
300339
Operation operation;
301340
StaticLabels staticLabels;
302341
String dynamicLabelKey;
342+
DynamicLabelExpression dynamicLabelExpression;
303343
ActionType type;
304344
}
305345

@@ -309,6 +349,21 @@ private static class ConvertedStaticLabels implements StaticLabels {
309349
List<String> ids;
310350
}
311351

352+
@Value
353+
@Accessors(fluent = true)
354+
private static class ConvertedDynamicLabelExpression implements DynamicLabelExpression {
355+
String labelExpression;
356+
List<TokenExtractionRule> tokenExtractionRules;
357+
}
358+
359+
@Value
360+
@Accessors(fluent = true)
361+
private static class ConvertedTokenExtractionRule implements TokenExtractionRule {
362+
String key;
363+
String alias;
364+
String regexCapture;
365+
}
366+
312367
@Value
313368
@Accessors(fluent = true)
314369
private static class ConvertedCondition implements Condition {

hypertrace-graphql-labels-schema-impl/src/main/java/org/hypertrace/graphql/label/deserialization/LabelApplicationRuleDeserializationConfig.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@
1010
import org.hypertrace.core.graphql.deserialization.ArgumentDeserializationConfig;
1111
import org.hypertrace.graphql.label.schema.rule.Action;
1212
import org.hypertrace.graphql.label.schema.rule.Condition;
13+
import org.hypertrace.graphql.label.schema.rule.DynamicLabelExpression;
1314
import org.hypertrace.graphql.label.schema.rule.LabelApplicationRule;
1415
import org.hypertrace.graphql.label.schema.rule.LabelApplicationRuleData;
1516
import org.hypertrace.graphql.label.schema.rule.LeafCondition;
1617
import org.hypertrace.graphql.label.schema.rule.StaticLabels;
1718
import org.hypertrace.graphql.label.schema.rule.StringCondition;
19+
import org.hypertrace.graphql.label.schema.rule.TokenExtractionRule;
1820
import org.hypertrace.graphql.label.schema.rule.UnaryCondition;
1921
import org.hypertrace.graphql.label.schema.rule.ValueCondition;
2022

@@ -38,6 +40,9 @@ public List<Module> jacksonModules() {
3840
LabelApplicationRuleData.class, LabelApplicationRuleDataArgument.class)
3941
.addAbstractTypeMapping(Action.class, ActionArgument.class)
4042
.addAbstractTypeMapping(StaticLabels.class, StaticLabelsArgument.class)
43+
.addAbstractTypeMapping(
44+
DynamicLabelExpression.class, DynamicLabelExpressionArgument.class)
45+
.addAbstractTypeMapping(TokenExtractionRule.class, TokenExtractionRuleArgument.class)
4146
.addAbstractTypeMapping(Condition.class, ConditionArgument.class)
4247
.addAbstractTypeMapping(LeafCondition.class, LeafConditionArgument.class)
4348
.addAbstractTypeMapping(ValueCondition.class, ValueConditionArgument.class)
@@ -92,6 +97,9 @@ private static class ActionArgument implements Action {
9297
@JsonProperty(DYNAMIC_LABEL_KEY_KEY)
9398
String dynamicLabelKey;
9499

100+
@JsonProperty(DYNAMIC_LABEL_EXPRESSION_KEY)
101+
DynamicLabelExpression dynamicLabelExpression;
102+
95103
@JsonProperty(ACTION_TYPE_KEY)
96104
ActionType type;
97105
}
@@ -104,6 +112,31 @@ private static class StaticLabelsArgument implements StaticLabels {
104112
List<String> ids;
105113
}
106114

115+
@Value
116+
@Accessors(fluent = true)
117+
@NoArgsConstructor(force = true)
118+
private static class DynamicLabelExpressionArgument implements DynamicLabelExpression {
119+
@JsonProperty(LABEL_EXPRESSION_KEY)
120+
String labelExpression;
121+
122+
@JsonProperty(TOKEN_EXTRACTION_RULES_KEY)
123+
List<TokenExtractionRule> tokenExtractionRules;
124+
}
125+
126+
@Value
127+
@Accessors(fluent = true)
128+
@NoArgsConstructor(force = true)
129+
private static class TokenExtractionRuleArgument implements TokenExtractionRule {
130+
@JsonProperty(KEY_NAME)
131+
String key;
132+
133+
@JsonProperty(ALIAS_KEY)
134+
String alias;
135+
136+
@JsonProperty(REGEX_CAPTURE_KEY)
137+
String regexCapture;
138+
}
139+
107140
@Value
108141
@Accessors(fluent = true)
109142
@NoArgsConstructor(force = true)

0 commit comments

Comments
 (0)