Skip to content

Commit 582821a

Browse files
authored
BUS-97: user friendly values (#24)
* BUS-97: user friendly values * BUS-97: user friendly values
1 parent 413facf commit 582821a

File tree

8 files changed

+217
-71
lines changed

8 files changed

+217
-71
lines changed

src/main/java/dev/vality/alerting/mayday/alertmanager/service/AlertmanagerService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ private AlertmanagerConfigSpec.ChildRoute buildRoute(CreateAlertDto createAlertD
6868
route.setGroupWait(ONE_SEC_WAIT);
6969
String repeatInterval = FormatUtil.formatMinutesDuration(createAlertDto.getParameters()
7070
.get(String.valueOf(
71-
AlertConfigurationRequiredParameter.ALERT_REPEAT_MINUTES.getSubstitutionName())).get(0));
71+
AlertConfigurationRequiredParameter.ALERT_REPEAT_MINUTES.getSubstitutionName())).get(0)
72+
.getValue());
7273
route.setGroupInterval(repeatInterval);
7374
var alertnameMatcher =
7475
AlertmanagerFunctionsUtil.createMatcher(PrometheusRuleLabel.ALERT_NAME, createAlertDto.getAlertId());
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package dev.vality.alerting.mayday.alerttemplate.model.dictionary;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Builder;
5+
import lombok.Data;
6+
7+
@Data
8+
@Builder
9+
@AllArgsConstructor
10+
public class DictionaryData {
11+
12+
private String value;
13+
private String userFriendlyValue;
14+
15+
public DictionaryData(String value) {
16+
this.value = value;
17+
}
18+
19+
public String getUserFriendlyValue() {
20+
return userFriendlyValue != null ? userFriendlyValue : value;
21+
}
22+
}

src/main/java/dev/vality/alerting/mayday/alerttemplate/service/DictionaryService.java

