diff --git a/src/main/java/dev/vality/exporter/limits/entity/LimitConfigEntity.java b/src/main/java/dev/vality/exporter/limits/entity/LimitConfigEntity.java new file mode 100644 index 0000000..3ec505a --- /dev/null +++ b/src/main/java/dev/vality/exporter/limits/entity/LimitConfigEntity.java @@ -0,0 +1,46 @@ +package dev.vality.exporter.limits.entity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.Column; +import javax.persistence.EmbeddedId; +import javax.persistence.Entity; +import javax.persistence.Table; +import java.io.Serializable; + +@Entity +@Builder +@Data +@AllArgsConstructor +@NoArgsConstructor +@Table(name = "limit_config") +public class LimitConfigEntity implements Serializable { + + @EmbeddedId + private LimitConfigPk pk; + + @Column(name = "time_range_type") + private String timeRangType; + + @Column(name = "time_range_type_calendar") + private String timeRangeTypeCalendar; + + @Column(name = "limit_context_type") + private String limitContextType; + + @Column(name = "limit_type_turnover_metric") + private String limitTypeTurnoverMetric; + + @Column(name = "limit_scope") + private String limitScope; + + @Column(name = "operation_limit_behaviour") + private String operationLimitBehaviour; + + @Column(name = "limit_scope_types_json") + private String limitScopeTypesJson; + +} diff --git a/src/main/java/dev/vality/exporter/limits/entity/LimitConfigPk.java b/src/main/java/dev/vality/exporter/limits/entity/LimitConfigPk.java new file mode 100644 index 0000000..4923a26 --- /dev/null +++ b/src/main/java/dev/vality/exporter/limits/entity/LimitConfigPk.java @@ -0,0 +1,25 @@ +package dev.vality.exporter.limits.entity; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.Column; +import javax.persistence.Embeddable; +import java.io.Serializable; + +@Embeddable +@Builder +@Data +@AllArgsConstructor +@NoArgsConstructor +public class LimitConfigPk implements Serializable { + + @Column(name = "limit_config_id") + private String limitConfigId; + + @Column(name = "sequence_id") + private Long sequenceId; + +} diff --git a/src/main/java/dev/vality/exporter/limits/model/CustomTag.java b/src/main/java/dev/vality/exporter/limits/model/CustomTag.java index 1b4ca40..43d8a46 100644 --- a/src/main/java/dev/vality/exporter/limits/model/CustomTag.java +++ b/src/main/java/dev/vality/exporter/limits/model/CustomTag.java @@ -20,6 +20,13 @@ public class CustomTag { public static final String WALLET_ID_TAG = "wallet_id"; public static final String WALLET_NAME_TAG = "wallet_name"; 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_CALENDAR = "time_range_type_calendar"; + public static final String LIMIT_CONTEXT_TYPE = "limit_context_type"; + public static final String LIMIT_TYPE_TURNOVER_METRIC = "limit_type_turnover_metric"; + public static final String LIMIT_SCOPE = "limit_scope"; + public static final String OPERATION_LIMIT_BEHAVIOUR = "operation_limit_behaviour"; + public static final String LIMIT_SCOPE_TYPES = "limit_scope_types"; public static Tag providerId(String providerId) { return Tag.of(PROVIDER_ID_TAG, providerId); @@ -76,4 +83,33 @@ public class CustomTag { public static Tag configId(String configId) { return Tag.of(CONFIG_ID_TAG, configId); } + + public static Tag timeRangType(String timeRangType) { + return Tag.of(TIME_RANGE_TYPE, timeRangType); + } + + public static Tag timeRangeTypeCalendar(String timeRangeTypeCalendar) { + return Tag.of(TIME_RANGE_TYPE_CALENDAR, timeRangeTypeCalendar); + } + + public static Tag limitContextType(String limitContextType) { + return Tag.of(LIMIT_CONTEXT_TYPE, limitContextType); + } + + public static Tag limitTypeTurnoverMetric(String limitTypeTurnoverMetric) { + return Tag.of(LIMIT_TYPE_TURNOVER_METRIC, limitTypeTurnoverMetric); + } + + public static Tag limitScope(String limitScope) { + return Tag.of(LIMIT_SCOPE, limitScope); + } + + public static Tag operationLimitBehaviour(String operationLimitBehaviour) { + return Tag.of(OPERATION_LIMIT_BEHAVIOUR, operationLimitBehaviour); + } + + + public static Tag limitScopeTypes(String limitScopeTypes) { + return Tag.of(LIMIT_SCOPE_TYPES, limitScopeTypes); + } } diff --git a/src/main/java/dev/vality/exporter/limits/model/Metric.java b/src/main/java/dev/vality/exporter/limits/model/Metric.java index fa89ba3..e66c851 100644 --- a/src/main/java/dev/vality/exporter/limits/model/Metric.java +++ b/src/main/java/dev/vality/exporter/limits/model/Metric.java @@ -7,10 +7,10 @@ import lombok.RequiredArgsConstructor; public enum Metric { LIMITS_BOUNDARY( - formatWithPrefix("limits_boundary"), + formatWithPrefix("limits_boundary_by_calendar"), "Limits boundary since last scrape"), LIMITS_AMOUNT( - formatWithPrefix("limits_amount"), + formatWithPrefix("limits_amount_by_calendar"), "Limits amount since last scrape"); @Getter diff --git a/src/main/java/dev/vality/exporter/limits/repository/LimitConfigRepository.java b/src/main/java/dev/vality/exporter/limits/repository/LimitConfigRepository.java new file mode 100644 index 0000000..06d545c --- /dev/null +++ b/src/main/java/dev/vality/exporter/limits/repository/LimitConfigRepository.java @@ -0,0 +1,23 @@ +package dev.vality.exporter.limits.repository; + +import dev.vality.exporter.limits.entity.LimitConfigEntity; +import dev.vality.exporter.limits.entity.LimitConfigPk; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +@SuppressWarnings("LineLength") +public interface LimitConfigRepository extends JpaRepository { + + @Query(value = "select lc " + + "from LimitConfigEntity as lc " + + "where lc.limit_config_id in :limitConfigIds " + + "and lc.time_range_type = :time_range_type" + + "and lc.current = true") + List findAllUsingLimitConfigIdsAndTimeRangType(@Param("limitConfigIds") List limitConfigIds, @Param("time_range_type") String timeRangType); + +} diff --git a/src/main/java/dev/vality/exporter/limits/service/LimitsService.java b/src/main/java/dev/vality/exporter/limits/service/LimitsService.java index a3d7fb4..8d4bf8f 100644 --- a/src/main/java/dev/vality/exporter/limits/service/LimitsService.java +++ b/src/main/java/dev/vality/exporter/limits/service/LimitsService.java @@ -1,15 +1,19 @@ package dev.vality.exporter.limits.service; +import dev.vality.exporter.limits.entity.LimitConfigEntity; import dev.vality.exporter.limits.model.CustomTag; import dev.vality.exporter.limits.model.LimitsData; import dev.vality.exporter.limits.model.Metric; +import dev.vality.exporter.limits.repository.LimitConfigRepository; import io.micrometer.core.instrument.Gauge; import io.micrometer.core.instrument.Tags; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import java.util.Comparator; import java.util.Map; +import java.util.stream.Collectors; @Service @RequiredArgsConstructor @@ -17,14 +21,40 @@ import java.util.Map; @SuppressWarnings("LineLength") public class LimitsService { + private static final String CALENDAR = "calendar"; + private final MeterRegistryService meterRegistryService; private final Map limitsBoundaryAggregatesMap; private final Map limitsAmountAggregatesMap; private final OpenSearchService openSearchService; + private final LimitConfigRepository limitConfigRepository; public void registerMetrics() { var limitsDataByInterval = openSearchService.getLimitsDataByInterval(); + log.info("limitsDataByInterval {}", limitsDataByInterval); + var limitConfigIds = limitsDataByInterval.stream() + .map(limitsData -> limitsData.getLimit().getConfigId()) + .distinct() + .toList(); + log.info("limitConfigIds {}", limitConfigIds); + var limitConfigEntities = limitConfigRepository.findAllUsingLimitConfigIdsAndTimeRangType(limitConfigIds, CALENDAR); + log.info("limitConfigEntities {}", limitConfigEntities); + var limitConfigsById = limitConfigEntities.stream().collect( + Collectors.groupingBy( + o -> o.getPk().getLimitConfigId(), + Collectors.mapping( + o -> o, + Collectors.collectingAndThen( + Collectors.toList(), + values -> values.stream() + .max(Comparator.comparing(limitConfigEntity -> limitConfigEntity.getPk().getSequenceId())) + .orElse(null))))); + log.info("limitConfigsById {}", limitConfigsById); for (var limitsData : limitsDataByInterval) { + var limitConfigEntity = limitConfigsById.get(limitsData.getLimit().getConfigId()); + if (limitConfigEntity == null) { + break; + } var id = String.format( "%s.%s.%s.%s.%s", limitsData.getLimit().getConfigId(), @@ -32,8 +62,9 @@ public class LimitsService { limitsData.getLimit().getRoute().getTerminalId(), limitsData.getLimit().getShopId(), limitsData.getLimit().getChange().getCurrency()); - gauge(limitsBoundaryAggregatesMap, Metric.LIMITS_BOUNDARY, id, getTags(limitsData), limitsData.getLimit().getBoundary()); - gauge(limitsAmountAggregatesMap, Metric.LIMITS_AMOUNT, id, getTags(limitsData), limitsData.getLimit().getAmount()); + log.info("id {}", id); + gauge(limitsBoundaryAggregatesMap, Metric.LIMITS_BOUNDARY, id, getTags(limitsData, limitConfigEntity), limitsData.getLimit().getBoundary()); + gauge(limitsAmountAggregatesMap, Metric.LIMITS_AMOUNT, id, getTags(limitsData, limitConfigEntity), limitsData.getLimit().getAmount()); } var registeredMetricsSize = meterRegistryService.getRegisteredMetricsSize(Metric.LIMITS_BOUNDARY.getName()) + meterRegistryService.getRegisteredMetricsSize(Metric.LIMITS_AMOUNT.getName()); log.info("Limits with final statuses metrics have been registered to 'prometheus', " + @@ -50,12 +81,18 @@ public class LimitsService { storage.put(id, Double.parseDouble(value)); } - private Tags getTags(LimitsData dto) { + private Tags getTags(LimitsData dto, LimitConfigEntity limitConfigEntity) { return Tags.of( CustomTag.terminalId(dto.getLimit().getRoute().getTerminalId()), CustomTag.providerId(dto.getLimit().getRoute().getProviderId()), CustomTag.currency(dto.getLimit().getChange().getCurrency()), CustomTag.shopId(dto.getLimit().getShopId()), - CustomTag.configId(dto.getLimit().getConfigId())); + CustomTag.configId(dto.getLimit().getConfigId()), + CustomTag.timeRangType(limitConfigEntity.getTimeRangType()), + CustomTag.timeRangeTypeCalendar(limitConfigEntity.getTimeRangeTypeCalendar()), + CustomTag.limitContextType(limitConfigEntity.getLimitContextType()), + CustomTag.limitTypeTurnoverMetric(limitConfigEntity.getLimitTypeTurnoverMetric()), + CustomTag.limitScope(limitConfigEntity.getLimitScope()), + CustomTag.operationLimitBehaviour(limitConfigEntity.getOperationLimitBehaviour())); } }