Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'io.micrometer:micrometer-registry-prometheus'
implementation("io.opentelemetry.instrumentation:opentelemetry-instrumentation-annotations:2.16.0")
implementation 'org.hibernate.orm:hibernate-micrometer'

implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation 'com.google.code.gson:gson:2.13.1'
Expand Down
2 changes: 2 additions & 0 deletions docker/mariadb/init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,5 @@ INSERT INTO `if`.asset (ticker, name) VALUES ('TRUMP', '오피셜트럼프');

INSERT INTO `if`.wallet (wallet_id, account_id, buy_price, roi, size, ticker) VALUES (1, 1, 0, 0, 500000000, 'BTC');
INSERT INTO `if`.wallet (wallet_id, account_id, buy_price, roi, size, ticker) VALUES (2, 1, 0, 0, 500000000, 'TRUMP');
INSERT INTO `if`.wallet (wallet_id, account_id, buy_price, roi, size, ticker) VALUES (3, 2, 0, 0, 500000000, 'BTC');
INSERT INTO `if`.wallet (wallet_id, account_id, buy_price, roi, size, ticker) VALUES (4, 2, 0, 0, 500000000, 'TRUMP');
47 changes: 39 additions & 8 deletions monitoring/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ services:
- /etc/localtime:/etc/localtime:ro
- ./opentelemetry-javaagent.jar:/app/opentelemetry-javaagent.jar
working_dir: /app
command: [ "java", "-jar", "coin-0.0.1-SNAPSHOT.jar", "--spring.profiles.active=dev,mariadb-local,actuator,apm" ]
command: [ "java", "-jar", "coin-0.0.1-SNAPSHOT.jar", "--spring.profiles.active=dev,it,mariadb-local,actuator,apm" ]
ports:
- "8080:8080"
env_file:
Expand All @@ -18,14 +18,16 @@ services:
- TZ=Asia/Seoul
- OTEL_SERVICE_NAME=my-spring-app
- OTEL_TRACES_EXPORTER=otlp
- OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318
- OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318
- OTEL_LOGS_EXPORTER=none
- OTEL_METRICS_EXPORTER=none
- OTEL_INSTRUMENTATION_METHODS_ENABLED=true
- JAVA_TOOL_OPTIONS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005, -javaagent:/app/opentelemetry-javaagent.jar
- JAVA_TOOL_OPTIONS=-javaagent:/app/opentelemetry-javaagent.jar
depends_on:
mariadb:
condition: service_healthy
otel-collector:
condition: service_started
networks:
- app-network
- monitoring-net
Expand All @@ -34,7 +36,7 @@ services:
image: mariadb:latest
container_name: mariadb2
ports:
- "3307:3306"
- "3306:3306"
env_file:
- ../docker/local.properties
environment:
Expand All @@ -60,13 +62,13 @@ services:
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.retention.time=30d'
- '--web.enable-remote-write-receiver'
ports:
- "9090:9090"
networks:
- monitoring-net
restart: unless-stopped

# --- 추가된 InfluxDB 서비스 ---
influxdb:
image: influxdb:2.7
container_name: influxdb
Expand Down Expand Up @@ -96,27 +98,56 @@ services:
networks:
- monitoring-net
restart: unless-stopped
depends_on: # --- 수정된 부분 ---
depends_on:
- prometheus
- jaeger
- influxdb

jaeger:
image: jaegertracing/all-in-one:latest
container_name: jaeger
user: "${UID}:${GID}"
environment:
- SPAN_STORAGE_TYPE=badger
- BADGER_EPHEMERAL=false
- BADGER_DIRECTORY_VALUE=/tmp/jaeger/data
- BADGER_DIRECTORY_KEY=/tmp/jaeger/keys
- COLLECTOR_OTLP_ENABLED=true
- COLLECTOR_OTLP_GRPC_HOST_PORT=0.0.0.0:4317
- COLLECTOR_OTLP_HTTP_HOST_PORT=0.0.0.0:4318
volumes:
- jaeger_data:/tmp/jaeger
ports:
- "16686:16686" # UI
- "4319:4317"
- "4320:4318"
networks:
- monitoring-net


otel-collector:
image: otel/opentelemetry-collector-contrib:latest
command: ["--config=/etc/otel-collector-config.yml"]
volumes:
- ./otel/otel-collector-config.yml:/etc/otel-collector-config.yml
ports:
- "16686:16686"
- "8889:8889"
- "4317:4317"
- "4318:4318"
- "13133:13133"
networks:
- monitoring-net
depends_on:
jaeger:
condition: service_started

volumes:
prometheus_data: {}
grafana_data: {}
mariadb_data:
driver: local
influxdb_data: {} # --- 추가된 부분 ---
influxdb_data: {}
jaeger_data: {}

