Merge remote-tracking branch 'upstream/develop' into develop

pull/872/head
weihu 3 years ago
commit 12b2397a68

2
.gitignore vendored

@ -39,4 +39,4 @@ build/
### Docs ### ### Docs ###
docs/node_modules docs/node_modules
docs/build docs/build
docs/.docusaurus docs/.docusaurus

@ -0,0 +1,56 @@
<img align="center" width="400" alt="image" src="https://user-images.githubusercontent.com/77398366/181906454-b46f6a14-7c2c-4b8f-8b0a-40432521bed8.png">
# Dynamic and observable thread pool framework
[![Gitee](https://gitee.com/itmachen/hippo4j/badge/star.svg?theme=gvp)](https://gitee.com/itmachen/hippo4j) [![GitHub](https://img.shields.io/github/stars/opengoofy/hippo4j)](https://github.com/opengoofy/hippo4j) [![Docker Pulls](https://img.shields.io/docker/pulls/hippo4j/hippo4j-server.svg)](https://store.docker.com/community/images/hippo4j/hippo4j-server) [![Contributors](https://img.shields.io/github/contributors/opengoofy/hippo4j?color=3ba272)](https://github.com/opengoofy/hippo4j/graphs/contributors) [![License](https://img.shields.io/github/license/opengoofy/hippo4j?color=5470c6)](https://github.com/opengoofy/hippo4j/blob/develop/LICENSE)
-------
## Thread pool pain points
A thread pool is a tool for managing threads based on the idea of pooling.
Using a thread pool reduces the overhead of creating and destroying threads and avoids running out of system resources due to too many threads.
The use of thread pools is essential in highly concurrent and high-volume task processing scenarios.
If you have actually used thread pools in your projects, I believe you may have encountered the following pain points:
- Thread pools are defined randomly, with too many thread resources, causing high server load.
- The thread pool parameters are not easily evaluated and the business is at risk of failure.
- Thread pool task execution time exceeds the average execution cycle and developers are not informed.
- Thread pool tasks pile up and affect business operations.
- Wireless process pool monitoring when the service has timeouts, meltdowns, and other problems.
- Thread pools do not support the passing of runtime variables, such as MDC contexts.
- When a project is closed, a large number of running thread pool tasks are discarded.
- Thread pool running, task execution stopped, don't know the problem.
## What is Hippo-4J
Hippo-4J through the JDK thread pool enhancements, as well as extending the three-party framework underlying thread pools and other features for business systems to improve online operational security capabilities.
The following functional support is provided:
- Global Control - Managing Application Thread Pool Instances.
- Dynamic changes - dynamically changing thread pool parameters at application runtime.
- Notify alarms - Four built-in alarm notification policies.
- Run Monitoring - Real-time view of thread pool runtime data.
- Feature extensions - support for thread pooling task passing contexts, etc.
- Multiple Modes - Two built-in usage modes: Configuration Center Mode and No Middleware Mode.
- Container Management - Tomcat, Jetty, Undertow container thread pool runtime view and thread count changes.
- Framework adaptation - Dubbo, Hystrix, Polaris, RabbitMQ, RocketMQ and other consumer thread pool runtime data view and thread count changes.
## Quick Start
For local presentation purposes, see [Quick start](https://hippo4j.cn/docs/user_docs/user_guide/quick-start).
Demo Environment: [http://console.hippo4j.cn/index.html](http://console.hippo4j.cn/index.html).
## Who is using
More companies with access are welcome to register at [registration address](https://github.com/opengoofy/hippo4j/issues/13), registration is only for product promotion.
## Contributors
Thanks to all the developers who contributed to the project. If interested in contributing, refer to [good first issue](https://github.com/opengoofy/hippo4j/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22).

@ -1,5 +1,7 @@
<img align="center" width="400" alt="image" src="https://user-images.githubusercontent.com/77398366/181906454-b46f6a14-7c2c-4b8f-8b0a-40432521bed8.png"> <img align="center" width="400" alt="image" src="https://user-images.githubusercontent.com/77398366/181906454-b46f6a14-7c2c-4b8f-8b0a-40432521bed8.png">
中文 | [English](https://github.com/opengoofy/hippo4j/blob/develop/README-EN.md)
# 动态可观测线程池框架,提高线上运行保障能力 # 动态可观测线程池框架,提高线上运行保障能力
[![Gitee](https://gitee.com/itmachen/hippo4j/badge/star.svg?theme=gvp)](https://gitee.com/itmachen/hippo4j) [![GitHub](https://img.shields.io/github/stars/opengoofy/hippo4j)](https://github.com/opengoofy/hippo4j) [![Docker Pulls](https://img.shields.io/docker/pulls/hippo4j/hippo4j-server.svg)](https://store.docker.com/community/images/hippo4j/hippo4j-server) [![Contributors](https://img.shields.io/github/contributors/opengoofy/hippo4j?color=3ba272)](https://github.com/opengoofy/hippo4j/graphs/contributors) [![License](https://img.shields.io/github/license/opengoofy/hippo4j?color=5470c6)](https://github.com/opengoofy/hippo4j/blob/develop/LICENSE) [![Gitee](https://gitee.com/itmachen/hippo4j/badge/star.svg?theme=gvp)](https://gitee.com/itmachen/hippo4j) [![GitHub](https://img.shields.io/github/stars/opengoofy/hippo4j)](https://github.com/opengoofy/hippo4j) [![Docker Pulls](https://img.shields.io/docker/pulls/hippo4j/hippo4j-server.svg)](https://store.docker.com/community/images/hippo4j/hippo4j-server) [![Contributors](https://img.shields.io/github/contributors/opengoofy/hippo4j?color=3ba272)](https://github.com/opengoofy/hippo4j/graphs/contributors) [![License](https://img.shields.io/github/license/opengoofy/hippo4j?color=5470c6)](https://github.com/opengoofy/hippo4j/blob/develop/LICENSE)
@ -36,7 +38,7 @@ Hippo-4J 通过对 JDK 线程池增强,以及扩展三方框架底层线程池
- 功能扩展 - 支持线程池任务传递上下文;项目关闭时,支持等待线程池在指定时间内完成任务。 - 功能扩展 - 支持线程池任务传递上下文;项目关闭时,支持等待线程池在指定时间内完成任务。
- 多种模式 - 内置两种使用模式:[依赖配置中心](https://hippo4j.cn/docs/user_docs/getting_started/config/hippo4j-config-start) 和 [无中间件依赖](https://hippo4j.cn/docs/user_docs/getting_started/server/hippo4j-server-start)。 - 多种模式 - 内置两种使用模式:[依赖配置中心](https://hippo4j.cn/docs/user_docs/getting_started/config/hippo4j-config-start) 和 [无中间件依赖](https://hippo4j.cn/docs/user_docs/getting_started/server/hippo4j-server-start)。
- 容器管理 - Tomcat、Jetty、Undertow 容器线程池运行时查看和线程数变更。 - 容器管理 - Tomcat、Jetty、Undertow 容器线程池运行时查看和线程数变更。
- 中间件适配 - Dubbo、Hystrix、Polaris、RabbitMQ、RocketMQ 等消费线程池运行时数据查看和线程数变更。 - 框架适配 - Dubbo、Hystrix、RabbitMQ、RocketMQ 等消费线程池运行时数据查看和线程数变更。
## 快速开始 ## 快速开始

@ -21,7 +21,7 @@ docker run -d -p 6691:6691 --name hippo4j-server \
-e DATASOURCE_DB=hippo4j_manager \ -e DATASOURCE_DB=hippo4j_manager \
-e DATASOURCE_USERNAME=root \ -e DATASOURCE_USERNAME=root \
-e DATASOURCE_PASSWORD=root \ -e DATASOURCE_PASSWORD=root \
hippo4j/hippo4j-server hippo4j/hippo4j-server
``` ```
访问 Server 控制台,路径 `http://localhost:6691/index.html` 默认用户名密码admin / 123456 访问 Server 控制台,路径 `http://localhost:6691/index.html` 默认用户名密码admin / 123456
@ -33,10 +33,10 @@ hippo4j/hippo4j-server
方式一: 方式一:
```shell ```shell
# 进入到 hippo4j-server 工程路径下 # 进入到 hippo4j-server/hippo4j-bootstrap 工程路径下
mvn clean package -Dskip.spotless.apply=true mvn clean package -Dskip.spotless.apply=true
# 默认打包是打包的 tag 是 latest # 默认打包是打包的 tag 是 latest
docker build -t hippo4j/hippo4j-server ../hippo4j-server docker build -t hippo4j/hippo4j-server ../hippo4j-bootstrap
``` ```
方式二: 方式二:

@ -1,40 +1 @@
--- --- sidebar_position: 3 --- # 快速开始 ## 服务启动 使用 Docker 运行服务端,默认使用内置 H2 数据库,数据持久化到 Docker 容器存储卷中。 ```shell docker run -d -p 6691:6691 --name hippo4j-server hippo4j/hippo4j-server ``` > 如果没有 Docker可以使用源码编译的方式启动 [Hippo4J-Server/Hippo4J-Bootstrap](https://github.com/longtai-cn/hippo4j/tree/develop/hippo4j-server/hippo4j-bootstrap) 模块下 ServerApplication 应用类。 启动示例项目,[hippo4j-spring-boot-starter-example](https://github.com/opengoofy/hippo4j/tree/develop/hippo4j-example/hippo4j-spring-boot-starter-example) 模块下 Hippo4JServerExampleApplication 应用类。 访问 Server 控制台,路径 `http://localhost:6691/index.html`默认用户名密码admin / 123456 ## 配置变更 访问控制台动态线程池菜单下线程池实例,修改动态线程池相关参数。 ![](https://images-machen.oss-cn-beijing.aliyuncs.com/image-20220813173811668.png) 观察 Hippo4j-Example 控制台日志输出,日志输出包括不限于此信息即为成功。 ```tex 2022-09-10 00:23:29.783 INFO 50322 --- [change.config_0] c.h.s.s.c.ServerThreadPoolDynamicRefresh : [message-consume] Dynamic thread pool change parameter. corePoolSize: 2 => 4 maximumPoolSize: 6 => 12 capacity: 1024 => 2048 keepAliveTime: 9999 => 9999 executeTimeOut: 800 => 3000 rejectedType: SyncPutQueuePolicy => RunsOldestTaskPolicy allowCoreThreadTimeOut: true => true ``` 另外,当 Client 集群部署时,可以修改某一个实例,或选择 `全部修改` 按钮,修改所有实例线程池信息。
sidebar_position: 3
---
# 快速开始
## 服务启动
使用 Docker 运行服务端,默认使用内置 H2 数据库,数据持久化到 Docker 容器存储卷中。
```shell
docker run -d -p 6691:6691 --name hippo4j-server hippo4j/hippo4j-server
```
> 如果没有 Docker可以使用源码编译的方式启动 [Hippo4J-Server](https://github.com/longtai-cn/hippo4j/tree/develop/hippo4j-server) 模块下 ServerApplication 应用类。
启动示例项目,[hippo4j-spring-boot-starter-example](https://github.com/opengoofy/hippo4j/tree/develop/hippo4j-example/hippo4j-spring-boot-starter-example) 模块下 Hippo4JServerExampleApplication 应用类。
访问 Server 控制台,路径 `http://localhost:6691/index.html`默认用户名密码admin / 123456
## 配置变更
访问控制台动态线程池菜单下线程池实例,修改动态线程池相关参数。
![](https://images-machen.oss-cn-beijing.aliyuncs.com/image-20220813173811668.png)
观察 Hippo4j-Example 控制台日志输出,日志输出包括不限于此信息即为成功。
```tex
2022-09-10 00:23:29.783 INFO 50322 --- [change.config_0] c.h.s.s.c.ServerThreadPoolDynamicRefresh : [message-consume] Dynamic thread pool change parameter.
corePoolSize: 2 => 4
maximumPoolSize: 6 => 12
capacity: 1024 => 2048
keepAliveTime: 9999 => 9999
executeTimeOut: 800 => 3000
rejectedType: SyncPutQueuePolicy => RunsOldestTaskPolicy
allowCoreThreadTimeOut: true => true
```
另外,当 Client 集群部署时,可以修改某一个实例,或选择 `全部修改` 按钮,修改所有实例线程池信息。

@ -17,30 +17,39 @@
package cn.hippo4j.common.enums; package cn.hippo4j.common.enums;
/**
* Enumeration of thread pool audit status.
*/
public enum VerifyEnum { public enum VerifyEnum {
/** /**
* unVerify * To verify
*/ */
TO_VERIFY(0, "待审核"), TO_VERIFY(0, "待审核"),
/** /**
* accept * Verify accept
*/ */
VERIFY_ACCEPT(1, "审核通过"), VERIFY_ACCEPT(1, "审核通过"),
/** /**
* reject * Verify reject
*/ */
VERIFY_REJECT(2, "审核拒绝"), VERIFY_REJECT(2, "审核拒绝"),
/** /**
* invalid * Verify invalid
*/ */
VERIFY_INVALID(3, "失效"); VERIFY_INVALID(3, "失效");
/**
* Verify status
*/
private final Integer verifyStatus; private final Integer verifyStatus;
/**
* Desc
*/
private final String desc; private final String desc;
VerifyEnum(Integer verifyStatus, String desc) { VerifyEnum(Integer verifyStatus, String desc) {

File diff suppressed because one or more lines are too long

@ -1 +0,0 @@
.editor-container[data-v-7505e034]{height:82vh;overflow:auto}

File diff suppressed because one or more lines are too long

@ -1,893 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="216"
height="144"
id="svg4136"
version="1.1"
inkscape:version="0.91 r"
sodipodi:docname="jsoneditor-icons.svg">
<title
id="title6512">JSON Editor Icons</title>
<metadata
id="metadata4148">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title>JSON Editor Icons</dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs4146" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1028"
id="namedview4144"
showgrid="true"
inkscape:zoom="4"
inkscape:cx="97.217248"
inkscape:cy="59.950227"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg4136"
showguides="false"
borderlayer="false"
inkscape:showpageshadow="true"
showborder="true">
<inkscape:grid
type="xygrid"
id="grid4640"
empspacing="24" />
</sodipodi:namedview>
<!-- Created with SVG-edit - http://svg-edit.googlecode.com/ -->
<g
id="g4394">
<rect
x="4"
y="4"
width="16"
height="16"
id="svg_1"
style="fill:#1aae1c;fill-opacity:1;stroke:none;stroke-width:0" />
<rect
style="fill:#ec3f29;fill-opacity:0.94117647;stroke:none;stroke-width:0"
x="28.000006"
y="3.999995"
width="16"
height="16"
id="svg_1-7" />
<rect
id="rect4165"
height="16"
width="16"
y="3.999995"
x="52.000004"
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0" />
<rect
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0"
x="172.00002"
y="3.9999852"
width="16"
height="16"
id="rect4175" />
<rect
style="fill:#4c4c4c;fill-opacity:1;stroke:none;stroke-width:0"
x="196"
y="3.999995"
width="16"
height="16"
id="rect4175-3" />
<g
style="stroke:none"
id="g4299">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="svg_1-1"
height="1.9999986"
width="9.9999924"
y="10.999998"
x="7.0000048" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="svg_1-1-1"
height="9.9999838"
width="1.9999955"
y="7.0000114"
x="11.000005" />
</g>
<g
style="stroke:none"
transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,19.029435,12.000001)"
id="g4299-3">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="svg_1-1-0"
height="1.9999986"
width="9.9999924"
y="10.999998"
x="7.0000048" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="svg_1-1-1-9"
height="9.9999838"
width="1.9999955"
y="7.0000114"
x="11.000005" />
</g>
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="55.000004"
y="7.0000048"
width="6.9999909"
height="6.9999905"
id="svg_1-7-5" />
<rect
id="rect4354"
height="6.9999905"
width="6.9999909"
y="10.00001"
x="58"
style="fill:#ffffff;fill-opacity:1;stroke:#4c4c4c;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#3c80df;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.94117647"
x="58.000004"
y="10.000005"
width="6.9999909"
height="6.9999905"
id="svg_1-7-5-7" />
<g
id="g4378">
<rect
id="svg_1-7-5-3"
height="1.9999965"
width="7.9999909"
y="10.999999"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="7.0000005"
width="11.999995"
height="1.9999946"
id="rect4374" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="14.999996"
width="3.9999928"
height="1.9999995"
id="rect4376" />
</g>
<g
id="g4383"
transform="matrix(1,0,0,-1,-23.999995,23.999995)">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="10.999999"
width="7.9999909"
height="1.9999965"
id="rect4385" />
<rect
id="rect4387"
height="1.9999946"
width="11.999995"
y="7.0000005"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
id="rect4389"
height="1.9999995"
width="3.9999928"
y="14.999996"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
</g>
<rect
y="3.9999199"
x="76"
height="16"
width="16"
id="rect3754-4"
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
<path
sodipodi:nodetypes="cccccccc"
inkscape:connector-curvature="0"
id="path4351"
d="m 85.10447,6.0157384 -0.0156,1.4063 c 3.02669,-0.2402 0.33008,3.6507996 2.48438,4.5780996 -2.18694,1.0938 0.49191,4.9069 -2.45313,4.5781 l -0.0156,1.4219 c 5.70828,0.559 1.03264,-5.1005 4.70313,-5.2656 l 0,-1.4063 c -3.61303,-0.027 1.11893,-5.7069996 -4.70313,-5.3124996 z"
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="cccccccc"
inkscape:connector-curvature="0"
id="path4351-9"
d="m 82.78125,5.9984384 0.0156,1.4063 c -3.02668,-0.2402 -0.33007,3.6506996 -2.48437,4.5780996 2.18694,1.0938 -0.49192,4.9069 2.45312,4.5781 l 0.0156,1.4219 c -5.70827,0.559 -1.03263,-5.1004 -4.70312,-5.2656 l 0,-1.4063 c 3.61303,-0.027 -1.11894,-5.7070996 4.70312,-5.3124996 z"
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
y="3.9999199"
x="100"
height="16"
width="16"
id="rect3754-25"
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
<path
inkscape:connector-curvature="0"
id="path2987"
d="m 103.719,5.6719384 0,12.7187996 3.03125,0 0,-1.5313 -1.34375,0 0,-9.6249996 1.375,0 0,-1.5625 z"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
<path
inkscape:connector-curvature="0"
id="path2987-1"
d="m 112.2185,5.6721984 0,12.7187996 -3.03125,0 0,-1.5313 1.34375,0 0,-9.6249996 -1.375,0 0,-1.5625 z"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
<rect
y="3.9999199"
x="124"
height="16"
width="16"
id="rect3754-73"
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
<path
sodipodi:nodetypes="ccccccccc"
inkscape:connector-curvature="0"
id="path3780"
d="m 126.2824,17.602938 1.78957,0 1.14143,-2.8641 5.65364,0 1.14856,2.8641 1.76565,0 -4.78687,-11.1610996 -1.91903,0 z"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
<path
inkscape:connector-curvature="0"
id="path3782"
d="m 129.72704,13.478838 4.60852,0.01 -2.30426,-5.5497996 z"
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
<rect
y="3.9999199"
x="148"
height="16"
width="16"
id="rect3754-35"
style="fill:#4c4c4c;fill-opacity:1;stroke:none" />
<path
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0"
id="path5008-2"
d="m 156.47655,5.8917384 0,2.1797 0.46093,2.3983996 1.82813,0 0.39844,-2.3983996 0,-2.1797 z"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
<path
sodipodi:nodetypes="ccccccc"
inkscape:connector-curvature="0"
id="path5008-2-8"
d="m 152.51561,5.8906384 0,2.1797 0.46094,2.3983996 1.82812,0 0.39844,-2.3983996 0,-2.1797 z"
style="fill:#ffffff;fill-opacity:1;stroke:none" />
</g>
<rect
x="4"
y="27.999994"
width="16"
height="16"
id="rect4432"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0"
x="28.000006"
y="27.99999"
width="16"
height="16"
id="rect4434" />
<rect
id="rect4436"
height="16"
width="16"
y="27.99999"
x="52.000004"
style="fill:#d3d3d3;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
style="fill:#d3d3d3;stroke:#000000;stroke-width:0"
x="172.00002"
y="27.999981"
width="16"
height="16"
id="rect4446" />
<rect
style="fill:#d3d3d3;stroke:#000000;stroke-width:0"
x="196"
y="27.99999"
width="16"
height="16"
id="rect4448" />
<g
id="g4466"
style="stroke:none"
transform="translate(0,23.999995)">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="rect4468"
height="1.9999986"
width="9.9999924"
y="10.999998"
x="7.0000048" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="rect4470"
height="9.9999838"
width="1.9999955"
y="7.0000114"
x="11.000005" />
</g>
<g
transform="matrix(0.70710678,-0.70710678,0.70710678,0.70710678,19.029435,35.999996)"
id="g4472"
style="stroke:none">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="rect4474"
height="1.9999986"
width="9.9999924"
y="10.999998"
x="7.0000048" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0"
id="rect4476"
height="9.9999838"
width="1.9999955"
y="7.0000114"
x="11.000005" />
</g>
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="55.000004"
y="31"
width="6.9999909"
height="6.9999905"
id="rect4478" />
<rect
id="rect4480"
height="6.9999905"
width="6.9999909"
y="34.000008"
x="58"
style="fill:#ffffff;fill-opacity:1;stroke:#d3d3d3;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#d3d3d3;stroke-width:0;stroke-miterlimit:4;stroke-dasharray:none"
x="58.000004"
y="34.000004"
width="6.9999909"
height="6.9999905"
id="rect4482" />
<g
id="g4484"
transform="translate(0,23.999995)">
<rect
id="rect4486"
height="1.9999965"
width="7.9999909"
y="10.999999"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="7.0000005"
width="11.999995"
height="1.9999946"
id="rect4488" />
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="14.999996"
width="3.9999928"
height="1.9999995"
id="rect4490" />
</g>
<g
id="g4492"
transform="matrix(1,0,0,-1,-23.999995,47.99999)">
<rect
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0"
x="198"
y="10.999999"
width="7.9999909"
height="1.9999965"
id="rect4494" />
<rect
id="rect4496"
height="1.9999946"
width="11.999995"
y="7.0000005"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
<rect
id="rect4498"
height="1.9999995"
width="3.9999928"
y="14.999996"
x="198"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0" />
</g>
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
id="rect3754-8"
width="16"
height="16"
x="76"
y="27.99992" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 85.10448,30.015537 -0.0156,1.4063 c 3.02668,-0.2402 0.33007,3.6508 2.48438,4.5781 -2.18695,1.0938 0.49191,4.90688 -2.45313,4.57808 l -0.0156,1.4219 c 5.70827,0.559 1.03263,-5.10048 4.70313,-5.26558 l 0,-1.4063 c -3.61304,-0.027 1.11893,-5.707 -4.70313,-5.3125 z"
id="path4351-1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0.2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 82.78126,29.998237 0.0156,1.4063 c -3.02668,-0.2402 -0.33008,3.6507 -2.48438,4.5781 2.18694,1.0938 -0.49191,4.90688 2.45313,4.57808 l 0.0156,1.4219 c -5.70828,0.559 -1.03264,-5.10038 -4.70313,-5.26558 l 0,-1.4063 c 3.61303,-0.027 -1.11893,-5.7071 4.70313,-5.3125 z"
id="path4351-9-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccccccc" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
id="rect3754-65"
width="16"
height="16"
x="100"
y="27.99992" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 103.719,29.671937 0,12.71878 3.03125,0 0,-1.5313 -1.34375,0 0,-9.62498 1.375,0 0,-1.5625 z"
id="path2987-8"
inkscape:connector-curvature="0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 112.2185,29.671937 0,12.71878 -3.03125,0 0,-1.5313 1.34375,0 0,-9.62498 -1.375,0 0,-1.5625 z"
id="path2987-1-9"
inkscape:connector-curvature="0" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
id="rect3754-92"
width="16"
height="16"
x="124"
y="27.99992" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 126.2824,41.602917 1.78957,0 1.14143,-2.86408 5.65364,0 1.14856,2.86408 1.76565,0 -4.78687,-11.16108 -1.91902,0 z"
id="path3780-9"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccccc" />
<path
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
d="m 129.72704,37.478837 4.60852,0.01 -2.30426,-5.5498 z"
id="path3782-2"
inkscape:connector-curvature="0" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none"
id="rect3754-47"
width="16"
height="16"
x="148"
y="27.99992" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 156.47656,29.891737 0,2.1797 0.46093,2.3984 1.82813,0 0.39844,-2.3984 0,-2.1797 z"
id="path5008-2-1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:none"
d="m 152.51562,29.890637 0,2.1797 0.46094,2.3984 1.82812,0 0.39844,-2.3984 0,-2.1797 z"
id="path5008-2-8-8"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccccccc" />
<rect
id="svg_1-7-2"
height="1.9999961"
width="11.999996"
y="64"
x="54"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
id="svg_1-7-2-2"
height="2.9999905"
width="2.9999907"
y="52"
x="80.000008"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="85.000008"
y="52"
width="2.9999907"
height="2.9999905"
id="rect4561" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="80.000008"
y="58"
width="2.9999907"
height="2.9999905"
id="rect4563" />
<rect
id="rect4565"
height="2.9999905"
width="2.9999907"
y="58"
x="85.000008"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
id="rect4567"
height="2.9999905"
width="2.9999907"
y="64"
x="80.000008"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="85.000008"
y="64"
width="2.9999907"
height="2.9999905"
id="rect4569" />
<circle
style="opacity:1;fill:none;fill-opacity:1;stroke:#4c4c4c;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
id="path4571"
cx="110.06081"
cy="57.939209"
r="4.7438836" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="116.64566"
y="-31.79752"
width="4.229713"
height="6.4053884"
id="rect4563-2"
transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)" />
<path
style="fill:#4c4c4c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 125,56 138.77027,56.095 132,64 Z"
id="path4613"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path4615"
d="M 149,64 162.77027,63.905 156,56 Z"
style="fill:#4c4c4c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="54"
y="53"
width="11.999996"
height="1.9999961"
id="rect4638" />
<rect
id="svg_1-7-2-24"
height="1.9999957"
width="12.99999"
y="-56"
x="53"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
transform="matrix(0,1,-1,0,0,0)" />
<rect
transform="matrix(0,1,-1,0,0,0)"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0"
x="53"
y="-66"
width="12.99999"
height="1.9999957"
id="rect4657" />
<rect
id="rect4659"
height="0.99999291"
width="11.999999"
y="57"
x="54"
style="fill:#4c4c4c;fill-opacity:0.98431373;stroke:none;stroke-width:0" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="54"
y="88.000122"
width="11.999996"
height="1.9999961"
id="rect4661" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="80.000008"
y="76.000122"
width="2.9999907"
height="2.9999905"
id="rect4663" />
<rect
id="rect4665"
height="2.9999905"
width="2.9999907"
y="76.000122"
x="85.000008"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
<rect
id="rect4667"
height="2.9999905"
width="2.9999907"
y="82.000122"
x="80.000008"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="85.000008"
y="82.000122"
width="2.9999907"
height="2.9999905"
id="rect4669" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="80.000008"
y="88.000122"
width="2.9999907"
height="2.9999905"
id="rect4671" />
<rect
id="rect4673"
height="2.9999905"
width="2.9999907"
y="88.000122"
x="85.000008"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
<circle
r="4.7438836"
cy="81.939331"
cx="110.06081"
id="circle4675"
style="opacity:1;fill:none;fill-opacity:1;stroke:#d3d3d3;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<rect
transform="matrix(0.70710678,0.70710678,-0.70710678,0.70710678,0,0)"
id="rect4677"
height="6.4053884"
width="4.229713"
y="-14.826816"
x="133.6163"
style="fill:#d3d3d3;fill-opacity:1;stroke:#d3d3d3;stroke-width:0;stroke-opacity:1" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path4679"
d="m 125,80.000005 13.77027,0.09499 L 132,87.999992 Z"
style="fill:#d3d3d3;fill-opacity:1;fill-rule:evenodd;stroke:#d3d3d3;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:#d3d3d3;fill-opacity:1;fill-rule:evenodd;stroke:#d3d3d3;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 149,88.0002 162.77027,87.9052 156,80.0002 Z"
id="path4681"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<rect
id="rect4683"
height="1.9999961"
width="11.999996"
y="77.000122"
x="54"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1" />
<rect
transform="matrix(0,1,-1,0,0,0)"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="77.000122"
y="-56"
width="12.99999"
height="1.9999957"
id="rect4685" />
<rect
id="rect4687"
height="1.9999957"
width="12.99999"
y="-66"
x="77.000122"
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
transform="matrix(0,1,-1,0,0,0)" />
<rect
style="fill:#d3d3d3;fill-opacity:1;stroke:none;stroke-width:0;stroke-opacity:1"
x="54"
y="81.000122"
width="11.999999"
height="0.99999291"
id="rect4689" />
<rect
id="rect4761-1"
height="1.9999945"
width="15.99999"
y="101"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<rect
id="rect4761-0"
height="1.9999945"
width="15.99999"
y="105"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<rect
id="rect4761-7"
height="1.9999945"
width="9"
y="109"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<rect
id="rect4761-1-1"
height="1.9999945"
width="12"
y="125"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<rect
id="rect4761-1-1-4"
height="1.9999945"
width="10"
y="137"
x="76.000008"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<rect
id="rect4761-1-1-4-4"
height="1.9999945"
width="10"
y="129"
x="82"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<rect
id="rect4761-1-1-4-4-3"
height="1.9999945"
width="9"
y="133"
x="82"
style="fill:#ffffff;fill-opacity:0.80000007;stroke:none;stroke-width:0" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.8;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 36.398438,100.0254 c -0.423362,-0.013 -0.846847,0.01 -1.265626,0.062 -1.656562,0.2196 -3.244567,0.9739 -4.507812,2.2266 L 29,100.5991 l -2.324219,7.7129 7.826172,-1.9062 -1.804687,-1.9063 c 1.597702,-1.5308 4.048706,-1.8453 5.984375,-0.7207 1.971162,1.1452 2.881954,3.3975 2.308593,5.5508 -0.573361,2.1533 -2.533865,3.6953 -4.830078,3.6953 l 0,3.0742 c 3.550756,0 6.710442,-2.4113 7.650391,-5.9414 0.939949,-3.5301 -0.618463,-7.2736 -3.710938,-9.0703 -1.159678,-0.6738 -2.431087,-1.0231 -3.701171,-1.0625 z"
id="path4138" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.8;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 59.722656,99.9629 c -1.270084,0.039 -2.541493,0.3887 -3.701172,1.0625 -3.092475,1.7967 -4.650886,5.5402 -3.710937,9.0703 0.939949,3.5301 4.09768,5.9414 7.648437,5.9414 l 0,-3.0742 c -2.296214,0 -4.256717,-1.542 -4.830078,-3.6953 -0.573361,-2.1533 0.337432,-4.4056 2.308594,-5.5508 1.935731,-1.1246 4.38863,-0.8102 5.986326,0.7207 l -1.806638,1.9063 7.828128,1.9062 -2.32422,-7.7129 -1.62696,1.7168 c -1.26338,-1.2531 -2.848917,-2.0088 -4.505855,-2.2285 -0.418778,-0.055 -0.842263,-0.076 -1.265625,-0.062 z"
id="path4138-1" />
<path
inkscape:connector-curvature="0"
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.966;stroke-miterlimit:4;stroke-dasharray:none"
d="m 10.5,100 0,2 -2.4999996,0 L 12,107 l 4,-5 -2.5,0 0,-2 -3,0 z"
id="path3055-0-77" />
<path
style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1.966;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 4.9850574,108.015 14.0298856,-0.03"
id="path5244-5-0-5"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
style="opacity:0.8;fill:none;stroke:#ffffff;stroke-width:1.966;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 4.9849874,132.015 14.0298866,-0.03"
id="path5244-5-0-5-8"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.4;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 36.398438,123.9629 c -0.423362,-0.013 -0.846847,0.01 -1.265626,0.062 -1.656562,0.2196 -3.244567,0.9739 -4.507812,2.2266 L 29,124.5366 l -2.324219,7.7129 7.826172,-1.9062 -1.804687,-1.9063 c 1.597702,-1.5308 4.048706,-1.8453 5.984375,-0.7207 1.971162,1.1453 2.881954,3.3975 2.308593,5.5508 -0.573361,2.1533 -2.533864,3.6953 -4.830078,3.6953 l 0,3.0742 c 3.550757,0 6.710442,-2.4093 7.650391,-5.9394 0.939949,-3.5301 -0.618463,-7.2756 -3.710938,-9.0723 -1.159678,-0.6737 -2.431087,-1.0231 -3.701171,-1.0625 z"
id="path4138-12" />
<path
inkscape:connector-curvature="0"
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;baseline-shift:baseline;text-anchor:start;white-space:normal;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.4;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.66157866;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 59.722656,123.9629 c -1.270084,0.039 -2.541493,0.3888 -3.701172,1.0625 -3.092475,1.7967 -4.650886,5.5422 -3.710937,9.0723 0.939949,3.5301 4.09768,5.9394 7.648437,5.9394 l 0,-3.0742 c -2.296214,0 -4.256717,-1.542 -4.830078,-3.6953 -0.573361,-2.1533 0.337432,-4.4055 2.308594,-5.5508 1.935731,-1.1246 4.38863,-0.8102 5.986326,0.7207 l -1.806638,1.9063 7.828128,1.9062 -2.32422,-7.7129 -1.62696,1.7168 c -1.26338,-1.2531 -2.848917,-2.0088 -4.505855,-2.2285 -0.418778,-0.055 -0.842263,-0.076 -1.265625,-0.062 z"
id="path4138-1-3" />
<path
id="path6191"
d="m 10.5,116 0,-2 -2.4999996,0 L 12,109 l 4,5 -2.5,0 0,2 -3,0 z"
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.966;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.966;stroke-miterlimit:4;stroke-dasharray:none"
d="m 10.5,129 0,-2 -2.4999996,0 L 12,122 l 4,5 -2.5,0 0,2 -3,0 z"
id="path6193" />
<path
id="path6195"
d="m 10.5,135 0,2 -2.4999996,0 L 12,142 l 4,-5 -2.5,0 0,-2 -3,0 z"
style="opacity:0.8;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.966;stroke-miterlimit:4;stroke-dasharray:none"
inkscape:connector-curvature="0" />
<path
sodipodi:type="star"
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
id="path4500"
sodipodi:sides="3"
sodipodi:cx="11.55581"
sodipodi:cy="60.073242"
sodipodi:r1="5.1116104"
sodipodi:r2="2.5558052"
sodipodi:arg1="0"
sodipodi:arg2="1.0471976"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 16.66742,60.073242 -3.833708,2.213392 -3.8337072,2.213393 0,-4.426785 0,-4.426784 3.8337082,2.213392 z"
inkscape:transform-center-x="-1.2779026" />
<path
inkscape:transform-center-x="1.277902"
d="m -31.500004,60.073242 -3.833708,2.213392 -3.833707,2.213393 0,-4.426785 0,-4.426784 3.833707,2.213392 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="false"
sodipodi:arg2="1.0471976"
sodipodi:arg1="0"
sodipodi:r2="2.5558052"
sodipodi:r1="5.1116104"
sodipodi:cy="60.073242"
sodipodi:cx="-36.611614"
sodipodi:sides="3"
id="path4502"
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
sodipodi:type="star"
transform="scale(-1,1)" />
<path
d="m 16.66742,60.073212 -3.833708,2.213392 -3.8337072,2.213392 0,-4.426784 0,-4.426785 3.8337082,2.213392 z"
inkscape:randomized="0"
inkscape:rounded="0"
inkscape:flatsided="false"
sodipodi:arg2="1.0471976"
sodipodi:arg1="0"
sodipodi:r2="2.5558052"
sodipodi:r1="5.1116104"
sodipodi:cy="60.073212"
sodipodi:cx="11.55581"
sodipodi:sides="3"
id="path4504"
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
sodipodi:type="star"
transform="matrix(0,1,-1,0,72.0074,71.7877)"
inkscape:transform-center-y="1.2779029" />
<path
inkscape:transform-center-y="-1.2779026"
transform="matrix(0,-1,-1,0,96,96)"
sodipodi:type="star"
style="fill:#4d4d4d;fill-opacity:0.90196078;stroke:#d3d3d3;stroke-width:0;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none"
id="path4506"
sodipodi:sides="3"
sodipodi:cx="11.55581"
sodipodi:cy="60.073212"
sodipodi:r1="5.1116104"
sodipodi:r2="2.5558052"
sodipodi:arg1="0"
sodipodi:arg2="1.0471976"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 16.66742,60.073212 -3.833708,2.213392 -3.8337072,2.213392 0,-4.426784 0,-4.426785 3.8337082,2.213392 z" />
<path
sodipodi:nodetypes="cccc"
inkscape:connector-curvature="0"
id="path4615-5"
d="m 171.82574,65.174193 16.34854,0 -8.17427,-13.348454 z"
style="fill:#fbb917;fill-opacity:1;fill-rule:evenodd;stroke:#fbb917;stroke-width:1.65161395;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 179,55 0,6 2,0 0,-6"
id="path4300"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
<path
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 179,62 0,2 2,0 0,-2"
id="path4300-6"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccc" />
</svg>

Before

Width:  |  Height:  |  Size: 35 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1 +0,0 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2fd02e04"],{"64b7":function(e,t,n){"use strict";n("de5f")},ab3b:function(e,t,n){"use strict";n.r(t);var a=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"app-container"},[n("split-pane",{attrs:{split:"vertical"},on:{resize:e.resize}},[n("template",{slot:"paneL"},[n("el-input",{attrs:{type:"textarea",rows:36,placeholder:"请输入内容",clearable:""},on:{change:e.originChange},model:{value:e.originText,callback:function(t){e.originText=t},expression:"originText"}})],1),e._v(" "),n("template",{slot:"paneR"},[n("div",{staticClass:"editor-container"},[n("JSONEditor",{attrs:{json:e.formatedValue}})],1)])],2)],1)},i=[],o=n("19ab"),r=n.n(o),s=n("33c3"),c={name:"JsonFormat",components:{splitPane:r.a,JSONEditor:s["a"]},data:function(){return{originText:"",formatedValue:""}},watch:{originText:function(e){try{this.formatedValue=JSON.parse(e)}catch(t){}}},methods:{resize:function(){},originChange:function(e){}}},l=c,u=(n("64b7"),n("2877")),p=Object(u["a"])(l,a,i,!1,null,"7505e034",null);t["default"]=p.exports},de5f:function(e,t,n){}}]);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -18,7 +18,6 @@
package cn.hippo4j.example.core.inittest; package cn.hippo4j.example.core.inittest;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
@ -29,8 +28,6 @@ import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static cn.hippo4j.common.constant.Constants.EXECUTE_TIMEOUT_TRACE;
/** /**
* Run state handler test. * Run state handler test.
*/ */
@ -81,7 +78,7 @@ public class RunStateHandlerTest {
/** /**
* When the execution of the thread pool task times out, the Trace flag is put into the MDC, and it is printed out when an alarm occurs. * When the execution of the thread pool task times out, the Trace flag is put into the MDC, and it is printed out when an alarm occurs.
*/ */
MDC.put(EXECUTE_TIMEOUT_TRACE, "39948722194639841.251.16612352194691531"); // MDC.put(EXECUTE_TIMEOUT_TRACE, "39948722194639841.251.16612352194691531");
try { try {
Thread.sleep(5000); Thread.sleep(5000);
} catch (InterruptedException e) { } catch (InterruptedException e) {

@ -30,7 +30,7 @@ public interface NotifyConfigBuilder {
/** /**
* Build notify. * Build notify.
* *
* @return * @return notify info
*/ */
Map<String, List<NotifyConfigDTO>> buildNotify(); Map<String, List<NotifyConfigDTO>> buildNotify();
} }

@ -60,8 +60,8 @@ public class DingSendMessageHandler extends AbstractRobotSendMessageHandler {
RobotMessageActualContent robotMessageActualContent = RobotMessageActualContent.builder() RobotMessageActualContent robotMessageActualContent = RobotMessageActualContent.builder()
.receiveSeparator(", @") .receiveSeparator(", @")
.changeSeparator(" -> ") .changeSeparator(" -> ")
.replaceTxt(DING_ALARM_TIMOUT_REPLACE_TXT) .replaceTxt(DING_ALARM_TIMEOUT_REPLACE_TXT)
.traceReplaceTxt(DING_ALARM_TIMOUT_TRACE_REPLACE_TXT) .traceReplaceTxt(DING_ALARM_TIMEOUT_TRACE_REPLACE_TXT)
.alarmMessageContent(Singleton.get(dingAlarmTxtKey, () -> FileUtil.readUtf8String(dingAlarmTxtKey))) .alarmMessageContent(Singleton.get(dingAlarmTxtKey, () -> FileUtil.readUtf8String(dingAlarmTxtKey)))
.configMessageContent(Singleton.get(dingConfigTxtKey, () -> FileUtil.readUtf8String(dingConfigTxtKey))) .configMessageContent(Singleton.get(dingConfigTxtKey, () -> FileUtil.readUtf8String(dingConfigTxtKey)))
.build(); .build();

@ -55,66 +55,46 @@ public class LarkSendMessageHandler implements SendMessageHandler<AlarmNotifyReq
@SneakyThrows @SneakyThrows
public void sendAlarmMessage(NotifyConfigDTO notifyConfig, AlarmNotifyRequest alarmNotifyRequest) { public void sendAlarmMessage(NotifyConfigDTO notifyConfig, AlarmNotifyRequest alarmNotifyRequest) {
String afterReceives = getReceives(notifyConfig.getReceives()); String afterReceives = getReceives(notifyConfig.getReceives());
String larkAlarmTimoutReplaceTxt; String larkAlarmTimeoutReplaceTxt;
String larkAlarmTxtKey = "message/robot/dynamic-thread-pool/lark-alarm.json"; String larkAlarmTxtKey = "message/robot/dynamic-thread-pool/lark-alarm.json";
String larkAlarmTxt = Singleton.get(larkAlarmTxtKey, () -> FileUtil.readUtf8String(larkAlarmTxtKey)); String larkAlarmTxt = Singleton.get(larkAlarmTxtKey, () -> FileUtil.readUtf8String(larkAlarmTxtKey));
String larkAlarmTimoutReplaceJsonKey = "message/robot/dynamic-thread-pool/lark-alarm-timeout-replace.json"; String larkAlarmTimeoutReplaceJsonKey = "message/robot/dynamic-thread-pool/lark-alarm-timeout-replace.json";
String larkAlarmTimoutReplaceJson = Singleton.get(larkAlarmTimoutReplaceJsonKey, () -> FileUtil.readUtf8String(larkAlarmTimoutReplaceJsonKey)); String larkAlarmTimeoutReplaceJson = Singleton.get(larkAlarmTimeoutReplaceJsonKey, () -> FileUtil.readUtf8String(larkAlarmTimeoutReplaceJsonKey));
if (Objects.equals(alarmNotifyRequest.getNotifyTypeEnum(), NotifyTypeEnum.TIMEOUT)) { if (Objects.equals(alarmNotifyRequest.getNotifyTypeEnum(), NotifyTypeEnum.TIMEOUT)) {
String executeTimeoutTrace = alarmNotifyRequest.getExecuteTimeoutTrace(); String executeTimeoutTrace = alarmNotifyRequest.getExecuteTimeoutTrace();
String larkAlarmTimoutTraceReplaceJsonKey = "message/robot/dynamic-thread-pool/lark-alarm-trace-replace.json"; String larkAlarmTimoutTraceReplaceJsonKey = "message/robot/dynamic-thread-pool/lark-alarm-trace-replace.json";
String larkAlarmTimoutTraceReplaceJson = Singleton.get(larkAlarmTimoutTraceReplaceJsonKey, () -> FileUtil.readUtf8String(larkAlarmTimoutTraceReplaceJsonKey)); String larkAlarmTimoutTraceReplaceJson = Singleton.get(larkAlarmTimoutTraceReplaceJsonKey, () -> FileUtil.readUtf8String(larkAlarmTimoutTraceReplaceJsonKey));
if (StringUtil.isNotBlank(executeTimeoutTrace)) { if (StringUtil.isNotBlank(executeTimeoutTrace)) {
String larkAlarmTimoutTraceReplaceTxt = String.format(larkAlarmTimoutTraceReplaceJson, executeTimeoutTrace); String larkAlarmTimoutTraceReplaceTxt = String.format(larkAlarmTimoutTraceReplaceJson, executeTimeoutTrace);
larkAlarmTimoutReplaceTxt = StringUtil.replace(larkAlarmTimoutReplaceJson, larkAlarmTimoutTraceReplaceJson, larkAlarmTimoutTraceReplaceTxt); larkAlarmTimeoutReplaceTxt = StringUtil.replace(larkAlarmTimeoutReplaceJson, larkAlarmTimoutTraceReplaceJson, larkAlarmTimoutTraceReplaceTxt);
} else { } else {
larkAlarmTimoutReplaceTxt = StringUtil.replace(larkAlarmTimoutReplaceJson, larkAlarmTimoutTraceReplaceJson, ""); larkAlarmTimeoutReplaceTxt = StringUtil.replace(larkAlarmTimeoutReplaceJson, larkAlarmTimoutTraceReplaceJson, "");
} }
larkAlarmTimoutReplaceTxt = String.format(larkAlarmTimoutReplaceTxt, alarmNotifyRequest.getExecuteTime(), alarmNotifyRequest.getExecuteTimeOut()); larkAlarmTimeoutReplaceTxt = String.format(larkAlarmTimeoutReplaceTxt, alarmNotifyRequest.getExecuteTime(), alarmNotifyRequest.getExecuteTimeOut());
larkAlarmTxt = StringUtil.replace(larkAlarmTxt, larkAlarmTimoutReplaceJson, larkAlarmTimoutReplaceTxt); larkAlarmTxt = StringUtil.replace(larkAlarmTxt, larkAlarmTimeoutReplaceJson, larkAlarmTimeoutReplaceTxt);
} else { } else {
larkAlarmTxt = StringUtil.replace(larkAlarmTxt, larkAlarmTimoutReplaceJson, ""); larkAlarmTxt = StringUtil.replace(larkAlarmTxt, larkAlarmTimeoutReplaceJson, "");
} }
String text = String.format(larkAlarmTxt, String text = String.format(larkAlarmTxt,
// 环境
alarmNotifyRequest.getActive(), alarmNotifyRequest.getActive(),
// 报警类型
alarmNotifyRequest.getNotifyTypeEnum(), alarmNotifyRequest.getNotifyTypeEnum(),
// 线程池ID
alarmNotifyRequest.getThreadPoolId(), alarmNotifyRequest.getThreadPoolId(),
// 应用名称
alarmNotifyRequest.getAppName(), alarmNotifyRequest.getAppName(),
// 实例信息
alarmNotifyRequest.getIdentify(), alarmNotifyRequest.getIdentify(),
// 核心线程数
alarmNotifyRequest.getCorePoolSize(), alarmNotifyRequest.getCorePoolSize(),
// 最大线程数
alarmNotifyRequest.getMaximumPoolSize(), alarmNotifyRequest.getMaximumPoolSize(),
// 当前线程数
alarmNotifyRequest.getPoolSize(), alarmNotifyRequest.getPoolSize(),
// 活跃线程数
alarmNotifyRequest.getActiveCount(), alarmNotifyRequest.getActiveCount(),
// 最大任务数
alarmNotifyRequest.getLargestPoolSize(), alarmNotifyRequest.getLargestPoolSize(),
// 线程池任务总量
alarmNotifyRequest.getCompletedTaskCount(), alarmNotifyRequest.getCompletedTaskCount(),
// 队列类型名称
alarmNotifyRequest.getQueueName(), alarmNotifyRequest.getQueueName(),
// 队列容量
alarmNotifyRequest.getCapacity(), alarmNotifyRequest.getCapacity(),
// 队列元素个数
alarmNotifyRequest.getQueueSize(), alarmNotifyRequest.getQueueSize(),
// 队列剩余个数
alarmNotifyRequest.getRemainingCapacity(), alarmNotifyRequest.getRemainingCapacity(),
// 拒绝策略名称
alarmNotifyRequest.getRejectedExecutionHandlerName(), alarmNotifyRequest.getRejectedExecutionHandlerName(),
// 拒绝策略次数
alarmNotifyRequest.getRejectCountNum(), alarmNotifyRequest.getRejectCountNum(),
// 告警手机号
afterReceives, afterReceives,
// 当前时间
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
// 报警频率
notifyConfig.getInterval()); notifyConfig.getInterval());
execute(notifyConfig.getSecretKey(), text); execute(notifyConfig.getSecretKey(), text);
} }
@ -127,34 +107,20 @@ public class LarkSendMessageHandler implements SendMessageHandler<AlarmNotifyReq
String larkNoticeJsonKey = "message/robot/dynamic-thread-pool/lark-config.json"; String larkNoticeJsonKey = "message/robot/dynamic-thread-pool/lark-config.json";
String larkNoticeJson = Singleton.get(larkNoticeJsonKey, () -> FileUtil.readUtf8String(larkNoticeJsonKey)); String larkNoticeJson = Singleton.get(larkNoticeJsonKey, () -> FileUtil.readUtf8String(larkNoticeJsonKey));
String text = String.format(larkNoticeJson, String text = String.format(larkNoticeJson,
// 环境
changeParameterNotifyRequest.getActive(), changeParameterNotifyRequest.getActive(),
// 线程池名称
threadPoolId, threadPoolId,
// 应用名称
changeParameterNotifyRequest.getAppName(), changeParameterNotifyRequest.getAppName(),
// 实例信息
changeParameterNotifyRequest.getIdentify(), changeParameterNotifyRequest.getIdentify(),
// 核心线程数
changeParameterNotifyRequest.getBeforeCorePoolSize() + " ➲ " + changeParameterNotifyRequest.getNowCorePoolSize(), changeParameterNotifyRequest.getBeforeCorePoolSize() + " ➲ " + changeParameterNotifyRequest.getNowCorePoolSize(),
// 最大线程数
changeParameterNotifyRequest.getBeforeMaximumPoolSize() + " ➲ " + changeParameterNotifyRequest.getNowMaximumPoolSize(), changeParameterNotifyRequest.getBeforeMaximumPoolSize() + " ➲ " + changeParameterNotifyRequest.getNowMaximumPoolSize(),
// 核心线程超时
changeParameterNotifyRequest.getBeforeAllowsCoreThreadTimeOut() + " ➲ " + changeParameterNotifyRequest.getNowAllowsCoreThreadTimeOut(), changeParameterNotifyRequest.getBeforeAllowsCoreThreadTimeOut() + " ➲ " + changeParameterNotifyRequest.getNowAllowsCoreThreadTimeOut(),
// 线程存活时间
changeParameterNotifyRequest.getBeforeKeepAliveTime() + " ➲ " + changeParameterNotifyRequest.getNowKeepAliveTime(), changeParameterNotifyRequest.getBeforeKeepAliveTime() + " ➲ " + changeParameterNotifyRequest.getNowKeepAliveTime(),
// 阻塞队列
changeParameterNotifyRequest.getBlockingQueueName(), changeParameterNotifyRequest.getBlockingQueueName(),
// 阻塞队列容量
changeParameterNotifyRequest.getBeforeQueueCapacity() + " ➲ " + changeParameterNotifyRequest.getNowQueueCapacity(), changeParameterNotifyRequest.getBeforeQueueCapacity() + " ➲ " + changeParameterNotifyRequest.getNowQueueCapacity(),
// 执行超时时间
changeParameterNotifyRequest.getBeforeExecuteTimeOut() + " ➲ " + changeParameterNotifyRequest.getNowExecuteTimeOut(), changeParameterNotifyRequest.getBeforeExecuteTimeOut() + " ➲ " + changeParameterNotifyRequest.getNowExecuteTimeOut(),
// 拒绝策略
changeParameterNotifyRequest.getBeforeRejectedName(), changeParameterNotifyRequest.getBeforeRejectedName(),
changeParameterNotifyRequest.getNowRejectedName(), changeParameterNotifyRequest.getNowRejectedName(),
// 告警手机号
afterReceives, afterReceives,
// 当前时间
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
execute(notifyConfig.getSecretKey(), text); execute(notifyConfig.getSecretKey(), text);
} }

@ -37,22 +37,22 @@ public abstract class AbstractRobotSendMessageHandler implements SendMessageHand
/** /**
* Build message actual content. * Build message actual content.
* *
* @return * @return robot message actual content
*/ */
protected abstract RobotMessageActualContent buildMessageActualContent(); protected abstract RobotMessageActualContent buildMessageActualContent();
/** /**
* Execute. * Execute.
* *
* @param robotMessageExecuteDTO * @param robotMessageExecuteDTO robot message execute dto
*/ */
protected abstract void execute(RobotMessageExecuteDTO robotMessageExecuteDTO); protected abstract void execute(RobotMessageExecuteDTO robotMessageExecuteDTO);
/** /**
* Send alarm message. * Send alarm message.
* *
* @param notifyConfig * @param notifyConfig notify config
* @param alarmNotifyRequest * @param alarmNotifyRequest alarm notify request
*/ */
public void sendAlarmMessage(NotifyConfigDTO notifyConfig, AlarmNotifyRequest alarmNotifyRequest) { public void sendAlarmMessage(NotifyConfigDTO notifyConfig, AlarmNotifyRequest alarmNotifyRequest) {
RobotMessageActualContent robotMessageActualContent = buildMessageActualContent(); RobotMessageActualContent robotMessageActualContent = buildMessageActualContent();
@ -75,45 +75,25 @@ public abstract class AbstractRobotSendMessageHandler implements SendMessageHand
alarmContentTxt = StringUtil.replace(alarmContentTxt, "${timout-content}", replaceTxt); alarmContentTxt = StringUtil.replace(alarmContentTxt, "${timout-content}", replaceTxt);
String text = String.format( String text = String.format(
alarmContentTxt, alarmContentTxt,
// 环境
alarmNotifyRequest.getActive(), alarmNotifyRequest.getActive(),
// 报警类型
alarmNotifyRequest.getNotifyTypeEnum(), alarmNotifyRequest.getNotifyTypeEnum(),
// 线程池ID
alarmNotifyRequest.getThreadPoolId(), alarmNotifyRequest.getThreadPoolId(),
// 应用名称
alarmNotifyRequest.getAppName(), alarmNotifyRequest.getAppName(),
// 实例信息
alarmNotifyRequest.getIdentify(), alarmNotifyRequest.getIdentify(),
// 核心线程数
alarmNotifyRequest.getCorePoolSize(), alarmNotifyRequest.getCorePoolSize(),
// 最大线程数
alarmNotifyRequest.getMaximumPoolSize(), alarmNotifyRequest.getMaximumPoolSize(),
// 当前线程数
alarmNotifyRequest.getPoolSize(), alarmNotifyRequest.getPoolSize(),
// 活跃线程数
alarmNotifyRequest.getActiveCount(), alarmNotifyRequest.getActiveCount(),
// 最大任务数
alarmNotifyRequest.getLargestPoolSize(), alarmNotifyRequest.getLargestPoolSize(),
// 线程池任务总量
alarmNotifyRequest.getCompletedTaskCount(), alarmNotifyRequest.getCompletedTaskCount(),
// 队列类型名称
alarmNotifyRequest.getQueueName(), alarmNotifyRequest.getQueueName(),
// 队列容量
alarmNotifyRequest.getCapacity(), alarmNotifyRequest.getCapacity(),
// 队列元素个数
alarmNotifyRequest.getQueueSize(), alarmNotifyRequest.getQueueSize(),
// 队列剩余个数
alarmNotifyRequest.getRemainingCapacity(), alarmNotifyRequest.getRemainingCapacity(),
// 拒绝策略名称
alarmNotifyRequest.getRejectedExecutionHandlerName(), alarmNotifyRequest.getRejectedExecutionHandlerName(),
// 拒绝策略次数
alarmNotifyRequest.getRejectCountNum(), alarmNotifyRequest.getRejectCountNum(),
// 告警手机号
Joiner.on(robotMessageActualContent.getReceiveSeparator()).join(notifyConfig.getReceives().split(",")), Joiner.on(robotMessageActualContent.getReceiveSeparator()).join(notifyConfig.getReceives().split(",")),
// 报警频率
notifyConfig.getInterval(), notifyConfig.getInterval(),
// 当前时间
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
execute(RobotMessageExecuteDTO.builder().text(text).notifyConfig(notifyConfig).build()); execute(RobotMessageExecuteDTO.builder().text(text).notifyConfig(notifyConfig).build());
} }
@ -121,8 +101,8 @@ public abstract class AbstractRobotSendMessageHandler implements SendMessageHand
/** /**
* Send change message. * Send change message.
* *
* @param notifyConfig * @param notifyConfig notify config
* @param changeParameterNotifyRequest * @param changeParameterNotifyRequest change parameter notify request
*/ */
public void sendChangeMessage(NotifyConfigDTO notifyConfig, ChangeParameterNotifyRequest changeParameterNotifyRequest) { public void sendChangeMessage(NotifyConfigDTO notifyConfig, ChangeParameterNotifyRequest changeParameterNotifyRequest) {
RobotMessageActualContent robotMessageActualContent = buildMessageActualContent(); RobotMessageActualContent robotMessageActualContent = buildMessageActualContent();
@ -130,34 +110,20 @@ public abstract class AbstractRobotSendMessageHandler implements SendMessageHand
String changeSeparator = robotMessageActualContent.getChangeSeparator(); String changeSeparator = robotMessageActualContent.getChangeSeparator();
String text = String.format( String text = String.format(
robotMessageActualContent.getConfigMessageContent(), robotMessageActualContent.getConfigMessageContent(),
// 环境
changeParameterNotifyRequest.getActive(), changeParameterNotifyRequest.getActive(),
// 线程池名称
threadPoolId, threadPoolId,
// 应用名称
changeParameterNotifyRequest.getAppName(), changeParameterNotifyRequest.getAppName(),
// 实例信息
changeParameterNotifyRequest.getIdentify(), changeParameterNotifyRequest.getIdentify(),
// 核心线程数
changeParameterNotifyRequest.getBeforeCorePoolSize() + changeSeparator + changeParameterNotifyRequest.getNowCorePoolSize(), changeParameterNotifyRequest.getBeforeCorePoolSize() + changeSeparator + changeParameterNotifyRequest.getNowCorePoolSize(),
// 最大线程数
changeParameterNotifyRequest.getBeforeMaximumPoolSize() + changeSeparator + changeParameterNotifyRequest.getNowMaximumPoolSize(), changeParameterNotifyRequest.getBeforeMaximumPoolSize() + changeSeparator + changeParameterNotifyRequest.getNowMaximumPoolSize(),
// 核心线程超时
changeParameterNotifyRequest.getBeforeAllowsCoreThreadTimeOut() + changeSeparator + changeParameterNotifyRequest.getNowAllowsCoreThreadTimeOut(), changeParameterNotifyRequest.getBeforeAllowsCoreThreadTimeOut() + changeSeparator + changeParameterNotifyRequest.getNowAllowsCoreThreadTimeOut(),
// 线程存活时间
changeParameterNotifyRequest.getBeforeKeepAliveTime() + changeSeparator + changeParameterNotifyRequest.getNowKeepAliveTime(), changeParameterNotifyRequest.getBeforeKeepAliveTime() + changeSeparator + changeParameterNotifyRequest.getNowKeepAliveTime(),
// 执行超时时间
changeParameterNotifyRequest.getBeforeExecuteTimeOut() + changeSeparator + changeParameterNotifyRequest.getNowExecuteTimeOut(), changeParameterNotifyRequest.getBeforeExecuteTimeOut() + changeSeparator + changeParameterNotifyRequest.getNowExecuteTimeOut(),
// 阻塞队列
changeParameterNotifyRequest.getBlockingQueueName(), changeParameterNotifyRequest.getBlockingQueueName(),
// 阻塞队列容量
changeParameterNotifyRequest.getBeforeQueueCapacity() + changeSeparator + changeParameterNotifyRequest.getNowQueueCapacity(), changeParameterNotifyRequest.getBeforeQueueCapacity() + changeSeparator + changeParameterNotifyRequest.getNowQueueCapacity(),
// 拒绝策略
changeParameterNotifyRequest.getBeforeRejectedName(), changeParameterNotifyRequest.getBeforeRejectedName(),
changeParameterNotifyRequest.getNowRejectedName(), changeParameterNotifyRequest.getNowRejectedName(),
// 告警手机号
Joiner.on(robotMessageActualContent.getReceiveSeparator()).join(notifyConfig.getReceives().split(",")), Joiner.on(robotMessageActualContent.getReceiveSeparator()).join(notifyConfig.getReceives().split(",")),
// 当前时间
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
execute(RobotMessageExecuteDTO.builder().text(text).notifyConfig(notifyConfig).build()); execute(RobotMessageExecuteDTO.builder().text(text).notifyConfig(notifyConfig).build());
} }

@ -40,14 +40,14 @@ public class DingAlarmConstants {
/** /**
* Trace info * Trace info
*/ */
public static final String DING_ALARM_TIMOUT_TRACE_REPLACE_TXT = "<font color=#708090 size=2>链路信息:%s</font> \n\n "; public static final String DING_ALARM_TIMEOUT_TRACE_REPLACE_TXT = "<font color=#708090 size=2>链路信息:%s</font> \n\n ";
/** /**
* Replace task timeout template * Replace task timeout template
*/ */
public static final String DING_ALARM_TIMOUT_REPLACE_TXT = public static final String DING_ALARM_TIMEOUT_REPLACE_TXT =
"<font color=#708090 size=2>任务执行时间:%d / ms </font> \n\n " + "<font color=#708090 size=2>任务执行时间:%d / ms </font> \n\n " +
"<font color=#708090 size=2>超时时间:%d / ms</font> \n\n " + "<font color=#708090 size=2>超时时间:%d / ms</font> \n\n " +
DING_ALARM_TIMOUT_TRACE_REPLACE_TXT + DING_ALARM_TIMEOUT_TRACE_REPLACE_TXT +
" --- \n\n "; " --- \n\n ";
} }

@ -17,12 +17,6 @@
package cn.hippo4j.message.service; package cn.hippo4j.message.service;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import cn.hippo4j.common.constant.Constants; import cn.hippo4j.common.constant.Constants;
import cn.hippo4j.common.toolkit.IdUtil; import cn.hippo4j.common.toolkit.IdUtil;
import cn.hippo4j.common.toolkit.StringUtil; import cn.hippo4j.common.toolkit.StringUtil;
@ -30,6 +24,12 @@ import cn.hippo4j.message.dto.AlarmControlDTO;
import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.Caffeine;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
/** /**
* Alarm control assembly. * Alarm control assembly.
*/ */
@ -42,8 +42,8 @@ public class AlarmControlHandler {
/** /**
* Control message push alarm frequency. * Control message push alarm frequency.
* *
* @param alarmControl * @param alarmControl alarm control
* @return * @return is it possible to send
*/ */
public boolean isSendAlarm(AlarmControlDTO alarmControl) { public boolean isSendAlarm(AlarmControlDTO alarmControl) {
String threadPoolKey = alarmControl.buildPk(); String threadPoolKey = alarmControl.buildPk();
@ -72,9 +72,9 @@ public class AlarmControlHandler {
/** /**
* Init cache and lock. * Init cache and lock.
* *
* @param threadPoolId * @param threadPoolId thread-pool id
* @param platform * @param platform platform
* @param interval * @param interval interval
*/ */
public void initCacheAndLock(String threadPoolId, String platform, Integer interval) { public void initCacheAndLock(String threadPoolId, String platform, Integer interval) {
String threadPoolKey = threadPoolId + Constants.GROUP_KEY_DELIMITER + platform; String threadPoolKey = threadPoolId + Constants.GROUP_KEY_DELIMITER + platform;

@ -109,9 +109,9 @@ public class Hippo4jBaseSendMessageService implements Hippo4jSendMessageService,
/** /**
* Is send alarm. * Is send alarm.
* *
* @param threadPoolId * @param threadPoolId thread-pool id
* @param platform * @param platform platform
* @param typeEnum * @param typeEnum type enum
* @return * @return
*/ */
private boolean isSendAlarm(String threadPoolId, String platform, NotifyTypeEnum typeEnum) { private boolean isSendAlarm(String threadPoolId, String platform, NotifyTypeEnum typeEnum) {
@ -123,6 +123,15 @@ public class Hippo4jBaseSendMessageService implements Hippo4jSendMessageService,
return alarmControlHandler.isSendAlarm(alarmControl); return alarmControlHandler.isSendAlarm(alarmControl);
} }
/**
* Put platform.
*
* @param notifyConfigs notify configs
*/
public synchronized void putPlatform(Map<String, List<NotifyConfigDTO>> notifyConfigs) {
this.notifyConfigs.putAll(notifyConfigs);
}
@Override @Override
public void run(String... args) throws Exception { public void run(String... args) throws Exception {
Map<String, SendMessageHandler> sendMessageHandlerMap = Map<String, SendMessageHandler> sendMessageHandlerMap =
@ -131,13 +140,4 @@ public class Hippo4jBaseSendMessageService implements Hippo4jSendMessageService,
Map<String, List<NotifyConfigDTO>> buildNotify = notifyConfigBuilder.buildNotify(); Map<String, List<NotifyConfigDTO>> buildNotify = notifyConfigBuilder.buildNotify();
notifyConfigs.putAll(buildNotify); notifyConfigs.putAll(buildNotify);
} }
/**
* Put platform.
*
* @param notifyConfigs
*/
public synchronized void putPlatform(Map<String, List<NotifyConfigDTO>> notifyConfigs) {
this.notifyConfigs.putAll(notifyConfigs);
}
} }

@ -29,15 +29,15 @@ public interface Hippo4jSendMessageService {
/** /**
* Send dynamic thread pool alert notifications. * Send dynamic thread pool alert notifications.
* *
* @param typeEnum * @param typeEnum type enum
* @param alarmNotifyRequest * @param alarmNotifyRequest alarm notify request
*/ */
void sendAlarmMessage(NotifyTypeEnum typeEnum, AlarmNotifyRequest alarmNotifyRequest); void sendAlarmMessage(NotifyTypeEnum typeEnum, AlarmNotifyRequest alarmNotifyRequest);
/** /**
* Send dynamic thread pool parameter change notification. * Send dynamic thread pool parameter change notification.
* *
* @param changeParameterNotifyRequest * @param changeParameterNotifyRequest change parameter notify request
*/ */
void sendChangeMessage(ChangeParameterNotifyRequest changeParameterNotifyRequest); void sendChangeMessage(ChangeParameterNotifyRequest changeParameterNotifyRequest);
} }

@ -26,25 +26,25 @@ import cn.hippo4j.message.request.base.NotifyRequest;
public interface SendMessageHandler<T extends NotifyRequest, R extends NotifyRequest> { public interface SendMessageHandler<T extends NotifyRequest, R extends NotifyRequest> {
/** /**
* Get type. * Get the message send type.
* *
* @return * @return message type
*/ */
String getType(); String getType();
/** /**
* Send alarm message. * Send alarm message.
* *
* @param notifyConfig * @param notifyConfig notify config
* @param alarmNotifyRequest * @param alarmNotifyRequest alarm notify request
*/ */
void sendAlarmMessage(NotifyConfigDTO notifyConfig, T alarmNotifyRequest); void sendAlarmMessage(NotifyConfigDTO notifyConfig, T alarmNotifyRequest);
/** /**
* Send change message. * Send change message.
* *
* @param notifyConfig * @param notifyConfig notify config
* @param changeParameterNotifyRequest * @param changeParameterNotifyRequest change parameter notify request
*/ */
void sendChangeMessage(NotifyConfigDTO notifyConfig, R changeParameterNotifyRequest); void sendChangeMessage(NotifyConfigDTO notifyConfig, R changeParameterNotifyRequest);
} }

@ -14,8 +14,8 @@
"content": "** 超时时间:** %s", "content": "** 超时时间:** %s",
"tag": "lark_md" "tag": "lark_md"
} }
}, }
{ ,{
"is_short": true, "is_short": true,
"text": { "text": {
"content": "** 链路信息:** %s", "content": "** 链路信息:** %s",

@ -1,5 +1,5 @@
{ ,{
"is_short": true, "is_short": true,
"text": { "text": {
"content": "** 链路信息:** %s", "content": "** 链路信息:** %s",

@ -142,8 +142,8 @@
"content": "** 超时时间:** %s", "content": "** 超时时间:** %s",
"tag": "lark_md" "tag": "lark_md"
} }
}, }
{ ,{
"is_short": true, "is_short": true,
"text": { "text": {
"content": "** 链路信息:** %s", "content": "** 链路信息:** %s",

@ -22,7 +22,7 @@ import cn.hippo4j.message.enums.NotifyTypeEnum;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
public class AlarmControlHandlerTest { public final class AlarmControlHandlerTest {
@Test @Test
public void assertIsNotSendAlarm() { public void assertIsNotSendAlarm() {

@ -13,6 +13,17 @@
<dependency> <dependency>
<groupId>cn.hippo4j</groupId> <groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-core</artifactId> <artifactId>hippo4j-core</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-adapter-web</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-adapter-base</artifactId>
<version>${revision}</version>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

@ -0,0 +1,43 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.monitor.base;
import cn.hippo4j.adapter.base.ThreadPoolAdapter;
import cn.hippo4j.adapter.base.ThreadPoolAdapterState;
import cn.hippo4j.common.config.ApplicationContextHolder;
import java.util.Map;
/**
* Abstract adapter thread-pool monitor.
*/
public abstract class AbstractAdapterThreadPoolMonitor implements AdapterThreadPoolMonitor {
/**
* Execute collection thread pool running data.
*
* @param threadPoolAdapterState thread-pool adapter state
*/
protected abstract void execute(ThreadPoolAdapterState threadPoolAdapterState);
@Override
public void collect() {
Map<String, ThreadPoolAdapter> threadPoolAdapterMap = ApplicationContextHolder.getBeansOfType(ThreadPoolAdapter.class);
threadPoolAdapterMap.forEach((beanName, bean) -> bean.getThreadPoolStates().forEach(each -> execute(each)));
}
}

@ -20,24 +20,24 @@ package cn.hippo4j.monitor.base;
import cn.hippo4j.common.model.ThreadPoolRunStateInfo; import cn.hippo4j.common.model.ThreadPoolRunStateInfo;
import cn.hippo4j.core.executor.manage.GlobalThreadPoolManage; import cn.hippo4j.core.executor.manage.GlobalThreadPoolManage;
import cn.hippo4j.core.executor.state.ThreadPoolRunStateHandler; import cn.hippo4j.core.executor.state.ThreadPoolRunStateHandler;
import lombok.RequiredArgsConstructor;
import javax.annotation.Resource;
import java.util.List; import java.util.List;
/** /**
* Abstract dynamic thread-pool monitor. * Abstract dynamic thread-pool monitor.
*/ */
@RequiredArgsConstructor
public abstract class AbstractDynamicThreadPoolMonitor implements DynamicThreadPoolMonitor { public abstract class AbstractDynamicThreadPoolMonitor implements DynamicThreadPoolMonitor {
private final ThreadPoolRunStateHandler threadPoolRunStateHandler; @Resource
private ThreadPoolRunStateHandler threadPoolRunStateHandler;
/** /**
* Execute collection thread pool running data. * Execute collection thread pool running data.
* *
* @param poolRunStateInfo * @param dynamicThreadPoolRunStateInfo dynamic thread-pool run state info
*/ */
protected abstract void execute(ThreadPoolRunStateInfo poolRunStateInfo); protected abstract void execute(ThreadPoolRunStateInfo dynamicThreadPoolRunStateInfo);
@Override @Override
public void collect() { public void collect() {

@ -0,0 +1,45 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.monitor.base;
import cn.hippo4j.adapter.web.WebThreadPoolService;
import cn.hippo4j.common.model.ThreadPoolRunStateInfo;
import javax.annotation.Resource;
/**
* Abstract web thread-pool monitor.
*/
public abstract class AbstractWebThreadPoolMonitor implements WebThreadPoolMonitor {
@Resource
private WebThreadPoolService webThreadPoolService;
/**
* Execute collection thread pool running data.
*
* @param webThreadPoolRunStateInfo web thread-pool run state info
*/
protected abstract void execute(ThreadPoolRunStateInfo webThreadPoolRunStateInfo);
@Override
public void collect() {
ThreadPoolRunStateInfo webThreadPoolRunStateInfo = webThreadPoolService.getWebRunStateInfo();
execute(webThreadPoolRunStateInfo);
}
}

@ -0,0 +1,25 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.monitor.base;
/**
* Adapter thread-pool monitor.
*/
public interface AdapterThreadPoolMonitor extends ThreadPoolMonitor {
}

@ -0,0 +1,39 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.monitor.base;
/**
* Monitor thread-pool type enum.
*/
public enum MonitorThreadPoolTypeEnum {
/**
* Dynamic thread-pool
*/
DYNAMIC,
/**
* Web thread-pool
*/
WEB,
/**
* Adapter thread-pool
*/
ADAPTER
}

@ -18,19 +18,19 @@
package cn.hippo4j.monitor.base; package cn.hippo4j.monitor.base;
/** /**
* Thread-pool monitor. * Thread-pool runtime monitor.
*/ */
public interface ThreadPoolMonitor { public interface ThreadPoolMonitor {
/** /**
* Get type. * Get thread-pool monitoring type.
* *
* @return * @return monitoring type
*/ */
String getType(); String getType();
/** /**
* Collect data. * Collect thread-pool runtime data.
*/ */
void collect(); void collect();
} }

@ -15,7 +15,11 @@
* limitations under the License. * limitations under the License.
*/ */
package cn.hippo4j.auth.secuity; package cn.hippo4j.monitor.base;
/**
* Web thread-pool monitor.
*/
public interface WebThreadPoolMonitor extends ThreadPoolMonitor {
public final class JwtTokenManagerTest {
} }

@ -0,0 +1,40 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.monitor.elasticsearch;
import cn.hippo4j.common.model.ThreadPoolRunStateInfo;
import cn.hippo4j.monitor.base.AbstractDynamicThreadPoolMonitor;
import cn.hippo4j.monitor.base.MonitorTypeEnum;
import lombok.extern.slf4j.Slf4j;
/**
* Adapter thread-pool elastic-search monitor handler.
*/
@Slf4j
public class AdapterThreadPoolElasticSearchMonitorHandler extends AbstractDynamicThreadPoolMonitor {
@Override
protected void execute(ThreadPoolRunStateInfo poolRunStateInfo) {
// TODO
}
@Override
public String getType() {
return MonitorTypeEnum.ELASTICSEARCH.name().toLowerCase();
}
}

@ -15,26 +15,25 @@
* limitations under the License. * limitations under the License.
*/ */
package cn.hippo4j.monitor.es; package cn.hippo4j.monitor.elasticsearch;
import cn.hippo4j.common.config.ApplicationContextHolder; import cn.hippo4j.common.config.ApplicationContextHolder;
import cn.hippo4j.common.model.ThreadPoolRunStateInfo; import cn.hippo4j.common.model.ThreadPoolRunStateInfo;
import cn.hippo4j.common.toolkit.BeanUtil; import cn.hippo4j.common.toolkit.BeanUtil;
import cn.hippo4j.common.toolkit.FileUtil; import cn.hippo4j.common.toolkit.FileUtil;
import cn.hippo4j.common.toolkit.JSONUtil; import cn.hippo4j.common.toolkit.JSONUtil;
import cn.hippo4j.core.executor.state.ThreadPoolRunStateHandler;
import cn.hippo4j.monitor.es.model.EsThreadPoolRunStateInfo;
import cn.hippo4j.monitor.base.AbstractDynamicThreadPoolMonitor; import cn.hippo4j.monitor.base.AbstractDynamicThreadPoolMonitor;
import cn.hippo4j.monitor.base.MonitorTypeEnum; import cn.hippo4j.monitor.base.MonitorTypeEnum;
import cn.hippo4j.monitor.elasticsearch.model.ElasticSearchThreadPoolRunStateInfo;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.admin.indices.alias.Alias; import org.elasticsearch.action.admin.indices.alias.Alias;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
@ -47,20 +46,16 @@ import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
/** /**
* Elastic-search monitor handler. * Dynamic thread-pool elastic-search monitor handler.
*/ */
@Slf4j @Slf4j
public class EsMonitorHandler extends AbstractDynamicThreadPoolMonitor { public class DynamicThreadPoolElasticSearchMonitorHandler extends AbstractDynamicThreadPoolMonitor {
public EsMonitorHandler(ThreadPoolRunStateHandler threadPoolRunStateHandler) {
super(threadPoolRunStateHandler);
}
private AtomicBoolean isIndexExist = null; private AtomicBoolean isIndexExist = null;
@Override @Override
protected void execute(ThreadPoolRunStateInfo poolRunStateInfo) { protected void execute(ThreadPoolRunStateInfo poolRunStateInfo) {
EsThreadPoolRunStateInfo esThreadPoolRunStateInfo = BeanUtil.convert(poolRunStateInfo, EsThreadPoolRunStateInfo.class); ElasticSearchThreadPoolRunStateInfo esThreadPoolRunStateInfo = BeanUtil.convert(poolRunStateInfo, ElasticSearchThreadPoolRunStateInfo.class);
Environment environment = ApplicationContextHolder.getInstance().getEnvironment(); Environment environment = ApplicationContextHolder.getInstance().getEnvironment();
String indexName = environment.getProperty("es.thread-pool-state.index.name", "thread-pool-state"); String indexName = environment.getProperty("es.thread-pool-state.index.name", "thread-pool-state");
String applicationName = environment.getProperty("spring.application.name", "application"); String applicationName = environment.getProperty("spring.application.name", "application");
@ -75,8 +70,8 @@ public class EsMonitorHandler extends AbstractDynamicThreadPoolMonitor {
this.log2Es(esThreadPoolRunStateInfo, indexName); this.log2Es(esThreadPoolRunStateInfo, indexName);
} }
public void log2Es(EsThreadPoolRunStateInfo esThreadPoolRunStateInfo, String indexName) { public void log2Es(ElasticSearchThreadPoolRunStateInfo esThreadPoolRunStateInfo, String indexName) {
RestHighLevelClient client = EsClientHolder.getClient(); RestHighLevelClient client = ElasticSearchClientHolder.getClient();
try { try {
IndexRequest request = new IndexRequest(indexName, "_doc"); IndexRequest request = new IndexRequest(indexName, "_doc");
request.id(esThreadPoolRunStateInfo.getId()); request.id(esThreadPoolRunStateInfo.getId());
@ -99,7 +94,7 @@ public class EsMonitorHandler extends AbstractDynamicThreadPoolMonitor {
boolean exists = false; boolean exists = false;
GetIndexRequest request = new GetIndexRequest(index); GetIndexRequest request = new GetIndexRequest(index);
try { try {
RestHighLevelClient client = EsClientHolder.getClient(); RestHighLevelClient client = ElasticSearchClientHolder.getClient();
exists = client.indices().exists(request, RequestOptions.DEFAULT); exists = client.indices().exists(request, RequestOptions.DEFAULT);
} catch (IOException e) { } catch (IOException e) {
log.error("check es index fail"); log.error("check es index fail");
@ -110,7 +105,7 @@ public class EsMonitorHandler extends AbstractDynamicThreadPoolMonitor {
} }
public void createIndex(String index, String type, String mapping, Integer shards, Integer replicas, String alias) { public void createIndex(String index, String type, String mapping, Integer shards, Integer replicas, String alias) {
RestHighLevelClient client = EsClientHolder.getClient(); RestHighLevelClient client = ElasticSearchClientHolder.getClient();
boolean acknowledged = false; boolean acknowledged = false;
CreateIndexRequest request = new CreateIndexRequest(index); CreateIndexRequest request = new CreateIndexRequest(index);
if (StringUtils.hasText(mapping)) { if (StringUtils.hasText(mapping)) {

@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
package cn.hippo4j.monitor.es; package cn.hippo4j.monitor.elasticsearch;
import cn.hippo4j.common.config.ApplicationContextHolder; import cn.hippo4j.common.config.ApplicationContextHolder;
import cn.hippo4j.common.toolkit.StringUtil; import cn.hippo4j.common.toolkit.StringUtil;
@ -37,7 +37,7 @@ import java.util.List;
* Elastic-search client holder. * Elastic-search client holder.
*/ */
@Slf4j @Slf4j
public class EsClientHolder { public class ElasticSearchClientHolder {
private static String host; private static String host;

@ -0,0 +1,40 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.monitor.elasticsearch;
import cn.hippo4j.common.model.ThreadPoolRunStateInfo;
import cn.hippo4j.monitor.base.AbstractDynamicThreadPoolMonitor;
import cn.hippo4j.monitor.base.MonitorTypeEnum;
import lombok.extern.slf4j.Slf4j;
/**
* Web thread-pool elastic-search monitor handler.
*/
@Slf4j
public class WebThreadPoolElasticSearchMonitorHandler extends AbstractDynamicThreadPoolMonitor {
@Override
protected void execute(ThreadPoolRunStateInfo poolRunStateInfo) {
// TODO
}
@Override
public String getType() {
return MonitorTypeEnum.ELASTICSEARCH.name().toLowerCase();
}
}

@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
package cn.hippo4j.monitor.es.model; package cn.hippo4j.monitor.elasticsearch.model;
import cn.hippo4j.common.model.ThreadPoolRunStateInfo; import cn.hippo4j.common.model.ThreadPoolRunStateInfo;
import lombok.Getter; import lombok.Getter;
@ -26,7 +26,7 @@ import lombok.Setter;
*/ */
@Getter @Getter
@Setter @Setter
public class EsThreadPoolRunStateInfo extends ThreadPoolRunStateInfo { public class ElasticSearchThreadPoolRunStateInfo extends ThreadPoolRunStateInfo {
private String Id; private String Id;

@ -0,0 +1,41 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.monitor.local.log;
import cn.hippo4j.adapter.base.ThreadPoolAdapterState;
import cn.hippo4j.common.toolkit.JSONUtil;
import cn.hippo4j.monitor.base.AbstractAdapterThreadPoolMonitor;
import cn.hippo4j.monitor.base.MonitorTypeEnum;
import lombok.extern.slf4j.Slf4j;
/**
* Adapter thread-pool local log monitor handler.
*/
@Slf4j
public class AdapterThreadPoolLocalLogMonitorHandler extends AbstractAdapterThreadPoolMonitor {
@Override
protected void execute(ThreadPoolAdapterState threadPoolAdapterState) {
log.info("{}", JSONUtil.toJSONString(threadPoolAdapterState));
}
@Override
public String getType() {
return MonitorTypeEnum.LOG.name().toLowerCase();
}
}

@ -19,20 +19,15 @@ package cn.hippo4j.monitor.local.log;
import cn.hippo4j.common.model.ThreadPoolRunStateInfo; import cn.hippo4j.common.model.ThreadPoolRunStateInfo;
import cn.hippo4j.common.toolkit.JSONUtil; import cn.hippo4j.common.toolkit.JSONUtil;
import cn.hippo4j.core.executor.state.ThreadPoolRunStateHandler;
import cn.hippo4j.monitor.base.AbstractDynamicThreadPoolMonitor; import cn.hippo4j.monitor.base.AbstractDynamicThreadPoolMonitor;
import cn.hippo4j.monitor.base.MonitorTypeEnum; import cn.hippo4j.monitor.base.MonitorTypeEnum;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
/** /**
* Local log monitor handler. * Dynamic thread-pool local log monitor handler.
*/ */
@Slf4j @Slf4j
public class LocalLogMonitorHandler extends AbstractDynamicThreadPoolMonitor { public class DynamicThreadPoolLocalLogMonitorHandler extends AbstractDynamicThreadPoolMonitor {
public LocalLogMonitorHandler(ThreadPoolRunStateHandler threadPoolRunStateHandler) {
super(threadPoolRunStateHandler);
}
@Override @Override
protected void execute(ThreadPoolRunStateInfo poolRunStateInfo) { protected void execute(ThreadPoolRunStateInfo poolRunStateInfo) {

@ -0,0 +1,41 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.monitor.local.log;
import cn.hippo4j.common.model.ThreadPoolRunStateInfo;
import cn.hippo4j.common.toolkit.JSONUtil;
import cn.hippo4j.monitor.base.AbstractWebThreadPoolMonitor;
import cn.hippo4j.monitor.base.MonitorTypeEnum;
import lombok.extern.slf4j.Slf4j;
/**
* Web thread-pool local log monitor handler.
*/
@Slf4j
public class WebThreadPoolLocalLogMonitorHandler extends AbstractWebThreadPoolMonitor {
@Override
protected void execute(ThreadPoolRunStateInfo poolRunStateInfo) {
log.info("{}", JSONUtil.toJSONString(poolRunStateInfo));
}
@Override
public String getType() {
return MonitorTypeEnum.LOG.name().toLowerCase();
}
}

@ -15,21 +15,24 @@
* limitations under the License. * limitations under the License.
*/ */
package cn.hippo4j.springboot.starter.monitor.local.log; package cn.hippo4j.monitor.micrometer;
import cn.hippo4j.core.executor.state.ThreadPoolRunStateHandler; import cn.hippo4j.adapter.base.ThreadPoolAdapterState;
import cn.hippo4j.monitor.local.log.LocalLogMonitorHandler; import cn.hippo4j.monitor.base.AbstractAdapterThreadPoolMonitor;
import org.springframework.context.annotation.Bean; import cn.hippo4j.monitor.base.MonitorTypeEnum;
import org.springframework.context.annotation.Configuration;
/** /**
* Local log monitor configuration. * Adapter thread-pool micrometer monitor handler.
*/ */
@Configuration public class AdapterThreadPoolMicrometerMonitorHandler extends AbstractAdapterThreadPoolMonitor {
public class LocalLogMonitorConfiguration {
@Bean @Override
public LocalLogMonitorHandler localLogMonitorHandler(ThreadPoolRunStateHandler threadPoolRunStateHandler) { protected void execute(ThreadPoolAdapterState threadPoolAdapterState) {
return new LocalLogMonitorHandler(threadPoolRunStateHandler);
}
@Override
public String getType() {
return MonitorTypeEnum.MICROMETER.name().toLowerCase();
} }
} }

@ -21,7 +21,6 @@ import cn.hippo4j.common.config.ApplicationContextHolder;
import cn.hippo4j.common.model.ThreadPoolRunStateInfo; import cn.hippo4j.common.model.ThreadPoolRunStateInfo;
import cn.hippo4j.common.toolkit.BeanUtil; import cn.hippo4j.common.toolkit.BeanUtil;
import cn.hippo4j.common.toolkit.CollectionUtil; import cn.hippo4j.common.toolkit.CollectionUtil;
import cn.hippo4j.core.executor.state.ThreadPoolRunStateHandler;
import cn.hippo4j.monitor.base.AbstractDynamicThreadPoolMonitor; import cn.hippo4j.monitor.base.AbstractDynamicThreadPoolMonitor;
import cn.hippo4j.monitor.base.MonitorTypeEnum; import cn.hippo4j.monitor.base.MonitorTypeEnum;
import io.micrometer.core.instrument.Metrics; import io.micrometer.core.instrument.Metrics;
@ -32,9 +31,9 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
/** /**
* Micrometer monitor handler. * Dynamic thread-pool micrometer monitor handler.
*/ */
public class MicrometerMonitorHandler extends AbstractDynamicThreadPoolMonitor { public class DynamicThreadPoolMicrometerMonitorHandler extends AbstractDynamicThreadPoolMonitor {
private final static String METRIC_NAME_PREFIX = "dynamic.thread-pool"; private final static String METRIC_NAME_PREFIX = "dynamic.thread-pool";
@ -44,10 +43,6 @@ public class MicrometerMonitorHandler extends AbstractDynamicThreadPoolMonitor {
private final Map<String, ThreadPoolRunStateInfo> RUN_STATE_CACHE = new ConcurrentHashMap<>(); private final Map<String, ThreadPoolRunStateInfo> RUN_STATE_CACHE = new ConcurrentHashMap<>();
public MicrometerMonitorHandler(ThreadPoolRunStateHandler threadPoolRunStateHandler) {
super(threadPoolRunStateHandler);
}
@Override @Override
protected void execute(ThreadPoolRunStateInfo poolRunStateInfo) { protected void execute(ThreadPoolRunStateInfo poolRunStateInfo) {
ThreadPoolRunStateInfo stateInfo = RUN_STATE_CACHE.get(poolRunStateInfo.getTpId()); ThreadPoolRunStateInfo stateInfo = RUN_STATE_CACHE.get(poolRunStateInfo.getTpId());

@ -15,21 +15,24 @@
* limitations under the License. * limitations under the License.
*/ */
package cn.hippo4j.springboot.starter.monitor.es; package cn.hippo4j.monitor.micrometer;
import cn.hippo4j.core.executor.state.ThreadPoolRunStateHandler; import cn.hippo4j.common.model.ThreadPoolRunStateInfo;
import cn.hippo4j.monitor.es.EsMonitorHandler; import cn.hippo4j.monitor.base.AbstractWebThreadPoolMonitor;
import org.springframework.context.annotation.Bean; import cn.hippo4j.monitor.base.MonitorTypeEnum;
import org.springframework.context.annotation.Configuration;
/** /**
* Elastic-search monitor auto configuration. * Web thread-pool micrometer monitor handler.
*/ */
@Configuration public class WebThreadPoolMicrometerMonitorHandler extends AbstractWebThreadPoolMonitor {
public class EsMonitorAutoConfiguration {
@Bean @Override
public EsMonitorHandler esMonitorHandler(ThreadPoolRunStateHandler threadPoolRunStateHandler) { protected void execute(ThreadPoolRunStateInfo webThreadPoolRunStateInfo) {
return new EsMonitorHandler(threadPoolRunStateHandler);
}
@Override
public String getType() {
return MonitorTypeEnum.MICROMETER.name().toLowerCase();
} }
} }

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>cn.hippo4j</groupId> <groupId>cn.hippo4j</groupId>
<artifactId>hippo4j-all</artifactId> <artifactId>hippo4j-server</artifactId>
<version>${revision}</version> <version>${revision}</version>
</parent> </parent>
<artifactId>hippo4j-auth</artifactId> <artifactId>hippo4j-auth</artifactId>

@ -0,0 +1,66 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.hippo4j.auth.secuity;
import cn.hippo4j.auth.security.JwtTokenManager;
import cn.hippo4j.common.toolkit.Assert;
import cn.hippo4j.common.toolkit.CollectionUtil;
import cn.hippo4j.common.toolkit.StringUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.junit.Test;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import java.util.Collection;
public final class JwtTokenManagerTest {
private static final String USERNAME = "test";
@Test
public void createTokenTest() {
JwtTokenManager jwtTokenManager = new JwtTokenManager();
String token = jwtTokenManager.createToken(USERNAME);
Assert.isTrue(StringUtil.isNotBlank(token));
}
@Test
public void validateTokenTest() {
JwtTokenManager jwtTokenManager = new JwtTokenManager();
String token = jwtTokenManager.createToken(USERNAME);
jwtTokenManager.validateToken(token);
}
@Test
public void getAuthenticationTest() {
JwtTokenManager jwtTokenManager = new JwtTokenManager();
String token = jwtTokenManager.createToken(USERNAME);
Authentication authentication = jwtTokenManager.getAuthentication(token);
Assert.isTrue(authentication.isAuthenticated());
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
Assert.isTrue(CollectionUtil.isEmpty(authorities));
Object credentials = authentication.getCredentials();
Assert.isTrue(ObjectUtils.isEmpty(credentials));
Object details = authentication.getDetails();
Assert.isTrue(ObjectUtils.isEmpty(details));
Object principal = authentication.getPrincipal();
Assert.isTrue(ObjectUtils.isNotEmpty(principal));
String name = authentication.getName();
Assert.isTrue(StringUtil.isNotBlank(name));
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save