Skip to content

Commit 2fef77c

Browse files
authored
feat: WebSocket 로깅 인터셉터 작성 (#635)
* feat: WebSocket 로깅 인터셉터 작성 * refactor: Principal 명시적 형 변환 대신 null 체크하여 형 변환
1 parent c0a4f42 commit 2fef77c

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed

src/main/java/com/example/solidconnection/chat/config/StompWebSocketConfig.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.example.solidconnection.chat.config.StompProperties.OutboundProperties;
66
import com.example.solidconnection.security.config.CorsProperties;
77
import java.util.List;
8+
import java.util.Optional;
89
import lombok.RequiredArgsConstructor;
910
import org.springframework.context.annotation.Configuration;
1011
import org.springframework.messaging.simp.config.ChannelRegistration;
@@ -24,6 +25,7 @@ public class StompWebSocketConfig implements WebSocketMessageBrokerConfigurer {
2425
private final CorsProperties corsProperties;
2526
private final WebSocketHandshakeInterceptor webSocketHandshakeInterceptor;
2627
private final CustomHandshakeHandler customHandshakeHandler;
28+
private final Optional<WebSocketLoggingInterceptor> webSocketLoggingInterceptor;
2729

2830
@Override
2931
public void registerStompEndpoints(StompEndpointRegistry registry) {
@@ -39,7 +41,12 @@ public void registerStompEndpoints(StompEndpointRegistry registry) {
3941
@Override
4042
public void configureClientInboundChannel(ChannelRegistration registration) {
4143
InboundProperties inboundProperties = stompProperties.threadPool().inbound();
42-
registration.interceptors(stompHandler).taskExecutor().corePoolSize(inboundProperties.corePoolSize()).maxPoolSize(inboundProperties.maxPoolSize()).queueCapacity(inboundProperties.queueCapacity());
44+
webSocketLoggingInterceptor.ifPresent(registration::interceptors);
45+
registration.interceptors(stompHandler)
46+
.taskExecutor()
47+
.corePoolSize(inboundProperties.corePoolSize())
48+
.maxPoolSize(inboundProperties.maxPoolSize())
49+
.queueCapacity(inboundProperties.queueCapacity());
4350
}
4451

4552
@Override
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.example.solidconnection.chat.config;
2+
3+
import com.example.solidconnection.security.authentication.TokenAuthentication;
4+
import com.example.solidconnection.security.userdetails.SiteUserDetails;
5+
import java.security.Principal;
6+
import lombok.extern.slf4j.Slf4j;
7+
import org.springframework.context.annotation.Profile;
8+
import org.springframework.messaging.Message;
9+
import org.springframework.messaging.MessageChannel;
10+
import org.springframework.messaging.simp.stomp.StompCommand;
11+
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
12+
import org.springframework.messaging.support.ChannelInterceptor;
13+
import org.springframework.stereotype.Component;
14+
15+
@Slf4j
16+
@Component
17+
@Profile("dev")
18+
public class WebSocketLoggingInterceptor implements ChannelInterceptor {
19+
20+
@Override
21+
public Message<?> preSend(Message<?> message, MessageChannel channel) {
22+
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
23+
StompCommand command = accessor.getCommand();
24+
25+
if (command != null) {
26+
Long userId = extractUserId(accessor);
27+
String destination = accessor.getDestination();
28+
logStompMessage(command, destination, userId);
29+
}
30+
31+
return message;
32+
}
33+
34+
private void logStompMessage(StompCommand command, String destination, Long userId) {
35+
switch (command) {
36+
case CONNECT -> log.info("[WEBSOCKET] CONNECT userId = {}", userId);
37+
case SUBSCRIBE -> log.info("[WEBSOCKET] SUBSCRIBE {} userId = {}", destination, userId);
38+
case SEND -> log.info("[WEBSOCKET] SEND {} userId = {}", destination, userId);
39+
case DISCONNECT -> log.info("[WEBSOCKET] DISCONNECT userId = {}", userId);
40+
default -> {
41+
}
42+
}
43+
}
44+
45+
private Long extractUserId(StompHeaderAccessor accessor) {
46+
Principal user = accessor.getUser();
47+
if (user instanceof TokenAuthentication tokenAuth) {
48+
Object principal = tokenAuth.getPrincipal();
49+
if (principal instanceof SiteUserDetails details) {
50+
return details.getSiteUser().getId();
51+
}
52+
}
53+
return null;
54+
}
55+
}

0 commit comments

Comments
 (0)