networks:
app-network:
Expand Down
47 changes: 47 additions & 0 deletions monitoring/otel/otel-collector-config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318

processors:
batch:
timeout: 500ms
send_batch_size: 8192
send_batch_max_size: 16384
probabilistic_sampler:
sampling_percentage: 1

connectors:
spanmetrics:
histogram:
explicit:
buckets: [100us, 1ms, 2ms, 6ms, 10ms, 100ms, 250ms, 500ms, 1s]

exporters:
otlp/jaeger:
endpoint: jaeger:4317
tls:
insecure: true

prometheus:
endpoint: "0.0.0.0:8889"

service:
pipelines:
traces/metrics:
receivers: [otlp]
processors: [batch]
exporters: [spanmetrics]

traces/jaeger:
receivers: [otlp]
processors: [probabilistic_sampler,batch]
exporters: [otlp/jaeger]

metrics:
receivers: [spanmetrics]
processors: [batch]
exporters: [prometheus]
6 changes: 5 additions & 1 deletion monitoring/prometheus/prometheus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@ scrape_configs:
- job_name: 'my-app'
static_configs:
- targets: [ 'app:8080' ]
metrics_path: /actuator/prometheus
metrics_path: /actuator/prometheus
- job_name: 'otel-collector'
scrape_interval: 15s
static_configs:
- targets: [ 'otel-collector:8889' ]
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.cleanengine.coin.configuration;

import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.config.MeterFilter;
import io.micrometer.core.instrument.config.MeterFilterReply;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

@Profile("actuator")
@Configuration
public class MicrometerConfig {
@Bean
public MeterFilter meterFilter() {
final String hibernateFilterPrefix = "hibernate.statements";

return new MeterFilter() {
@Override
public MeterFilterReply accept(Meter.Id id) {
if (id.getName().startsWith("hibernate.")) {
if(id.getName().startsWith(hibernateFilterPrefix)) {
return MeterFilterReply.ACCEPT;
}
else{
return MeterFilterReply.DENY;
}
}
return MeterFilterReply.NEUTRAL;
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import java.util.Optional;

@Slf4j
@Component
//@Component
public class InMemoryWaitingOrdersManager implements WaitingOrdersManager {
private final HashMap<String, WaitingOrders> waitingOrdersMap = new HashMap<>();

Expand All @@ -29,7 +29,7 @@ public WaitingOrders getWaitingOrders(String ticker) {

@Override
public void removeWaitingOrders(String ticker) {

waitingOrdersMap.remove(ticker);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.cleanengine.coin.order.adapter.out.persistentce.order.queue;

import com.cleanengine.coin.common.domain.port.PriorityQueueStore;
import com.cleanengine.coin.order.domain.BuyOrder;

import java.util.Comparator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.atomic.AtomicLong;

public class NestedInMemoryBuyOrderSkipListSet implements PriorityQueueStore<BuyOrder> {
private final ConcurrentSkipListMap<Double, ConcurrentSkipListSet<BuyOrder>> map = new ConcurrentSkipListMap<>(Comparator.reverseOrder());
private final AtomicLong size = new AtomicLong();

@Override
public void put(BuyOrder item) {
if(item == null) throw new IllegalArgumentException("item cannot be null.");

map.compute(item.getPrice(), (key, buyOrders) -> {
if(buyOrders == null) {
buyOrders = new ConcurrentSkipListSet<>();
}
boolean added = buyOrders.add(item);
if(added) size.incrementAndGet();
return buyOrders;
});
}

@Override
public BuyOrder poll() {
while(true) {
Map.Entry<Double, ConcurrentSkipListSet<BuyOrder>> firstEntry = map.firstEntry();

if (firstEntry == null) {
return null;
}

ConcurrentSkipListSet<BuyOrder> buyOrders = firstEntry.getValue();
try {
BuyOrder order = buyOrders.first();
this.remove(order);
return order;
} catch (NoSuchElementException e) {
continue;
}
}
}

@Override
public BuyOrder peek() {
while(true) {
Map.Entry<Double, ConcurrentSkipListSet<BuyOrder>> firstEntry = map.firstEntry();

if (firstEntry == null) {
return null;
}

ConcurrentSkipListSet<BuyOrder> buyOrders = firstEntry.getValue();
try {
return buyOrders.first();
} catch (NoSuchElementException e) {
continue;
}
}
}

@Override
public BuyOrder remove(BuyOrder item) {
if (item == null) return null;

map.computeIfPresent(item.getPrice(), (key, orders) -> {
boolean removed = orders.remove(item);
if (removed) size.decrementAndGet();
return orders.isEmpty() ? null : orders;
});

return item;
}

@Override
public long size() {
return size.get();
}

@Override
public boolean isEmpty() {
return map.isEmpty();
}

@Override
public void clear() {
map.clear();
}
}
Loading