mirror of
https://github.com/valitydev/exporter-limits.git
synced 2024-11-06 00:25:22 +00:00
Add metrics for payout limits (#7)
This commit is contained in:
parent
c705972006
commit
62c40a4edf
@ -10,12 +10,22 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
public class StorageConfig {
|
public class StorageConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public Map<String, Double> limitsBoundaryAggregatesMap() {
|
public Map<String, Double> paymentlimitsBoundaryAggregatesMap() {
|
||||||
return new ConcurrentHashMap<>();
|
return new ConcurrentHashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@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<>();
|
return new ConcurrentHashMap<>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
package dev.vality.exporter.limits.error;
|
||||||
|
|
||||||
|
public class UnknownLimitTypeException extends RuntimeException {
|
||||||
|
|
||||||
|
public UnknownLimitTypeException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,7 @@ public class CustomTag {
|
|||||||
public static final String PROVIDER_ID_TAG = "provider_id";
|
public static final String PROVIDER_ID_TAG = "provider_id";
|
||||||
public static final String TERMINAL_ID_TAG = "terminal_id";
|
public static final String TERMINAL_ID_TAG = "terminal_id";
|
||||||
public static final String SHOP_ID_TAG = "shop_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 CURRENCY_TAG = "currency";
|
||||||
public static final String CONFIG_ID_TAG = "config_id";
|
public static final String CONFIG_ID_TAG = "config_id";
|
||||||
public static final String TIME_RANGE_TYPE = "time_range_type";
|
public static final String TIME_RANGE_TYPE = "time_range_type";
|
||||||
@ -31,6 +32,10 @@ public class CustomTag {
|
|||||||
return Tag.of(SHOP_ID_TAG, shopId);
|
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) {
|
public static Tag currency(String currency) {
|
||||||
return Tag.of(CURRENCY_TAG, currency);
|
return Tag.of(CURRENCY_TAG, currency);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
package dev.vality.exporter.limits.model;
|
||||||
|
|
||||||
|
public enum LimitType {
|
||||||
|
PAYMENT,
|
||||||
|
PAYOUT
|
||||||
|
}
|
@ -50,6 +50,8 @@ public class LimitsData {
|
|||||||
@JsonProperty("party_id")
|
@JsonProperty("party_id")
|
||||||
private String partyId;
|
private String partyId;
|
||||||
private Route route;
|
private Route route;
|
||||||
|
@JsonProperty("wallet_id")
|
||||||
|
private String walletId;
|
||||||
@JsonProperty("shop_id")
|
@JsonProperty("shop_id")
|
||||||
private String shopId;
|
private String shopId;
|
||||||
|
|
||||||
|
@ -6,12 +6,19 @@ import lombok.RequiredArgsConstructor;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public enum Metric {
|
public enum Metric {
|
||||||
|
|
||||||
CALENDAR_LIMITS_BOUNDARY(
|
CALENDAR_PAYMENT_LIMITS_BOUNDARY(
|
||||||
formatWithPrefix("limits_boundary_by_calendar"),
|
formatWithPrefix("payment_limits_boundary_by_calendar"),
|
||||||
"Calendar limits boundary since last scrape"),
|
"Calendar payment limits boundary since last scrape"),
|
||||||
CALENDAR_LIMITS_AMOUNT(
|
CALENDAR_PAYMENT_LIMITS_AMOUNT(
|
||||||
formatWithPrefix("limits_amount_by_calendar"),
|
formatWithPrefix("payment_limits_amount_by_calendar"),
|
||||||
"Calendar limits amount since last scrape");
|
"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
|
@Getter
|
||||||
private final String name;
|
private final String name;
|
||||||
|
@ -4,7 +4,9 @@ import com.fasterxml.jackson.core.type.TypeReference;
|
|||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import dev.vality.exporter.limits.entity.LimitConfigEntity;
|
import dev.vality.exporter.limits.entity.LimitConfigEntity;
|
||||||
import dev.vality.exporter.limits.entity.TimeRangeType;
|
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.CustomTag;
|
||||||
|
import dev.vality.exporter.limits.model.LimitType;
|
||||||
import dev.vality.exporter.limits.model.LimitsData;
|
import dev.vality.exporter.limits.model.LimitsData;
|
||||||
import dev.vality.exporter.limits.model.Metric;
|
import dev.vality.exporter.limits.model.Metric;
|
||||||
import dev.vality.exporter.limits.repository.LimitConfigRepository;
|
import dev.vality.exporter.limits.repository.LimitConfigRepository;
|
||||||
@ -14,6 +16,7 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -28,8 +31,10 @@ import java.util.stream.Collectors;
|
|||||||
public class LimitsService {
|
public class LimitsService {
|
||||||
|
|
||||||
private final MeterRegistryService meterRegistryService;
|
private final MeterRegistryService meterRegistryService;
|
||||||
private final Map<String, Double> limitsBoundaryAggregatesMap;
|
private final Map<String, Double> paymentLimitsBoundaryAggregatesMap;
|
||||||
private final Map<String, Double> limitsAmountAggregatesMap;
|
private final Map<String, Double> paymentLimitsAmountAggregatesMap;
|
||||||
|
private final Map<String, Double> payoutLimitsBoundaryAggregatesMap;
|
||||||
|
private final Map<String, Double> payoutLimitsAmountAggregatesMap;
|
||||||
private final OpenSearchService openSearchService;
|
private final OpenSearchService openSearchService;
|
||||||
private final LimitConfigRepository limitConfigRepository;
|
private final LimitConfigRepository limitConfigRepository;
|
||||||
private final ObjectMapper objectMapper;
|
private final ObjectMapper objectMapper;
|
||||||
@ -57,17 +62,47 @@ public class LimitsService {
|
|||||||
log.warn("limitConfigEntity null, no gauge limitsData {}", limitsData);
|
log.warn("limitConfigEntity null, no gauge limitsData {}", limitsData);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
var id = String.format(
|
|
||||||
"%s.%s.%s.%s.%s",
|
var limitType = getLimitType(limitsData);
|
||||||
limitsData.getLimit().getConfigId(),
|
switch (limitType) {
|
||||||
limitsData.getLimit().getRoute().getProviderId(),
|
case PAYMENT -> {
|
||||||
limitsData.getLimit().getRoute().getTerminalId(),
|
var id = String.format(
|
||||||
limitsData.getLimit().getShopId(),
|
"%s.%s.%s.%s.%s",
|
||||||
limitsData.getLimit().getChange().getCurrency());
|
limitsData.getLimit().getConfigId(),
|
||||||
gauge(limitsBoundaryAggregatesMap, Metric.CALENDAR_LIMITS_BOUNDARY, id, getTags(limitsData, limitConfigEntity), limitsData.getLimit().getBoundary());
|
limitsData.getLimit().getRoute().getProviderId(),
|
||||||
gauge(limitsAmountAggregatesMap, Metric.CALENDAR_LIMITS_AMOUNT, id, getTags(limitsData, limitConfigEntity), limitsData.getLimit().getAmount());
|
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', " +
|
log.info("Limits metrics have been registered to 'prometheus', " +
|
||||||
"registeredMetricsSize = {}, clientSize = {}", registeredMetricsSize, limitsDataByInterval.size());
|
"registeredMetricsSize = {}, clientSize = {}", registeredMetricsSize, limitsDataByInterval.size());
|
||||||
}
|
}
|
||||||
@ -82,7 +117,19 @@ public class LimitsService {
|
|||||||
storage.put(id, Double.parseDouble(value));
|
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(
|
var tags = Tags.of(
|
||||||
CustomTag.terminalId(dto.getLimit().getRoute().getTerminalId()),
|
CustomTag.terminalId(dto.getLimit().getRoute().getTerminalId()),
|
||||||
CustomTag.providerId(dto.getLimit().getRoute().getProviderId()),
|
CustomTag.providerId(dto.getLimit().getRoute().getProviderId()),
|
||||||
@ -92,6 +139,24 @@ public class LimitsService {
|
|||||||
CustomTag.timeRangType(limitConfigEntity.getTimeRangType().name()),
|
CustomTag.timeRangType(limitConfigEntity.getTimeRangType().name()),
|
||||||
CustomTag.limitContextType(limitConfigEntity.getLimitContextType()),
|
CustomTag.limitContextType(limitConfigEntity.getLimitContextType()),
|
||||||
CustomTag.limitScopeTypes(getLimitScopeTypes(limitConfigEntity.getLimitScopeTypesJson())));
|
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) {
|
if (limitConfigEntity.getTimeRangeTypeCalendar() != null) {
|
||||||
tags = tags.and(CustomTag.timeRangeTypeCalendar(limitConfigEntity.getTimeRangeTypeCalendar()));
|
tags = tags.and(CustomTag.timeRangeTypeCalendar(limitConfigEntity.getTimeRangeTypeCalendar()));
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,9 @@ import org.opensearch.client.json.JsonData;
|
|||||||
import org.opensearch.client.opensearch.OpenSearchClient;
|
import org.opensearch.client.opensearch.OpenSearchClient;
|
||||||
import org.opensearch.client.opensearch._types.SortOrder;
|
import org.opensearch.client.opensearch._types.SortOrder;
|
||||||
import org.opensearch.client.opensearch._types.mapping.FieldType;
|
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.MatchPhraseQuery;
|
||||||
|
import org.opensearch.client.opensearch._types.query_dsl.Query;
|
||||||
import org.opensearch.client.opensearch._types.query_dsl.RangeQuery;
|
import org.opensearch.client.opensearch._types.query_dsl.RangeQuery;
|
||||||
import org.opensearch.client.opensearch.core.search.Hit;
|
import org.opensearch.client.opensearch.core.search.Hit;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
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 DATE_TIME = "date_time";
|
||||||
private static final String STRICT_DATE_OPTIONAL_TIME = "strict_date_optional_time";
|
private static final String STRICT_DATE_OPTIONAL_TIME = "strict_date_optional_time";
|
||||||
private static final String HELLGATE = "hellgate";
|
private static final String HELLGATE = "hellgate";
|
||||||
|
private static final String FISTFUL = "fistful";
|
||||||
private static final String LIMITS = "\"Limit change commited\"";
|
private static final String LIMITS = "\"Limit change commited\"";
|
||||||
|
|
||||||
private final OpenSearchProperties openSearchProperties;
|
private final OpenSearchProperties openSearchProperties;
|
||||||
@ -62,9 +65,16 @@ public class OpenSearchService {
|
|||||||
.format(STRICT_DATE_OPTIONAL_TIME)
|
.format(STRICT_DATE_OPTIONAL_TIME)
|
||||||
.build()
|
.build()
|
||||||
._toQuery(),
|
._toQuery(),
|
||||||
new MatchPhraseQuery.Builder()
|
new BoolQuery.Builder()
|
||||||
.field(KUBERNETES_CONTAINER_NAME)
|
.should(new Query(new MatchPhraseQuery.Builder()
|
||||||
.query(HELLGATE)
|
.field(KUBERNETES_CONTAINER_NAME)
|
||||||
|
.query(HELLGATE)
|
||||||
|
.build()),
|
||||||
|
new Query(new MatchPhraseQuery.Builder()
|
||||||
|
.field(KUBERNETES_CONTAINER_NAME)
|
||||||
|
.query(FISTFUL)
|
||||||
|
.build()))
|
||||||
|
.minimumShouldMatch("1")
|
||||||
.build()
|
.build()
|
||||||
._toQuery()))),
|
._toQuery()))),
|
||||||
LimitsData.class)
|
LimitsData.class)
|
||||||
|
Loading…
Reference in New Issue
Block a user