Add metrics for payout limits (#7)

This commit is contained in:
Egor Cherniak 2023-09-08 14:07:56 +03:00 committed by GitHub
parent c705972006
commit 62c40a4edf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 137 additions and 24 deletions

View File

@ -10,12 +10,22 @@ import java.util.concurrent.ConcurrentHashMap;
public class StorageConfig {
@Bean
public Map<String, Double> limitsBoundaryAggregatesMap() {
public Map<String, Double> paymentlimitsBoundaryAggregatesMap() {
return new ConcurrentHashMap<>();
}
@Bean
public Map<String, Double> limitsAmountAggregatesMap() {
public Map<String, Double> paymentlimitsAmountAggregatesMap() {
return new ConcurrentHashMap<>();
}
@Bean
public Map<String, Double> payoutlimitsBoundaryAggregatesMap() {
return new ConcurrentHashMap<>();
}
@Bean
public Map<String, Double> payoutlimitsAmountAggregatesMap() {
return new ConcurrentHashMap<>();
}
}

View File

@ -0,0 +1,8 @@
package dev.vality.exporter.limits.error;
public class UnknownLimitTypeException extends RuntimeException {
public UnknownLimitTypeException(String message) {
super(message);
}
}

View File

@ -9,6 +9,7 @@ public class CustomTag {
public static final String PROVIDER_ID_TAG = "provider_id";
public static final String TERMINAL_ID_TAG = "terminal_id";
public static final String SHOP_ID_TAG = "shop_id";
public static final String WALLET_ID_TAG = "wallet_id";
public static final String CURRENCY_TAG = "currency";
public static final String CONFIG_ID_TAG = "config_id";
public static final String TIME_RANGE_TYPE = "time_range_type";
@ -31,6 +32,10 @@ public class CustomTag {
return Tag.of(SHOP_ID_TAG, shopId);
}
public static Tag walletId(String walletId) {
return Tag.of(WALLET_ID_TAG, walletId);
}
public static Tag currency(String currency) {
return Tag.of(CURRENCY_TAG, currency);
}

View File

@ -0,0 +1,6 @@
package dev.vality.exporter.limits.model;
public enum LimitType {
PAYMENT,
PAYOUT
}

View File

@ -50,6 +50,8 @@ public class LimitsData {
@JsonProperty("party_id")
private String partyId;
private Route route;
@JsonProperty("wallet_id")
private String walletId;
@JsonProperty("shop_id")
private String shopId;

View File

@ -6,12 +6,19 @@ import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public enum Metric {
CALENDAR_LIMITS_BOUNDARY(
formatWithPrefix("limits_boundary_by_calendar"),
"Calendar limits boundary since last scrape"),
CALENDAR_LIMITS_AMOUNT(
formatWithPrefix("limits_amount_by_calendar"),
"Calendar limits amount since last scrape");
CALENDAR_PAYMENT_LIMITS_BOUNDARY(
formatWithPrefix("payment_limits_boundary_by_calendar"),
"Calendar payment limits boundary since last scrape"),
CALENDAR_PAYMENT_LIMITS_AMOUNT(
formatWithPrefix("payment_limits_amount_by_calendar"),
"Calendar payment limits amount since last scrape"),
CALENDAR_PAYOUT_LIMITS_BOUNDARY(
formatWithPrefix("payout_limits_boundary_by_calendar"),
"Calendar payout limits boundary since last scrape"),
CALENDAR_PAYOUT_LIMITS_AMOUNT(
formatWithPrefix("payout_limits_amount_by_calendar"),
"Calendar payout limits amount since last scrape");
@Getter
private final String name;

View File

@ -4,7 +4,9 @@ import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import dev.vality.exporter.limits.entity.LimitConfigEntity;
import dev.vality.exporter.limits.entity.TimeRangeType;
import dev.vality.exporter.limits.error.UnknownLimitTypeException;
import dev.vality.exporter.limits.model.CustomTag;
import dev.vality.exporter.limits.model.LimitType;
import dev.vality.exporter.limits.model.LimitsData;
import dev.vality.exporter.limits.model.Metric;
import dev.vality.exporter.limits.repository.LimitConfigRepository;
@ -14,6 +16,7 @@ import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import java.util.Comparator;
import java.util.List;
@ -28,8 +31,10 @@ import java.util.stream.Collectors;
public class LimitsService {
private final MeterRegistryService meterRegistryService;
private final Map<String, Double> limitsBoundaryAggregatesMap;
private final Map<String, Double> limitsAmountAggregatesMap;
private final Map<String, Double> paymentLimitsBoundaryAggregatesMap;
private final Map<String, Double> paymentLimitsAmountAggregatesMap;
private final Map<String, Double> payoutLimitsBoundaryAggregatesMap;
private final Map<String, Double> payoutLimitsAmountAggregatesMap;
private final OpenSearchService openSearchService;
private final LimitConfigRepository limitConfigRepository;
private final ObjectMapper objectMapper;
@ -57,17 +62,47 @@ public class LimitsService {
log.warn("limitConfigEntity null, no gauge limitsData {}", limitsData);
break;
}
var id = String.format(
"%s.%s.%s.%s.%s",
limitsData.getLimit().getConfigId(),
limitsData.getLimit().getRoute().getProviderId(),
limitsData.getLimit().getRoute().getTerminalId(),
limitsData.getLimit().getShopId(),
limitsData.getLimit().getChange().getCurrency());
gauge(limitsBoundaryAggregatesMap, Metric.CALENDAR_LIMITS_BOUNDARY, id, getTags(limitsData, limitConfigEntity), limitsData.getLimit().getBoundary());
gauge(limitsAmountAggregatesMap, Metric.CALENDAR_LIMITS_AMOUNT, id, getTags(limitsData, limitConfigEntity), limitsData.getLimit().getAmount());
var limitType = getLimitType(limitsData);
switch (limitType) {
case PAYMENT -> {
var id = String.format(
"%s.%s.%s.%s.%s",
limitsData.getLimit().getConfigId(),
limitsData.getLimit().getRoute().getProviderId(),
limitsData.getLimit().getRoute().getTerminalId(),
limitsData.getLimit().getShopId(),
limitsData.getLimit().getChange().getCurrency());
gauge(paymentLimitsBoundaryAggregatesMap, Metric.CALENDAR_PAYMENT_LIMITS_BOUNDARY, id,
getPaymentLimitTags(limitsData, limitConfigEntity),
limitsData.getLimit().getBoundary());
gauge(paymentLimitsAmountAggregatesMap, Metric.CALENDAR_PAYMENT_LIMITS_AMOUNT, id,
getPaymentLimitTags(limitsData,
limitConfigEntity), limitsData.getLimit().getAmount());
}
case PAYOUT -> {
var id = String.format(
"%s.%s.%s.%s.%s",
limitsData.getLimit().getConfigId(),
limitsData.getLimit().getRoute().getProviderId(),
limitsData.getLimit().getRoute().getTerminalId(),
limitsData.getLimit().getWalletId(),
limitsData.getLimit().getChange().getCurrency());
gauge(payoutLimitsBoundaryAggregatesMap, Metric.CALENDAR_PAYOUT_LIMITS_BOUNDARY, id,
getPayoutLimitTags(limitsData, limitConfigEntity),
limitsData.getLimit().getBoundary());
gauge(payoutLimitsAmountAggregatesMap, Metric.CALENDAR_PAYOUT_LIMITS_AMOUNT, id,
getPayoutLimitTags(limitsData,
limitConfigEntity), limitsData.getLimit().getAmount());
}
default -> throw new UnknownLimitTypeException(String.format("Limit type '%s' is unknown!", limitType));
}
}
var registeredMetricsSize = meterRegistryService.getRegisteredMetricsSize(Metric.CALENDAR_LIMITS_BOUNDARY.getName()) + meterRegistryService.getRegisteredMetricsSize(Metric.CALENDAR_LIMITS_AMOUNT.getName());
var registeredMetricsSize =
meterRegistryService.getRegisteredMetricsSize(Metric.CALENDAR_PAYMENT_LIMITS_BOUNDARY.getName()) +
meterRegistryService.getRegisteredMetricsSize(Metric.CALENDAR_PAYMENT_LIMITS_AMOUNT.getName()) +
meterRegistryService.getRegisteredMetricsSize(Metric.CALENDAR_PAYOUT_LIMITS_BOUNDARY.getName()) +
meterRegistryService.getRegisteredMetricsSize(Metric.CALENDAR_PAYOUT_LIMITS_AMOUNT.getName());
log.info("Limits metrics have been registered to 'prometheus', " +
"registeredMetricsSize = {}, clientSize = {}", registeredMetricsSize, limitsDataByInterval.size());
}
@ -82,7 +117,19 @@ public class LimitsService {
storage.put(id, Double.parseDouble(value));
}
private Tags getTags(LimitsData dto, LimitConfigEntity limitConfigEntity) {
private LimitType getLimitType(LimitsData limitsData) {
if (!ObjectUtils.isEmpty(limitsData.getPayment())) {
return LimitType.PAYMENT;
}
if (!ObjectUtils.isEmpty(limitsData.getLimit().getWalletId())) {
return LimitType.PAYOUT;
}
throw new UnknownLimitTypeException("Unable to define limit type from this data: " + limitsData);
}
private Tags getPaymentLimitTags(LimitsData dto, LimitConfigEntity limitConfigEntity) {
var tags = Tags.of(
CustomTag.terminalId(dto.getLimit().getRoute().getTerminalId()),
CustomTag.providerId(dto.getLimit().getRoute().getProviderId()),
@ -92,6 +139,24 @@ public class LimitsService {
CustomTag.timeRangType(limitConfigEntity.getTimeRangType().name()),
CustomTag.limitContextType(limitConfigEntity.getLimitContextType()),
CustomTag.limitScopeTypes(getLimitScopeTypes(limitConfigEntity.getLimitScopeTypesJson())));
return tags.and(getCommonTags(limitConfigEntity));
}
private Tags getPayoutLimitTags(LimitsData dto, LimitConfigEntity limitConfigEntity) {
var tags = Tags.of(
CustomTag.terminalId(dto.getLimit().getRoute().getTerminalId()),
CustomTag.providerId(dto.getLimit().getRoute().getProviderId()),
CustomTag.currency(dto.getLimit().getChange().getCurrency()),
CustomTag.walletId(dto.getLimit().getWalletId()),
CustomTag.configId(dto.getLimit().getConfigId()),
CustomTag.timeRangType(limitConfigEntity.getTimeRangType().name()),
CustomTag.limitContextType(limitConfigEntity.getLimitContextType()),
CustomTag.limitScopeTypes(getLimitScopeTypes(limitConfigEntity.getLimitScopeTypesJson())));
return tags.and(getCommonTags(limitConfigEntity));
}
private Tags getCommonTags(LimitConfigEntity limitConfigEntity) {
Tags tags = Tags.empty();
if (limitConfigEntity.getTimeRangeTypeCalendar() != null) {
tags = tags.and(CustomTag.timeRangeTypeCalendar(limitConfigEntity.getTimeRangeTypeCalendar()));
}

View File

@ -9,7 +9,9 @@ import org.opensearch.client.json.JsonData;
import org.opensearch.client.opensearch.OpenSearchClient;
import org.opensearch.client.opensearch._types.SortOrder;
import org.opensearch.client.opensearch._types.mapping.FieldType;
import org.opensearch.client.opensearch._types.query_dsl.BoolQuery;
import org.opensearch.client.opensearch._types.query_dsl.MatchPhraseQuery;
import org.opensearch.client.opensearch._types.query_dsl.Query;
import org.opensearch.client.opensearch._types.query_dsl.RangeQuery;
import org.opensearch.client.opensearch.core.search.Hit;
import org.springframework.beans.factory.annotation.Value;
@ -28,6 +30,7 @@ public class OpenSearchService {
private static final String DATE_TIME = "date_time";
private static final String STRICT_DATE_OPTIONAL_TIME = "strict_date_optional_time";
private static final String HELLGATE = "hellgate";
private static final String FISTFUL = "fistful";
private static final String LIMITS = "\"Limit change commited\"";
private final OpenSearchProperties openSearchProperties;
@ -62,9 +65,16 @@ public class OpenSearchService {
.format(STRICT_DATE_OPTIONAL_TIME)
.build()
._toQuery(),
new MatchPhraseQuery.Builder()
.field(KUBERNETES_CONTAINER_NAME)
.query(HELLGATE)
new BoolQuery.Builder()
.should(new Query(new MatchPhraseQuery.Builder()
.field(KUBERNETES_CONTAINER_NAME)
.query(HELLGATE)
.build()),
new Query(new MatchPhraseQuery.Builder()
.field(KUBERNETES_CONTAINER_NAME)
.query(FISTFUL)
.build()))
.minimumShouldMatch("1")
.build()
._toQuery()))),
LimitsData.class)