Lines changed: 63 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import dev.vality.alerting.mayday.alerttemplate.dao.DawayDao;
44
import dev.vality.alerting.mayday.alerttemplate.model.alerttemplate.DictionaryType;
55
import dev.vality.alerting.mayday.alerttemplate.model.daway.*;
6+
import dev.vality.alerting.mayday.alerttemplate.model.dictionary.DictionaryData;
67
import lombok.RequiredArgsConstructor;
78
import lombok.extern.slf4j.Slf4j;
89
import org.springframework.stereotype.Service;
@@ -19,7 +20,7 @@ public class DictionaryService {
1920

2021
private final DawayDao dawayDao;
2122

22-
public Map<String, String> getDictionary(DictionaryType type) {
23+
public Map<String, DictionaryData> getDictionary(DictionaryType type) {
2324
return switch (type) {
2425
case TERMINALS -> convertTerminalsToDictionary(dawayDao.getAllTerminals());
2526
case PAYMENT_TERMINALS -> convertTerminalsToDictionary(dawayDao.getPaymentTerminals());
@@ -30,50 +31,64 @@ public Map<String, String> getDictionary(DictionaryType type) {
3031
case WALLETS -> convertWalletsToDictionary(dawayDao.getWallets());
3132
case SHOPS -> convertShopsToDictionary(dawayDao.getShops());
3233
case CURRENCIES -> convertCurrenciesToDictionary(dawayDao.getCurrencies());
33-
case PAYMENT_LIMIT_SCOPES -> Map.of("Провайдер", "provider",
34-
"Провайдер + терминал", "provider,terminal",
35-
"Провайдер + терминал + магазин", "provider,shop,terminal",
36-
"Терминал", "terminal",
37-
"Магазин", "shop");
38-
case PAYOUT_LIMIT_SCOPES -> Map.of("Провайдер", "provider",
39-
"Провайдер + терминал", "provider,terminal",
40-
"Провайдер + терминал + кошелек", "provider,terminal,wallet",
41-
"Терминал", "terminal",
42-
"Кошелёк", "wallet");
43-
case CONDITIONAL_BOUNDARIES -> Map.of("Больше порогового значения", ">", "Меньше порогового значения", "<");
44-
case TIME_INTERVAL_BOUNDARIES -> Map.of("Да", "unless", "Нет", "and");
45-
case AGGREGATION_INTERVALS -> Map.of("5 минут", "5m", "15 минут", "15m", "30 минут", "30m",
46-
"1 час", "1h", "3 часа", "3h", "6 часов", "6h", "12 часов", "12h", "24 часа", "24h", "Текущий " +
47-
"календарный день (MSK)", "today_msk");
34+
case PAYMENT_LIMIT_SCOPES -> Map.of(
35+
"Провайдер", new DictionaryData("provider"),
36+
"Провайдер + терминал", new DictionaryData("provider,terminal"),
37+
"Провайдер + терминал + магазин", new DictionaryData("provider,shop,terminal"),
38+
"Терминал", new DictionaryData("terminal"),
39+
"Магазин", new DictionaryData("shop")
40+
);
41+
case PAYOUT_LIMIT_SCOPES -> Map.of(
42+
"Провайдер", new DictionaryData("provider"),
43+
"Провайдер + терминал", new DictionaryData("provider,terminal"),
44+
"Провайдер + терминал + кошелек", new DictionaryData("provider,terminal,wallet"),
45+
"Терминал", new DictionaryData("terminal"),
46+
"Кошелёк", new DictionaryData("wallet")
47+
);
48+
case CONDITIONAL_BOUNDARIES -> Map.of(
49+
"Больше порогового значения", new DictionaryData(">"),
50+
"Меньше порогового значения", new DictionaryData("<")
51+
);
52+
case TIME_INTERVAL_BOUNDARIES -> Map.of(
53+
"Да", new DictionaryData("unless"),
54+
"Нет", new DictionaryData("and")
55+
);
56+
case AGGREGATION_INTERVALS -> Map.of(
57+
"5 минут", new DictionaryData("5m"),
58+
"15 минут", new DictionaryData("15m"),
59+
"30 минут", new DictionaryData("30m"),
60+
"1 час", new DictionaryData("1h"),
61+
"3 часа", new DictionaryData("3h"),
62+
"6 часов", new DictionaryData("6h"),
63+
"12 часов", new DictionaryData("12h"),
64+
"24 часа", new DictionaryData("24h"),
65+
"Текущий календарный день (MSK)", new DictionaryData("today_msk"));
4866
};
4967
}
5068

51-
private Map<String, String> convertTerminalsToDictionary(List<Terminal> terminals) {
69+
private Map<String, DictionaryData> convertTerminalsToDictionary(List<Terminal> terminals) {
5270
return terminals.stream()
53-
.collect(Collectors.toMap(
54-
terminal -> formatDictionaryKey(Integer.toString(terminal.getId()), terminal.getName()),
55-
terminal -> Integer.toString(terminal.getId())));
71+
.map(terminal -> createDictionaryData(terminal.getId(), terminal.getName()))
72+
.collect(Collectors.toMap(DictionaryData::getUserFriendlyValue, dictionaryData -> dictionaryData));
5673
}
5774

58-
private Map<String, String> convertProvidersToDictionary(List<Provider> providers) {
75+
private Map<String, DictionaryData> convertProvidersToDictionary(List<Provider> providers) {
5976
return providers.stream()
60-
.collect(Collectors.toMap(
61-
provider -> formatDictionaryKey(Integer.toString(provider.getId()), provider.getName()),
62-
provider -> Integer.toString(provider.getId())));
77+
.map(provider -> createDictionaryData(provider.getId(), provider.getName()))
78+
.collect(Collectors.toMap(DictionaryData::getUserFriendlyValue, dictionaryData -> dictionaryData));
6379
}
6480

65-
private Map<String, String> convertWalletsToDictionary(List<Wallet> wallets) {
81+
private Map<String, DictionaryData> convertWalletsToDictionary(List<Wallet> wallets) {
6682
return wallets.stream()
67-
.collect(Collectors.toMap(
68-
wallet -> formatDictionaryKey(wallet.getId(), wallet.getName()),
69-
Wallet::getId));
83+
.map(wallet -> createDictionaryData(wallet.getId(), wallet.getName()))
84+
.collect(Collectors.toMap(DictionaryData::getUserFriendlyValue, dictionaryData -> dictionaryData));
7085
}
7186

72-
private Map<String, String> convertShopsToDictionary(List<Shop> shops) {
73-
return shops.stream()
74-
.collect(Collectors.toMap(
75-
shop -> formatDictionaryKey(formatShopId(shop.getId()), shop.getName()),
76-
Shop::getId));
87+
private Map<String, DictionaryData> convertShopsToDictionary(List<Shop> shops) {
88+
return shops.stream().collect(Collectors.toMap(
89+
shop -> formatDictionaryString(formatShopId(shop.getId()), shop.getName()),
90+
shop -> createDictionaryData(shop.getId(), shop.getName())
91+
));
7792
}
7893

7994
// Возвращаем только часть UUID, т.к иначе строка выходит слишком длинной
@@ -87,15 +102,25 @@ private String formatShopId(String shopId) {
87102
}
88103
}
89104

90-
private Map<String, String> convertCurrenciesToDictionary(List<Currency> currencies) {
105+
private Map<String, DictionaryData> convertCurrenciesToDictionary(List<Currency> currencies) {
91106
return currencies.stream()
92-
.collect(Collectors.toMap(
93-
currency -> formatDictionaryKey(currency.getSymbolicCode(), currency.getName()),
94-
Currency::getSymbolicCode));
107+
.map(currency -> createDictionaryData(currency.getSymbolicCode(), currency.getName()))
108+
.collect(Collectors.toMap(DictionaryData::getUserFriendlyValue, dictionaryData -> dictionaryData));
95109
}
96110

97-
private String formatDictionaryKey(String id, String description) {
111+
private String formatDictionaryString(String id, String description) {
98112
return String.format("(%s) %s", id, description);
99113
}
100114

115+
private DictionaryData createDictionaryData(String id, String description) {
116+
return DictionaryData.builder()
117+
.value(id)
118+
.userFriendlyValue(formatDictionaryString(id, description))
119+
.build();
120+
}
121+
122+
private DictionaryData createDictionaryData(Integer id, String description) {
123+
return createDictionaryData(Integer.toString(id), description);
124+
}
125+
101126
}

src/main/java/dev/vality/alerting/mayday/alerttemplate/service/helper/TemplateHelper.java

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import dev.vality.alerting.mayday.ParameterInfo;
55
import dev.vality.alerting.mayday.alerttemplate.error.AlertConfigurationException;
66
import dev.vality.alerting.mayday.alerttemplate.model.alerttemplate.AlertTemplate;
7+
import dev.vality.alerting.mayday.alerttemplate.model.dictionary.DictionaryData;
78
import dev.vality.alerting.mayday.alerttemplate.service.DictionaryService;
89
import dev.vality.alerting.mayday.common.constant.AlertConfigurationRequiredParameter;
910
import dev.vality.alerting.mayday.common.dto.CreateAlertDto;
@@ -18,14 +19,15 @@
1819
import java.util.List;
1920
import java.util.Map;
2021
import java.util.stream.Collectors;
22+
import java.util.stream.Stream;
2123

2224
@Slf4j
2325
@Component
2426
@RequiredArgsConstructor
2527
public class TemplateHelper {
2628

2729
private static final String anyClientValue = "-";
28-
private static final String anyPrometheusValue = ".*";
30+
private static final DictionaryData anyPrometheusValue = new DictionaryData(".*");
2931
private static final String anyUserFriendlyValue = "<любое значение>";
3032
private static final String multiValuePrometheusDelimiter = "|";
3133
private static final String multiValueUserFriendlyDelimiter = ",";
@@ -37,7 +39,7 @@ public CreateAlertDto preparePrometheusRuleData(CreateAlertRequest createAlertRe
3739
List<AlertTemplate.AlertConfigurationParameter>
3840
metricParams) {
3941

40-
Map<String, List<String>> parameters = mergeParameters(createAlertRequest.getParameters(), metricParams);
42+
var parameters = mergeParameters(createAlertRequest.getParameters(), metricParams);
4143
String queryExpression = prepareMetricExpression(metricTemplate, parameters);
4244
log.debug("Prepared prometheus expression: {}", queryExpression);
4345
String alertId = generateAlertId(createAlertRequest, queryExpression);
@@ -52,10 +54,10 @@ public CreateAlertDto preparePrometheusRuleData(CreateAlertRequest createAlertRe
5254
.build();
5355
}
5456

55-
protected Map<String, List<String>> mergeParameters(List<ParameterInfo> externalParamsInfo,
56-
List<AlertTemplate.AlertConfigurationParameter>
57-
maydayParamsInfo) {
58-
Map<String, List<String>> params = maydayParamsInfo.stream()
57+
protected Map<String, List<DictionaryData>> mergeParameters(List<ParameterInfo> externalParamsInfo,
58+
List<AlertTemplate.AlertConfigurationParameter>
59+
maydayParamsInfo) {
60+
Map<String, List<DictionaryData>> params = maydayParamsInfo.stream()
5961
.map(maydayParamInfo -> {
6062
var externalParamInfos = externalParamsInfo.stream()
6163
.filter(userParamInfo ->
@@ -65,7 +67,7 @@ protected Map<String, List<String>> mergeParameters(List<ParameterInfo> external
6567
validateMultipleValues(maydayParamInfo, externalParamInfos);
6668
validateMandatoryValues(maydayParamInfo, externalParamInfos);
6769

68-
List<String> values = new ArrayList<>();
70+
List<DictionaryData> values = new ArrayList<>();
6971
if (!maydayParamInfo.getMandatory() && externalParamInfos.size() == 1) {
7072
values.add(hasNoValue(externalParamInfos.get(0)) ? anyPrometheusValue :
7173
getParameterValue(maydayParamInfo, externalParamInfos.get(0)));
@@ -86,14 +88,16 @@ protected Map<String, List<String>> mergeParameters(List<ParameterInfo> external
8688
Arrays.stream(AlertConfigurationRequiredParameter.values()).forEach(
8789
requiredParameter -> {
8890
var param = getRequiredParameter(String.valueOf(requiredParameter.getId()), externalParamsInfo);
89-
params.put(requiredParameter.getSubstitutionName(), List.of(param.getValue()));
91+
params.put(requiredParameter.getSubstitutionName(),
92+
Stream.of(param.getValue()).map(DictionaryData::new).toList()
93+
);
9094
}
9195
);
9296
return params;
9397
}
9498

9599
private void validateMultipleValues(AlertTemplate.AlertConfigurationParameter maydayParamInfo,
96-
List<ParameterInfo> externalParamInfos) {
100+
List<ParameterInfo> externalParamInfos) {
97101
if (externalParamInfos.size() > 1 && !maydayParamInfo.getMultipleValues()) {
98102
throw new AlertConfigurationException(String.format("Parameter '%s' cannot have " +
99103
"multiple values!", maydayParamInfo.getSubstitutionName()));
@@ -122,54 +126,59 @@ protected String generateAlertId(CreateAlertRequest createAlertRequest, String p
122126
.getBytes(StandardCharsets.UTF_8));
123127
}
124128

125-
protected String prepareMetricExpression(AlertTemplate metricTemplate, Map<String, List<String>> parameters) {
129+
protected String prepareMetricExpression(AlertTemplate metricTemplate,
130+
Map<String, List<DictionaryData>> parameters) {
126131
return prepareTemplate(metricTemplate.getPrometheusQuery(), parameters);
127132
}
128133

129-
protected String prepareUserFriendlyAlertName(AlertTemplate metricTemplate, Map<String, List<String>> parameters) {
134+
protected String prepareUserFriendlyAlertName(AlertTemplate metricTemplate,
135+
Map<String, List<DictionaryData>> parameters) {
130136
return prepareUserFriendlyTemplate(metricTemplate.getAlertNameTemplate(), parameters);
131137
}
132138

133-
protected String prepareMetricAlertMessage(AlertTemplate metricTemplate, Map<String, List<String>> parameters) {
139+
protected String prepareMetricAlertMessage(AlertTemplate metricTemplate,
140+
Map<String, List<DictionaryData>> parameters) {
134141
return prepareUserFriendlyTemplate(metricTemplate.getAlertNotificationTemplate(), parameters);
135142
}
136143

137-
private String prepareTemplate(String template, Map<String, List<String>> replacements) {
144+
private String prepareTemplate(String template, Map<String, List<DictionaryData>> replacements) {
138145
String preparedTemplate = template;
139146
var replacementsEntries = replacements.entrySet();
140-
for (Map.Entry<String, List<String>> entry : replacementsEntries) {
141-
String value = entry.getValue().size() == 1
142-
? entry.getValue().get(0) : String.join(multiValuePrometheusDelimiter, entry.getValue());
147+
for (Map.Entry<String, List<DictionaryData>> entry : replacementsEntries) {
148+
var value = entry.getValue().stream()
149+
.map(DictionaryData::getValue)
150+
.collect(Collectors.joining(multiValuePrometheusDelimiter));
143151
preparedTemplate = preparedTemplate.replace(formatReplacementVariable(entry.getKey()), value);
144152
}
145153
return preparedTemplate;
146154
}
147155

148-
private String prepareUserFriendlyTemplate(String template, Map<String, List<String>> replacements) {
156+
private String prepareUserFriendlyTemplate(String template, Map<String, List<DictionaryData>> replacements) {
149157
String preparedTemplate = template;
150158
var replacementsEntries = replacements.entrySet();
151-
for (Map.Entry<String, List<String>> entry : replacementsEntries) {
152-
String value = entry.getValue().size() == 1
153-
? formatAnyValue(entry.getValue().get(0)) : String.join(multiValueUserFriendlyDelimiter,
154-
entry.getValue());
159+
for (Map.Entry<String, List<DictionaryData>> entry : replacementsEntries) {
160+
var value = entry.getValue().stream()
161+
.map(DictionaryData::getUserFriendlyValue)
162+
.map(this::formatAnyValue)
163+
.collect(Collectors.joining(multiValueUserFriendlyDelimiter));
155164
preparedTemplate = preparedTemplate.replace(formatReplacementVariable(entry.getKey()), value);
156165
}
157166
return preparedTemplate;
158167
}
159168

160169
private String formatAnyValue(String value) {
161-
if (anyPrometheusValue.equals(value)) {
170+
if (anyPrometheusValue.getValue().equals(value)) {
162171
return anyUserFriendlyValue;
163172
}
164173
return value;
165174
}
166175

167-
private String getParameterValue(AlertTemplate.AlertConfigurationParameter maydayParamInfo,
168-
ParameterInfo userParamInfo) {
176+
private DictionaryData getParameterValue(AlertTemplate.AlertConfigurationParameter maydayParamInfo,
177+
ParameterInfo userParamInfo) {
169178
if (maydayParamInfo.getDictionaryName() != null) {
170179
return dictionaryService.getDictionary(maydayParamInfo.getDictionaryName()).get(userParamInfo.getValue());
171180
}
172-
return userParamInfo.getValue();
181+
return new DictionaryData(userParamInfo.getValue());
173182
}
174183

175184
private String formatReplacementVariable(String variableName) {

src/main/java/dev/vality/alerting/mayday/common/dto/CreateAlertDto.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package dev.vality.alerting.mayday.common.dto;
22

3+
import dev.vality.alerting.mayday.alerttemplate.model.dictionary.DictionaryData;
34
import lombok.Builder;
45
import lombok.Data;
56

@@ -14,5 +15,5 @@ public class CreateAlertDto {
1415
private String prometheusQuery;
1516
private String userFriendlyAlertName;
1617
private String userFriendlyAlertDescription;
17-
private Map<String, List<String>> parameters;
18+
private Map<String, List<DictionaryData>> parameters;
1819
}

0 commit comments

Comments
 (0)