Skip to content
Merged

Dev #164

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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,6 @@ out/
### 로컬 환경변수 ###
local.properties
/logs
docker-compose.override.yml

docker-compose.override.yml
opentelemetry-javaagent.jar
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ dependencies {
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.8'
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 'com.squareup.okhttp3:okhttp:4.12.0'
implementation 'com.google.code.gson:gson:2.13.1'
Expand Down
106 changes: 106 additions & 0 deletions monitoring/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
version: '3.8'

services:
app:
image: eclipse-temurin:21-jre-alpine
container_name: my-spring-app2
volumes:
- ../build/libs/coin-0.0.1-SNAPSHOT.jar:/app/coin-0.0.1-SNAPSHOT.jar
- /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" ]
ports:
- "8080:8080"
env_file:
- ../docker/local.properties
environment:
- TZ=Asia/Seoul
- OTEL_SERVICE_NAME=my-spring-app
- OTEL_TRACES_EXPORTER=otlp
- OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger: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
depends_on:
mariadb:
condition: service_healthy
networks:
- app-network
- monitoring-net

mariadb:
image: mariadb:latest
container_name: mariadb2
ports:
- "3306:3306"
env_file:
- ../docker/local.properties
environment:
- TZ=Asia/Seoul
volumes:
- mariadb_data:/var/lib/mysql
- ../docker/mariadb/init.sql:/docker-entrypoint-initdb.d/init.sql
healthcheck:
test: [ "CMD", "healthcheck.sh", "--connect", "--innodb_initialized" ]
interval: 10s
timeout: 5s
retries: 10
networks:
- app-network
- monitoring-net

prometheus:
image: prom/prometheus:v2.53.0
container_name: prometheus
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.retention.time=30d'
ports:
- "9090:9090"
networks:
- monitoring-net
restart: unless-stopped

grafana:
image: grafana/grafana:11.0.0
container_name: grafana
volumes:
- grafana_data:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning
ports:
- "3000:3000"
networks:
- monitoring-net
restart: unless-stopped
depends_on:
- prometheus
- jaeger

jaeger:
image: jaegertracing/all-in-one:latest
container_name: jaeger
ports:
- "16686:16686"
- "4317:4317"
- "4318:4318"
networks:
- monitoring-net

volumes:
prometheus_data: {}
grafana_data: {}
mariadb_data:
driver: local

networks:
app-network:
name: app-network
driver: bridge
monitoring-net:
name: monitoring-net
driver: bridge
9 changes: 9 additions & 0 deletions monitoring/grafana/provisioning/datsources/datasource.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: 1

datasources:
- name: Prometheus
type: prometheus
url: http://prometheus:9090
access: proxy
isDefault: true
editable: true
11 changes: 11 additions & 0 deletions monitoring/prometheus/prometheus.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
global:
scrape_interval: 10s

scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['prometheus:9090']
- job_name: 'my-app'
static_configs:
- targets: [ 'app:8080' ]
metrics_path: /actuator/prometheus
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.cleanengine.coin.common.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface StartNewTrace {
String value() default "";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.cleanengine.coin.common.annotation;

import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Scope;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;

@Aspect
@Component
@RequiredArgsConstructor
public class StartNewTraceAspect {

@Around("@annotation(com.cleanengine.coin.common.annotation.StartNewTrace)")
public Object createNewTrace(ProceedingJoinPoint joinPoint) throws Throwable {
Tracer tracer = GlobalOpenTelemetry.getTracer("com.cleanengine.coin");

MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
StartNewTrace newTraceAnnotation = method.getAnnotation(StartNewTrace.class);

String spanName = newTraceAnnotation.value().isEmpty() ?
signature.getDeclaringType().getSimpleName() + "." + method.getName() :
newTraceAnnotation.value();

Span span = tracer.spanBuilder(spanName).setNoParent().startSpan();

try (Scope scope = span.makeCurrent()) {
return joinPoint.proceed();
} catch (Exception e) {
span.recordException(e);
throw e;
} finally {
span.end();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.cleanengine.coin.configuration;


import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
Expand All @@ -11,14 +12,8 @@
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

private static final String[] ALLOWED_ORIGINS = {
"http://localhost:63342",
"http://localhost:63343",
"http://localhost:8080",
"http://localhost:5500",
"http://localhost:5173",
"https://investfuture.my"
};
@Value("${spring.security.allowed-origins}")
private String[] allowedOrigins;

@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
Expand All @@ -34,9 +29,7 @@ public void registerStompEndpoints(StompEndpointRegistry registry) {

private void registerEndpoint(StompEndpointRegistry registry, String endpoint) {
registry.addEndpoint(endpoint)
.setAllowedOrigins(ALLOWED_ORIGINS);
.setAllowedOrigins(allowedOrigins);
}

}


}
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,26 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.servers.Server;

@Configuration
public class SwaggerConfig {

@Bean
public OpenAPI openAPI() {
// API 기본 정보 설정
Info info = new Info()
.title("investFuture API Document")
.title("InvestFuture API Document")
.version("1.0")
.description(
"환영합니다.\n")
.description("Private API 호출 시 Cookie에 직접 설정해주세요!\n")
.contact(new io.swagger.v3.oas.models.info.Contact().email("billage.official@gmail.com"));

// JWT 인증 방식 설정
String jwtScheme = "jwtAuth";
SecurityRequirement securityRequirement = new SecurityRequirement().addList(jwtScheme);
Components components = new Components()
.addSecuritySchemes(jwtScheme, new SecurityScheme()
.name("Authorization")
.type(SecurityScheme.Type.HTTP)
.in(SecurityScheme.In.HEADER)
.scheme("Bearer")
.bearerFormat("JWT"));

// Swagger UI 설정 및 보안 추가
return new OpenAPI()
.addServersItem(new Server().url("http://localhost:8080")) // 추가적인 서버 URL 설정 가능
.components(components)
.info(info)
.addSecurityItem(securityRequirement);
.info(info);
}

}
62 changes: 51 additions & 11 deletions src/main/java/com/cleanengine/coin/orderbook/domain/OrderBook.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,38 +22,42 @@ public void updateOrderBookOnNewOrder(boolean isBuyOrder, Double price, Double o
if(isBuyOrder){
BuyOrderBookUnit buyOrderBookUnit = buyOrderBookUnitMap.get(price);
if(buyOrderBookUnit == null){
buyOrderBookUnit = new BuyOrderBookUnit(price, orderSize);
buyOrderBookUnitMap.put(price, buyOrderBookUnit);
buyOrderBookUnitListSet.add(buyOrderBookUnit);
addBuyOrderBookUnit(price, orderSize);
} else {
buyOrderBookUnit.addOrder(orderSize);
}
} else {
SellOrderBookUnit sellOrderBookUnit = sellOrderBookUnitMap.get(price);
if(sellOrderBookUnit == null){
sellOrderBookUnit = new SellOrderBookUnit(price, orderSize);
sellOrderBookUnitMap.put(price, sellOrderBookUnit);
sellOrderBookUnitListSet.add(sellOrderBookUnit);
addSellOrderBookUnit(price, orderSize);
} else {
sellOrderBookUnit.addOrder(orderSize);
}
}
}

public void updateOrderBookOnTradeExecuted(boolean isBuyOrder, Double price, Double orderSize) {
if(isBuyOrder){
if(approxEquals(orderSize, 0.0) || approxEquals(price, 0.0)){
throw new IllegalArgumentException("orderSize or price cannot be 0.0");
}

if(isBuyOrder) {
BuyOrderBookUnit buyOrderBookUnit = buyOrderBookUnitMap.get(price);
if(buyOrderBookUnit == null) {
return;
}
buyOrderBookUnit.executeTrade(orderSize);
if(approxEquals(buyOrderBookUnit.getSize(), 0.0)){
buyOrderBookUnitMap.remove(price);
buyOrderBookUnitListSet.remove(buyOrderBookUnit);
removeBuyOrderBookUnit(buyOrderBookUnit, price);
}
} else {
SellOrderBookUnit sellOrderBookUnit = sellOrderBookUnitMap.get(price);
if(sellOrderBookUnit == null) {
return;
}
sellOrderBookUnit.executeTrade(orderSize);
if(approxEquals(sellOrderBookUnit.getSize(), 0.0)){
sellOrderBookUnitMap.remove(price);
sellOrderBookUnitListSet.remove(sellOrderBookUnit);
removeSellOrderBookUnit(sellOrderBookUnit, price);
}
}
}
Expand All @@ -71,4 +75,40 @@ public List<OrderBookUnit> getSellOrderBookList(int size){
.limit(size)
.collect(Collectors.toList());
}

protected synchronized void addBuyOrderBookUnit(Double price, Double size) {
BuyOrderBookUnit buyOrderBookUnit = buyOrderBookUnitMap.get(price);
if(buyOrderBookUnit != null){
return;
}

buyOrderBookUnit = new BuyOrderBookUnit(price, size);
buyOrderBookUnitMap.put(price, buyOrderBookUnit);
buyOrderBookUnitListSet.add(buyOrderBookUnit);
}

protected synchronized void addSellOrderBookUnit(Double price, Double size) {
SellOrderBookUnit sellOrderBookUnit = sellOrderBookUnitMap.get(price);
if(sellOrderBookUnit != null){
return;
}

sellOrderBookUnit = new SellOrderBookUnit(price, size);
sellOrderBookUnitMap.put(price, sellOrderBookUnit);
sellOrderBookUnitListSet.add(sellOrderBookUnit);
}

protected synchronized void removeBuyOrderBookUnit(BuyOrderBookUnit buyOrderBookUnit, Double price) {
if(approxEquals(buyOrderBookUnit.getSize(), 0.0)) {
buyOrderBookUnitMap.remove(price);
buyOrderBookUnitListSet.remove(buyOrderBookUnit);
}
}

protected synchronized void removeSellOrderBookUnit(SellOrderBookUnit sellOrderBookUnit, Double price) {
if(approxEquals(sellOrderBookUnit.getSize(), 0.0)) {
sellOrderBookUnitMap.remove(price);
sellOrderBookUnitListSet.remove(sellOrderBookUnit);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

@Slf4j
@Component
@WorkingServerProfile
@RequiredArgsConstructor
public class ApiScheduler {

Expand Down
Loading
Loading