From beca62a4ae7180e5ac31347d8cb37462b103bea1 Mon Sep 17 00:00:00 2001 From: hyeonda02 Date: Tue, 26 Aug 2025 14:00:51 +0900 Subject: [PATCH 1/3] =?UTF-8?q?Feat=20:=20=EC=82=AC=EC=9A=A9=EB=9F=89?= =?UTF-8?q?=EC=9D=B4=20=EB=A7=8E=EC=9D=80=20=EC=88=9C=EC=84=9C=EB=A1=9C=20?= =?UTF-8?q?=ED=83=9C=EA=B7=B8=EB=A5=BC=20=EC=A1=B0=ED=9A=8C=ED=95=98?= =?UTF-8?q?=EB=8A=94=20API=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- grafana/dashboards/main 2.yaml | 11 + grafana/dashboards/spring-boot-board 2.json | 2924 +++++++++++++++++ grafana/datasources/datasources 2.yaml | 14 + grafana/docker-compose 2.yml | 38 + grafana/prometheus-config 2.yaml | 8 + .../controller/CareerSearchController.java | 17 + .../career/service/CareerSearchService.java | 4 + .../service/CareerSearchServiceImpl.java | 9 + .../server/tag/dto/TagUsageResponseDto.java | 13 + .../tag/repository/TagJpaRepository.java | 23 + .../server/tag/repository/TagRepository.java | 3 + .../tag/repository/TagRepositoryImpl.java | 8 + .../CareerSearchServiceImplTest 2.java | 202 ++ .../service/CareerServiceImplTest 2.java | 380 +++ 14 files changed, 3654 insertions(+) create mode 100644 grafana/dashboards/main 2.yaml create mode 100644 grafana/dashboards/spring-boot-board 2.json create mode 100644 grafana/datasources/datasources 2.yaml create mode 100644 grafana/docker-compose 2.yml create mode 100644 grafana/prometheus-config 2.yaml create mode 100644 src/main/java/umc/kkijuk/server/tag/dto/TagUsageResponseDto.java create mode 100644 src/test/java/umc/kkijuk/server/unitTest/career/service/CareerSearchServiceImplTest 2.java create mode 100644 src/test/java/umc/kkijuk/server/unitTest/career/service/CareerServiceImplTest 2.java diff --git a/grafana/dashboards/main 2.yaml b/grafana/dashboards/main 2.yaml new file mode 100644 index 00000000..a26d4a30 --- /dev/null +++ b/grafana/dashboards/main 2.yaml @@ -0,0 +1,11 @@ +apiVersion: 1 + +providers: + - name: 'default' + orgId: 1 + folder: '' + type: file + disableDeletion: false + updateIntervalSeconds: 10 + options: + path: /var/lib/grafana/dashboards \ No newline at end of file diff --git a/grafana/dashboards/spring-boot-board 2.json b/grafana/dashboards/spring-boot-board 2.json new file mode 100644 index 00000000..8de412d2 --- /dev/null +++ b/grafana/dashboards/spring-boot-board 2.json @@ -0,0 +1,2924 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 1, + "links": [], + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 54, + "panels": [], + "title": "Basic Statistics", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 1, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 1 + }, + "id": 52, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.6.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "process_uptime_seconds{application=\"$application\", instance=\"$instance\", namespace=\"$Namespace\"}", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "", + "metric": "", + "range": true, + "refId": "A", + "step": 14400 + } + ], + "title": "Uptime", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 1, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)" + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 70 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 90 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 6, + "y": 1 + }, + "id": 58, + "maxDataPoints": 100, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "sizing": "auto" + }, + "pluginVersion": "11.6.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", area=\"heap\", namespace=\"$Namespace\"})*100/sum(jvm_memory_max_bytes{application=\"$application\",instance=\"$instance\", area=\"heap\", namespace=\"$Namespace\"})", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "range": true, + "refId": "A", + "step": 14400 + } + ], + "title": "Heap Used", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 1, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + }, + { + "options": { + "from": -1e+32, + "result": { + "text": "N/A" + }, + "to": 0 + }, + "type": "range" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)" + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 70 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 90 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 11, + "y": 1 + }, + "id": 60, + "maxDataPoints": 100, + "options": { + "minVizHeight": 75, + "minVizWidth": 75, + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true, + "sizing": "auto" + }, + "pluginVersion": "11.6.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "sum(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", area=\"nonheap\", namespace=\"$Namespace\"})*100/sum(jvm_memory_max_bytes{application=\"$application\",instance=\"$instance\", area=\"nonheap\", namespace=\"$Namespace\"})", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "", + "range": true, + "refId": "A", + "step": 14400 + } + ], + "title": "Non-Heap Used", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 8, + "x": 16, + "y": 1 + }, + "id": 66, + "options": { + "alertThreshold": true, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.6.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "process_files_open_files{application=\"$application\", instance=\"$instance\", namespace=\"$Namespace\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Open Files", + "range": true, + "refId": "A" + } + ], + "title": "Process Open Files", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "dateTimeAsIso" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 6, + "x": 0, + "y": 4 + }, + "id": 56, + "maxDataPoints": 100, + "options": { + "colorMode": "value", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.6.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "process_start_time_seconds{application=\"$application\", instance=\"$instance\", namespace=\"$Namespace\"}*1000", + "format": "time_series", + "intervalFactor": 2, + "legendFormat": "", + "metric": "", + "range": true, + "refId": "A", + "step": 14400 + } + ], + "title": "Start time", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 7 + }, + "id": 95, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.6.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "system_cpu_usage{instance=\"$instance\", application=\"$application\", namespace=\"$Namespace\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "System CPU Usage", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "process_cpu_usage{instance=\"$instance\", application=\"$application\", namespace=\"$Namespace\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Process CPU Usage", + "range": true, + "refId": "B" + } + ], + "title": "CPU Usage", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 7 + }, + "id": 96, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.6.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "system_load_average_1m{instance=\"$instance\", application=\"$application\", namespace=\"$Namespace\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Load Average [1m]", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "system_cpu_count{instance=\"$instance\", application=\"$application\", namespace=\"$Namespace\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "CPU Core Size", + "range": true, + "refId": "B" + } + ], + "title": "Load Average", + "type": "timeseries" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 14 + }, + "id": 103, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 4, + "x": 0, + "y": 15 + }, + "id": 104, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.6.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(http_server_requests_seconds_count{application=\"$application\", uri!=\"/actuator/prometheus\"})", + "instant": true, + "interval": "", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "timeFrom": "24h", + "title": "Total Requests", + "transformations": [ + { + "id": "seriesToRows", + "options": {} + }, + { + "id": "sortBy", + "options": { + "fields": {}, + "sort": [ + { + "field": "Time" + } + ] + } + } + ], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 8, + "x": 4, + "y": 15 + }, + "id": 105, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "value_and_name", + "wideLayout": true + }, + "pluginVersion": "11.6.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum by(uri) (http_server_requests_seconds_count{application=\"$application\", uri!=\"/actuator/prometheus\"})", + "instant": true, + "interval": "", + "legendFormat": "{{method}} {{uri}}", + "range": true, + "refId": "A" + } + ], + "timeFrom": "24h", + "title": "Requests Count", + "transformations": [ + { + "id": "seriesToRows", + "options": {} + }, + { + "id": "sortBy", + "options": { + "fields": {}, + "sort": [ + { + "field": "Time" + } + ] + } + }, + { + "id": "partitionByValues", + "options": { + "fields": [ + "Metric" + ] + } + } + ], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "continuous-GrYlRd" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 15 + }, + "id": 106, + "options": { + "displayMode": "lcd", + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "maxVizHeight": 300, + "minVizHeight": 10, + "minVizWidth": 0, + "namePlacement": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showUnfilled": true, + "sizing": "auto", + "valueMode": "color" + }, + "pluginVersion": "11.6.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum by(uri)(http_server_requests_seconds_sum{application=\"$application\"}) / sum by(uri)(http_server_requests_seconds_count{application=\"$application\"})", + "interval": "", + "legendFormat": "{{method}} {{uri}}", + "range": true, + "refId": "A" + } + ], + "title": "Requests Average Duration", + "type": "bargauge" + } + ], + "title": "Observability", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 15 + }, + "id": 48, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 268 + }, + "id": 85, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.5.1", + "repeat": "memory_pool_heap", + "repeatDirection": "h", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "jvm_memory_used_bytes{instance=\"$instance\", application=\"$application\", id=\"$memory_pool_heap\", namespace=\"$Namespace\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Used", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "jvm_memory_committed_bytes{instance=\"$instance\", application=\"$application\", id=\"$memory_pool_heap\", namespace=\"$Namespace\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Commited", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "jvm_memory_max_bytes{instance=\"$instance\", application=\"$application\", id=\"$memory_pool_heap\", namespace=\"$Namespace\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Max", + "range": true, + "refId": "B" + } + ], + "title": "$memory_pool_heap (heap)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 408 + }, + "id": 88, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.5.1", + "repeat": "memory_pool_nonheap", + "repeatDirection": "h", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "jvm_memory_used_bytes{instance=\"$instance\", application=\"$application\", id=\"${memory_pool_nonheap:raw}\", namespace=\"$Namespace\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Used", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "jvm_memory_committed_bytes{instance=\"$instance\", application=\"$application\", id=\"${memory_pool_nonheap:raw}\", namespace=\"$Namespace\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Commited", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "jvm_memory_max_bytes{instance=\"$instance\", application=\"$application\", id=\"${memory_pool_nonheap:raw}\", namespace=\"$Namespace\"}", + "format": "time_series", + "hide": false, + "intervalFactor": 1, + "legendFormat": "Max", + "range": true, + "refId": "B" + } + ], + "title": "$memory_pool_nonheap (non-heap)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 416 + }, + "id": 82, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.6.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "jvm_buffer_memory_used_bytes{instance=\"$instance\", application=\"$application\", id=\"direct\", namespace=\"$Namespace\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Used Bytes", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "jvm_buffer_total_capacity_bytes{instance=\"$instance\", application=\"$application\", id=\"direct\", namespace=\"$Namespace\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Capacity Bytes", + "range": true, + "refId": "B" + } + ], + "title": "Direct Buffers", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 416 + }, + "id": 68, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.6.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "jvm_threads_daemon_threads{instance=\"$instance\", application=\"$application\", namespace=\"$Namespace\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Daemon", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "jvm_threads_live_threads{instance=\"$instance\", application=\"$application\", namespace=\"$Namespace\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Live", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "jvm_threads_peak_threads{instance=\"$instance\", application=\"$application\", namespace=\"$Namespace\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Peak", + "range": true, + "refId": "C" + } + ], + "title": "Threads", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 423 + }, + "id": 78, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.6.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "irate(jvm_gc_memory_allocated_bytes_total{instance=\"$instance\", application=\"$application\", namespace=\"$Namespace\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "allocated", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "irate(jvm_gc_memory_promoted_bytes_total{instance=\"$instance\", application=\"$application\", namespace=\"$Namespace\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "promoted", + "range": true, + "refId": "B" + } + ], + "title": "Memory Allocate/Promote", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 424 + }, + "id": 83, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.6.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "jvm_buffer_memory_used_bytes{instance=\"$instance\", application=\"$application\", id=\"mapped\", namespace=\"$Namespace\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Used Bytes", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "jvm_buffer_total_capacity_bytes{instance=\"$instance\", application=\"$application\", id=\"mapped\", namespace=\"$Namespace\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Capacity Bytes", + "range": true, + "refId": "B" + } + ], + "title": "Mapped Buffers", + "type": "timeseries" + } + ], + "title": "JVM Statistics - Memory", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 16 + }, + "id": 72, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 0, + "y": 269 + }, + "id": 74, + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "min", + "sum" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.6.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "irate(jvm_gc_pause_seconds_count{instance=\"$instance\", application=\"$application\", namespace=\"$Namespace\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{action}} [{{cause}}]", + "range": true, + "refId": "A" + } + ], + "title": "GC Count", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 12, + "x": 12, + "y": 269 + }, + "id": 76, + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "min", + "sum" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.6.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "irate(jvm_gc_pause_seconds_sum{instance=\"$instance\", application=\"$application\", namespace=\"$Namespace\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{action}} [{{cause}}]", + "range": true, + "refId": "A" + } + ], + "title": "GC Stop the World Duration", + "type": "timeseries" + } + ], + "title": "JVM Statistics - GC", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 17 + }, + "id": 34, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 0, + "y": 18 + }, + "id": 44, + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.6.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "hikaricp_connections{instance=\"$instance\", application=\"$application\", pool=\"$hikaricp\", namespace=\"$Namespace\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Connections Size", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "normal" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 20, + "x": 4, + "y": 18 + }, + "id": 36, + "options": { + "legend": { + "calcs": [ + "mean", + "lastNotNull", + "max", + "min" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.6.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "hikaricp_connections_active{instance=\"$instance\", application=\"$application\", pool=\"$hikaricp\", namespace=\"$Namespace\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Active", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "hikaricp_connections_idle{instance=\"$instance\", application=\"$application\", pool=\"$hikaricp\", namespace=\"$Namespace\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Idle", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "hikaricp_connections_pending{instance=\"$instance\", application=\"$application\", pool=\"$hikaricp\", namespace=\"$Namespace\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Pending", + "range": true, + "refId": "C" + } + ], + "title": "Connections", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 4, + "x": 0, + "y": 22 + }, + "id": 46, + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "percentChangeColorMode": "standard", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "11.6.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "hikaricp_connections_timeout_total{instance=\"$instance\", application=\"$application\", pool=\"$hikaricp\", namespace=\"$Namespace\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Connection Timeout Count", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 8, + "x": 0, + "y": 26 + }, + "id": 38, + "options": { + "alertThreshold": true, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.6.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "expr": "hikaricp_connections_creation_seconds_sum{instance=\"$instance\", application=\"$application\", pool=\"$hikaricp\"} / hikaricp_connections_creation_seconds_count{instance=\"$instance\", application=\"$application\", pool=\"$hikaricp\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Creation Time", + "refId": "A" + } + ], + "title": "Connection Creation Time", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 8, + "x": 8, + "y": 26 + }, + "id": 42, + "options": { + "alertThreshold": true, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.6.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "expr": "hikaricp_connections_usage_seconds_sum{instance=\"$instance\", application=\"$application\", pool=\"$hikaricp\"} / hikaricp_connections_usage_seconds_count{instance=\"$instance\", application=\"$application\", pool=\"$hikaricp\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Usage Time", + "refId": "A" + } + ], + "title": "Connection Usage Time", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 8, + "x": 16, + "y": 26 + }, + "id": 40, + "options": { + "alertThreshold": true, + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.6.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "expr": "hikaricp_connections_acquire_seconds_sum{instance=\"$instance\", application=\"$application\", pool=\"$hikaricp\"} / hikaricp_connections_acquire_seconds_count{instance=\"$instance\", application=\"$application\", pool=\"$hikaricp\"}", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "Acquire Time", + "refId": "A" + } + ], + "title": "Connection Acquire Time", + "type": "timeseries" + } + ], + "title": "Database Connection Pool HikariCP Statistics", + "type": "row" + }, + { + "collapsed": true, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 18 + }, + "id": 18, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 19 + }, + "id": 4, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.6.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "irate(http_server_requests_seconds_count{instance=\"$instance\", application=\"$application\", uri!~\".*(prometheus|health).*\", namespace=\"$Namespace\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{method}} [{{status}}] - {{uri}}", + "range": true, + "refId": "A" + } + ], + "title": "Request Count", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "barWidthFactor": 0.6, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 26 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "min" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "hideZeros": false, + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "11.6.0", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "editorMode": "code", + "expr": "irate(http_server_requests_seconds_sum{instance=\"$instance\", application=\"$application\", exception=\"none\", uri!~\".*(prometheus|health).*\", namespace=\"$Namespace\"}[$__rate_interval]) / irate(http_server_requests_seconds_count{instance=\"$instance\", application=\"$application\", exception=\"none\",uri!~\".*(prometheus|health).*\", namespace=\"$Namespace\"}[$__rate_interval])", + "format": "time_series", + "intervalFactor": 1, + "legendFormat": "{{method}} [{{status}}] - {{uri}}", + "range": true, + "refId": "A" + } + ], + "title": "Response Time", + "type": "timeseries" + } + ], + "title": "HTTP Statistics", + "type": "row" + } + ], + "preload": false, + "refresh": "", + "schemaVersion": 41, + "tags": [ + "app" + ], + "templating": { + "list": [ + { + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "definition": "label_values(jvm_info,application)", + "includeAll": false, + "label": "Application", + "name": "application", + "options": [], + "query": { + "query": "label_values(jvm_info,application)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": "", + "value": "" + }, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "definition": "label_values(jvm_info,namespace)", + "includeAll": false, + "name": "Namespace", + "options": [], + "query": { + "query": "label_values(jvm_info,namespace)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "", + "type": "query" + }, + { + "current": { + "text": "host.docker.internal:8080", + "value": "host.docker.internal:8080" + }, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "definition": "label_values(jvm_info{application=\"$application\", namespace=\"$Namespace\"},instance)", + "includeAll": false, + "label": "Instance", + "name": "instance", + "options": [], + "query": { + "query": "label_values(jvm_info{application=\"$application\", namespace=\"$Namespace\"},instance)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": "HikariPool-1", + "value": "HikariPool-1" + }, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "definition": "", + "includeAll": false, + "label": "HikariCP-Pool", + "name": "hikaricp", + "options": [], + "query": { + "query": "label_values(hikaricp_connections{instance=\"$instance\", application=\"$application\"}, pool)", + "refId": "Prometheus-hikaricp-Variable-Query" + }, + "refresh": 2, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "definition": "label_values(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", area=\"heap\"},id)", + "includeAll": true, + "label": "Memory Pool (heap)", + "name": "memory_pool_heap", + "options": [], + "query": { + "query": "label_values(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", area=\"heap\"},id)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "", + "sort": 1, + "type": "query" + }, + { + "current": { + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "definition": "label_values(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", area=\"nonheap\"},id)", + "includeAll": true, + "label": "Memory Pool (nonheap)", + "name": "memory_pool_nonheap", + "options": [], + "query": { + "query": "label_values(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", area=\"nonheap\"},id)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 2, + "regex": "", + "sort": 1, + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Spring Boot Dashboard", + "uid": "SpringBootDashboard", + "version": 1 +} \ No newline at end of file diff --git a/grafana/datasources/datasources 2.yaml b/grafana/datasources/datasources 2.yaml new file mode 100644 index 00000000..2f149dc9 --- /dev/null +++ b/grafana/datasources/datasources 2.yaml @@ -0,0 +1,14 @@ +apiVersion: 1 + +deleteDatasources: + - name: prometheus + - name: loki + +datasources: + - name: prometheus + uid: prometheus + type: prometheus + access: proxy + url: http://kkijuk-prometheus:9090 + isDefault: true + editable: true \ No newline at end of file diff --git a/grafana/docker-compose 2.yml b/grafana/docker-compose 2.yml new file mode 100644 index 00000000..6f796b0e --- /dev/null +++ b/grafana/docker-compose 2.yml @@ -0,0 +1,38 @@ +version: '3.8' + +services: + ## monitoring + prometheus: + image: prom/prometheus:latest + container_name: kkijuk-prometheus + volumes: + - ./prometheus-config.yaml:/etc/prometheus/prometheus-config.yaml + command: + - '--config.file=/etc/prometheus/prometheus-config.yaml' + ports: + - "9090:9090" + networks: + - monitoring-network + + grafana: + image: grafana/grafana:latest + container_name: kkijuk-grafana +# set in instance +# environment: +# - GF_SECURITY_ADMIN_USER=local +# - GF_SECURITY_ADMIN_PASSWORD=local + volumes: + - ./datasources:/etc/grafana/provisioning/datasources + - ./dashboards:/etc/grafana/provisioning/dashboards + - ./dashboards:/var/lib/grafana/dashboards + ports: + - "3000:3000" + networks: + - monitoring-network + +networks: + monitoring-network: + driver: bridge + +volumes: + loki_data: \ No newline at end of file diff --git a/grafana/prometheus-config 2.yaml b/grafana/prometheus-config 2.yaml new file mode 100644 index 00000000..72b6e721 --- /dev/null +++ b/grafana/prometheus-config 2.yaml @@ -0,0 +1,8 @@ +global: + scrape_interval: 15s + +scrape_configs: + - job_name: prometheus + metrics_path: '/actuator/prometheus' + static_configs: + - targets: ['host.docker.internal:8088'] \ No newline at end of file diff --git a/src/main/java/umc/kkijuk/server/career/controller/CareerSearchController.java b/src/main/java/umc/kkijuk/server/career/controller/CareerSearchController.java index 47a4cf75..a263ee19 100644 --- a/src/main/java/umc/kkijuk/server/career/controller/CareerSearchController.java +++ b/src/main/java/umc/kkijuk/server/career/controller/CareerSearchController.java @@ -12,6 +12,7 @@ import umc.kkijuk.server.member.service.MemberService; import java.util.List; +import umc.kkijuk.server.tag.dto.TagUsageResponseDto; @Tag(name="Search Career", description = "활동 조회 및 검색 관련 API") @RestController @@ -92,6 +93,22 @@ public CareerResponse findTag( ); } + @GetMapping("/find/taglist/count") + @Operation( + summary = "활동 검색 - 태그 ( 사용량이 많은 태그 순으로 조회 )", + description = "검색어를 포함하는 활동 태그들을 사용량 순으로 조회합니다. " + + "query 값으로 검색어(keyword)를 요청해주세요. " ) + public CareerResponse> findTagWithCount( + @RequestHeader("Authorization") String token, + @RequestParam(name="keyword")String keyword + ) { + Member requestMember = loginUser.extractMemberId(token); + return CareerResponse.success( + CareerResponseMessage.CAREER_SEARCH_SUCCESS, + careerSearchService.findAllTagWithCount(requestMember, keyword) + ); + } + @GetMapping("/find/tag") @Operation( summary = "활동 검색 - 태그 ( 선택한 태그에 대한 활동 기록 조회 )", diff --git a/src/main/java/umc/kkijuk/server/career/service/CareerSearchService.java b/src/main/java/umc/kkijuk/server/career/service/CareerSearchService.java index c69a9d82..6e2dde23 100644 --- a/src/main/java/umc/kkijuk/server/career/service/CareerSearchService.java +++ b/src/main/java/umc/kkijuk/server/career/service/CareerSearchService.java @@ -1,10 +1,12 @@ package umc.kkijuk.server.career.service; import umc.kkijuk.server.career.controller.response.*; +import umc.kkijuk.server.career.controller.response.FindTagResponse.SearchTagResponse; import umc.kkijuk.server.member.domain.Member; import java.util.List; import java.util.Map; +import umc.kkijuk.server.tag.dto.TagUsageResponseDto; public interface CareerSearchService { List findCareerForTimeline(Member requestMember); @@ -21,4 +23,6 @@ public interface CareerSearchService { List findCareerWithKeyword(Member requestMember, String keyword, String sort); List findCareerForNewDetail(Member requestMember); + + List findAllTagWithCount(Member requestMember, String keyword); } diff --git a/src/main/java/umc/kkijuk/server/career/service/CareerSearchServiceImpl.java b/src/main/java/umc/kkijuk/server/career/service/CareerSearchServiceImpl.java index 5bc73e5a..36271f0a 100644 --- a/src/main/java/umc/kkijuk/server/career/service/CareerSearchServiceImpl.java +++ b/src/main/java/umc/kkijuk/server/career/service/CareerSearchServiceImpl.java @@ -2,9 +2,11 @@ import lombok.Builder; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import umc.kkijuk.server.career.controller.response.*; +import umc.kkijuk.server.career.controller.response.FindTagResponse.SearchTagResponse; import umc.kkijuk.server.career.domain.*; import umc.kkijuk.server.career.dto.converter.BaseCareerConverter; import umc.kkijuk.server.career.repository.*; @@ -16,6 +18,7 @@ import umc.kkijuk.server.detail.repository.CareerDetailRepository; import umc.kkijuk.server.member.domain.Member; import umc.kkijuk.server.tag.domain.Tag; +import umc.kkijuk.server.tag.dto.TagUsageResponseDto; import umc.kkijuk.server.tag.repository.TagRepository; import java.time.LocalDate; @@ -334,6 +337,12 @@ public List findCareerForNewDetail(Member requestMember) { .collect(Collectors.toList()); } + @Override + public List findAllTagWithCount(Member requestMember, String keyword) { + List tags = tagRepository.findPopularTagsByMemberAndKeyword(requestMember.getId(),keyword, PageRequest.of(0, 10)); + return tags; + } + //타임라인 쪽에서 데이터 구별 하기 위함 private CareerType resolveCareerType(BaseCareer career) { diff --git a/src/main/java/umc/kkijuk/server/tag/dto/TagUsageResponseDto.java b/src/main/java/umc/kkijuk/server/tag/dto/TagUsageResponseDto.java new file mode 100644 index 00000000..37ec0e12 --- /dev/null +++ b/src/main/java/umc/kkijuk/server/tag/dto/TagUsageResponseDto.java @@ -0,0 +1,13 @@ +package umc.kkijuk.server.tag.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class TagUsageResponseDto { + private Long id; + private String name; + private long usageCount; + +} diff --git a/src/main/java/umc/kkijuk/server/tag/repository/TagJpaRepository.java b/src/main/java/umc/kkijuk/server/tag/repository/TagJpaRepository.java index 1f893206..914c7df5 100644 --- a/src/main/java/umc/kkijuk/server/tag/repository/TagJpaRepository.java +++ b/src/main/java/umc/kkijuk/server/tag/repository/TagJpaRepository.java @@ -1,5 +1,6 @@ package umc.kkijuk.server.tag.repository; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -8,6 +9,7 @@ import java.util.List; import java.util.Optional; +import umc.kkijuk.server.tag.dto.TagUsageResponseDto; public interface TagJpaRepository extends JpaRepository { boolean existsByNameAndMemberId(String name, Long memberId); @@ -18,4 +20,25 @@ public interface TagJpaRepository extends JpaRepository { "ORDER BY CASE WHEN tag.name = :keyword THEN 0 ELSE 1 END, tag.name ASC") List findByKeywordAndMemberId(@Param("keyword") String keyword, @Param("memberId") Long memberId); Optional findById(Long Id); + + @Query(""" + select new umc.kkijuk.server.tag.dto.TagUsageResponseDto( + t.id, t.name, count(cdt.id) + ) + from Tag t + left join CareerDetailTag cdt on cdt.tag = t + left join cdt.baseCareerDetail bcd + where t.memberId = :memberId + and t.name like concat('%', :keyword, '%') + and (bcd is null or bcd.memberId = :memberId) + group by t.id, t.name + order by count(cdt.id) desc, t.name asc + """) + List findPopularTagsByMemberAndKeyword( + @Param("memberId") Long memberId, + @Param("keyword") String keyword, + Pageable pageable + ); + + } diff --git a/src/main/java/umc/kkijuk/server/tag/repository/TagRepository.java b/src/main/java/umc/kkijuk/server/tag/repository/TagRepository.java index f689ebba..5afb8a13 100644 --- a/src/main/java/umc/kkijuk/server/tag/repository/TagRepository.java +++ b/src/main/java/umc/kkijuk/server/tag/repository/TagRepository.java @@ -1,9 +1,11 @@ package umc.kkijuk.server.tag.repository; +import org.springframework.data.domain.Pageable; import umc.kkijuk.server.tag.domain.Tag; import java.util.List; import java.util.Optional; +import umc.kkijuk.server.tag.dto.TagUsageResponseDto; public interface TagRepository { boolean existsByNameAndMemberId(String tagName, Long memberId); @@ -17,4 +19,5 @@ public interface TagRepository { void delete(Tag deleteTag); List findByKeywordAndMemberId(String keyword, Long id); + List findPopularTagsByMemberAndKeyword(Long memberId, String keyword, Pageable pageable); } diff --git a/src/main/java/umc/kkijuk/server/tag/repository/TagRepositoryImpl.java b/src/main/java/umc/kkijuk/server/tag/repository/TagRepositoryImpl.java index e6285d5b..caef0ba6 100644 --- a/src/main/java/umc/kkijuk/server/tag/repository/TagRepositoryImpl.java +++ b/src/main/java/umc/kkijuk/server/tag/repository/TagRepositoryImpl.java @@ -1,11 +1,14 @@ package umc.kkijuk.server.tag.repository; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Repository; import umc.kkijuk.server.tag.domain.Tag; import java.util.List; import java.util.Optional; +import umc.kkijuk.server.tag.dto.TagUsageResponseDto; @Repository @RequiredArgsConstructor @@ -41,4 +44,9 @@ public void delete(Tag deleteTag) { public List findByKeywordAndMemberId(String keyword, Long id) { return tagJpaRepository.findByKeywordAndMemberId(keyword,id); } + + @Override + public List findPopularTagsByMemberAndKeyword(Long memberId, String keyword, Pageable pageable) { + return tagJpaRepository.findPopularTagsByMemberAndKeyword(memberId, keyword, pageable); + } } diff --git a/src/test/java/umc/kkijuk/server/unitTest/career/service/CareerSearchServiceImplTest 2.java b/src/test/java/umc/kkijuk/server/unitTest/career/service/CareerSearchServiceImplTest 2.java new file mode 100644 index 00000000..c27301f2 --- /dev/null +++ b/src/test/java/umc/kkijuk/server/unitTest/career/service/CareerSearchServiceImplTest 2.java @@ -0,0 +1,202 @@ +package umc.kkijuk.server.unitTest.career.service; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import umc.kkijuk.server.career.controller.response.*; +import umc.kkijuk.server.career.domain.*; +import umc.kkijuk.server.career.repository.*; +import umc.kkijuk.server.detail.domain.BaseCareerDetail; +import umc.kkijuk.server.detail.domain.CareerType; +import umc.kkijuk.server.detail.repository.CareerDetailRepository; +import umc.kkijuk.server.member.domain.Member; +import umc.kkijuk.server.tag.domain.Tag; +import umc.kkijuk.server.tag.repository.TagRepository; + +import java.lang.reflect.Field; +import java.time.LocalDate; +import java.util.*; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class CareerSearchServiceImplTest { + + @InjectMocks + private umc.kkijuk.server.career.service.CareerSearchServiceImpl careerSearchService; + + @Mock private ActivityRepository activityRepository; + @Mock private CircleRepository circleRepository; + @Mock private CompetitionRepository competitionRepository; + @Mock private EduCareerRepository eduCareerRepository; + @Mock private ProjectRepository projectRepository; + @Mock private EmploymentRepository employmentRepository; + @Mock private CareerEtcRepository etcRepository; + @Mock private CareerDetailRepository detailRepository; + @Mock private TagRepository tagRepository; + + private final Long memberId = 1L; + private final Member member = Member.builder().id(memberId).build(); + + @Test + @DisplayName("[CareerSearch] 타임라인용 커리어 전체 조회 시 날짜 기준으로 정렬된 리스트가 반환되어야 한다.") + void findCareerForTimeline_shouldReturnSortedTimelineResponses() { + Activity activity = Activity.builder() + .memberId(memberId).name("Activity").endDate(LocalDate.of(2024, 5, 1)).build(); + setId(activity, 1L); + + Competition competition = Competition.builder() + .memberId(memberId).name("Competition").enddate(LocalDate.of(2023, 6, 15)).build(); + setId(competition, 2L); + + when(activityRepository.findByMemberId(memberId)).thenReturn(List.of(activity)); + when(competitionRepository.findByMemberId(memberId)).thenReturn(List.of(competition)); + when(circleRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); + when(eduCareerRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); + when(projectRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); + when(employmentRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); + when(etcRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); + + List result = careerSearchService.findCareerForTimeline(member); + + assertEquals(2, result.size()); + assertEquals("Activity", result.get(0).getTitle()); + } + + @Test + @DisplayName("[CareerSearch] 카테고리별 커리어 목록을 조회하면 분류된 Map이 반환되어야 한다.") + void findAllCareerGroupedCategory_shouldReturnGroupedMap() { + Activity activity = Activity.builder() + .memberId(memberId).name("Act").startDate(LocalDate.of(2023, 1, 1)).build(); + setId(activity, 1L); + + when(activityRepository.findByMemberId(memberId)).thenReturn(List.of(activity)); + when(circleRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); + when(competitionRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); + when(eduCareerRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); + when(projectRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); + when(employmentRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); + when(etcRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); + + Map> result = careerSearchService.findAllCareerGroupedCategory(memberId); + + assertEquals(7, result.size()); + assertTrue(result.containsKey("대외활동")); + assertEquals(1, result.get("대외활동").size()); + } + + @Test + @DisplayName("[CareerSearch] 연도별 커리어 조회 시 시작년도 기준으로 그룹핑되어야 한다.") + void findAllCareerGroupedYear_shouldGroupByStartYear() { + Project project = Project.builder() + .memberId(memberId).name("Project").startdate(LocalDate.of(2023, 2, 1)).build(); + setId(project, 1L); + + when(projectRepository.findByMemberId(memberId)).thenReturn(List.of(project)); + when(competitionRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); + when(activityRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); + when(circleRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); + when(eduCareerRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); + when(employmentRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); + when(etcRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); + + Map> result = careerSearchService.findAllCareerGroupedYear(memberId); + + assertTrue(result.containsKey("2023")); + assertEquals(1, result.get("2023").size()); + } + + @Test + @DisplayName("[CareerSearch] 전체 커리어 목록 조회 시 종료일 기준 내림차순 정렬되어야 한다.") + void findAllCareer_shouldReturnSortedList() { + Project project = Project.builder() + .memberId(memberId).name("Project").enddate(LocalDate.of(2024, 3, 15)).build(); + setId(project, 1L); + + when(projectRepository.findByMemberId(memberId)).thenReturn(List.of(project)); + when(detailRepository.findByCareerIdAndCareerType(eq(CareerType.PROJECT), eq(1L))).thenReturn(Collections.emptyList()); + when(competitionRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); + when(activityRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); + when(circleRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); + when(eduCareerRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); + when(employmentRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); + when(etcRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); + + List result = careerSearchService.findAllCareer(memberId); + + assertEquals(1, result.size()); + ProjectResponse response = (ProjectResponse) result.get(0); + assertEquals("Project", response.getName()); + } + + @Test + @DisplayName("[CareerSearch] 활동 상세 조회 시 본인 소유 Activity가 존재하면 반환되어야 한다.") + void findCareer_shouldReturnActivityResponse() { + Long careerId = 10L; + Activity activity = Activity.builder() + .memberId(memberId).name("활동").build(); + setId(activity, careerId); + + when(activityRepository.findById(careerId)).thenReturn(Optional.of(activity)); + when(detailRepository.findByCareerIdAndCareerType(eq(CareerType.ACTIVITY), eq(careerId))).thenReturn(Collections.emptyList()); + + BaseCareerResponse response = careerSearchService.findCareer(member, careerId, "activity"); + + assertTrue(response instanceof ActivityResponse); + ActivityResponse activityResponse = (ActivityResponse) response; + assertEquals("활동", activityResponse.getName()); + } + + @Test + @DisplayName("[CareerSearch] 키워드로 태그 검색 시 태그 목록과 연결된 상세 개수가 반환되어야 한다.") + void findAllTag_shouldReturnTagsAndDetailCount() { + Tag tag = Tag.builder().id(1L).memberId(memberId).name("keyword").build(); + BaseCareerDetail detail = mock(BaseCareerDetail.class); + + when(tagRepository.findByKeywordAndMemberId("keyword", memberId)).thenReturn(List.of(tag)); + when(detailRepository.findByTag(tag.getId())).thenReturn(List.of(detail)); + + FindTagResponse.SearchTagResponse result = careerSearchService.findAllTag(member, "keyword"); + + assertEquals(1, result.getTagList().size()); + assertEquals(1, result.getDetailCount()); + } + + @Test + @DisplayName("[CareerSearch] 커리어 키워드 검색 시 이름에 키워드가 포함된 커리어가 정렬되어 반환되어야 한다.") + void findCareerWithKeyword_shouldReturnFilteredList() { + Activity act = Activity.builder() + .memberId(memberId).name("검색활동").startDate(LocalDate.of(2023, 3, 1)).build(); + setId(act, 1L); + + when(activityRepository.findByMemberIdAndNameContaining(eq(memberId), anyString())).thenReturn(List.of(act)); + when(competitionRepository.findByMemberIdAndNameContaining(eq(memberId), anyString())).thenReturn(Collections.emptyList()); + when(circleRepository.findByMemberIdAndNameContaining(eq(memberId), anyString())).thenReturn(Collections.emptyList()); + when(eduCareerRepository.findByMemberIdAndNameContaining(eq(memberId), anyString())).thenReturn(Collections.emptyList()); + when(projectRepository.findByMemberIdAndNameContaining(eq(memberId), anyString())).thenReturn(Collections.emptyList()); + when(employmentRepository.findByMemberIdAndNameContaining(eq(memberId), anyString())).thenReturn(Collections.emptyList()); + when(etcRepository.findByMemberIdAndNameContaining(eq(memberId), anyString())).thenReturn(Collections.emptyList()); + + List result = careerSearchService.findCareerWithKeyword(member, "검색", "new"); + + assertEquals(1, result.size()); + assertEquals("검색활동", result.get(0).getCareerTitle()); + } + + + private void setId(Object entity, Long id) { + try { + Field field = entity.getClass().getDeclaredField("id"); + field.setAccessible(true); + field.set(entity, id); + } catch (Exception e) { + throw new RuntimeException("ID 주입 실패", e); + } + } +} + diff --git a/src/test/java/umc/kkijuk/server/unitTest/career/service/CareerServiceImplTest 2.java b/src/test/java/umc/kkijuk/server/unitTest/career/service/CareerServiceImplTest 2.java new file mode 100644 index 00000000..da7ddd1b --- /dev/null +++ b/src/test/java/umc/kkijuk/server/unitTest/career/service/CareerServiceImplTest 2.java @@ -0,0 +1,380 @@ +package umc.kkijuk.server.unitTest.career.service; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import umc.kkijuk.server.career.controller.response.*; +import umc.kkijuk.server.career.domain.*; +import umc.kkijuk.server.career.dto.*; +import umc.kkijuk.server.career.repository.*; +import umc.kkijuk.server.career.service.CareerServiceImpl; +import umc.kkijuk.server.common.service.RecordUpdateManager; +import umc.kkijuk.server.member.domain.Member; +import umc.kkijuk.server.record.domain.Record; +import umc.kkijuk.server.record.repository.RecordRepository; + +import java.lang.reflect.Field; +import java.time.LocalDate; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + + + +@ExtendWith(MockitoExtension.class) +class CareerServiceImplTest { + + @InjectMocks + private CareerServiceImpl careerService; + + @Mock + private ActivityRepository activityRepository; + + @Mock + private CircleRepository circleRepository; + + @Mock + private CompetitionRepository competitionRepository; + + @Mock + private EduCareerRepository eduCareerRepository; + + @Mock + private EmploymentRepository employmentRepository; + + @Mock + private ProjectRepository projectRepository; + + @Mock + private CareerEtcRepository etcRepository; + + @Mock + private RecordRepository recordRepository; + + @Mock + private RecordUpdateManager recordUpdateManager; + + @Test + @DisplayName("[CreateCareer] Activity를 생성하면 활동이 저장되고 Record의 타임스탬프가 갱신되어야 한다.") + void createActivity_shouldSaveActivityAndUpdateRecord() { + Member member = Member.builder().id(1L).build(); + ActivityReqDto reqDto = ActivityReqDto.builder() + .name("동아리 활동").unknown(false) + .enddate(LocalDate.of(2023, 12, 31)).build(); + Record mockRecord = Record.builder().memberId(member.getId()).build(); + + when(recordRepository.findByMemberId(member.getId())).thenReturn(mockRecord); + when(activityRepository.save(any(Activity.class))).thenAnswer(invocation -> invocation.getArgument(0)); + + ActivityResponse response = careerService.createActivity(member, reqDto); + + assertNotNull(response); + assertEquals("동아리 활동", response.getName()); + verify(activityRepository).save(any(Activity.class)); + verify(recordUpdateManager).updateRecordTimestamp(mockRecord); + } + + @Test + @DisplayName("[CreateCareer] Circle을 생성하면 저장되고 Record의 타임스탬프가 갱신되어야 한다.") + void createCircle_shouldSaveCircleAndUpdateRecord() { + Member member = Member.builder().id(1L).build(); + CircleReqDto reqDto = CircleReqDto.builder() + .name("소모임").unknown(false) + .enddate(LocalDate.of(2023, 10, 10)).build(); + Record mockRecord = Record.builder().memberId(member.getId()).build(); + + when(recordRepository.findByMemberId(member.getId())).thenReturn(mockRecord); + when(circleRepository.save(any(Circle.class))).thenAnswer(invocation -> invocation.getArgument(0)); + + CircleResponse response = careerService.createCircle(member, reqDto); + + assertNotNull(response); + assertEquals("소모임", response.getName()); + verify(circleRepository).save(any(Circle.class)); + verify(recordUpdateManager).updateRecordTimestamp(mockRecord); + } + + @Test + @DisplayName("[CreateCareer] Competition을 생성하면 저장되고 Record의 타임스탬프가 갱신되어야 한다.") + void createCompetition_shouldSaveCompetitionAndUpdateRecord() { + Member member = Member.builder().id(1L).build(); + CompetitionReqDto reqDto = CompetitionReqDto.builder() + .name("공모전").unknown(false) + .enddate(LocalDate.of(2024, 1, 1)).build(); + Record mockRecord = Record.builder().memberId(member.getId()).build(); + + when(recordRepository.findByMemberId(member.getId())).thenReturn(mockRecord); + when(competitionRepository.save(any(Competition.class))).thenAnswer(invocation -> invocation.getArgument(0)); + + CompetitionResponse response = careerService.createCompetition(member, reqDto); + + assertNotNull(response); + assertEquals("공모전", response.getName()); + verify(competitionRepository).save(any(Competition.class)); + verify(recordUpdateManager).updateRecordTimestamp(mockRecord); + } + + @Test + @DisplayName("[CreateCareer] EduCareer를 생성하면 저장되고 Record의 타임스탬프가 갱신되어야 한다.") + void createEduCareer_shouldSaveEduCareerAndUpdateRecord() { + Member member = Member.builder().id(1L).build(); + EduCareerReqDto reqDto = EduCareerReqDto.builder() + .name("교육 이력") + .unknown(false) + .enddate(LocalDate.of(2022, 5, 15)) + .time(120) + .build(); + + Record mockRecord = Record.builder().memberId(member.getId()).build(); + + when(recordRepository.findByMemberId(member.getId())).thenReturn(mockRecord); + when(eduCareerRepository.save(any(EduCareer.class))).thenAnswer(invocation -> invocation.getArgument(0)); + + EduCareerResponse response = careerService.crateEduCareer(member, reqDto); + + assertNotNull(response); + assertEquals("교육 이력", response.getName()); + verify(eduCareerRepository).save(any(EduCareer.class)); + verify(recordUpdateManager).updateRecordTimestamp(mockRecord); + } + + @Test + @DisplayName("[CreateCareer] Employment를 생성하면 저장되고 Record의 타임스탬프가 갱신되어야 한다.") + void createEmployment_shouldSaveEmploymentAndUpdateRecord() { + Member member = Member.builder().id(1L).build(); + EmploymentReqDto reqDto = EmploymentReqDto.builder() + .name("직장").unknown(false) + .enddate(LocalDate.of(2021, 8, 1)).build(); + Record mockRecord = Record.builder().memberId(member.getId()).build(); + + when(recordRepository.findByMemberId(member.getId())).thenReturn(mockRecord); + when(employmentRepository.save(any(Employment.class))).thenAnswer(invocation -> invocation.getArgument(0)); + + EmploymentResponse response = careerService.createEmployment(member, reqDto); + + assertNotNull(response); + assertEquals("직장", response.getName()); + verify(employmentRepository).save(any(Employment.class)); + verify(recordUpdateManager).updateRecordTimestamp(mockRecord); + } + + @Test + @DisplayName("[CreateCareer] Project를 생성하면 저장되고 Record의 타임스탬프가 갱신되어야 한다.") + void createProject_shouldSaveProjectAndUpdateRecord() { + Member member = Member.builder().id(1L).build(); + ProjectReqDto reqDto = ProjectReqDto.builder() + .name("사이드 프로젝트").unknown(false) + .enddate(LocalDate.of(2024, 12, 1)).build(); + Record mockRecord = Record.builder().memberId(member.getId()).build(); + + when(recordRepository.findByMemberId(member.getId())).thenReturn(mockRecord); + when(projectRepository.save(any(Project.class))).thenAnswer(invocation -> invocation.getArgument(0)); + + ProjectResponse response = careerService.createProject(member, reqDto); + + assertNotNull(response); + assertEquals("사이드 프로젝트", response.getName()); + verify(projectRepository).save(any(Project.class)); + verify(recordUpdateManager).updateRecordTimestamp(mockRecord); + } + + @Test + @DisplayName("[CreateCareer] Etc를 생성하면 저장되고 Record의 타임스탬프가 갱신되어야 한다.") + void createEtc_shouldSaveEtcAndUpdateRecord() { + Member member = Member.builder().id(1L).build(); + EtcReqDto reqDto = EtcReqDto.builder() + .name("기타 활동").unknown(false) + .enddate(LocalDate.of(2020, 2, 2)).build(); + Record mockRecord = Record.builder().memberId(member.getId()).build(); + + when(recordRepository.findByMemberId(member.getId())).thenReturn(mockRecord); + when(etcRepository.save(any(CareerEtc.class))).thenAnswer(invocation -> invocation.getArgument(0)); + + EtcResponse response = careerService.createEtc(member, reqDto); + + assertNotNull(response); + assertEquals("기타 활동", response.getName()); + verify(etcRepository).save(any(CareerEtc.class)); + verify(recordUpdateManager).updateRecordTimestamp(mockRecord); + } + + @Test + @DisplayName("[DeleteCareer] Activity를 삭제하면 Repository에서 제거되고 Record의 타임스탬프가 갱신되어야 한다.") + void deleteActivity_shouldRemoveActivityAndUpdateRecord() { + // given + Long memberId = 1L; + Long activityId = 100L; + + Member member = Member.builder().id(memberId).build(); + Activity activity = Activity.builder().memberId(memberId).build(); + setId(activity, activityId); + Record mockRecord = Record.builder().memberId(memberId).build(); + + when(activityRepository.findById(activityId)).thenReturn(Optional.of(activity)); + when(recordRepository.findByMemberId(memberId)).thenReturn(mockRecord); + + // when + careerService.deleteActivity(member, activityId); + + // then + verify(activityRepository).delete(activity); + verify(recordUpdateManager).updateRecordTimestamp(mockRecord); + } + + @Test + @DisplayName("[DeleteCareer] Circle을 삭제하면 Repository에서 제거되고 Record의 타임스탬프가 갱신되어야 한다.") + void deleteCircle_shouldRemoveCircleAndUpdateRecord() { + // given + Long memberId = 1L; + Long circleId = 101L; + + Member member = Member.builder().id(memberId).build(); + Circle circle = Circle.builder().memberId(memberId).build(); + setId(circle, circleId); + Record record = Record.builder().memberId(memberId).build(); + + when(circleRepository.findById(circleId)).thenReturn(Optional.of(circle)); + when(recordRepository.findByMemberId(memberId)).thenReturn(record); + + // when + careerService.deleteCircle(member, circleId); + + // then + verify(circleRepository).delete(circle); + verify(recordUpdateManager).updateRecordTimestamp(record); + } + + @Test + @DisplayName("[DeleteCareer] Competition을 삭제하면 Repository에서 제거되고 Record의 타임스탬프가 갱신되어야 한다.") + void deleteCompetition_shouldRemoveCompetitionAndUpdateRecord() { + // given + Long memberId = 1L; + Long compId = 102L; + + Member member = Member.builder().id(memberId).build(); + Competition competition = Competition.builder().memberId(memberId).build(); + setId(competition, compId); + Record record = Record.builder().memberId(memberId).build(); + + when(competitionRepository.findById(compId)).thenReturn(Optional.of(competition)); + when(recordRepository.findByMemberId(memberId)).thenReturn(record); + + // when + careerService.deleteComp(member, compId); + + // then + verify(competitionRepository).delete(competition); + verify(recordUpdateManager).updateRecordTimestamp(record); + } + + @Test + @DisplayName("[DeleteCareer] EduCareer를 삭제하면 Repository에서 제거되고 Record의 타임스탬프가 갱신되어야 한다.") + void deleteEduCareer_shouldRemoveEduCareerAndUpdateRecord() { + // given + Long memberId = 1L; + Long eduId = 103L; + + Member member = Member.builder().id(memberId).build(); + EduCareer edu = EduCareer.builder().memberId(memberId).build(); + setId(edu, eduId); + Record record = Record.builder().memberId(memberId).build(); + + when(eduCareerRepository.findById(eduId)).thenReturn(Optional.of(edu)); + when(recordRepository.findByMemberId(memberId)).thenReturn(record); + + // when + careerService.deleteEdu(member, eduId); + + // then + verify(eduCareerRepository).delete(edu); + verify(recordUpdateManager).updateRecordTimestamp(record); + } + + @Test + @DisplayName("[DeleteCareer] Employment를 삭제하면 Repository에서 제거되고 Record의 타임스탬프가 갱신되어야 한다.") + void deleteEmployment_shouldRemoveEmploymentAndUpdateRecord() { + // given + Long memberId = 1L; + Long empId = 104L; + + Member member = Member.builder().id(memberId).build(); + Employment emp = Employment.builder().memberId(memberId).build(); + setId(emp, empId); + Record record = Record.builder().memberId(memberId).build(); + + when(employmentRepository.findById(empId)).thenReturn(Optional.of(emp)); + when(recordRepository.findByMemberId(memberId)).thenReturn(record); + + // when + careerService.deleteEmp(member, empId); + + // then + verify(employmentRepository).delete(emp); + verify(recordUpdateManager).updateRecordTimestamp(record); + } + + @Test + @DisplayName("[DeleteCareer] Project를 삭제하면 Repository에서 제거되고 Record의 타임스탬프가 갱신되어야 한다.") + void deleteProject_shouldRemoveProjectAndUpdateRecord() { + // given + Long memberId = 1L; + Long projectId = 105L; + + Member member = Member.builder().id(memberId).build(); + Project project = Project.builder().memberId(memberId).build(); + setId(project, projectId); + Record record = Record.builder().memberId(memberId).build(); + + when(projectRepository.findById(projectId)).thenReturn(Optional.of(project)); + when(recordRepository.findByMemberId(memberId)).thenReturn(record); + + // when + careerService.deleteProject(member, projectId); + + // then + verify(projectRepository).delete(project); + verify(recordUpdateManager).updateRecordTimestamp(record); + } + + @Test + @DisplayName("[DeleteCareer] Etc를 삭제하면 Repository에서 제거되고 Record의 타임스탬프가 갱신되어야 한다.") + void deleteEtc_shouldRemoveEtcAndUpdateRecord() { + // given + Long memberId = 1L; + Long etcId = 106L; + + Member member = Member.builder().id(memberId).build(); + CareerEtc etc = CareerEtc.builder().memberId(memberId).build(); + setId(etc, etcId); + Record record = Record.builder().memberId(memberId).build(); + + when(etcRepository.findById(etcId)).thenReturn(Optional.of(etc)); + when(recordRepository.findByMemberId(memberId)).thenReturn(record); + + // when + careerService.deleteEtc(member, etcId); + + // then + verify(etcRepository).delete(etc); + verify(recordUpdateManager).updateRecordTimestamp(record); + } + + private void setId(Object entity, Long id) { + try { + Field field = entity.getClass().getDeclaredField("id"); + field.setAccessible(true); + field.set(entity, id); + } catch (Exception e) { + throw new RuntimeException("ID 주입 실패", e); + } + } + + +} + From cbf673e8f1d90c41a3136d1edd866fe05bebe96e Mon Sep 17 00:00:00 2001 From: hyeonda02 Date: Tue, 26 Aug 2025 14:34:50 +0900 Subject: [PATCH 2/3] =?UTF-8?q?Refactor=20:=20=ED=95=84=EC=9A=94=20?= =?UTF-8?q?=EC=97=86=EB=8A=94=20=ED=8C=8C=EC=9D=BC=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- grafana/dashboards/main 2.yaml | 11 - grafana/dashboards/spring-boot-board 2.json | 2924 ----------------- grafana/datasources/datasources 2.yaml | 14 - grafana/docker-compose 2.yml | 38 - grafana/prometheus-config 2.yaml | 8 - .../CareerSearchServiceImplTest 2.java | 202 -- .../service/CareerServiceImplTest 2.java | 380 --- 7 files changed, 3577 deletions(-) delete mode 100644 grafana/dashboards/main 2.yaml delete mode 100644 grafana/dashboards/spring-boot-board 2.json delete mode 100644 grafana/datasources/datasources 2.yaml delete mode 100644 grafana/docker-compose 2.yml delete mode 100644 grafana/prometheus-config 2.yaml delete mode 100644 src/test/java/umc/kkijuk/server/unitTest/career/service/CareerSearchServiceImplTest 2.java delete mode 100644 src/test/java/umc/kkijuk/server/unitTest/career/service/CareerServiceImplTest 2.java diff --git a/grafana/dashboards/main 2.yaml b/grafana/dashboards/main 2.yaml deleted file mode 100644 index a26d4a30..00000000 --- a/grafana/dashboards/main 2.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: 1 - -providers: - - name: 'default' - orgId: 1 - folder: '' - type: file - disableDeletion: false - updateIntervalSeconds: 10 - options: - path: /var/lib/grafana/dashboards \ No newline at end of file diff --git a/grafana/dashboards/spring-boot-board 2.json b/grafana/dashboards/spring-boot-board 2.json deleted file mode 100644 index 8de412d2..00000000 --- a/grafana/dashboards/spring-boot-board 2.json +++ /dev/null @@ -1,2924 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": 1, - "links": [], - "panels": [ - { - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 54, - "panels": [], - "title": "Basic Statistics", - "type": "row" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "decimals": 1, - "mappings": [ - { - "options": { - "match": "null", - "result": { - "text": "N/A" - } - }, - "type": "special" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 3, - "w": 6, - "x": 0, - "y": 1 - }, - "id": 52, - "maxDataPoints": 100, - "options": { - "colorMode": "value", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "11.6.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "process_uptime_seconds{application=\"$application\", instance=\"$instance\", namespace=\"$Namespace\"}", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "metric": "", - "range": true, - "refId": "A", - "step": 14400 - } - ], - "title": "Uptime", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "decimals": 1, - "mappings": [ - { - "options": { - "match": "null", - "result": { - "text": "N/A" - } - }, - "type": "special" - } - ], - "max": 100, - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "rgba(50, 172, 45, 0.97)" - }, - { - "color": "rgba(237, 129, 40, 0.89)", - "value": 70 - }, - { - "color": "rgba(245, 54, 54, 0.9)", - "value": 90 - } - ] - }, - "unit": "percent" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 5, - "x": 6, - "y": 1 - }, - "id": 58, - "maxDataPoints": 100, - "options": { - "minVizHeight": 75, - "minVizWidth": 75, - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showThresholdLabels": false, - "showThresholdMarkers": true, - "sizing": "auto" - }, - "pluginVersion": "11.6.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", area=\"heap\", namespace=\"$Namespace\"})*100/sum(jvm_memory_max_bytes{application=\"$application\",instance=\"$instance\", area=\"heap\", namespace=\"$Namespace\"})", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "", - "range": true, - "refId": "A", - "step": 14400 - } - ], - "title": "Heap Used", - "type": "gauge" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "decimals": 1, - "mappings": [ - { - "options": { - "match": "null", - "result": { - "text": "N/A" - } - }, - "type": "special" - }, - { - "options": { - "from": -1e+32, - "result": { - "text": "N/A" - }, - "to": 0 - }, - "type": "range" - } - ], - "max": 100, - "min": 0, - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "rgba(50, 172, 45, 0.97)" - }, - { - "color": "rgba(237, 129, 40, 0.89)", - "value": 70 - }, - { - "color": "rgba(245, 54, 54, 0.9)", - "value": 90 - } - ] - }, - "unit": "percent" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 5, - "x": 11, - "y": 1 - }, - "id": 60, - "maxDataPoints": 100, - "options": { - "minVizHeight": 75, - "minVizWidth": 75, - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showThresholdLabels": false, - "showThresholdMarkers": true, - "sizing": "auto" - }, - "pluginVersion": "11.6.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "sum(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", area=\"nonheap\", namespace=\"$Namespace\"})*100/sum(jvm_memory_max_bytes{application=\"$application\",instance=\"$instance\", area=\"nonheap\", namespace=\"$Namespace\"})", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "range": true, - "refId": "A", - "step": 14400 - } - ], - "title": "Non-Heap Used", - "type": "gauge" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "locale" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 8, - "x": 16, - "y": 1 - }, - "id": 66, - "options": { - "alertThreshold": true, - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.6.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "process_files_open_files{application=\"$application\", instance=\"$instance\", namespace=\"$Namespace\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Open Files", - "range": true, - "refId": "A" - } - ], - "title": "Process Open Files", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [ - { - "options": { - "match": "null", - "result": { - "text": "N/A" - } - }, - "type": "special" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "dateTimeAsIso" - }, - "overrides": [] - }, - "gridPos": { - "h": 3, - "w": 6, - "x": 0, - "y": 4 - }, - "id": 56, - "maxDataPoints": 100, - "options": { - "colorMode": "value", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "11.6.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "process_start_time_seconds{application=\"$application\", instance=\"$instance\", namespace=\"$Namespace\"}*1000", - "format": "time_series", - "intervalFactor": 2, - "legendFormat": "", - "metric": "", - "range": true, - "refId": "A", - "step": 14400 - } - ], - "title": "Start time", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 7 - }, - "id": 95, - "options": { - "legend": { - "calcs": [ - "mean", - "lastNotNull", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.6.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "system_cpu_usage{instance=\"$instance\", application=\"$application\", namespace=\"$Namespace\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "System CPU Usage", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "process_cpu_usage{instance=\"$instance\", application=\"$application\", namespace=\"$Namespace\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Process CPU Usage", - "range": true, - "refId": "B" - } - ], - "title": "CPU Usage", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 7 - }, - "id": 96, - "options": { - "legend": { - "calcs": [ - "mean", - "lastNotNull", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.6.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "system_load_average_1m{instance=\"$instance\", application=\"$application\", namespace=\"$Namespace\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Load Average [1m]", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "system_cpu_count{instance=\"$instance\", application=\"$application\", namespace=\"$Namespace\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "CPU Core Size", - "range": true, - "refId": "B" - } - ], - "title": "Load Average", - "type": "timeseries" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 14 - }, - "id": 103, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 4, - "x": 0, - "y": 15 - }, - "id": 104, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "11.6.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "exemplar": true, - "expr": "sum(http_server_requests_seconds_count{application=\"$application\", uri!=\"/actuator/prometheus\"})", - "instant": true, - "interval": "", - "legendFormat": "", - "range": true, - "refId": "A" - } - ], - "timeFrom": "24h", - "title": "Total Requests", - "transformations": [ - { - "id": "seriesToRows", - "options": {} - }, - { - "id": "sortBy", - "options": { - "fields": {}, - "sort": [ - { - "field": "Time" - } - ] - } - } - ], - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 8, - "x": 4, - "y": 15 - }, - "id": 105, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "value_and_name", - "wideLayout": true - }, - "pluginVersion": "11.6.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "exemplar": true, - "expr": "sum by(uri) (http_server_requests_seconds_count{application=\"$application\", uri!=\"/actuator/prometheus\"})", - "instant": true, - "interval": "", - "legendFormat": "{{method}} {{uri}}", - "range": true, - "refId": "A" - } - ], - "timeFrom": "24h", - "title": "Requests Count", - "transformations": [ - { - "id": "seriesToRows", - "options": {} - }, - { - "id": "sortBy", - "options": { - "fields": {}, - "sort": [ - { - "field": "Time" - } - ] - } - }, - { - "id": "partitionByValues", - "options": { - "fields": [ - "Metric" - ] - } - } - ], - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "continuous-GrYlRd" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 15 - }, - "id": 106, - "options": { - "displayMode": "lcd", - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": false - }, - "maxVizHeight": 300, - "minVizHeight": 10, - "minVizWidth": 0, - "namePlacement": "auto", - "orientation": "horizontal", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showUnfilled": true, - "sizing": "auto", - "valueMode": "color" - }, - "pluginVersion": "11.6.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "exemplar": true, - "expr": "sum by(uri)(http_server_requests_seconds_sum{application=\"$application\"}) / sum by(uri)(http_server_requests_seconds_count{application=\"$application\"})", - "interval": "", - "legendFormat": "{{method}} {{uri}}", - "range": true, - "refId": "A" - } - ], - "title": "Requests Average Duration", - "type": "bargauge" - } - ], - "title": "Observability", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 15 - }, - "id": 48, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 24, - "x": 0, - "y": 268 - }, - "id": 85, - "options": { - "legend": { - "calcs": [ - "mean", - "lastNotNull", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.5.1", - "repeat": "memory_pool_heap", - "repeatDirection": "h", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "jvm_memory_used_bytes{instance=\"$instance\", application=\"$application\", id=\"$memory_pool_heap\", namespace=\"$Namespace\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Used", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "jvm_memory_committed_bytes{instance=\"$instance\", application=\"$application\", id=\"$memory_pool_heap\", namespace=\"$Namespace\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Commited", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "jvm_memory_max_bytes{instance=\"$instance\", application=\"$application\", id=\"$memory_pool_heap\", namespace=\"$Namespace\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Max", - "range": true, - "refId": "B" - } - ], - "title": "$memory_pool_heap (heap)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 24, - "x": 0, - "y": 408 - }, - "id": 88, - "options": { - "legend": { - "calcs": [ - "mean", - "lastNotNull", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "9.5.1", - "repeat": "memory_pool_nonheap", - "repeatDirection": "h", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "jvm_memory_used_bytes{instance=\"$instance\", application=\"$application\", id=\"${memory_pool_nonheap:raw}\", namespace=\"$Namespace\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Used", - "range": true, - "refId": "C" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "jvm_memory_committed_bytes{instance=\"$instance\", application=\"$application\", id=\"${memory_pool_nonheap:raw}\", namespace=\"$Namespace\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Commited", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "jvm_memory_max_bytes{instance=\"$instance\", application=\"$application\", id=\"${memory_pool_nonheap:raw}\", namespace=\"$Namespace\"}", - "format": "time_series", - "hide": false, - "intervalFactor": 1, - "legendFormat": "Max", - "range": true, - "refId": "B" - } - ], - "title": "$memory_pool_nonheap (non-heap)", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 0, - "y": 416 - }, - "id": 82, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.6.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "jvm_buffer_memory_used_bytes{instance=\"$instance\", application=\"$application\", id=\"direct\", namespace=\"$Namespace\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Used Bytes", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "jvm_buffer_total_capacity_bytes{instance=\"$instance\", application=\"$application\", id=\"direct\", namespace=\"$Namespace\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Capacity Bytes", - "range": true, - "refId": "B" - } - ], - "title": "Direct Buffers", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 416 - }, - "id": 68, - "options": { - "legend": { - "calcs": [ - "mean", - "lastNotNull", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.6.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "jvm_threads_daemon_threads{instance=\"$instance\", application=\"$application\", namespace=\"$Namespace\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Daemon", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "jvm_threads_live_threads{instance=\"$instance\", application=\"$application\", namespace=\"$Namespace\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Live", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "jvm_threads_peak_threads{instance=\"$instance\", application=\"$application\", namespace=\"$Namespace\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Peak", - "range": true, - "refId": "C" - } - ], - "title": "Threads", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "bytes" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 423 - }, - "id": 78, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.6.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "irate(jvm_gc_memory_allocated_bytes_total{instance=\"$instance\", application=\"$application\", namespace=\"$Namespace\"}[$__rate_interval])", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "allocated", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "irate(jvm_gc_memory_promoted_bytes_total{instance=\"$instance\", application=\"$application\", namespace=\"$Namespace\"}[$__rate_interval])", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "promoted", - "range": true, - "refId": "B" - } - ], - "title": "Memory Allocate/Promote", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 12, - "x": 12, - "y": 424 - }, - "id": 83, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.6.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "jvm_buffer_memory_used_bytes{instance=\"$instance\", application=\"$application\", id=\"mapped\", namespace=\"$Namespace\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Used Bytes", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "jvm_buffer_total_capacity_bytes{instance=\"$instance\", application=\"$application\", id=\"mapped\", namespace=\"$Namespace\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Capacity Bytes", - "range": true, - "refId": "B" - } - ], - "title": "Mapped Buffers", - "type": "timeseries" - } - ], - "title": "JVM Statistics - Memory", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 16 - }, - "id": 72, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "locale" - }, - "overrides": [] - }, - "gridPos": { - "h": 10, - "w": 12, - "x": 0, - "y": 269 - }, - "id": 74, - "options": { - "legend": { - "calcs": [ - "mean", - "max", - "min", - "sum" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.6.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "irate(jvm_gc_pause_seconds_count{instance=\"$instance\", application=\"$application\", namespace=\"$Namespace\"}[$__rate_interval])", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{action}} [{{cause}}]", - "range": true, - "refId": "A" - } - ], - "title": "GC Count", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 10, - "w": 12, - "x": 12, - "y": 269 - }, - "id": 76, - "options": { - "legend": { - "calcs": [ - "mean", - "max", - "min", - "sum" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.6.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "irate(jvm_gc_pause_seconds_sum{instance=\"$instance\", application=\"$application\", namespace=\"$Namespace\"}[$__rate_interval])", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{action}} [{{cause}}]", - "range": true, - "refId": "A" - } - ], - "title": "GC Stop the World Duration", - "type": "timeseries" - } - ], - "title": "JVM Statistics - GC", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 17 - }, - "id": 34, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [ - { - "options": { - "match": "null", - "result": { - "text": "N/A" - } - }, - "type": "special" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "none" - }, - "overrides": [] - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 0, - "y": 18 - }, - "id": 44, - "maxDataPoints": 100, - "options": { - "colorMode": "none", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "11.6.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "hikaricp_connections{instance=\"$instance\", application=\"$application\", pool=\"$hikaricp\", namespace=\"$Namespace\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "", - "range": true, - "refId": "A" - } - ], - "title": "Connections Size", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "normal" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "short" - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 20, - "x": 4, - "y": 18 - }, - "id": 36, - "options": { - "legend": { - "calcs": [ - "mean", - "lastNotNull", - "max", - "min" - ], - "displayMode": "table", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.6.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "hikaricp_connections_active{instance=\"$instance\", application=\"$application\", pool=\"$hikaricp\", namespace=\"$Namespace\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Active", - "range": true, - "refId": "B" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "hikaricp_connections_idle{instance=\"$instance\", application=\"$application\", pool=\"$hikaricp\", namespace=\"$Namespace\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Idle", - "range": true, - "refId": "A" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "hikaricp_connections_pending{instance=\"$instance\", application=\"$application\", pool=\"$hikaricp\", namespace=\"$Namespace\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Pending", - "range": true, - "refId": "C" - } - ], - "title": "Connections", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [ - { - "options": { - "match": "null", - "result": { - "text": "N/A" - } - }, - "type": "special" - } - ], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "none" - }, - "overrides": [] - }, - "gridPos": { - "h": 4, - "w": 4, - "x": 0, - "y": 22 - }, - "id": 46, - "maxDataPoints": 100, - "options": { - "colorMode": "none", - "graphMode": "none", - "justifyMode": "auto", - "orientation": "horizontal", - "percentChangeColorMode": "standard", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "", - "values": false - }, - "showPercentChange": false, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "11.6.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "hikaricp_connections_timeout_total{instance=\"$instance\", application=\"$application\", pool=\"$hikaricp\", namespace=\"$Namespace\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "", - "range": true, - "refId": "A" - } - ], - "title": "Connection Timeout Count", - "type": "stat" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 8, - "x": 0, - "y": 26 - }, - "id": 38, - "options": { - "alertThreshold": true, - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.6.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "expr": "hikaricp_connections_creation_seconds_sum{instance=\"$instance\", application=\"$application\", pool=\"$hikaricp\"} / hikaricp_connections_creation_seconds_count{instance=\"$instance\", application=\"$application\", pool=\"$hikaricp\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Creation Time", - "refId": "A" - } - ], - "title": "Connection Creation Time", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 8, - "x": 8, - "y": 26 - }, - "id": 42, - "options": { - "alertThreshold": true, - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.6.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "expr": "hikaricp_connections_usage_seconds_sum{instance=\"$instance\", application=\"$application\", pool=\"$hikaricp\"} / hikaricp_connections_usage_seconds_count{instance=\"$instance\", application=\"$application\", pool=\"$hikaricp\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Usage Time", - "refId": "A" - } - ], - "title": "Connection Usage Time", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 6, - "w": 8, - "x": 16, - "y": 26 - }, - "id": 40, - "options": { - "alertThreshold": true, - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.6.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "expr": "hikaricp_connections_acquire_seconds_sum{instance=\"$instance\", application=\"$application\", pool=\"$hikaricp\"} / hikaricp_connections_acquire_seconds_count{instance=\"$instance\", application=\"$application\", pool=\"$hikaricp\"}", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "Acquire Time", - "refId": "A" - } - ], - "title": "Connection Acquire Time", - "type": "timeseries" - } - ], - "title": "Database Connection Pool HikariCP Statistics", - "type": "row" - }, - { - "collapsed": true, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 18 - }, - "id": 18, - "panels": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "none" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 24, - "x": 0, - "y": 19 - }, - "id": 4, - "options": { - "legend": { - "calcs": [], - "displayMode": "table", - "placement": "right", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.6.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "irate(http_server_requests_seconds_count{instance=\"$instance\", application=\"$application\", uri!~\".*(prometheus|health).*\", namespace=\"$Namespace\"}[$__rate_interval])", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{method}} [{{status}}] - {{uri}}", - "range": true, - "refId": "A" - } - ], - "title": "Request Count", - "type": "timeseries" - }, - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "barWidthFactor": 0.6, - "drawStyle": "line", - "fillOpacity": 10, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "never", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] - }, - "unit": "s" - }, - "overrides": [] - }, - "gridPos": { - "h": 7, - "w": 24, - "x": 0, - "y": 26 - }, - "id": 2, - "options": { - "legend": { - "calcs": [ - "mean", - "max", - "min" - ], - "displayMode": "table", - "placement": "right", - "showLegend": true - }, - "tooltip": { - "hideZeros": false, - "mode": "multi", - "sort": "none" - } - }, - "pluginVersion": "11.6.0", - "targets": [ - { - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "editorMode": "code", - "expr": "irate(http_server_requests_seconds_sum{instance=\"$instance\", application=\"$application\", exception=\"none\", uri!~\".*(prometheus|health).*\", namespace=\"$Namespace\"}[$__rate_interval]) / irate(http_server_requests_seconds_count{instance=\"$instance\", application=\"$application\", exception=\"none\",uri!~\".*(prometheus|health).*\", namespace=\"$Namespace\"}[$__rate_interval])", - "format": "time_series", - "intervalFactor": 1, - "legendFormat": "{{method}} [{{status}}] - {{uri}}", - "range": true, - "refId": "A" - } - ], - "title": "Response Time", - "type": "timeseries" - } - ], - "title": "HTTP Statistics", - "type": "row" - } - ], - "preload": false, - "refresh": "", - "schemaVersion": 41, - "tags": [ - "app" - ], - "templating": { - "list": [ - { - "current": { - "text": "", - "value": "" - }, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "definition": "label_values(jvm_info,application)", - "includeAll": false, - "label": "Application", - "name": "application", - "options": [], - "query": { - "query": "label_values(jvm_info,application)", - "refId": "PrometheusVariableQueryEditor-VariableQuery" - }, - "refresh": 2, - "regex": "", - "sort": 1, - "type": "query" - }, - { - "current": { - "text": "", - "value": "" - }, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "definition": "label_values(jvm_info,namespace)", - "includeAll": false, - "name": "Namespace", - "options": [], - "query": { - "query": "label_values(jvm_info,namespace)", - "refId": "PrometheusVariableQueryEditor-VariableQuery" - }, - "refresh": 2, - "regex": "", - "type": "query" - }, - { - "current": { - "text": "host.docker.internal:8080", - "value": "host.docker.internal:8080" - }, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "definition": "label_values(jvm_info{application=\"$application\", namespace=\"$Namespace\"},instance)", - "includeAll": false, - "label": "Instance", - "name": "instance", - "options": [], - "query": { - "query": "label_values(jvm_info{application=\"$application\", namespace=\"$Namespace\"},instance)", - "refId": "PrometheusVariableQueryEditor-VariableQuery" - }, - "refresh": 2, - "regex": "", - "sort": 1, - "type": "query" - }, - { - "current": { - "text": "HikariPool-1", - "value": "HikariPool-1" - }, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "definition": "", - "includeAll": false, - "label": "HikariCP-Pool", - "name": "hikaricp", - "options": [], - "query": { - "query": "label_values(hikaricp_connections{instance=\"$instance\", application=\"$application\"}, pool)", - "refId": "Prometheus-hikaricp-Variable-Query" - }, - "refresh": 2, - "regex": "", - "sort": 1, - "type": "query" - }, - { - "current": { - "text": "All", - "value": "$__all" - }, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "definition": "label_values(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", area=\"heap\"},id)", - "includeAll": true, - "label": "Memory Pool (heap)", - "name": "memory_pool_heap", - "options": [], - "query": { - "query": "label_values(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", area=\"heap\"},id)", - "refId": "PrometheusVariableQueryEditor-VariableQuery" - }, - "refresh": 2, - "regex": "", - "sort": 1, - "type": "query" - }, - { - "current": { - "text": "All", - "value": "$__all" - }, - "datasource": { - "type": "prometheus", - "uid": "prometheus" - }, - "definition": "label_values(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", area=\"nonheap\"},id)", - "includeAll": true, - "label": "Memory Pool (nonheap)", - "name": "memory_pool_nonheap", - "options": [], - "query": { - "query": "label_values(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", area=\"nonheap\"},id)", - "refId": "PrometheusVariableQueryEditor-VariableQuery" - }, - "refresh": 2, - "regex": "", - "sort": 1, - "type": "query" - } - ] - }, - "time": { - "from": "now-1h", - "to": "now" - }, - "timepicker": {}, - "timezone": "", - "title": "Spring Boot Dashboard", - "uid": "SpringBootDashboard", - "version": 1 -} \ No newline at end of file diff --git a/grafana/datasources/datasources 2.yaml b/grafana/datasources/datasources 2.yaml deleted file mode 100644 index 2f149dc9..00000000 --- a/grafana/datasources/datasources 2.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: 1 - -deleteDatasources: - - name: prometheus - - name: loki - -datasources: - - name: prometheus - uid: prometheus - type: prometheus - access: proxy - url: http://kkijuk-prometheus:9090 - isDefault: true - editable: true \ No newline at end of file diff --git a/grafana/docker-compose 2.yml b/grafana/docker-compose 2.yml deleted file mode 100644 index 6f796b0e..00000000 --- a/grafana/docker-compose 2.yml +++ /dev/null @@ -1,38 +0,0 @@ -version: '3.8' - -services: - ## monitoring - prometheus: - image: prom/prometheus:latest - container_name: kkijuk-prometheus - volumes: - - ./prometheus-config.yaml:/etc/prometheus/prometheus-config.yaml - command: - - '--config.file=/etc/prometheus/prometheus-config.yaml' - ports: - - "9090:9090" - networks: - - monitoring-network - - grafana: - image: grafana/grafana:latest - container_name: kkijuk-grafana -# set in instance -# environment: -# - GF_SECURITY_ADMIN_USER=local -# - GF_SECURITY_ADMIN_PASSWORD=local - volumes: - - ./datasources:/etc/grafana/provisioning/datasources - - ./dashboards:/etc/grafana/provisioning/dashboards - - ./dashboards:/var/lib/grafana/dashboards - ports: - - "3000:3000" - networks: - - monitoring-network - -networks: - monitoring-network: - driver: bridge - -volumes: - loki_data: \ No newline at end of file diff --git a/grafana/prometheus-config 2.yaml b/grafana/prometheus-config 2.yaml deleted file mode 100644 index 72b6e721..00000000 --- a/grafana/prometheus-config 2.yaml +++ /dev/null @@ -1,8 +0,0 @@ -global: - scrape_interval: 15s - -scrape_configs: - - job_name: prometheus - metrics_path: '/actuator/prometheus' - static_configs: - - targets: ['host.docker.internal:8088'] \ No newline at end of file diff --git a/src/test/java/umc/kkijuk/server/unitTest/career/service/CareerSearchServiceImplTest 2.java b/src/test/java/umc/kkijuk/server/unitTest/career/service/CareerSearchServiceImplTest 2.java deleted file mode 100644 index c27301f2..00000000 --- a/src/test/java/umc/kkijuk/server/unitTest/career/service/CareerSearchServiceImplTest 2.java +++ /dev/null @@ -1,202 +0,0 @@ -package umc.kkijuk.server.unitTest.career.service; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import umc.kkijuk.server.career.controller.response.*; -import umc.kkijuk.server.career.domain.*; -import umc.kkijuk.server.career.repository.*; -import umc.kkijuk.server.detail.domain.BaseCareerDetail; -import umc.kkijuk.server.detail.domain.CareerType; -import umc.kkijuk.server.detail.repository.CareerDetailRepository; -import umc.kkijuk.server.member.domain.Member; -import umc.kkijuk.server.tag.domain.Tag; -import umc.kkijuk.server.tag.repository.TagRepository; - -import java.lang.reflect.Field; -import java.time.LocalDate; -import java.util.*; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.*; - -@ExtendWith(MockitoExtension.class) -public class CareerSearchServiceImplTest { - - @InjectMocks - private umc.kkijuk.server.career.service.CareerSearchServiceImpl careerSearchService; - - @Mock private ActivityRepository activityRepository; - @Mock private CircleRepository circleRepository; - @Mock private CompetitionRepository competitionRepository; - @Mock private EduCareerRepository eduCareerRepository; - @Mock private ProjectRepository projectRepository; - @Mock private EmploymentRepository employmentRepository; - @Mock private CareerEtcRepository etcRepository; - @Mock private CareerDetailRepository detailRepository; - @Mock private TagRepository tagRepository; - - private final Long memberId = 1L; - private final Member member = Member.builder().id(memberId).build(); - - @Test - @DisplayName("[CareerSearch] 타임라인용 커리어 전체 조회 시 날짜 기준으로 정렬된 리스트가 반환되어야 한다.") - void findCareerForTimeline_shouldReturnSortedTimelineResponses() { - Activity activity = Activity.builder() - .memberId(memberId).name("Activity").endDate(LocalDate.of(2024, 5, 1)).build(); - setId(activity, 1L); - - Competition competition = Competition.builder() - .memberId(memberId).name("Competition").enddate(LocalDate.of(2023, 6, 15)).build(); - setId(competition, 2L); - - when(activityRepository.findByMemberId(memberId)).thenReturn(List.of(activity)); - when(competitionRepository.findByMemberId(memberId)).thenReturn(List.of(competition)); - when(circleRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); - when(eduCareerRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); - when(projectRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); - when(employmentRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); - when(etcRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); - - List result = careerSearchService.findCareerForTimeline(member); - - assertEquals(2, result.size()); - assertEquals("Activity", result.get(0).getTitle()); - } - - @Test - @DisplayName("[CareerSearch] 카테고리별 커리어 목록을 조회하면 분류된 Map이 반환되어야 한다.") - void findAllCareerGroupedCategory_shouldReturnGroupedMap() { - Activity activity = Activity.builder() - .memberId(memberId).name("Act").startDate(LocalDate.of(2023, 1, 1)).build(); - setId(activity, 1L); - - when(activityRepository.findByMemberId(memberId)).thenReturn(List.of(activity)); - when(circleRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); - when(competitionRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); - when(eduCareerRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); - when(projectRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); - when(employmentRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); - when(etcRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); - - Map> result = careerSearchService.findAllCareerGroupedCategory(memberId); - - assertEquals(7, result.size()); - assertTrue(result.containsKey("대외활동")); - assertEquals(1, result.get("대외활동").size()); - } - - @Test - @DisplayName("[CareerSearch] 연도별 커리어 조회 시 시작년도 기준으로 그룹핑되어야 한다.") - void findAllCareerGroupedYear_shouldGroupByStartYear() { - Project project = Project.builder() - .memberId(memberId).name("Project").startdate(LocalDate.of(2023, 2, 1)).build(); - setId(project, 1L); - - when(projectRepository.findByMemberId(memberId)).thenReturn(List.of(project)); - when(competitionRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); - when(activityRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); - when(circleRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); - when(eduCareerRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); - when(employmentRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); - when(etcRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); - - Map> result = careerSearchService.findAllCareerGroupedYear(memberId); - - assertTrue(result.containsKey("2023")); - assertEquals(1, result.get("2023").size()); - } - - @Test - @DisplayName("[CareerSearch] 전체 커리어 목록 조회 시 종료일 기준 내림차순 정렬되어야 한다.") - void findAllCareer_shouldReturnSortedList() { - Project project = Project.builder() - .memberId(memberId).name("Project").enddate(LocalDate.of(2024, 3, 15)).build(); - setId(project, 1L); - - when(projectRepository.findByMemberId(memberId)).thenReturn(List.of(project)); - when(detailRepository.findByCareerIdAndCareerType(eq(CareerType.PROJECT), eq(1L))).thenReturn(Collections.emptyList()); - when(competitionRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); - when(activityRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); - when(circleRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); - when(eduCareerRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); - when(employmentRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); - when(etcRepository.findByMemberId(memberId)).thenReturn(Collections.emptyList()); - - List result = careerSearchService.findAllCareer(memberId); - - assertEquals(1, result.size()); - ProjectResponse response = (ProjectResponse) result.get(0); - assertEquals("Project", response.getName()); - } - - @Test - @DisplayName("[CareerSearch] 활동 상세 조회 시 본인 소유 Activity가 존재하면 반환되어야 한다.") - void findCareer_shouldReturnActivityResponse() { - Long careerId = 10L; - Activity activity = Activity.builder() - .memberId(memberId).name("활동").build(); - setId(activity, careerId); - - when(activityRepository.findById(careerId)).thenReturn(Optional.of(activity)); - when(detailRepository.findByCareerIdAndCareerType(eq(CareerType.ACTIVITY), eq(careerId))).thenReturn(Collections.emptyList()); - - BaseCareerResponse response = careerSearchService.findCareer(member, careerId, "activity"); - - assertTrue(response instanceof ActivityResponse); - ActivityResponse activityResponse = (ActivityResponse) response; - assertEquals("활동", activityResponse.getName()); - } - - @Test - @DisplayName("[CareerSearch] 키워드로 태그 검색 시 태그 목록과 연결된 상세 개수가 반환되어야 한다.") - void findAllTag_shouldReturnTagsAndDetailCount() { - Tag tag = Tag.builder().id(1L).memberId(memberId).name("keyword").build(); - BaseCareerDetail detail = mock(BaseCareerDetail.class); - - when(tagRepository.findByKeywordAndMemberId("keyword", memberId)).thenReturn(List.of(tag)); - when(detailRepository.findByTag(tag.getId())).thenReturn(List.of(detail)); - - FindTagResponse.SearchTagResponse result = careerSearchService.findAllTag(member, "keyword"); - - assertEquals(1, result.getTagList().size()); - assertEquals(1, result.getDetailCount()); - } - - @Test - @DisplayName("[CareerSearch] 커리어 키워드 검색 시 이름에 키워드가 포함된 커리어가 정렬되어 반환되어야 한다.") - void findCareerWithKeyword_shouldReturnFilteredList() { - Activity act = Activity.builder() - .memberId(memberId).name("검색활동").startDate(LocalDate.of(2023, 3, 1)).build(); - setId(act, 1L); - - when(activityRepository.findByMemberIdAndNameContaining(eq(memberId), anyString())).thenReturn(List.of(act)); - when(competitionRepository.findByMemberIdAndNameContaining(eq(memberId), anyString())).thenReturn(Collections.emptyList()); - when(circleRepository.findByMemberIdAndNameContaining(eq(memberId), anyString())).thenReturn(Collections.emptyList()); - when(eduCareerRepository.findByMemberIdAndNameContaining(eq(memberId), anyString())).thenReturn(Collections.emptyList()); - when(projectRepository.findByMemberIdAndNameContaining(eq(memberId), anyString())).thenReturn(Collections.emptyList()); - when(employmentRepository.findByMemberIdAndNameContaining(eq(memberId), anyString())).thenReturn(Collections.emptyList()); - when(etcRepository.findByMemberIdAndNameContaining(eq(memberId), anyString())).thenReturn(Collections.emptyList()); - - List result = careerSearchService.findCareerWithKeyword(member, "검색", "new"); - - assertEquals(1, result.size()); - assertEquals("검색활동", result.get(0).getCareerTitle()); - } - - - private void setId(Object entity, Long id) { - try { - Field field = entity.getClass().getDeclaredField("id"); - field.setAccessible(true); - field.set(entity, id); - } catch (Exception e) { - throw new RuntimeException("ID 주입 실패", e); - } - } -} - diff --git a/src/test/java/umc/kkijuk/server/unitTest/career/service/CareerServiceImplTest 2.java b/src/test/java/umc/kkijuk/server/unitTest/career/service/CareerServiceImplTest 2.java deleted file mode 100644 index da7ddd1b..00000000 --- a/src/test/java/umc/kkijuk/server/unitTest/career/service/CareerServiceImplTest 2.java +++ /dev/null @@ -1,380 +0,0 @@ -package umc.kkijuk.server.unitTest.career.service; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import umc.kkijuk.server.career.controller.response.*; -import umc.kkijuk.server.career.domain.*; -import umc.kkijuk.server.career.dto.*; -import umc.kkijuk.server.career.repository.*; -import umc.kkijuk.server.career.service.CareerServiceImpl; -import umc.kkijuk.server.common.service.RecordUpdateManager; -import umc.kkijuk.server.member.domain.Member; -import umc.kkijuk.server.record.domain.Record; -import umc.kkijuk.server.record.repository.RecordRepository; - -import java.lang.reflect.Field; -import java.time.LocalDate; -import java.util.Optional; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - - - -@ExtendWith(MockitoExtension.class) -class CareerServiceImplTest { - - @InjectMocks - private CareerServiceImpl careerService; - - @Mock - private ActivityRepository activityRepository; - - @Mock - private CircleRepository circleRepository; - - @Mock - private CompetitionRepository competitionRepository; - - @Mock - private EduCareerRepository eduCareerRepository; - - @Mock - private EmploymentRepository employmentRepository; - - @Mock - private ProjectRepository projectRepository; - - @Mock - private CareerEtcRepository etcRepository; - - @Mock - private RecordRepository recordRepository; - - @Mock - private RecordUpdateManager recordUpdateManager; - - @Test - @DisplayName("[CreateCareer] Activity를 생성하면 활동이 저장되고 Record의 타임스탬프가 갱신되어야 한다.") - void createActivity_shouldSaveActivityAndUpdateRecord() { - Member member = Member.builder().id(1L).build(); - ActivityReqDto reqDto = ActivityReqDto.builder() - .name("동아리 활동").unknown(false) - .enddate(LocalDate.of(2023, 12, 31)).build(); - Record mockRecord = Record.builder().memberId(member.getId()).build(); - - when(recordRepository.findByMemberId(member.getId())).thenReturn(mockRecord); - when(activityRepository.save(any(Activity.class))).thenAnswer(invocation -> invocation.getArgument(0)); - - ActivityResponse response = careerService.createActivity(member, reqDto); - - assertNotNull(response); - assertEquals("동아리 활동", response.getName()); - verify(activityRepository).save(any(Activity.class)); - verify(recordUpdateManager).updateRecordTimestamp(mockRecord); - } - - @Test - @DisplayName("[CreateCareer] Circle을 생성하면 저장되고 Record의 타임스탬프가 갱신되어야 한다.") - void createCircle_shouldSaveCircleAndUpdateRecord() { - Member member = Member.builder().id(1L).build(); - CircleReqDto reqDto = CircleReqDto.builder() - .name("소모임").unknown(false) - .enddate(LocalDate.of(2023, 10, 10)).build(); - Record mockRecord = Record.builder().memberId(member.getId()).build(); - - when(recordRepository.findByMemberId(member.getId())).thenReturn(mockRecord); - when(circleRepository.save(any(Circle.class))).thenAnswer(invocation -> invocation.getArgument(0)); - - CircleResponse response = careerService.createCircle(member, reqDto); - - assertNotNull(response); - assertEquals("소모임", response.getName()); - verify(circleRepository).save(any(Circle.class)); - verify(recordUpdateManager).updateRecordTimestamp(mockRecord); - } - - @Test - @DisplayName("[CreateCareer] Competition을 생성하면 저장되고 Record의 타임스탬프가 갱신되어야 한다.") - void createCompetition_shouldSaveCompetitionAndUpdateRecord() { - Member member = Member.builder().id(1L).build(); - CompetitionReqDto reqDto = CompetitionReqDto.builder() - .name("공모전").unknown(false) - .enddate(LocalDate.of(2024, 1, 1)).build(); - Record mockRecord = Record.builder().memberId(member.getId()).build(); - - when(recordRepository.findByMemberId(member.getId())).thenReturn(mockRecord); - when(competitionRepository.save(any(Competition.class))).thenAnswer(invocation -> invocation.getArgument(0)); - - CompetitionResponse response = careerService.createCompetition(member, reqDto); - - assertNotNull(response); - assertEquals("공모전", response.getName()); - verify(competitionRepository).save(any(Competition.class)); - verify(recordUpdateManager).updateRecordTimestamp(mockRecord); - } - - @Test - @DisplayName("[CreateCareer] EduCareer를 생성하면 저장되고 Record의 타임스탬프가 갱신되어야 한다.") - void createEduCareer_shouldSaveEduCareerAndUpdateRecord() { - Member member = Member.builder().id(1L).build(); - EduCareerReqDto reqDto = EduCareerReqDto.builder() - .name("교육 이력") - .unknown(false) - .enddate(LocalDate.of(2022, 5, 15)) - .time(120) - .build(); - - Record mockRecord = Record.builder().memberId(member.getId()).build(); - - when(recordRepository.findByMemberId(member.getId())).thenReturn(mockRecord); - when(eduCareerRepository.save(any(EduCareer.class))).thenAnswer(invocation -> invocation.getArgument(0)); - - EduCareerResponse response = careerService.crateEduCareer(member, reqDto); - - assertNotNull(response); - assertEquals("교육 이력", response.getName()); - verify(eduCareerRepository).save(any(EduCareer.class)); - verify(recordUpdateManager).updateRecordTimestamp(mockRecord); - } - - @Test - @DisplayName("[CreateCareer] Employment를 생성하면 저장되고 Record의 타임스탬프가 갱신되어야 한다.") - void createEmployment_shouldSaveEmploymentAndUpdateRecord() { - Member member = Member.builder().id(1L).build(); - EmploymentReqDto reqDto = EmploymentReqDto.builder() - .name("직장").unknown(false) - .enddate(LocalDate.of(2021, 8, 1)).build(); - Record mockRecord = Record.builder().memberId(member.getId()).build(); - - when(recordRepository.findByMemberId(member.getId())).thenReturn(mockRecord); - when(employmentRepository.save(any(Employment.class))).thenAnswer(invocation -> invocation.getArgument(0)); - - EmploymentResponse response = careerService.createEmployment(member, reqDto); - - assertNotNull(response); - assertEquals("직장", response.getName()); - verify(employmentRepository).save(any(Employment.class)); - verify(recordUpdateManager).updateRecordTimestamp(mockRecord); - } - - @Test - @DisplayName("[CreateCareer] Project를 생성하면 저장되고 Record의 타임스탬프가 갱신되어야 한다.") - void createProject_shouldSaveProjectAndUpdateRecord() { - Member member = Member.builder().id(1L).build(); - ProjectReqDto reqDto = ProjectReqDto.builder() - .name("사이드 프로젝트").unknown(false) - .enddate(LocalDate.of(2024, 12, 1)).build(); - Record mockRecord = Record.builder().memberId(member.getId()).build(); - - when(recordRepository.findByMemberId(member.getId())).thenReturn(mockRecord); - when(projectRepository.save(any(Project.class))).thenAnswer(invocation -> invocation.getArgument(0)); - - ProjectResponse response = careerService.createProject(member, reqDto); - - assertNotNull(response); - assertEquals("사이드 프로젝트", response.getName()); - verify(projectRepository).save(any(Project.class)); - verify(recordUpdateManager).updateRecordTimestamp(mockRecord); - } - - @Test - @DisplayName("[CreateCareer] Etc를 생성하면 저장되고 Record의 타임스탬프가 갱신되어야 한다.") - void createEtc_shouldSaveEtcAndUpdateRecord() { - Member member = Member.builder().id(1L).build(); - EtcReqDto reqDto = EtcReqDto.builder() - .name("기타 활동").unknown(false) - .enddate(LocalDate.of(2020, 2, 2)).build(); - Record mockRecord = Record.builder().memberId(member.getId()).build(); - - when(recordRepository.findByMemberId(member.getId())).thenReturn(mockRecord); - when(etcRepository.save(any(CareerEtc.class))).thenAnswer(invocation -> invocation.getArgument(0)); - - EtcResponse response = careerService.createEtc(member, reqDto); - - assertNotNull(response); - assertEquals("기타 활동", response.getName()); - verify(etcRepository).save(any(CareerEtc.class)); - verify(recordUpdateManager).updateRecordTimestamp(mockRecord); - } - - @Test - @DisplayName("[DeleteCareer] Activity를 삭제하면 Repository에서 제거되고 Record의 타임스탬프가 갱신되어야 한다.") - void deleteActivity_shouldRemoveActivityAndUpdateRecord() { - // given - Long memberId = 1L; - Long activityId = 100L; - - Member member = Member.builder().id(memberId).build(); - Activity activity = Activity.builder().memberId(memberId).build(); - setId(activity, activityId); - Record mockRecord = Record.builder().memberId(memberId).build(); - - when(activityRepository.findById(activityId)).thenReturn(Optional.of(activity)); - when(recordRepository.findByMemberId(memberId)).thenReturn(mockRecord); - - // when - careerService.deleteActivity(member, activityId); - - // then - verify(activityRepository).delete(activity); - verify(recordUpdateManager).updateRecordTimestamp(mockRecord); - } - - @Test - @DisplayName("[DeleteCareer] Circle을 삭제하면 Repository에서 제거되고 Record의 타임스탬프가 갱신되어야 한다.") - void deleteCircle_shouldRemoveCircleAndUpdateRecord() { - // given - Long memberId = 1L; - Long circleId = 101L; - - Member member = Member.builder().id(memberId).build(); - Circle circle = Circle.builder().memberId(memberId).build(); - setId(circle, circleId); - Record record = Record.builder().memberId(memberId).build(); - - when(circleRepository.findById(circleId)).thenReturn(Optional.of(circle)); - when(recordRepository.findByMemberId(memberId)).thenReturn(record); - - // when - careerService.deleteCircle(member, circleId); - - // then - verify(circleRepository).delete(circle); - verify(recordUpdateManager).updateRecordTimestamp(record); - } - - @Test - @DisplayName("[DeleteCareer] Competition을 삭제하면 Repository에서 제거되고 Record의 타임스탬프가 갱신되어야 한다.") - void deleteCompetition_shouldRemoveCompetitionAndUpdateRecord() { - // given - Long memberId = 1L; - Long compId = 102L; - - Member member = Member.builder().id(memberId).build(); - Competition competition = Competition.builder().memberId(memberId).build(); - setId(competition, compId); - Record record = Record.builder().memberId(memberId).build(); - - when(competitionRepository.findById(compId)).thenReturn(Optional.of(competition)); - when(recordRepository.findByMemberId(memberId)).thenReturn(record); - - // when - careerService.deleteComp(member, compId); - - // then - verify(competitionRepository).delete(competition); - verify(recordUpdateManager).updateRecordTimestamp(record); - } - - @Test - @DisplayName("[DeleteCareer] EduCareer를 삭제하면 Repository에서 제거되고 Record의 타임스탬프가 갱신되어야 한다.") - void deleteEduCareer_shouldRemoveEduCareerAndUpdateRecord() { - // given - Long memberId = 1L; - Long eduId = 103L; - - Member member = Member.builder().id(memberId).build(); - EduCareer edu = EduCareer.builder().memberId(memberId).build(); - setId(edu, eduId); - Record record = Record.builder().memberId(memberId).build(); - - when(eduCareerRepository.findById(eduId)).thenReturn(Optional.of(edu)); - when(recordRepository.findByMemberId(memberId)).thenReturn(record); - - // when - careerService.deleteEdu(member, eduId); - - // then - verify(eduCareerRepository).delete(edu); - verify(recordUpdateManager).updateRecordTimestamp(record); - } - - @Test - @DisplayName("[DeleteCareer] Employment를 삭제하면 Repository에서 제거되고 Record의 타임스탬프가 갱신되어야 한다.") - void deleteEmployment_shouldRemoveEmploymentAndUpdateRecord() { - // given - Long memberId = 1L; - Long empId = 104L; - - Member member = Member.builder().id(memberId).build(); - Employment emp = Employment.builder().memberId(memberId).build(); - setId(emp, empId); - Record record = Record.builder().memberId(memberId).build(); - - when(employmentRepository.findById(empId)).thenReturn(Optional.of(emp)); - when(recordRepository.findByMemberId(memberId)).thenReturn(record); - - // when - careerService.deleteEmp(member, empId); - - // then - verify(employmentRepository).delete(emp); - verify(recordUpdateManager).updateRecordTimestamp(record); - } - - @Test - @DisplayName("[DeleteCareer] Project를 삭제하면 Repository에서 제거되고 Record의 타임스탬프가 갱신되어야 한다.") - void deleteProject_shouldRemoveProjectAndUpdateRecord() { - // given - Long memberId = 1L; - Long projectId = 105L; - - Member member = Member.builder().id(memberId).build(); - Project project = Project.builder().memberId(memberId).build(); - setId(project, projectId); - Record record = Record.builder().memberId(memberId).build(); - - when(projectRepository.findById(projectId)).thenReturn(Optional.of(project)); - when(recordRepository.findByMemberId(memberId)).thenReturn(record); - - // when - careerService.deleteProject(member, projectId); - - // then - verify(projectRepository).delete(project); - verify(recordUpdateManager).updateRecordTimestamp(record); - } - - @Test - @DisplayName("[DeleteCareer] Etc를 삭제하면 Repository에서 제거되고 Record의 타임스탬프가 갱신되어야 한다.") - void deleteEtc_shouldRemoveEtcAndUpdateRecord() { - // given - Long memberId = 1L; - Long etcId = 106L; - - Member member = Member.builder().id(memberId).build(); - CareerEtc etc = CareerEtc.builder().memberId(memberId).build(); - setId(etc, etcId); - Record record = Record.builder().memberId(memberId).build(); - - when(etcRepository.findById(etcId)).thenReturn(Optional.of(etc)); - when(recordRepository.findByMemberId(memberId)).thenReturn(record); - - // when - careerService.deleteEtc(member, etcId); - - // then - verify(etcRepository).delete(etc); - verify(recordUpdateManager).updateRecordTimestamp(record); - } - - private void setId(Object entity, Long id) { - try { - Field field = entity.getClass().getDeclaredField("id"); - field.setAccessible(true); - field.set(entity, id); - } catch (Exception e) { - throw new RuntimeException("ID 주입 실패", e); - } - } - - -} - From 319ca739bfc96152cfedf9f98b74fc928a7d6506 Mon Sep 17 00:00:00 2001 From: hyeonda02 Date: Tue, 26 Aug 2025 15:53:38 +0900 Subject: [PATCH 3/3] =?UTF-8?q?Feat=20:=20=ED=8A=B9=EC=A0=95=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9E=90=EC=9D=98=20=ED=99=9C=EB=8F=99=20=EA=B8=B0?= =?UTF-8?q?=EB=A1=9D=EC=97=90=EC=84=9C=20=EB=A7=8E=EC=9D=B4=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EB=90=9C=20=ED=83=9C=EA=B7=B8=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/career/controller/CareerSearchController.java | 8 +++----- .../kkijuk/server/career/service/CareerSearchService.java | 2 +- .../server/career/service/CareerSearchServiceImpl.java | 4 ++-- .../kkijuk/server/tag/repository/TagJpaRepository.java | 5 ++--- .../umc/kkijuk/server/tag/repository/TagRepository.java | 2 +- .../kkijuk/server/tag/repository/TagRepositoryImpl.java | 4 ++-- 6 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/main/java/umc/kkijuk/server/career/controller/CareerSearchController.java b/src/main/java/umc/kkijuk/server/career/controller/CareerSearchController.java index a263ee19..a60e327d 100644 --- a/src/main/java/umc/kkijuk/server/career/controller/CareerSearchController.java +++ b/src/main/java/umc/kkijuk/server/career/controller/CareerSearchController.java @@ -96,16 +96,14 @@ public CareerResponse findTag( @GetMapping("/find/taglist/count") @Operation( summary = "활동 검색 - 태그 ( 사용량이 많은 태그 순으로 조회 )", - description = "검색어를 포함하는 활동 태그들을 사용량 순으로 조회합니다. " + - "query 값으로 검색어(keyword)를 요청해주세요. " ) + description = "특정 사용자의 활동 태그들을 사용량 순으로 조회합니다. ") public CareerResponse> findTagWithCount( - @RequestHeader("Authorization") String token, - @RequestParam(name="keyword")String keyword + @RequestHeader("Authorization") String token ) { Member requestMember = loginUser.extractMemberId(token); return CareerResponse.success( CareerResponseMessage.CAREER_SEARCH_SUCCESS, - careerSearchService.findAllTagWithCount(requestMember, keyword) + careerSearchService.findAllTagWithCount(requestMember) ); } diff --git a/src/main/java/umc/kkijuk/server/career/service/CareerSearchService.java b/src/main/java/umc/kkijuk/server/career/service/CareerSearchService.java index 6e2dde23..834bb099 100644 --- a/src/main/java/umc/kkijuk/server/career/service/CareerSearchService.java +++ b/src/main/java/umc/kkijuk/server/career/service/CareerSearchService.java @@ -24,5 +24,5 @@ public interface CareerSearchService { List findCareerForNewDetail(Member requestMember); - List findAllTagWithCount(Member requestMember, String keyword); + List findAllTagWithCount(Member requestMember); } diff --git a/src/main/java/umc/kkijuk/server/career/service/CareerSearchServiceImpl.java b/src/main/java/umc/kkijuk/server/career/service/CareerSearchServiceImpl.java index 36271f0a..0dfc3c27 100644 --- a/src/main/java/umc/kkijuk/server/career/service/CareerSearchServiceImpl.java +++ b/src/main/java/umc/kkijuk/server/career/service/CareerSearchServiceImpl.java @@ -338,8 +338,8 @@ public List findCareerForNewDetail(Member requestMember) { } @Override - public List findAllTagWithCount(Member requestMember, String keyword) { - List tags = tagRepository.findPopularTagsByMemberAndKeyword(requestMember.getId(),keyword, PageRequest.of(0, 10)); + public List findAllTagWithCount(Member requestMember) { + List tags = tagRepository.findTopPopularTagsByMember(requestMember.getId(), PageRequest.of(0, 10)); return tags; } diff --git a/src/main/java/umc/kkijuk/server/tag/repository/TagJpaRepository.java b/src/main/java/umc/kkijuk/server/tag/repository/TagJpaRepository.java index 914c7df5..619a9ba2 100644 --- a/src/main/java/umc/kkijuk/server/tag/repository/TagJpaRepository.java +++ b/src/main/java/umc/kkijuk/server/tag/repository/TagJpaRepository.java @@ -29,16 +29,15 @@ t.id, t.name, count(cdt.id) left join CareerDetailTag cdt on cdt.tag = t left join cdt.baseCareerDetail bcd where t.memberId = :memberId - and t.name like concat('%', :keyword, '%') and (bcd is null or bcd.memberId = :memberId) group by t.id, t.name order by count(cdt.id) desc, t.name asc """) - List findPopularTagsByMemberAndKeyword( + List findTopPopularTagsByMember( @Param("memberId") Long memberId, - @Param("keyword") String keyword, Pageable pageable ); + } diff --git a/src/main/java/umc/kkijuk/server/tag/repository/TagRepository.java b/src/main/java/umc/kkijuk/server/tag/repository/TagRepository.java index 5afb8a13..32d09561 100644 --- a/src/main/java/umc/kkijuk/server/tag/repository/TagRepository.java +++ b/src/main/java/umc/kkijuk/server/tag/repository/TagRepository.java @@ -19,5 +19,5 @@ public interface TagRepository { void delete(Tag deleteTag); List findByKeywordAndMemberId(String keyword, Long id); - List findPopularTagsByMemberAndKeyword(Long memberId, String keyword, Pageable pageable); + List findTopPopularTagsByMember(Long memberId, Pageable pageable); } diff --git a/src/main/java/umc/kkijuk/server/tag/repository/TagRepositoryImpl.java b/src/main/java/umc/kkijuk/server/tag/repository/TagRepositoryImpl.java index caef0ba6..301aa1f3 100644 --- a/src/main/java/umc/kkijuk/server/tag/repository/TagRepositoryImpl.java +++ b/src/main/java/umc/kkijuk/server/tag/repository/TagRepositoryImpl.java @@ -46,7 +46,7 @@ public List findByKeywordAndMemberId(String keyword, Long id) { } @Override - public List findPopularTagsByMemberAndKeyword(Long memberId, String keyword, Pageable pageable) { - return tagJpaRepository.findPopularTagsByMemberAndKeyword(memberId, keyword, pageable); + public List findTopPopularTagsByMember(Long memberId, Pageable pageable) { + return tagJpaRepository.findTopPopularTagsByMember(memberId, pageable); } }