diff --git a/src/main/java/com/example/solidconnection/chat/config/StompWebSocketConfig.java b/src/main/java/com/example/solidconnection/chat/config/StompWebSocketConfig.java index 51259a0e1..c7631172d 100644 --- a/src/main/java/com/example/solidconnection/chat/config/StompWebSocketConfig.java +++ b/src/main/java/com/example/solidconnection/chat/config/StompWebSocketConfig.java @@ -5,6 +5,7 @@ import com.example.solidconnection.chat.config.StompProperties.OutboundProperties; import com.example.solidconnection.security.config.CorsProperties; import java.util.List; +import java.util.Optional; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.ChannelRegistration; @@ -24,6 +25,7 @@ public class StompWebSocketConfig implements WebSocketMessageBrokerConfigurer { private final CorsProperties corsProperties; private final WebSocketHandshakeInterceptor webSocketHandshakeInterceptor; private final CustomHandshakeHandler customHandshakeHandler; + private final Optional webSocketLoggingInterceptor; @Override public void registerStompEndpoints(StompEndpointRegistry registry) { @@ -39,7 +41,12 @@ public void registerStompEndpoints(StompEndpointRegistry registry) { @Override public void configureClientInboundChannel(ChannelRegistration registration) { InboundProperties inboundProperties = stompProperties.threadPool().inbound(); - registration.interceptors(stompHandler).taskExecutor().corePoolSize(inboundProperties.corePoolSize()).maxPoolSize(inboundProperties.maxPoolSize()).queueCapacity(inboundProperties.queueCapacity()); + webSocketLoggingInterceptor.ifPresent(registration::interceptors); + registration.interceptors(stompHandler) + .taskExecutor() + .corePoolSize(inboundProperties.corePoolSize()) + .maxPoolSize(inboundProperties.maxPoolSize()) + .queueCapacity(inboundProperties.queueCapacity()); } @Override diff --git a/src/main/java/com/example/solidconnection/chat/config/WebSocketLoggingInterceptor.java b/src/main/java/com/example/solidconnection/chat/config/WebSocketLoggingInterceptor.java new file mode 100644 index 000000000..ea137ade7 --- /dev/null +++ b/src/main/java/com/example/solidconnection/chat/config/WebSocketLoggingInterceptor.java @@ -0,0 +1,55 @@ +package com.example.solidconnection.chat.config; + +import com.example.solidconnection.security.authentication.TokenAuthentication; +import com.example.solidconnection.security.userdetails.SiteUserDetails; +import java.security.Principal; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Profile; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.simp.stomp.StompCommand; +import org.springframework.messaging.simp.stomp.StompHeaderAccessor; +import org.springframework.messaging.support.ChannelInterceptor; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +@Profile("dev") +public class WebSocketLoggingInterceptor implements ChannelInterceptor { + + @Override + public Message preSend(Message message, MessageChannel channel) { + StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message); + StompCommand command = accessor.getCommand(); + + if (command != null) { + Long userId = extractUserId(accessor); + String destination = accessor.getDestination(); + logStompMessage(command, destination, userId); + } + + return message; + } + + private void logStompMessage(StompCommand command, String destination, Long userId) { + switch (command) { + case CONNECT -> log.info("[WEBSOCKET] CONNECT userId = {}", userId); + case SUBSCRIBE -> log.info("[WEBSOCKET] SUBSCRIBE {} userId = {}", destination, userId); + case SEND -> log.info("[WEBSOCKET] SEND {} userId = {}", destination, userId); + case DISCONNECT -> log.info("[WEBSOCKET] DISCONNECT userId = {}", userId); + default -> { + } + } + } + + private Long extractUserId(StompHeaderAccessor accessor) { + Principal user = accessor.getUser(); + if (user instanceof TokenAuthentication tokenAuth) { + Object principal = tokenAuth.getPrincipal(); + if (principal instanceof SiteUserDetails details) { + return details.getSiteUser().getId(); + } + } + return null; + } +}