mirror of
https://github.com/valitydev/exporter-business-metrics.git
synced 2024-11-06 09:05:22 +00:00
add withdrawal metrics scrape
This commit is contained in:
parent
b259b99318
commit
f3c9a699eb
44
postgres/request_withdrawal.sql
Normal file
44
postgres/request_withdrawal.sql
Normal file
@ -0,0 +1,44 @@
|
||||
with w4 as (with w3 as (with w2 as (with w1 as (select w.wallet_id,
|
||||
coalesce(w.provider_id, -1) as provider_id,
|
||||
coalesce(w.terminal_id, '-1') as terminal_id,
|
||||
w.currency_code,
|
||||
w.withdrawal_status
|
||||
from dw.withdrawal as w
|
||||
where w.event_created_at > now() - interval '60 second'
|
||||
and w.current)
|
||||
select w1.*,
|
||||
p.name as provider_name
|
||||
from w1
|
||||
inner join dw.provider as p
|
||||
on w1.provider_id = p.provider_ref_id and
|
||||
p.current)
|
||||
select w2.*,
|
||||
t.name as terminal_name
|
||||
from w2
|
||||
inner join dw.terminal as t
|
||||
on w2.terminal_id = t.terminal_ref_id::varchar and
|
||||
t.current)
|
||||
select w3.*,
|
||||
w.wallet_name as wallet_name
|
||||
from w3
|
||||
inner join dw.wallet as w
|
||||
on w3.wallet_id = w.wallet_id and
|
||||
w.current)
|
||||
select provider_id,
|
||||
provider_name,
|
||||
terminal_id,
|
||||
terminal_name,
|
||||
wallet_id,
|
||||
wallet_name,
|
||||
currency_code,
|
||||
withdrawal_status,
|
||||
count(withdrawal_status)
|
||||
from w4
|
||||
group by provider_id,
|
||||
provider_name,
|
||||
terminal_id,
|
||||
terminal_name,
|
||||
wallet_id,
|
||||
wallet_name,
|
||||
currency_code,
|
||||
withdrawal_status
|
@ -16,4 +16,12 @@ public class GaugeConfig {
|
||||
.baseUnit(Metric.PAYMENTS_COUNT.getUnit())
|
||||
.register(meterRegistry);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MultiGauge multiGaugeWithdrawalsCount(MeterRegistry meterRegistry) {
|
||||
return MultiGauge.builder(Metric.WITHDRAWALS_COUNT.getName())
|
||||
.description(Metric.WITHDRAWALS_COUNT.getDescription())
|
||||
.baseUnit(Metric.WITHDRAWALS_COUNT.getUnit())
|
||||
.register(meterRegistry);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,34 @@
|
||||
package dev.vality.exporter.businessmetrics.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 = "withdrawal")
|
||||
public class WithdrawalEntity implements Serializable {
|
||||
|
||||
@EmbeddedId
|
||||
private WithdrawalPk pk;
|
||||
|
||||
@Column(name = "wallet_id")
|
||||
private String walletId;
|
||||
|
||||
@Column(name = "provider_id")
|
||||
private String providerId;
|
||||
|
||||
@Column(name = "terminal_id")
|
||||
private String terminalId;
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package dev.vality.exporter.businessmetrics.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 WithdrawalPk implements Serializable {
|
||||
|
||||
@Column(name = "withdrawal_id")
|
||||
private String withdrawalId;
|
||||
|
||||
@Column(name = "sequence_id")
|
||||
private String sequenceId;
|
||||
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
package dev.vality.exporter.businessmetrics.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@NamedNativeQuery(
|
||||
name = "getWithdrawalsMetricsByInterval",
|
||||
query = """
|
||||
with w4 as (with w3 as (with w2 as (with w1 as (select w.wallet_id,
|
||||
coalesce(w.provider_id, -1) as provider_id,
|
||||
coalesce(w.terminal_id, '-1') as terminal_id,
|
||||
w.currency_code,
|
||||
w.withdrawal_status
|
||||
from dw.withdrawal as w
|
||||
where w.event_created_at > :startPeriodDate
|
||||
and w.current)
|
||||
select w1.*,
|
||||
p.name as provider_name
|
||||
from w1
|
||||
inner join dw.provider as p
|
||||
on w1.provider_id = p.provider_ref_id and
|
||||
p.current)
|
||||
select w2.*,
|
||||
t.name as terminal_name
|
||||
from w2
|
||||
inner join dw.terminal as t
|
||||
on w2.terminal_id = t.terminal_ref_id::varchar and
|
||||
t.current)
|
||||
select w3.*,
|
||||
w.wallet_name as wallet_name
|
||||
from w3
|
||||
inner join dw.wallet as w
|
||||
on w3.wallet_id = w.wallet_id and
|
||||
w.current)
|
||||
select provider_id as providerId,
|
||||
provider_name as providerName,
|
||||
terminal_id as terminalId,
|
||||
terminal_name as terminalName,
|
||||
wallet_id as walletId,
|
||||
wallet_name as walletName,
|
||||
currency_code as currencyCode,
|
||||
withdrawal_status as status,
|
||||
count(withdrawal_status) as count
|
||||
from w4
|
||||
group by provider_id,
|
||||
provider_name,
|
||||
terminal_id,
|
||||
terminal_name,
|
||||
wallet_id,
|
||||
wallet_name,
|
||||
currency_code,
|
||||
withdrawal_status
|
||||
""",
|
||||
resultSetMapping = "WithdrawalsMetricDtoList")
|
||||
@SqlResultSetMapping(
|
||||
name = "WithdrawalsMetricDtoList",
|
||||
classes = @ConstructorResult(
|
||||
targetClass = WithdrawalsMetricDto.class,
|
||||
columns = {
|
||||
@ColumnResult(name = "providerId", type = String.class),
|
||||
@ColumnResult(name = "providerName", type = String.class),
|
||||
@ColumnResult(name = "terminalId", type = String.class),
|
||||
@ColumnResult(name = "terminalName", type = String.class),
|
||||
@ColumnResult(name = "walletId", type = String.class),
|
||||
@ColumnResult(name = "walletName", type = String.class),
|
||||
@ColumnResult(name = "currencyCode", type = String.class),
|
||||
@ColumnResult(name = "status", type = String.class),
|
||||
@ColumnResult(name = "count", type = String.class)}))
|
||||
@SuppressWarnings("LineLength")
|
||||
public class WithdrawalsMetricDto {
|
||||
|
||||
@Id
|
||||
private Long id;
|
||||
private String providerId;
|
||||
private String providerName;
|
||||
private String terminalId;
|
||||
private String terminalName;
|
||||
private String walletId;
|
||||
private String walletName;
|
||||
private String currencyCode;
|
||||
private String status;
|
||||
private String count;
|
||||
|
||||
public WithdrawalsMetricDto() {
|
||||
}
|
||||
|
||||
public WithdrawalsMetricDto(String providerId, String providerName, String terminalId, String terminalName, String walletId, String walletName, String currencyCode, String status, String count) {
|
||||
this.providerId = providerId;
|
||||
this.providerName = providerName;
|
||||
this.terminalId = terminalId;
|
||||
this.terminalName = terminalName;
|
||||
this.walletId = walletId;
|
||||
this.walletName = walletName;
|
||||
this.currencyCode = currencyCode;
|
||||
this.status = status;
|
||||
this.count = count;
|
||||
}
|
||||
}
|
@ -17,6 +17,8 @@ public class CustomTag {
|
||||
public static final String BANK_TAG = "issuer_bank";
|
||||
public static final String BANK_CARD_PAYMENT_SYSTEM_TAG = "issuer_bank_card_payment_system";
|
||||
public static final String STATUS_TAG = "status";
|
||||
public static final String WALLET_ID_TAG = "wallet_id";
|
||||
public static final String WALLET_NAME_TAG = "wallet_name";
|
||||
|
||||
public static Tag providerId(String providerId) {
|
||||
return Tag.of(PROVIDER_ID_TAG, providerId);
|
||||
@ -61,4 +63,12 @@ public class CustomTag {
|
||||
public static Tag status(String status) {
|
||||
return Tag.of(STATUS_TAG, status);
|
||||
}
|
||||
|
||||
public static Tag walletId(String walletId) {
|
||||
return Tag.of(WALLET_ID_TAG, walletId);
|
||||
}
|
||||
|
||||
public static Tag walletName(String walletName) {
|
||||
return Tag.of(WALLET_NAME_TAG, walletName);
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,11 @@ public enum Metric {
|
||||
PAYMENTS_COUNT(
|
||||
formatWithPrefix("payments"),
|
||||
"Payments count since last scrape",
|
||||
"count"),
|
||||
|
||||
WITHDRAWALS_COUNT(
|
||||
formatWithPrefix("withdrawals"),
|
||||
"Withdrawals count since last scrape",
|
||||
"count");
|
||||
|
||||
@Getter
|
||||
|
@ -0,0 +1,20 @@
|
||||
package dev.vality.exporter.businessmetrics.repository;
|
||||
|
||||
import dev.vality.exporter.businessmetrics.entity.WithdrawalEntity;
|
||||
import dev.vality.exporter.businessmetrics.entity.WithdrawalPk;
|
||||
import dev.vality.exporter.businessmetrics.entity.WithdrawalsMetricDto;
|
||||
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.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface WithdrawalRepository extends JpaRepository<WithdrawalEntity, WithdrawalPk> {
|
||||
|
||||
@Query(name = "getWithdrawalsMetricsByInterval", nativeQuery = true)
|
||||
List<WithdrawalsMetricDto> getWithdrawalsMetricsByInterval(@Param("startPeriodDate") LocalDateTime startPeriodDate);
|
||||
|
||||
}
|
@ -10,12 +10,10 @@ import org.springframework.stereotype.Service;
|
||||
public class MetricsService {
|
||||
|
||||
private final PaymentService paymentService;
|
||||
private final WithdrawalService withdrawalService;
|
||||
|
||||
public void registerMetrics() {
|
||||
registerPaymentsMetrics();
|
||||
}
|
||||
|
||||
private void registerPaymentsMetrics() {
|
||||
paymentService.registerMetrics();
|
||||
withdrawalService.registerMetrics();
|
||||
}
|
||||
}
|
||||
|
@ -32,14 +32,14 @@ public class PaymentService {
|
||||
private final MeterRegistry meterRegistry;
|
||||
|
||||
public void registerMetrics() {
|
||||
var paymentsMetrics = paymentRepository.getPaymentsMetricsByInterval(getStartPeriodDate());
|
||||
var metrics = paymentRepository.getPaymentsMetricsByInterval(getStartPeriodDate());
|
||||
log.info("Actual payments metrics have been got from 'daway' db, " +
|
||||
"interval = {}, count = {}", intervalTime, paymentsMetrics.size());
|
||||
"interval = {}, count = {}", intervalTime, metrics.size());
|
||||
final var pendingCount = new LongAdder();
|
||||
final var failedCount = new LongAdder();
|
||||
final var capturedCount = new LongAdder();
|
||||
final var otherStatusCount = new LongAdder();
|
||||
var rows = paymentsMetrics.stream()
|
||||
var rows = metrics.stream()
|
||||
.peek(dto -> {
|
||||
switch (dto.getStatus()) {
|
||||
case "pending" -> pendingCount.increment();
|
||||
|
@ -0,0 +1,77 @@
|
||||
package dev.vality.exporter.businessmetrics.service;
|
||||
|
||||
import dev.vality.exporter.businessmetrics.entity.WithdrawalsMetricDto;
|
||||
import dev.vality.exporter.businessmetrics.model.CustomTag;
|
||||
import dev.vality.exporter.businessmetrics.model.Metric;
|
||||
import dev.vality.exporter.businessmetrics.repository.WithdrawalRepository;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.MultiGauge;
|
||||
import io.micrometer.core.instrument.Tags;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
@SuppressWarnings("LineLength")
|
||||
public class WithdrawalService {
|
||||
|
||||
@Value("${interval.time}")
|
||||
private String intervalTime;
|
||||
|
||||
private final WithdrawalRepository withdrawalRepository;
|
||||
private final MultiGauge multiGaugeWithdrawalsCount;
|
||||
private final MeterRegistry meterRegistry;
|
||||
|
||||
public void registerMetrics() {
|
||||
var metrics = withdrawalRepository.getWithdrawalsMetricsByInterval(getStartPeriodDate());
|
||||
log.info("Actual withdrawal metrics have been got from 'daway' db, " +
|
||||
"interval = {}, count = {}", intervalTime, metrics.size());
|
||||
final var pendingCount = new LongAdder();
|
||||
final var failedCount = new LongAdder();
|
||||
final var succeededCount = new LongAdder();
|
||||
final var otherStatusCount = new LongAdder();
|
||||
var rows = metrics.stream()
|
||||
.peek(dto -> {
|
||||
switch (dto.getStatus()) {
|
||||
case "pending" -> pendingCount.increment();
|
||||
case "succeeded" -> succeededCount.increment();
|
||||
case "failed" -> failedCount.increment();
|
||||
default -> otherStatusCount.increment();
|
||||
}
|
||||
})
|
||||
.map(dto -> {
|
||||
final var value = Double.parseDouble(dto.getCount());
|
||||
return MultiGauge.Row.of(getTags(dto), this, o -> value);
|
||||
})
|
||||
.collect(Collectors.<MultiGauge.Row<?>>toList());
|
||||
multiGaugeWithdrawalsCount.register(rows, true);
|
||||
var registeredMetricsSize = meterRegistry.get(Metric.WITHDRAWALS_COUNT.getName()).gauges().size();
|
||||
log.info("Actual withdrawal metrics have been registered to 'prometheus', " +
|
||||
"registeredMetricsSize = {}, pendingCount = {}, failedCount = {}, succeededCount = {}, otherStatusCount = {}", registeredMetricsSize, pendingCount, failedCount, succeededCount, otherStatusCount);
|
||||
}
|
||||
|
||||
private LocalDateTime getStartPeriodDate() {
|
||||
return LocalDateTime.now(ZoneOffset.UTC).minus(Long.parseLong(intervalTime), ChronoUnit.SECONDS);
|
||||
}
|
||||
|
||||
private Tags getTags(WithdrawalsMetricDto dto) {
|
||||
return Tags.of(
|
||||
CustomTag.providerId(dto.getProviderId()),
|
||||
CustomTag.providerName(dto.getProviderName()),
|
||||
CustomTag.terminalId(dto.getTerminalId()),
|
||||
CustomTag.terminalName(dto.getTerminalName()),
|
||||
CustomTag.walletId(dto.getWalletId()),
|
||||
CustomTag.walletName(dto.getWalletName()),
|
||||
CustomTag.currency(dto.getCurrencyCode()),
|
||||
CustomTag.status(dto.getStatus()));
|
||||
}
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
package dev.vality.exporter.businessmetrics;
|
||||
|
||||
import dev.vality.exporter.businessmetrics.entity.PaymentsMetricDto;
|
||||
import dev.vality.exporter.businessmetrics.entity.WithdrawalsMetricDto;
|
||||
import dev.vality.exporter.businessmetrics.repository.PaymentRepository;
|
||||
import dev.vality.exporter.businessmetrics.repository.WithdrawalRepository;
|
||||
import dev.vality.exporter.businessmetrics.service.SchedulerRegisterMetricsService;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
@ -35,6 +37,9 @@ public class FlowTest {
|
||||
@MockBean
|
||||
private PaymentRepository paymentRepository;
|
||||
|
||||
@MockBean
|
||||
private WithdrawalRepository withdrawalRepository;
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@ -48,7 +53,7 @@ public class FlowTest {
|
||||
@BeforeEach
|
||||
public void init() {
|
||||
mocks = MockitoAnnotations.openMocks(this);
|
||||
preparedMocks = new Object[]{paymentRepository};
|
||||
preparedMocks = new Object[]{paymentRepository, withdrawalRepository};
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@ -60,21 +65,31 @@ public class FlowTest {
|
||||
@Test
|
||||
public void metricsHaveBeenRegisteredTest() throws Exception {
|
||||
var paymentsMetrics = getPaymentsMetricDtos();
|
||||
var withdrawalsMetrics = getWithdrawalsMetricDto();
|
||||
when(paymentRepository.getPaymentsMetricsByInterval(any())).thenReturn(paymentsMetrics);
|
||||
when(withdrawalRepository.getWithdrawalsMetricsByInterval(any())).thenReturn(withdrawalsMetrics);
|
||||
schedulerRegisterMetricsService.registerMetricsTask();
|
||||
verify(paymentRepository, times(1)).getPaymentsMetricsByInterval(any());
|
||||
verify(withdrawalRepository, times(1)).getWithdrawalsMetricsByInterval(any());
|
||||
var mvcResult = mockMvc.perform(get("/actuator/prometheus"))
|
||||
.andReturn();
|
||||
var prometheusResponse = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
var actualMetrics = Arrays.stream(prometheusResponse.split("\n"))
|
||||
.filter(row -> row.startsWith("ebm_")).toList();
|
||||
Assertions.assertEquals(paymentsMetrics.size(), actualMetrics.size());
|
||||
Assertions.assertEquals(paymentsMetrics.size() + withdrawalsMetrics.size(), actualMetrics.size());
|
||||
}
|
||||
|
||||
private List<PaymentsMetricDto> getPaymentsMetricDtos() {
|
||||
return List.of(
|
||||
new PaymentsMetricDto("1", "mts", "1", "mts rub", "1", "gucci", "rub", "rus", "kaspi jsp", "pending", "1"),
|
||||
new PaymentsMetricDto("2", "xxx", "2", "xxx usd", "1", "kaspi", "kzt", "kz", "kaspi jsp", "captured", "1"),
|
||||
new PaymentsMetricDto("3", "reppay", "3", "reppay kzt", "1", "kaspi", "usd", "usa", "undefined", "failed", "1"));
|
||||
new PaymentsMetricDto("1", "mts", "1", "mts rub", "1", "gucci", "rub", "rus", "kaspi jsp", "visa", "pending", "1"),
|
||||
new PaymentsMetricDto("2", "xxx", "2", "xxx usd", "1", "kaspi", "kzt", "kz", "kaspi jsp", "visa", "captured", "1"),
|
||||
new PaymentsMetricDto("3", "reppay", "3", "reppay kzt", "1", "kaspi", "usd", "usa", "undefined", "visa", "failed", "1"));
|
||||
}
|
||||
|
||||
private List<WithdrawalsMetricDto> getWithdrawalsMetricDto() {
|
||||
return List.of(
|
||||
new WithdrawalsMetricDto("1", "mts", "1", "mts rub", "1", "gucci", "rub", "pending", "1"),
|
||||
new WithdrawalsMetricDto("2", "xxx", "2", "xxx usd", "1", "kaspi", "kzt", "succeeded", "1"),
|
||||
new WithdrawalsMetricDto("3", "reppay", "3", "reppay kzt", "1", "kaspi", "usd", "failed", "1"));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user