shjung 2 년 전
부모
커밋
e345bf15d5

+ 61 - 0
src/main/java/com/its/op/controller/ResourceMonitoringController.java

@@ -0,0 +1,61 @@
+package com.its.op.controller;
+
+import com.its.op.dto.ThreadMonitoringDto;
+import com.its.op.service.ResourceMonitoringService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Slf4j
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/api/resource")
+@Api(tags = "00.공통-99.리소스 모니터링")
+public class ResourceMonitoringController {
+
+    private final ResourceMonitoringService resourceMonitoringService;
+
+    @ApiOperation(value = "스레드 리소스 현재값 저장", response = ThreadMonitoringDto.class, responseContainer = "ArrayList")
+    @PutMapping(path="/threads/save/{tag}", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ResponseEntity<List<ThreadMonitoringDto>> threadMonitoringSave(@PathVariable final String tag) {
+        List<ThreadMonitoringDto> result = this.resourceMonitoringService.threadMonitoringSave(tag);
+        return ResponseEntity.ok(result);
+    }
+
+    @ApiOperation(value = "스레드 리소스 삭제", response = ThreadMonitoringDto.class, responseContainer = "ArrayList")
+    @DeleteMapping(path="/threads/delete/{tag}", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ResponseEntity<List<ThreadMonitoringDto>> threadMonitoringDelete(@PathVariable final String tag) {
+        List<ThreadMonitoringDto> result = this.resourceMonitoringService.threadMonitoringDelete(tag);
+        return ResponseEntity.ok(result);
+        //return ResponseEntity.ok().build();
+    }
+
+    @ApiOperation(value = "스레드 리소스 저장값 조회", response = ThreadMonitoringDto.class, responseContainer = "ArrayList")
+    @GetMapping(path="/threads/query/{tag}", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ResponseEntity<List<ThreadMonitoringDto>> threadMonitoringQuery(@PathVariable final String tag) {
+        List<ThreadMonitoringDto> result = this.resourceMonitoringService.threadMonitoringQuery(tag);
+        return ResponseEntity.ok(result);
+    }
+
+    @ApiOperation(value = "스레드 리소스 저장값과 현재값 비교", response = ThreadMonitoringDto.class, responseContainer = "ArrayList")
+    @GetMapping(path="/threads/diff/{tag}", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ResponseEntity<List<ThreadMonitoringDto>> threadMonitoringDiff(@PathVariable final String tag) {
+        List<ThreadMonitoringDto> result = this.resourceMonitoringService.threadMonitoringDiff(tag);
+        return ResponseEntity.ok(result);
+    }
+
+
+    @ApiOperation(value = "스레드 리소스 현재값 조회", response = ThreadMonitoringDto.class, responseContainer = "ArrayList")
+    @GetMapping(path="/threads", produces = MediaType.APPLICATION_JSON_VALUE)
+    public ResponseEntity<List<ThreadMonitoringDto>> threadMonitoringCurrent() {
+        List<ThreadMonitoringDto> result = this.resourceMonitoringService.threadMonitoringCurrent();
+        return ResponseEntity.ok(result);
+    }
+
+}

+ 35 - 0
src/main/java/com/its/op/dto/ThreadMonitoringDto.java

@@ -0,0 +1,35 @@
+package com.its.op.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@ApiModel("ThreadMonitoringDto(Thread Monitoring Dto)")
+public class ThreadMonitoringDto {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty("name")
+    @JsonProperty("name")
+    private String name;
+
+    @ApiModelProperty("state")
+    @JsonProperty("state")
+    private String state;
+
+    @ApiModelProperty("priority")
+    @JsonProperty("priority")
+    private Integer priority;
+
+    @ApiModelProperty("Daemon thread 여부")
+    @JsonProperty("is_daemon")
+    private boolean isDaemon;
+
+}

+ 1 - 1
src/main/java/com/its/op/security/WebMvcConfig.java

@@ -24,7 +24,7 @@ public class WebMvcConfig implements WebMvcConfigurer {
 
         registry.addInterceptor(new ApiInterceptor())
                 .addPathPatterns("/api/**")                         // API Controller interceptors
-                .excludePathPatterns("/facility/**", "/wall/**", "/dashboard/**")    // 해당 경로는 인터셉터가 가로채지 않는다.
+                .excludePathPatterns("/facility/**", "/wall/**", "/dashboard/**", "/api/resource/**")    // 해당 경로는 인터셉터가 가로채지 않는다.
                 ;
     }
 

+ 5 - 2
src/main/java/com/its/op/security/WebSecurityConfig.java

@@ -48,6 +48,10 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
         web.ignoring().antMatchers(HttpMethod.POST, "/cs-api/**");  // GET Method 는 모두 통과
         web.ignoring().antMatchers(HttpMethod.PUT, "/cs-api/**");  // GET Method 는 모두 통과
         web.ignoring().antMatchers(HttpMethod.DELETE, "/cs-api/**");  // GET Method 는 모두 통과
+        web.ignoring().antMatchers(HttpMethod.GET, "/resource/**");  // GET Method 는 모두 통과
+        web.ignoring().antMatchers(HttpMethod.POST, "/resource/**");  // GET Method 는 모두 통과
+        web.ignoring().antMatchers(HttpMethod.PUT, "/resource/**");  // GET Method 는 모두 통과
+        web.ignoring().antMatchers(HttpMethod.DELETE, "/resource/**");  // GET Method 는 모두 통과
     }
 
     @Override
@@ -66,9 +70,8 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
                     .antMatchers("/swagger-ui.html", "/swagger/**", "/swagger-resources/**", "/webjars/**", "/v2/api-docs").permitAll()
                     // 웹소켓 권한 설정하지
                     .antMatchers("/ws/**").permitAll()
+                    .antMatchers("/api/resource/**").permitAll()
 //                    .antMatchers("/api/**").permitAll()
-                    // API 권한 설정하지
-                    .antMatchers("/api/**").permitAll()
                     // 지도 URI 권한 설정하지
                     .antMatchers("/MAPDATA/**").permitAll()
                     .antMatchers("/download/**").permitAll()

+ 102 - 0
src/main/java/com/its/op/service/ResourceMonitoringService.java

@@ -0,0 +1,102 @@
+package com.its.op.service;
+
+import com.its.op.dto.ThreadMonitoringDto;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Slf4j
+@RequiredArgsConstructor
+@Service
+public class ResourceMonitoringService {
+
+    private final Map<String, Set<Thread>> threadMap = new HashMap<String, Set<Thread>>();
+
+    private Set<Thread> getActiveThreadSet() {
+        Set<Thread> activeThreads = Thread.getAllStackTraces().keySet();
+        for (Thread t : activeThreads) {
+            log.info("{}", t);
+        }
+        return activeThreads;
+    }
+
+    public List<ThreadMonitoringDto> threadMonitoringSave(String tag) {
+        List<ThreadMonitoringDto> result = new ArrayList<>();
+        Set<Thread> currentThreadSet = getActiveThreadSet();
+        for (Thread t : currentThreadSet) {
+            result.add(ThreadMonitoringDto.builder()
+                    .name(t.getName())
+                    .state(t.getState().toString())
+                    .priority(t.getPriority())
+                    .isDaemon(t.isDaemon())
+                    .build());
+        }
+        this.threadMap.put(tag, currentThreadSet);
+        return result;
+    }
+
+    public List<ThreadMonitoringDto> threadMonitoringDelete(String tag) {
+        List<ThreadMonitoringDto> result = new ArrayList<>();
+        Set<Thread> tagThreadSet = this.threadMap.get(tag);
+        for (Thread t : tagThreadSet) {
+            result.add(ThreadMonitoringDto.builder()
+                    .name(t.getName())
+                    .state(t.getState().toString())
+                    .priority(t.getPriority())
+                    .isDaemon(t.isDaemon())
+                    .build());
+        }
+        this.threadMap.remove(tag);
+        return result;
+    }
+
+    public List<ThreadMonitoringDto> threadMonitoringQuery(String tag) {
+        List<ThreadMonitoringDto> result = new ArrayList<>();
+        Set<Thread> tagThreadSet = this.threadMap.get(tag);
+        for (Thread t : tagThreadSet) {
+            result.add(ThreadMonitoringDto.builder()
+                    .name(t.getName())
+                    .state(t.getState().toString())
+                    .priority(t.getPriority())
+                    .isDaemon(t.isDaemon())
+                    .build());
+        }
+        return result;
+    }
+
+    public List<ThreadMonitoringDto> threadMonitoringDiff(String tag) {
+        Set<Thread> tagThreadSet = this.threadMap.get(tag);
+        Set<Thread> currentThreadSet = getActiveThreadSet();
+
+        List<ThreadMonitoringDto> result = currentThreadSet.stream()
+                .filter(Thread::isAlive)
+                .filter(thread -> !tagThreadSet.contains(thread))
+                .sorted(Comparator.comparing(Thread::getName))
+                .map(thread -> ThreadMonitoringDto.builder()
+                        .name(thread.getName())
+                        .state(thread.getState().toString())
+                        .priority(thread.getPriority())
+                        .isDaemon(thread.isDaemon())
+                        .build())
+                .collect(Collectors.toList());
+
+        return result;
+    }
+
+    public List<ThreadMonitoringDto> threadMonitoringCurrent() {
+        List<ThreadMonitoringDto> result = new ArrayList<>();
+        Set<Thread> currentThreadSet = getActiveThreadSet();
+        for (Thread t : currentThreadSet) {
+            result.add(ThreadMonitoringDto.builder()
+                    .name(t.getName())
+                    .state(t.getState().toString())
+                    .priority(t.getPriority())
+                    .isDaemon(t.isDaemon())
+                    .build());
+        }
+        return result;
+    }
+}