├── .gitignore
├── .idea
├── $PROJECT_FILE$
├── compiler.xml
├── dictionaries
│ └── wangji.xml
├── encodings.xml
├── inspectionProfiles
│ └── Project_Default.xml
├── libraries
│ ├── Maven__ch_qos_logback_logback_classic_1_2_3.xml
│ ├── Maven__ch_qos_logback_logback_core_1_2_3.xml
│ ├── Maven__com_aliyun_alibaba_dingtalk_service_sdk_1_0_1.xml
│ ├── Maven__com_fasterxml_jackson_core_jackson_annotations_2_11_4.xml
│ ├── Maven__com_fasterxml_jackson_core_jackson_core_2_11_4.xml
│ ├── Maven__com_fasterxml_jackson_core_jackson_databind_2_11_4.xml
│ ├── Maven__com_fasterxml_jackson_datatype_jackson_datatype_jdk8_2_11_4.xml
│ ├── Maven__com_fasterxml_jackson_datatype_jackson_datatype_jsr310_2_11_4.xml
│ ├── Maven__com_fasterxml_jackson_module_jackson_module_parameter_names_2_11_4.xml
│ ├── Maven__com_google_code_findbugs_jsr305_3_0_2.xml
│ ├── Maven__com_google_errorprone_error_prone_annotations_2_5_1.xml
│ ├── Maven__com_google_guava_failureaccess_1_0_1.xml
│ ├── Maven__com_google_guava_guava_30_1_1_jre.xml
│ ├── Maven__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml
│ ├── Maven__com_google_j2objc_j2objc_annotations_1_3.xml
│ ├── Maven__com_jayway_jsonpath_json_path_2_4_0.xml
│ ├── Maven__com_vaadin_external_google_android_json_0_0_20131108_vaadin1.xml
│ ├── Maven__commons_logging_commons_logging_1_1_1.xml
│ ├── Maven__io_micrometer_micrometer_core_1_6_6.xml
│ ├── Maven__jakarta_activation_jakarta_activation_api_1_2_2.xml
│ ├── Maven__jakarta_annotation_jakarta_annotation_api_1_3_5.xml
│ ├── Maven__jakarta_xml_bind_jakarta_xml_bind_api_2_3_3.xml
│ ├── Maven__javax_activation_activation_1_1.xml
│ ├── Maven__javax_jms_jms_1_1.xml
│ ├── Maven__javax_mail_mail_1_4.xml
│ ├── Maven__log4j_log4j_1_2_15.xml
│ ├── Maven__net_bytebuddy_byte_buddy_1_10_22.xml
│ ├── Maven__net_bytebuddy_byte_buddy_agent_1_10_22.xml
│ ├── Maven__net_minidev_accessors_smart_1_2.xml
│ ├── Maven__net_minidev_json_smart_2_3.xml
│ ├── Maven__org_apache_logging_log4j_log4j_api_2_13_3.xml
│ ├── Maven__org_apache_logging_log4j_log4j_to_slf4j_2_13_3.xml
│ ├── Maven__org_apache_tomcat_embed_tomcat_embed_core_9_0_45.xml
│ ├── Maven__org_apache_tomcat_embed_tomcat_embed_websocket_9_0_45.xml
│ ├── Maven__org_apiguardian_apiguardian_api_1_1_0.xml
│ ├── Maven__org_assertj_assertj_core_3_18_1.xml
│ ├── Maven__org_checkerframework_checker_qual_3_8_0.xml
│ ├── Maven__org_codehaus_janino_commons_compiler_3_1_3.xml
│ ├── Maven__org_codehaus_janino_janino_3_1_3.xml
│ ├── Maven__org_glassfish_jakarta_el_3_0_3.xml
│ ├── Maven__org_hamcrest_hamcrest_2_2.xml
│ ├── Maven__org_hdrhistogram_HdrHistogram_2_1_12.xml
│ ├── Maven__org_junit_jupiter_junit_jupiter_5_7_1.xml
│ ├── Maven__org_junit_jupiter_junit_jupiter_api_5_7_1.xml
│ ├── Maven__org_junit_jupiter_junit_jupiter_engine_5_7_1.xml
│ ├── Maven__org_junit_jupiter_junit_jupiter_params_5_7_1.xml
│ ├── Maven__org_junit_platform_junit_platform_commons_1_7_1.xml
│ ├── Maven__org_junit_platform_junit_platform_engine_1_7_1.xml
│ ├── Maven__org_latencyutils_LatencyUtils_2_0_3.xml
│ ├── Maven__org_mockito_mockito_core_3_6_28.xml
│ ├── Maven__org_mockito_mockito_junit_jupiter_3_6_28.xml
│ ├── Maven__org_objenesis_objenesis_3_1.xml
│ ├── Maven__org_opentest4j_opentest4j_1_2_0.xml
│ ├── Maven__org_ow2_asm_asm_5_0_4.xml
│ ├── Maven__org_projectlombok_lombok_1_18_20.xml
│ ├── Maven__org_skyscreamer_jsonassert_1_5_0.xml
│ ├── Maven__org_slf4j_jul_to_slf4j_1_7_30.xml
│ ├── Maven__org_slf4j_slf4j_api_1_7_30.xml
│ ├── Maven__org_springframework_boot_spring_boot_2_4_5.xml
│ ├── Maven__org_springframework_boot_spring_boot_actuator_2_4_5.xml
│ ├── Maven__org_springframework_boot_spring_boot_actuator_autoconfigure_2_4_5.xml
│ ├── Maven__org_springframework_boot_spring_boot_autoconfigure_2_4_5.xml
│ ├── Maven__org_springframework_boot_spring_boot_configuration_processor_2_4_5.xml
│ ├── Maven__org_springframework_boot_spring_boot_devtools_2_4_5.xml
│ ├── Maven__org_springframework_boot_spring_boot_starter_2_4_5.xml
│ ├── Maven__org_springframework_boot_spring_boot_starter_actuator_2_4_5.xml
│ ├── Maven__org_springframework_boot_spring_boot_starter_json_2_4_5.xml
│ ├── Maven__org_springframework_boot_spring_boot_starter_logging_2_4_5.xml
│ ├── Maven__org_springframework_boot_spring_boot_starter_test_2_4_5.xml
│ ├── Maven__org_springframework_boot_spring_boot_starter_tomcat_2_4_5.xml
│ ├── Maven__org_springframework_boot_spring_boot_starter_web_2_4_5.xml
│ ├── Maven__org_springframework_boot_spring_boot_test_2_4_5.xml
│ ├── Maven__org_springframework_boot_spring_boot_test_autoconfigure_2_4_5.xml
│ ├── Maven__org_springframework_spring_aop_5_3_6.xml
│ ├── Maven__org_springframework_spring_beans_5_3_6.xml
│ ├── Maven__org_springframework_spring_context_5_3_6.xml
│ ├── Maven__org_springframework_spring_core_5_3_6.xml
│ ├── Maven__org_springframework_spring_expression_5_3_6.xml
│ ├── Maven__org_springframework_spring_jcl_5_3_6.xml
│ ├── Maven__org_springframework_spring_test_5_3_6.xml
│ ├── Maven__org_springframework_spring_web_5_3_6.xml
│ ├── Maven__org_springframework_spring_webmvc_5_3_6.xml
│ ├── Maven__org_xmlunit_xmlunit_core_2_7_0.xml
│ └── Maven__org_yaml_snakeyaml_1_27.xml
├── misc.xml
├── modules.xml
├── qaplug_profiles.xml
├── uiDesigner.xml
├── vcs.xml
└── workspace.xml
├── .mvn
└── wrapper
│ ├── MavenWrapperDownloader.java
│ ├── maven-wrapper.jar
│ └── maven-wrapper.properties
├── LOGBACK_README.md
├── README.md
├── dingtalk-robot-logback-demo
├── .gitignore
├── .mvn
│ └── wrapper
│ │ ├── MavenWrapperDownloader.java
│ │ ├── maven-wrapper.jar
│ │ └── maven-wrapper.properties
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── github
│ │ │ └── wangji92
│ │ │ └── logbackappenddemo
│ │ │ ├── DingtalkRobotLogbackDemoApplication.java
│ │ │ └── controller
│ │ │ └── TestController.java
│ └── resources
│ │ ├── application.properties
│ │ ├── logback-dingtalk-better.xml
│ │ ├── logback-dingtalk-custom-layout-append.xml
│ │ ├── logback-dingtalk-pattern-layout-append.xml
│ │ ├── logback-spring-autoconfig-dingtalk.xml
│ │ └── logback-spring-help-memory.xml
│ └── test
│ └── java
│ └── com
│ └── github
│ └── wangji92
│ └── logbackappenddemo
│ └── DingtalkRobotLogbackDemoApplicationTests.java
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── github
│ │ └── wangji92
│ │ └── dingtalkrobot
│ │ ├── DingTalkRobotAppendAutoConfiguration.java
│ │ ├── DingTalkRobotAppendProperties.java
│ │ ├── core
│ │ ├── DingTalkRobotAppendBuilder.java
│ │ ├── DingTalkRobotLogbackAppendBootstrap.java
│ │ └── DingTalkRobotSender.java
│ │ ├── logback
│ │ ├── append
│ │ │ └── DingTalkRobotAppend.java
│ │ ├── layout
│ │ │ └── DingTalkRobotLayout.java
│ │ ├── listener
│ │ │ └── LoggerStartupListener.java
│ │ ├── pattern
│ │ │ └── CenterBracketsTemplateConverter.java
│ │ └── property
│ │ │ └── LocalIpDefiner.java
│ │ └── utils
│ │ └── IpUtils.java
└── resources
│ ├── META-INF
│ └── spring.factories
│ ├── com
│ └── github
│ │ └── wangji92
│ │ └── dingtalkrobot
│ │ ├── logback-dingtalk-robot-base.xml
│ │ ├── logback-dingtalk-robot-custom-layout.xml
│ │ └── logback-dingtalk-robot-pattern-layout.xml
│ └── example
│ └── logback-dingtalk-robot-example.xml
└── test
└── java
└── com
└── github
└── wangji92
└── dingtalkrobot
└── DingtalkRobotLogbackAlarmSpringBootStartApplicationTests.java
/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | *.idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
--------------------------------------------------------------------------------
/.idea/$PROJECT_FILE$:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
23 |
24 |
--------------------------------------------------------------------------------
/.idea/dictionaries/wangji.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | dingtalk
5 | dingtalkrobot
6 | janino
7 | webhook
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__ch_qos_logback_logback_classic_1_2_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__ch_qos_logback_logback_core_1_2_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_aliyun_alibaba_dingtalk_service_sdk_1_0_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_annotations_2_11_4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_core_2_11_4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_databind_2_11_4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jdk8_2_11_4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_fasterxml_jackson_datatype_jackson_datatype_jsr310_2_11_4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_fasterxml_jackson_module_jackson_module_parameter_names_2_11_4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_google_code_findbugs_jsr305_3_0_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_google_errorprone_error_prone_annotations_2_5_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_google_guava_failureaccess_1_0_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_google_guava_guava_30_1_1_jre.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_google_guava_listenablefuture_9999_0_empty_to_avoid_conflict_with_guava.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_google_j2objc_j2objc_annotations_1_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_jayway_jsonpath_json_path_2_4_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__com_vaadin_external_google_android_json_0_0_20131108_vaadin1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__commons_logging_commons_logging_1_1_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__io_micrometer_micrometer_core_1_6_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__jakarta_activation_jakarta_activation_api_1_2_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__jakarta_annotation_jakarta_annotation_api_1_3_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__jakarta_xml_bind_jakarta_xml_bind_api_2_3_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__javax_activation_activation_1_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__javax_jms_jms_1_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__javax_mail_mail_1_4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__log4j_log4j_1_2_15.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__net_bytebuddy_byte_buddy_1_10_22.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__net_bytebuddy_byte_buddy_agent_1_10_22.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__net_minidev_accessors_smart_1_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__net_minidev_json_smart_2_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_logging_log4j_log4j_api_2_13_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_logging_log4j_log4j_to_slf4j_2_13_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_core_9_0_45.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apache_tomcat_embed_tomcat_embed_websocket_9_0_45.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_apiguardian_apiguardian_api_1_1_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_assertj_assertj_core_3_18_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_checkerframework_checker_qual_3_8_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_codehaus_janino_commons_compiler_3_1_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_codehaus_janino_janino_3_1_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_glassfish_jakarta_el_3_0_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_hamcrest_hamcrest_2_2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_hdrhistogram_HdrHistogram_2_1_12.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_5_7_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_api_5_7_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_engine_5_7_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_junit_jupiter_junit_jupiter_params_5_7_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_junit_platform_junit_platform_commons_1_7_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_junit_platform_junit_platform_engine_1_7_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_latencyutils_LatencyUtils_2_0_3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_mockito_mockito_core_3_6_28.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_mockito_mockito_junit_jupiter_3_6_28.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_objenesis_objenesis_3_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_opentest4j_opentest4j_1_2_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_ow2_asm_asm_5_0_4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_projectlombok_lombok_1_18_20.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_skyscreamer_jsonassert_1_5_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_slf4j_jul_to_slf4j_1_7_30.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_slf4j_slf4j_api_1_7_30.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_2_4_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_actuator_2_4_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_actuator_autoconfigure_2_4_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_autoconfigure_2_4_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_configuration_processor_2_4_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_devtools_2_4_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_2_4_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_actuator_2_4_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_json_2_4_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_logging_2_4_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_test_2_4_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_tomcat_2_4_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_starter_web_2_4_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_test_2_4_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_boot_spring_boot_test_autoconfigure_2_4_5.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_aop_5_3_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_beans_5_3_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_context_5_3_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_core_5_3_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_expression_5_3_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_jcl_5_3_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_test_5_3_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_web_5_3_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_springframework_spring_webmvc_5_3_6.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_xmlunit_xmlunit_core_2_7_0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/libraries/Maven__org_yaml_snakeyaml_1_27.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/uiDesigner.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | -
6 |
7 |
8 | -
9 |
10 |
11 | -
12 |
13 |
14 | -
15 |
16 |
17 | -
18 |
19 |
20 |
21 |
22 |
23 | -
24 |
25 |
26 |
27 |
28 |
29 | -
30 |
31 |
32 |
33 |
34 |
35 | -
36 |
37 |
38 |
39 |
40 |
41 | -
42 |
43 |
44 |
45 |
46 | -
47 |
48 |
49 |
50 |
51 | -
52 |
53 |
54 |
55 |
56 | -
57 |
58 |
59 |
60 |
61 | -
62 |
63 |
64 |
65 |
66 | -
67 |
68 |
69 |
70 |
71 | -
72 |
73 |
74 | -
75 |
76 |
77 |
78 |
79 | -
80 |
81 |
82 |
83 |
84 | -
85 |
86 |
87 |
88 |
89 | -
90 |
91 |
92 |
93 |
94 | -
95 |
96 |
97 |
98 |
99 | -
100 |
101 |
102 | -
103 |
104 |
105 | -
106 |
107 |
108 | -
109 |
110 |
111 | -
112 |
113 |
114 |
115 |
116 | -
117 |
118 |
119 | -
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2007-present the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | import java.net.*;
18 | import java.io.*;
19 | import java.nio.channels.*;
20 | import java.util.Properties;
21 |
22 | public class MavenWrapperDownloader {
23 |
24 | private static final String WRAPPER_VERSION = "0.5.6";
25 | /**
26 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
27 | */
28 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
29 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
30 |
31 | /**
32 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
33 | * use instead of the default one.
34 | */
35 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
36 | ".mvn/wrapper/maven-wrapper.properties";
37 |
38 | /**
39 | * Path where the maven-wrapper.jar will be saved to.
40 | */
41 | private static final String MAVEN_WRAPPER_JAR_PATH =
42 | ".mvn/wrapper/maven-wrapper.jar";
43 |
44 | /**
45 | * Name of the property which should be used to override the default download url for the wrapper.
46 | */
47 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
48 |
49 | public static void main(String args[]) {
50 | System.out.println("- Downloader started");
51 | File baseDirectory = new File(args[0]);
52 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
53 |
54 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
55 | // wrapperUrl parameter.
56 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
57 | String url = DEFAULT_DOWNLOAD_URL;
58 | if (mavenWrapperPropertyFile.exists()) {
59 | FileInputStream mavenWrapperPropertyFileInputStream = null;
60 | try {
61 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
62 | Properties mavenWrapperProperties = new Properties();
63 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
64 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
65 | } catch (IOException e) {
66 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
67 | } finally {
68 | try {
69 | if (mavenWrapperPropertyFileInputStream != null) {
70 | mavenWrapperPropertyFileInputStream.close();
71 | }
72 | } catch (IOException e) {
73 | // Ignore ...
74 | }
75 | }
76 | }
77 | System.out.println("- Downloading from: " + url);
78 |
79 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
80 | if (!outputFile.getParentFile().exists()) {
81 | if (!outputFile.getParentFile().mkdirs()) {
82 | System.out.println(
83 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
84 | }
85 | }
86 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
87 | try {
88 | downloadFileFromURL(url, outputFile);
89 | System.out.println("Done");
90 | System.exit(0);
91 | } catch (Throwable e) {
92 | System.out.println("- Error downloading");
93 | e.printStackTrace();
94 | System.exit(1);
95 | }
96 | }
97 |
98 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
99 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
100 | String username = System.getenv("MVNW_USERNAME");
101 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
102 | Authenticator.setDefault(new Authenticator() {
103 | @Override
104 | protected PasswordAuthentication getPasswordAuthentication() {
105 | return new PasswordAuthentication(username, password);
106 | }
107 | });
108 | }
109 | URL website = new URL(urlString);
110 | ReadableByteChannel rbc;
111 | rbc = Channels.newChannel(website.openStream());
112 | FileOutputStream fos = new FileOutputStream(destination);
113 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
114 | fos.close();
115 | rbc.close();
116 | }
117 |
118 | }
119 |
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WangJi92/dingtalk-robot-logback-append-spring-boot-start/5dab3ad095af371cdd84626eb275a49ced0cf1e3/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
3 |
--------------------------------------------------------------------------------
/LOGBACK_README.md:
--------------------------------------------------------------------------------
1 | # logback 一些不常用知识点
2 | ## 1、变量使用
3 | ### 1.1 使用变量添加默认值
4 | ```xml
5 | ${xxxLevel:-ERROR}
6 | ```
7 | ### 1.2 直接自定义变量
8 | 比如:日志需要获取本地的Ip 地址写在pattern 中 可以自己定义变量,比较灵活,比如获取本地Ip
9 | [http://logback.qos.ch/manual/configuration.html#definingPropsOnTheFly](http://logback.qos.ch/manual/configuration.html#definingPropsOnTheFly)
10 | ```java
11 | package ch.qos.logback.core.spi;
12 |
13 | public interface PropertyDefiner extends ContextAware {
14 |
15 | /**
16 | * Get the property value, defined by this property definer
17 | *
18 | * @return defined property value
19 | */
20 | String getPropertyValue();
21 | }
22 | ```
23 | ```xml
24 |
25 |
26 |
27 | round
28 | brown
29 | 24
30 |
31 |
32 |
33 |
34 | ```
35 | ### 1.3 直接使用系统变量
36 | eg 比如要获取 env | hostname, HOME 等等环境变量直接当前属性使用
37 | ```xml
38 | ${HOME}%n ${hostname}%n
39 | ```
40 |
41 | ### 1.4 直接定义属性不需要编码获取
42 |
43 | ```xml
44 |
45 |
46 |
47 | ```
48 |
49 | ## 2、使用表达式
50 |
51 |
52 | 比如说某个过滤器需要在xx条件才使用,比如 线上环境打开这个开关
53 | 需要引入包
54 | ```xml
55 |
56 | org.codehaus.janino
57 | janino
58 | 3.1.3
59 |
60 | ```
61 | ### if else
62 | [http://logback.qos.ch/manual/configuration.html#conditional](http://logback.qos.ch/manual/configuration.html#conditional)
63 | ```xml
64 |
65 |
66 |
67 |
68 |
69 |
70 | %d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger - %msg%n
71 |
72 |
73 |
74 |
75 |
76 |
77 | return formattedMessage.contains("通知");
78 |
79 |
80 | ACCEPT
81 |
82 | DENY
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 | ```
92 | ### evaluator
93 | 评估表达式 在logback 中大量使用这个表达式
94 | [http://logback.qos.ch/manual/layouts.html#Evaluators](http://logback.qos.ch/manual/layouts.html#Evaluators)
95 |
96 |
97 | xEx{depth, evaluator-1, ..., evaluator-n} 这里学到了一招 可以减少异常的深度,可以根据异常的信息进行判断是否打印
98 |
99 |
100 | eg pattern 变量中年使用
101 |
102 |
103 | [http://logback.qos.ch/manual/layouts.html#ClassicPatternLayout](http://logback.qos.ch/manual/layouts.html#ClassicPatternLayout)
104 | caller 只要满足条件 && 才答应出来
105 | ```xml
106 |
107 |
108 | logger.contains("chapters.layouts") && \
109 | message.contains("who calls thee")
110 |
111 |
112 |
113 |
114 |
115 | %-4relative [%thread] %-5level - %msg%n %caller{2, DISP_CALLER_EVAL}
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 | ```
125 | ## 3、自定义监听器
126 | 自定义监听器可以实现对于变量的注册、操作logcontext 等等! 有非常多的好处
127 | [http://logback.qos.ch/manual/configuration.html#contextListener](http://logback.qos.ch/manual/configuration.html#contextListener)
128 | ```xml
129 |
130 |
131 | true
132 |
133 | ....
134 |
135 | ```
136 | ```xml
137 | public interface LoggerContextListener {
138 |
139 | /**
140 | * Some listeners should not be removed when the LoggerContext is
141 | * reset. Such listeners are said to be reset resistant.
142 | * @return whether this listener is reset resistant or not.
143 | */
144 | boolean isResetResistant();
145 |
146 | void onStart(LoggerContext context);
147 |
148 | void onReset(LoggerContext context);
149 |
150 | void onStop(LoggerContext context);
151 |
152 | void onLevelChange(Logger logger, Level level);
153 | }
154 | ```
155 | ## 4、善用include
156 | logback 定义文件一大堆,可以通过include 的方法引入 比如定义框架 可以减少一些重复性的工作、引入即可。
157 | 结合if else 、变量 可以简单的编程都可以。
158 | [http://logback.qos.ch/manual/configuration.html#fileInclusion](http://logback.qos.ch/manual/configuration.html#fileInclusion)
159 | ```xml
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 | ```
171 | ```xml
172 |
173 |
174 |
175 | "%d - %m%n"
176 |
177 |
178 |
179 | ```
180 | ## 5、自定义转换器
181 | layout 中pattern中定义的转换器 比如thread 、level 你也可以自定义一个转换器去处理
182 | [http://logback.qos.ch/manual/layouts.html#customConversionSpecifier](http://logback.qos.ch/manual/layouts.html#customConversionSpecifier)
183 | ## 6、InvokingJoranConfiguratordirectly
184 | 直接调用启动logback ,比如spring 如何实现的呢?
185 | org.springframework.boot.logging.logback.LogbackLoggingSystem#configureByResourceUrl
186 |
187 |
188 | [http://logback.qos.ch/manual/configuration.html#joranDirectly](http://logback.qos.ch/manual/configuration.html#joranDirectly)
189 | Logback relies on a configuration library called Joran, part of logback-core. Logback's default configuration mechanism invokesJoranConfiguratoron the default configuration file it finds on the class path. If you wish to override logback's default configuration mechanism for whatever reason, you can do so by invokingJoranConfiguratordirectly. The next application,_MyApp3_, invokes JoranConfigurator on a configuration file passed as a parameter.
190 | ## 7、自定义Action
191 | 比如spring 中
192 | [http://logback.qos.ch/manual/onJoran.html#action](http://logback.qos.ch/manual/onJoran.html#action)
193 |
194 |
195 | org.springframework.boot.logging.logback.SpringProfileAction
196 | org.springframework.boot.logging.logback.SpringPropertyAction
197 | ```xml
198 |
199 |
201 | ```
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## 1、解决什么问题
2 | 基于钉钉机器人的 logback-append-spring-boot-start,可以通过自定义 logback-append 然后通过钉钉机器人的API 推送到钉钉群,解决线下或者线上 针对错误场景的消息推送,方便开发者快速发现问题解决问题,最终的目的是治理日志,减少异常日志,开发环境快速发现错误。
3 | ## 2、效果图
4 | 
5 | 
6 |
7 | ## 3、使用
8 | ### 3.1 依赖
9 | #### 3.1.1 外部依赖
10 | ```xml
11 | 30.1.1-jre
12 | 1.0.1
13 | 3.1.3
14 |
15 |
16 |
17 | com.google.guava
18 | guava
19 | ${guava-version}
20 | provided
21 |
22 |
23 |
24 |
25 | com.aliyun
26 | alibaba-dingtalk-service-sdk
27 | ${alibaba-dingtalk-service-sdk-version}
28 |
29 |
30 |
31 |
32 | org.codehaus.janino
33 | janino
34 | ${janino-version}
35 |
36 |
37 | .... logback的一些核心包 引入spring 基本上都有
38 | ```
39 | #### 3.1.2 start 包
40 | ```xml
41 |
42 | com.github.WangJi92
43 | dingtalk-robot-logback-append-spring-boot-start
44 |
45 | ```
46 | ### 3.2 相关配置信息
47 | ```properties
48 | # 自动配置打开 手动配置logback xml 引入关闭
49 | spring.dingtalk.logback.append.enable=true
50 |
51 | # 告警 应用相关配置 【应用名称 、当前环境】
52 | spring.dingtalk.logback.append.application-config.application-name=${spring.application.name}
53 | spring.dingtalk.logback.append.application-config.env=测试环境
54 |
55 | ## 日志 通知范围配置 【自动配置必须】
56 | spring.dingtalk.logback.append.log-config.append-logger-names[0]=root
57 |
58 | ## 处理ERROR 日志 【必须配置】
59 | spring.dingtalk.logback.append.log-config.log-level=ERROR
60 |
61 | ## 关键字过滤 两种方式 1、关键字 2、表达式 http://logback.qos.ch/manual/filters.html#EvaluatorFilter
62 | ## 可以都不配置 只处理loglevel 的过滤
63 |
64 | # 【自动配置支持关键字和表达式】 【手动配置仅支持表达式】
65 | #spring.dingtalk.logback.append.log-config.include-log-message-key-words[0]=dingding
66 | #spring.dingtalk.logback.append.log-config.include-log-message-key-words[1]=wangji
67 | spring.dingtalk.logback.append.log-config.kew-word-expression=return formattedMessage.contains("dingding") || formattedMessage.contains("wangji");
68 |
69 | ## 异步队列的配置 【需要注意队列的长度 可能丢日志】
70 | spring.dingtalk.logback.append.log-config.async-appender-queue-size=256
71 | spring.dingtalk.logback.append.log-config.async-appender-never-block=false
72 | spring.dingtalk.logback.append.log-config.async-appender-include-caller-data=true
73 |
74 | ## 钉钉机器人告警配置
75 | spring.dingtalk.logback.append.robot-config.robot-title=钉钉日志告警
76 | spring.dingtalk.logback.append.robot-config.webhook=https://oapi.dingtalk.com/robot/send?access_token=34b047c35744144f1433eb02fda6125ef850319e280ea4af6fe6e935ed7847df
77 | spring.dingtalk.logback.append.robot-config.sign-secret=SEC5c6533fc0e86b4f89f4dae5b3d7ee7c42c9d968e360915a21d8c4263ce39c9ca
78 |
79 | ## 钉钉告警发送速度限制 1分钟20次 guava 限制一下 1/3.5 ~=0.2875
80 | spring.dingtalk.logback.append.robot-config.rate-limiter-permits-per-second=0.2875
81 |
82 | # 钉钉通知 快捷链接配置
83 | spring.dingtalk.logback.append.quick-link-config.click-description=点击查看详情
84 |
85 | ## 链接地址支持配置各种变量[localIp]、[hostname] 等等 https://kaifa.baidu.com/searchPage?w=[localIp]
86 | ## 发现问题一键进入服务器、k8s集群的链接地址
87 | ## localIp 为logback 中定义的属性 目前已经有了 hostname、localIp、app 等等关键字
88 | ## 发现问题一键进入服务器、k8s集群的链接地址
89 | spring.dingtalk.logback.append.quick-link-config.click-url=https://kaifa.baidu.com/searchPage?w=[localIp]
90 |
91 | ```
92 |
93 | ### 3.3 自动装配
94 | 自动装配模式 不需要配置logback的xml通过编程的方式植入钉钉append。
95 | 如下为自动配置特有属性
96 |
97 | ```properties
98 | # 自动配置打开 手动配置logback xml 引入关闭
99 | spring.dingtalk.logback.append.enable=true
100 | ## 日志 通知范围配置 【自动配置必须】
101 | spring.dingtalk.logback.append.log-config.append-logger-names[0]=root
102 |
103 | ## 关键字过滤 两种方式 1、关键字 2、表达式 http://logback.qos.ch/manual/filters.html#EvaluatorFilter
104 | ## 可以都不配置 只处理loglevel 的过滤
105 | # 【自动配置支持关键字和表达式】 【手动配置仅支持表达式】
106 | #spring.dingtalk.logback.append.log-config.log-key-words[0]=dingding
107 | #spring.dingtalk.logback.append.log-config.log-key-words[1]=wangji
108 | spring.dingtalk.logback.append.log-config.kew-word-expression=return formattedMessage.contains("dingding") || formattedMessage.contains("wangji");
109 |
110 | ```
111 | 如何理解 append-logger-names 就是将钉钉日志 添加到具体的哪个logger 中去
112 | ```java
113 | private void addLoggerNameDingTalkRobotAppender(AsyncAppender asyncAppender) {
114 | DingTalkRobotAppendProperties.LogConfig logConfig = dingTalkRobotAppendProperties.getLogConfig();
115 | for (String loggerName : logConfig.getAppendLoggerNames()) {
116 | Logger logger = loggerContext.getLogger(loggerName);
117 | if (logger == null) {
118 | log.warn("dingtalk alarm logger name ={} not found", loggerName);
119 | continue;
120 | }
121 | logger.addAppender(asyncAppender);
122 | }
123 | }
124 | ```
125 |
126 |
127 | ### 3.3 手动配置xml
128 | * [com/github/wangji92/dingtalkrobot/logback-dingtalk-robot-base.xml](https://github.com/WangJi92/dingtalk-robot-logback-append-spring-boot-start/blob/master/src/main/resources/com/github/wangji92/dingtalkrobot/logback-dingtalk-robot-base.xml)
129 |
130 | 这个是基础配置的属性logback 中使用, spring 扩展logback 提供的 springProperty 标签注入logback 属性
131 | 先引入基础 然后引入具体的 layout ,可以在中间 修改基础引入的属性 比如 DINGTALK_ROBOT_LOG_PATTERN 这个属性 修改一下 ch.qos.logback.classic.encoder.PatternLayoutEncoder
132 | 中使用的日志的模板,使用 CBT_CONVERT_DINGTALK_ROBOT_LOG_PATTERN 进行替换。
133 |
134 | * [spring profile-specific-configuration](https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#profile-specific-configuration)
135 | * [org/springframework/boot/logging/logback/defaults.xml](https://github.com/spring-projects/spring-boot/blob/v2.4.5/spring-boot-project/spring-boot/src/main/resources/org/springframework/boot/logging/logback/defaults.xml)
136 |
137 |
138 | ```xml
139 |
141 | ```
142 |
143 | #### 3.3.1 pattern layout 定义的格式
144 | [com/github/wangji92/dingtalkrobot/logback-dingtalk-robot-pattern-layout.xml](https://github.com/WangJi92/dingtalk-robot-logback-append-spring-boot-start/blob/master/src/main/resources/com/github/wangji92/dingtalkrobot/logback-dingtalk-robot-pattern-layout.xml)
145 | ```xml
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 | ${CONSOLE_LOG_PATTERN}
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 | ```
176 | #### 3.3.2 手动编程定义的格式 [学习自己玩一下]
177 |
178 | [com/github/wangji92/dingtalkrobot/logback-dingtalk-robot-custom-layout.xml](https://github.com/WangJi92/dingtalk-robot-logback-append-spring-boot-start/blob/master/src/main/resources/com/github/wangji92/dingtalkrobot/logback-dingtalk-robot-custom-layout.xml)
179 |
180 | com.github.wangji92.dingtalkrobot.logback.layout.DingTalkRobotLayout
181 | ```xml
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 | ${CONSOLE_LOG_PATTERN}
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 | ```
211 | ### 4、logback 的一些 学习
212 |
213 | [logback append 开发过程中了解的总结](LOGBACK_README.md)
214 |
215 |
--------------------------------------------------------------------------------
/dingtalk-robot-logback-demo/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
--------------------------------------------------------------------------------
/dingtalk-robot-logback-demo/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2007-present the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * https://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | import java.net.*;
18 | import java.io.*;
19 | import java.nio.channels.*;
20 | import java.util.Properties;
21 |
22 | public class MavenWrapperDownloader {
23 |
24 | private static final String WRAPPER_VERSION = "0.5.6";
25 | /**
26 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
27 | */
28 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
29 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
30 |
31 | /**
32 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
33 | * use instead of the default one.
34 | */
35 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
36 | ".mvn/wrapper/maven-wrapper.properties";
37 |
38 | /**
39 | * Path where the maven-wrapper.jar will be saved to.
40 | */
41 | private static final String MAVEN_WRAPPER_JAR_PATH =
42 | ".mvn/wrapper/maven-wrapper.jar";
43 |
44 | /**
45 | * Name of the property which should be used to override the default download url for the wrapper.
46 | */
47 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
48 |
49 | public static void main(String args[]) {
50 | System.out.println("- Downloader started");
51 | File baseDirectory = new File(args[0]);
52 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
53 |
54 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
55 | // wrapperUrl parameter.
56 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
57 | String url = DEFAULT_DOWNLOAD_URL;
58 | if (mavenWrapperPropertyFile.exists()) {
59 | FileInputStream mavenWrapperPropertyFileInputStream = null;
60 | try {
61 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
62 | Properties mavenWrapperProperties = new Properties();
63 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
64 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
65 | } catch (IOException e) {
66 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
67 | } finally {
68 | try {
69 | if (mavenWrapperPropertyFileInputStream != null) {
70 | mavenWrapperPropertyFileInputStream.close();
71 | }
72 | } catch (IOException e) {
73 | // Ignore ...
74 | }
75 | }
76 | }
77 | System.out.println("- Downloading from: " + url);
78 |
79 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
80 | if (!outputFile.getParentFile().exists()) {
81 | if (!outputFile.getParentFile().mkdirs()) {
82 | System.out.println(
83 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
84 | }
85 | }
86 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
87 | try {
88 | downloadFileFromURL(url, outputFile);
89 | System.out.println("Done");
90 | System.exit(0);
91 | } catch (Throwable e) {
92 | System.out.println("- Error downloading");
93 | e.printStackTrace();
94 | System.exit(1);
95 | }
96 | }
97 |
98 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
99 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
100 | String username = System.getenv("MVNW_USERNAME");
101 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
102 | Authenticator.setDefault(new Authenticator() {
103 | @Override
104 | protected PasswordAuthentication getPasswordAuthentication() {
105 | return new PasswordAuthentication(username, password);
106 | }
107 | });
108 | }
109 | URL website = new URL(urlString);
110 | ReadableByteChannel rbc;
111 | rbc = Channels.newChannel(website.openStream());
112 | FileOutputStream fos = new FileOutputStream(destination);
113 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
114 | fos.close();
115 | rbc.close();
116 | }
117 |
118 | }
119 |
--------------------------------------------------------------------------------
/dingtalk-robot-logback-demo/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/WangJi92/dingtalk-robot-logback-append-spring-boot-start/5dab3ad095af371cdd84626eb275a49ced0cf1e3/dingtalk-robot-logback-demo/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/dingtalk-robot-logback-demo/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
3 |
--------------------------------------------------------------------------------
/dingtalk-robot-logback-demo/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM https://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM set title of command window
39 | title %0
40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
42 |
43 | @REM set %HOME% to equivalent of $HOME
44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45 |
46 | @REM Execute a user defined script before this one
47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
51 | :skipRcPre
52 |
53 | @setlocal
54 |
55 | set ERROR_CODE=0
56 |
57 | @REM To isolate internal variables from possible post scripts, we use another setlocal
58 | @setlocal
59 |
60 | @REM ==== START VALIDATION ====
61 | if not "%JAVA_HOME%" == "" goto OkJHome
62 |
63 | echo.
64 | echo Error: JAVA_HOME not found in your environment. >&2
65 | echo Please set the JAVA_HOME variable in your environment to match the >&2
66 | echo location of your Java installation. >&2
67 | echo.
68 | goto error
69 |
70 | :OkJHome
71 | if exist "%JAVA_HOME%\bin\java.exe" goto init
72 |
73 | echo.
74 | echo Error: JAVA_HOME is set to an invalid directory. >&2
75 | echo JAVA_HOME = "%JAVA_HOME%" >&2
76 | echo Please set the JAVA_HOME variable in your environment to match the >&2
77 | echo location of your Java installation. >&2
78 | echo.
79 | goto error
80 |
81 | @REM ==== END VALIDATION ====
82 |
83 | :init
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
122 |
123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
124 |
125 | FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
127 | )
128 |
129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
131 | if exist %WRAPPER_JAR% (
132 | if "%MVNW_VERBOSE%" == "true" (
133 | echo Found %WRAPPER_JAR%
134 | )
135 | ) else (
136 | if not "%MVNW_REPOURL%" == "" (
137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
138 | )
139 | if "%MVNW_VERBOSE%" == "true" (
140 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
141 | echo Downloading from: %DOWNLOAD_URL%
142 | )
143 |
144 | powershell -Command "&{"^
145 | "$webclient = new-object System.Net.WebClient;"^
146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
148 | "}"^
149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
150 | "}"
151 | if "%MVNW_VERBOSE%" == "true" (
152 | echo Finished downloading %WRAPPER_JAR%
153 | )
154 | )
155 | @REM End of extension
156 |
157 | @REM Provide a "standardized" way to retrieve the CLI args that will
158 | @REM work with both Windows and non-Windows executions.
159 | set MAVEN_CMD_LINE_ARGS=%*
160 |
161 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
162 | if ERRORLEVEL 1 goto error
163 | goto end
164 |
165 | :error
166 | set ERROR_CODE=1
167 |
168 | :end
169 | @endlocal & set ERROR_CODE=%ERROR_CODE%
170 |
171 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
172 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
173 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
174 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
175 | :skipRcPost
176 |
177 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
178 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
179 |
180 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
181 |
182 | exit /B %ERROR_CODE%
183 |
--------------------------------------------------------------------------------
/dingtalk-robot-logback-demo/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.4.5
9 |
10 |
11 | com.github.WangJi92
12 | dingtalk-robot-logback-demo
13 | 0.0.1-SNAPSHOT
14 | dingtalk-robot-logback-demo
15 | 钉钉告警demo
16 |
17 | 1.8
18 | 30.1.1-jre
19 |
20 |
21 |
22 | org.springframework.boot
23 | spring-boot-starter-web
24 |
25 |
26 |
27 | org.springframework.boot
28 | spring-boot-devtools
29 | runtime
30 | true
31 |
32 |
33 | org.springframework.boot
34 | spring-boot-configuration-processor
35 | true
36 |
37 |
38 | org.projectlombok
39 | lombok
40 | true
41 |
42 |
43 | org.springframework.boot
44 | spring-boot-starter-test
45 | test
46 |
47 |
48 | com.google.guava
49 | guava
50 | ${guava-version}
51 | provided
52 |
53 |
54 | com.github.WangJi92
55 | dingtalk-robot-logback-append-spring-boot-start
56 | 0.0.5
57 |
58 |
59 | org.springframework.boot
60 | spring-boot-starter-actuator
61 |
62 |
63 |
64 |
65 |
66 |
67 | org.springframework.boot
68 | spring-boot-maven-plugin
69 |
70 |
71 |
72 | org.projectlombok
73 | lombok
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/dingtalk-robot-logback-demo/src/main/java/com/github/wangji92/logbackappenddemo/DingtalkRobotLogbackDemoApplication.java:
--------------------------------------------------------------------------------
1 | package com.github.wangji92.logbackappenddemo;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | /**
7 | * @author 汪小哥
8 | */
9 | @SpringBootApplication
10 | public class DingtalkRobotLogbackDemoApplication {
11 |
12 | public static void main(String[] args) {
13 | SpringApplication.run(DingtalkRobotLogbackDemoApplication.class, args);
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/dingtalk-robot-logback-demo/src/main/java/com/github/wangji92/logbackappenddemo/controller/TestController.java:
--------------------------------------------------------------------------------
1 | package com.github.wangji92.logbackappenddemo.controller;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.slf4j.MDC;
5 | import org.springframework.http.ResponseEntity;
6 | import org.springframework.web.bind.annotation.GetMapping;
7 | import org.springframework.web.bind.annotation.RequestParam;
8 | import org.springframework.web.bind.annotation.RestController;
9 |
10 | /**
11 | * 模拟服务不正常
12 | *
13 | * @author 汪小哥
14 | * @date 02-04-2021
15 | */
16 | @RestController
17 | @Slf4j
18 | public class TestController {
19 |
20 | /**
21 | * 打印日志
22 | *
23 | * @param message
24 | * @return
25 | */
26 | @GetMapping("/logError")
27 | public ResponseEntity logError(@RequestParam(required = false) String message) {
28 | MDC.put("testMdc", "testMdc");
29 | MDC.put("testMdc2", "testMdc2");
30 | try {
31 | doException();
32 | } catch (Exception e) {
33 | log.error("exception {}", message, e);
34 | }
35 | return ResponseEntity.ok(200);
36 | }
37 |
38 | int doException() {
39 | int a = 1 / 0;
40 | return a;
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/dingtalk-robot-logback-demo/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | # \u914D\u7F6E \u8D70\u54EA\u4E2A logback xml
2 |
3 | #logging.config=classpath:logback-dingtalk-better.xml
4 | #logging.config=classpath:logback-dingtalk-custom-layout-append.xml
5 | #logging.config=classpath:logback-dingtalk-pattern-layout-append.xml
6 |
7 | #\u81EA\u52A8\u88C5\u914D spring.dingtalk.logback.append.enable=true \u4E0D\u9700\u8981\u914D\u7F6Exml
8 | logging.config=classpath:logback-spring-autoconfig-dingtalk.xml
9 |
10 | #\u7F16\u7801\u65B9\u5F0F \u4E0D\u7136\u4E71\u7801
11 | logging.charset.console=UTF-8
12 |
13 | spring.application.name=logback demo
14 |
15 | # \u81EA\u52A8\u914D\u7F6E\u5173\u95ED \u8D70xml
16 | spring.dingtalk.logback.append.enable=true
17 | # \u544A\u8B66 \u5E94\u7528\u76F8\u5173\u914D\u7F6E
18 | spring.dingtalk.logback.append.application-config.application-name=${spring.application.name}
19 | spring.dingtalk.logback.append.application-config.env=\u6D4B\u8BD5\u73AF\u5883
20 |
21 | ## \u65E5\u5FD7 \u901A\u77E5\u8303\u56F4\u914D\u7F6E
22 | spring.dingtalk.logback.append.log-config.append-logger-names[0]=root
23 |
24 | spring.dingtalk.logback.append.log-config.log-level=ERROR
25 | #spring.dingtalk.logback.append.log-config.include-log-message-key-words=dingding
26 | #spring.dingtalk.logback.append.log-config.include-log-message-key-words=wangji
27 |
28 | spring.dingtalk.logback.append.log-config.kew-word-expression=return formattedMessage.contains("dingding") || formattedMessage.contains("wangji");
29 | spring.dingtalk.logback.append.log-config.async-appender-queue-size=10
30 | spring.dingtalk.logback.append.log-config.async-appender-never-block=false
31 | spring.dingtalk.logback.append.log-config.async-appender-include-caller-data=true
32 |
33 | ## \u9489\u9489\u673A\u5668\u4EBA\u544A\u8B66\u914D\u7F6E
34 | spring.dingtalk.logback.append.robot-config.robot-title=\u9489\u9489\u65E5\u5FD7\u544A\u8B66
35 | spring.dingtalk.logback.append.robot-config.webhook=https://oapi.dingtalk.com/robot/send?access_token=34b047c35744144f1433eb02fda6125ef850319e280ea4af6fe6e935ed7847df
36 | spring.dingtalk.logback.append.robot-config.sign-secret=SEC5c6533fc0e86b4f89f4dae5b3d7ee7c42c9d968e360915a21d8c4263ce39c9ca
37 | spring.dingtalk.logback.append.robot-config.rate-limiter-permits-per-second=0.2875
38 |
39 | # \u9489\u9489\u901A\u77E5 \u5FEB\u6377\u94FE\u63A5\u914D\u7F6E
40 | spring.dingtalk.logback.append.quick-link-config.click-description=\u70B9\u51FB\u67E5\u770B\u8BE6\u60C5
41 | spring.dingtalk.logback.append.quick-link-config.click-url=https://kaifa.baidu.com/searchPage?w=[localIp]
42 |
43 |
44 |
--------------------------------------------------------------------------------
/dingtalk-robot-logback-demo/src/main/resources/logback-dingtalk-better.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | ${CONSOLE_LOG_PATTERN}
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/dingtalk-robot-logback-demo/src/main/resources/logback-dingtalk-custom-layout-append.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | ${CONSOLE_LOG_PATTERN}
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/dingtalk-robot-logback-demo/src/main/resources/logback-dingtalk-pattern-layout-append.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | ${CONSOLE_LOG_PATTERN}
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/dingtalk-robot-logback-demo/src/main/resources/logback-spring-autoconfig-dingtalk.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | ${CONSOLE_LOG_PATTERN}
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/dingtalk-robot-logback-demo/src/main/resources/logback-spring-help-memory.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 | logback
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | info
28 |
29 |
30 | ${CONSOLE_LOG_PATTERN}
31 |
32 | UTF-8
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | ${LOG_FILE}/web_debug.log
41 |
42 |
43 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
44 | UTF-8
45 |
46 |
47 |
48 |
49 | ${LOG_FILE}/web-debug-%d{yyyy-MM-dd}.%i.log
50 |
51 | 100MB
52 |
53 |
54 | 15
55 |
56 |
57 |
58 | debug
59 | ACCEPT
60 | DENY
61 |
62 |
63 |
64 |
65 |
66 |
67 | ${LOG_FILE}/web_info.log
68 |
69 |
70 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
71 | UTF-8
72 |
73 |
74 |
75 |
76 | ${LOG_FILE}/web-info-%d{yyyy-MM-dd}.%i.log
77 |
78 | 100MB
79 |
80 |
81 | 15
82 |
83 |
84 |
85 | info
86 | ACCEPT
87 | DENY
88 |
89 |
90 |
91 |
92 |
93 |
94 | ${LOG_FILE}/web_warn.log
95 |
96 |
97 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
98 | UTF-8
99 |
100 |
101 |
102 | ${LOG_FILE}/web-warn-%d{yyyy-MM-dd}.%i.log
103 |
104 | 100MB
105 |
106 |
107 | 15
108 |
109 |
110 |
111 | warn
112 | ACCEPT
113 | DENY
114 |
115 |
116 |
117 |
118 |
119 |
120 | ${LOG_FILE}/web_error.log
121 |
122 |
123 | %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
124 | UTF-8
125 |
126 |
127 |
128 | ${LOG_FILE}/web-error-%d{yyyy-MM-dd}.%i.log
129 |
130 | 100MB
131 |
132 |
133 | 15
134 |
135 |
136 |
137 | ERROR
138 | ACCEPT
139 | DENY
140 |
141 |
142 |
143 |
155 |
156 |
162 |
163 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
194 |
195 |
--------------------------------------------------------------------------------
/dingtalk-robot-logback-demo/src/test/java/com/github/wangji92/logbackappenddemo/DingtalkRobotLogbackDemoApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.github.wangji92.logbackappenddemo;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class DingtalkRobotLogbackDemoApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/mvnw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ----------------------------------------------------------------------------
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # https://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | # ----------------------------------------------------------------------------
20 |
21 | # ----------------------------------------------------------------------------
22 | # Maven Start Up Batch script
23 | #
24 | # Required ENV vars:
25 | # ------------------
26 | # JAVA_HOME - location of a JDK home dir
27 | #
28 | # Optional ENV vars
29 | # -----------------
30 | # M2_HOME - location of maven2's installed home dir
31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
32 | # e.g. to debug Maven itself, use
33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
35 | # ----------------------------------------------------------------------------
36 |
37 | if [ -z "$MAVEN_SKIP_RC" ]; then
38 |
39 | if [ -f /etc/mavenrc ]; then
40 | . /etc/mavenrc
41 | fi
42 |
43 | if [ -f "$HOME/.mavenrc" ]; then
44 | . "$HOME/.mavenrc"
45 | fi
46 |
47 | fi
48 |
49 | # OS specific support. $var _must_ be set to either true or false.
50 | cygwin=false
51 | darwin=false
52 | mingw=false
53 | case "$(uname)" in
54 | CYGWIN*) cygwin=true ;;
55 | MINGW*) mingw=true ;;
56 | Darwin*)
57 | darwin=true
58 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
59 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
60 | if [ -z "$JAVA_HOME" ]; then
61 | if [ -x "/usr/libexec/java_home" ]; then
62 | export JAVA_HOME="$(/usr/libexec/java_home)"
63 | else
64 | export JAVA_HOME="/Library/Java/Home"
65 | fi
66 | fi
67 | ;;
68 | esac
69 |
70 | if [ -z "$JAVA_HOME" ]; then
71 | if [ -r /etc/gentoo-release ]; then
72 | JAVA_HOME=$(java-config --jre-home)
73 | fi
74 | fi
75 |
76 | if [ -z "$M2_HOME" ]; then
77 | ## resolve links - $0 may be a link to maven's home
78 | PRG="$0"
79 |
80 | # need this for relative symlinks
81 | while [ -h "$PRG" ]; do
82 | ls=$(ls -ld "$PRG")
83 | link=$(expr "$ls" : '.*-> \(.*\)$')
84 | if expr "$link" : '/.*' >/dev/null; then
85 | PRG="$link"
86 | else
87 | PRG="$(dirname "$PRG")/$link"
88 | fi
89 | done
90 |
91 | saveddir=$(pwd)
92 |
93 | M2_HOME=$(dirname "$PRG")/..
94 |
95 | # make it fully qualified
96 | M2_HOME=$(cd "$M2_HOME" && pwd)
97 |
98 | cd "$saveddir"
99 | # echo Using m2 at $M2_HOME
100 | fi
101 |
102 | # For Cygwin, ensure paths are in UNIX format before anything is touched
103 | if $cygwin; then
104 | [ -n "$M2_HOME" ] &&
105 | M2_HOME=$(cygpath --unix "$M2_HOME")
106 | [ -n "$JAVA_HOME" ] &&
107 | JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
108 | [ -n "$CLASSPATH" ] &&
109 | CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
110 | fi
111 |
112 | # For Mingw, ensure paths are in UNIX format before anything is touched
113 | if $mingw; then
114 | [ -n "$M2_HOME" ] &&
115 | M2_HOME="$( (
116 | cd "$M2_HOME"
117 | pwd
118 | ))"
119 | [ -n "$JAVA_HOME" ] &&
120 | JAVA_HOME="$( (
121 | cd "$JAVA_HOME"
122 | pwd
123 | ))"
124 | fi
125 |
126 | if [ -z "$JAVA_HOME" ]; then
127 | javaExecutable="$(which javac)"
128 | if [ -n "$javaExecutable" ] && ! [ "$(expr \"$javaExecutable\" : '\([^ ]*\)')" = "no" ]; then
129 | # readlink(1) is not available as standard on Solaris 10.
130 | readLink=$(which readlink)
131 | if [ ! $(expr "$readLink" : '\([^ ]*\)') = "no" ]; then
132 | if $darwin; then
133 | javaHome="$(dirname \"$javaExecutable\")"
134 | javaExecutable="$(cd \"$javaHome\" && pwd -P)/javac"
135 | else
136 | javaExecutable="$(readlink -f \"$javaExecutable\")"
137 | fi
138 | javaHome="$(dirname \"$javaExecutable\")"
139 | javaHome=$(expr "$javaHome" : '\(.*\)/bin')
140 | JAVA_HOME="$javaHome"
141 | export JAVA_HOME
142 | fi
143 | fi
144 | fi
145 |
146 | if [ -z "$JAVACMD" ]; then
147 | if [ -n "$JAVA_HOME" ]; then
148 | if [ -x "$JAVA_HOME/jre/sh/java" ]; then
149 | # IBM's JDK on AIX uses strange locations for the executables
150 | JAVACMD="$JAVA_HOME/jre/sh/java"
151 | else
152 | JAVACMD="$JAVA_HOME/bin/java"
153 | fi
154 | else
155 | JAVACMD="$(which java)"
156 | fi
157 | fi
158 |
159 | if [ ! -x "$JAVACMD" ]; then
160 | echo "Error: JAVA_HOME is not defined correctly." >&2
161 | echo " We cannot execute $JAVACMD" >&2
162 | exit 1
163 | fi
164 |
165 | if [ -z "$JAVA_HOME" ]; then
166 | echo "Warning: JAVA_HOME environment variable is not set."
167 | fi
168 |
169 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
170 |
171 | # traverses directory structure from process work directory to filesystem root
172 | # first directory with .mvn subdirectory is considered project base directory
173 | find_maven_basedir() {
174 |
175 | if [ -z "$1" ]; then
176 | echo "Path not specified to find_maven_basedir"
177 | return 1
178 | fi
179 |
180 | basedir="$1"
181 | wdir="$1"
182 | while [ "$wdir" != '/' ]; do
183 | if [ -d "$wdir"/.mvn ]; then
184 | basedir=$wdir
185 | break
186 | fi
187 | # workaround for JBEAP-8937 (on Solaris 10/Sparc)
188 | if [ -d "${wdir}" ]; then
189 | wdir=$(
190 | cd "$wdir/.."
191 | pwd
192 | )
193 | fi
194 | # end of workaround
195 | done
196 | echo "${basedir}"
197 | }
198 |
199 | # concatenates all lines of a file
200 | concat_lines() {
201 | if [ -f "$1" ]; then
202 | echo "$(tr -s '\n' ' ' <"$1")"
203 | fi
204 | }
205 |
206 | BASE_DIR=$(find_maven_basedir "$(pwd)")
207 | if [ -z "$BASE_DIR" ]; then
208 | exit 1
209 | fi
210 |
211 | ##########################################################################################
212 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
213 | # This allows using the maven wrapper in projects that prohibit checking in binary data.
214 | ##########################################################################################
215 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
216 | if [ "$MVNW_VERBOSE" = true ]; then
217 | echo "Found .mvn/wrapper/maven-wrapper.jar"
218 | fi
219 | else
220 | if [ "$MVNW_VERBOSE" = true ]; then
221 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
222 | fi
223 | if [ -n "$MVNW_REPOURL" ]; then
224 | jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
225 | else
226 | jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
227 | fi
228 | while IFS="=" read key value; do
229 | case "$key" in wrapperUrl)
230 | jarUrl="$value"
231 | break
232 | ;;
233 | esac
234 | done <"$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
235 | if [ "$MVNW_VERBOSE" = true ]; then
236 | echo "Downloading from: $jarUrl"
237 | fi
238 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
239 | if $cygwin; then
240 | wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
241 | fi
242 |
243 | if command -v wget >/dev/null; then
244 | if [ "$MVNW_VERBOSE" = true ]; then
245 | echo "Found wget ... using wget"
246 | fi
247 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
248 | wget "$jarUrl" -O "$wrapperJarPath"
249 | else
250 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
251 | fi
252 | elif command -v curl >/dev/null; then
253 | if [ "$MVNW_VERBOSE" = true ]; then
254 | echo "Found curl ... using curl"
255 | fi
256 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
257 | curl -o "$wrapperJarPath" "$jarUrl" -f
258 | else
259 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
260 | fi
261 |
262 | else
263 | if [ "$MVNW_VERBOSE" = true ]; then
264 | echo "Falling back to using Java to download"
265 | fi
266 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
267 | # For Cygwin, switch paths to Windows format before running javac
268 | if $cygwin; then
269 | javaClass=$(cygpath --path --windows "$javaClass")
270 | fi
271 | if [ -e "$javaClass" ]; then
272 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
273 | if [ "$MVNW_VERBOSE" = true ]; then
274 | echo " - Compiling MavenWrapperDownloader.java ..."
275 | fi
276 | # Compiling the Java class
277 | ("$JAVA_HOME/bin/javac" "$javaClass")
278 | fi
279 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
280 | # Running the downloader
281 | if [ "$MVNW_VERBOSE" = true ]; then
282 | echo " - Running MavenWrapperDownloader.java ..."
283 | fi
284 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
285 | fi
286 | fi
287 | fi
288 | fi
289 | ##########################################################################################
290 | # End of extension
291 | ##########################################################################################
292 |
293 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
294 | if [ "$MVNW_VERBOSE" = true ]; then
295 | echo $MAVEN_PROJECTBASEDIR
296 | fi
297 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
298 |
299 | # For Cygwin, switch paths to Windows format before running java
300 | if $cygwin; then
301 | [ -n "$M2_HOME" ] &&
302 | M2_HOME=$(cygpath --path --windows "$M2_HOME")
303 | [ -n "$JAVA_HOME" ] &&
304 | JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
305 | [ -n "$CLASSPATH" ] &&
306 | CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
307 | [ -n "$MAVEN_PROJECTBASEDIR" ] &&
308 | MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
309 | fi
310 |
311 | # Provide a "standardized" way to retrieve the CLI args that will
312 | # work with both Windows and non-Windows executions.
313 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
314 | export MAVEN_CMD_LINE_ARGS
315 |
316 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
317 |
318 | exec "$JAVACMD" \
319 | $MAVEN_OPTS \
320 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
321 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
322 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
323 |
--------------------------------------------------------------------------------
/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM https://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM set title of command window
39 | title %0
40 | @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
42 |
43 | @REM set %HOME% to equivalent of $HOME
44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45 |
46 | @REM Execute a user defined script before this one
47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
51 | :skipRcPre
52 |
53 | @setlocal
54 |
55 | set ERROR_CODE=0
56 |
57 | @REM To isolate internal variables from possible post scripts, we use another setlocal
58 | @setlocal
59 |
60 | @REM ==== START VALIDATION ====
61 | if not "%JAVA_HOME%" == "" goto OkJHome
62 |
63 | echo.
64 | echo Error: JAVA_HOME not found in your environment. >&2
65 | echo Please set the JAVA_HOME variable in your environment to match the >&2
66 | echo location of your Java installation. >&2
67 | echo.
68 | goto error
69 |
70 | :OkJHome
71 | if exist "%JAVA_HOME%\bin\java.exe" goto init
72 |
73 | echo.
74 | echo Error: JAVA_HOME is set to an invalid directory. >&2
75 | echo JAVA_HOME = "%JAVA_HOME%" >&2
76 | echo Please set the JAVA_HOME variable in your environment to match the >&2
77 | echo location of your Java installation. >&2
78 | echo.
79 | goto error
80 |
81 | @REM ==== END VALIDATION ====
82 |
83 | :init
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
122 |
123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
124 |
125 | FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
127 | )
128 |
129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
131 | if exist %WRAPPER_JAR% (
132 | if "%MVNW_VERBOSE%" == "true" (
133 | echo Found %WRAPPER_JAR%
134 | )
135 | ) else (
136 | if not "%MVNW_REPOURL%" == "" (
137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
138 | )
139 | if "%MVNW_VERBOSE%" == "true" (
140 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
141 | echo Downloading from: %DOWNLOAD_URL%
142 | )
143 |
144 | powershell -Command "&{"^
145 | "$webclient = new-object System.Net.WebClient;"^
146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
148 | "}"^
149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
150 | "}"
151 | if "%MVNW_VERBOSE%" == "true" (
152 | echo Finished downloading %WRAPPER_JAR%
153 | )
154 | )
155 | @REM End of extension
156 |
157 | @REM Provide a "standardized" way to retrieve the CLI args that will
158 | @REM work with both Windows and non-Windows executions.
159 | set MAVEN_CMD_LINE_ARGS=%*
160 |
161 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
162 | if ERRORLEVEL 1 goto error
163 | goto end
164 |
165 | :error
166 | set ERROR_CODE=1
167 |
168 | :end
169 | @endlocal & set ERROR_CODE=%ERROR_CODE%
170 |
171 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
172 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
173 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
174 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
175 | :skipRcPost
176 |
177 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
178 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
179 |
180 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
181 |
182 | exit /B %ERROR_CODE%
183 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.github.WangJi92
7 | dingtalk-robot-logback-append-spring-boot-start
8 | 0.0.5
9 | dingtalk-robot-logback-append-spring-boot-start
10 | 自定义logback append 将日志 通过钉钉API将日志信息通知到群
11 | https://github.com/WangJi92/dingtalk-robot-logback-append-spring-boot-start
12 |
13 | 1.8
14 | 30.1.1-jre
15 | 1.0.1
16 | 3.1.3
17 | 2.4.5
18 |
19 |
20 |
21 | The Apache Software License, Version 2.0
22 | http://www.apache.org/licenses/LICENSE-2.0.txt
23 | repo
24 |
25 |
26 |
27 |
28 | https://github.com/WangJi92/dingtalk-robot-logback-append-spring-boot-start
29 | https://github.com/WangJi92/dingtalk-robot-logback-append-spring-boot-start.git
30 | https://github.com/WangJi92/dingtalk-robot-logback-append-spring-boot-start.gi
31 |
32 |
33 |
34 |
35 | wangji
36 | 983433479@qq.com
37 | https://github.com/WangJi92/dingtalk-robot-logback-append-spring-boot-start.gi
38 |
39 |
40 |
41 |
42 |
43 | org.springframework.boot
44 | spring-boot-dependencies
45 | ${spring-boot.version}
46 | pom
47 | import
48 |
49 |
50 |
51 |
52 |
53 | org.springframework.boot
54 | spring-boot-devtools
55 | runtime
56 | true
57 |
58 |
59 | org.springframework.boot
60 | spring-boot-starter
61 | provided
62 |
63 |
64 | org.springframework.boot
65 | spring-boot
66 | provided
67 |
68 |
69 | org.springframework
70 | spring-core
71 | provided
72 |
73 |
74 | org.springframework
75 | spring-context
76 | provided
77 |
78 |
79 | org.springframework.boot
80 | spring-boot-autoconfigure
81 | provided
82 |
83 |
84 | org.springframework.boot
85 | spring-boot-configuration-processor
86 | true
87 |
88 |
89 | org.projectlombok
90 | lombok
91 | true
92 |
93 |
94 | com.google.guava
95 | guava
96 | ${guava-version}
97 | provided
98 |
99 |
100 | com.aliyun
101 | alibaba-dingtalk-service-sdk
102 | ${alibaba-dingtalk-service-sdk-version}
103 |
104 |
105 | org.codehaus.janino
106 | janino
107 | ${janino-version}
108 |
109 |
110 |
111 |
112 |
113 |
114 | org.apache.maven.plugins
115 | maven-compiler-plugin
116 | 3.1
117 |
118 | 1.8
119 | 1.8
120 |
121 |
122 |
123 | org.apache.maven.plugins
124 | maven-source-plugin
125 | 3.0.1
126 |
127 | true
128 |
129 |
130 |
131 | compile
132 |
133 | jar
134 |
135 |
136 |
137 |
138 |
139 | org.apache.maven.plugins
140 | maven-javadoc-plugin
141 | 3.0.1
142 |
143 | false
144 | none
145 |
146 |
147 |
148 | package
149 |
150 | jar
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 | release
161 |
162 |
163 | oss
164 | https://oss.sonatype.org/content/repositories/snapshots/
165 |
166 |
167 | oss
168 | https://oss.sonatype.org/service/local/staging/deploy/maven2/
169 |
170 |
171 |
172 |
173 |
174 |
175 | org.apache.maven.plugins
176 | maven-source-plugin
177 | 3.0.1
178 |
179 |
180 | oss
181 | package
182 |
183 | jar-no-fork
184 |
185 |
186 |
187 |
188 |
189 |
190 | org.apache.maven.plugins
191 | maven-gpg-plugin
192 | 1.6
193 |
194 |
195 | oss
196 | verify
197 |
198 | sign
199 |
200 |
201 |
202 |
203 |
204 | org.sonatype.plugins
205 | nexus-staging-maven-plugin
206 | 1.6.8
207 | true
208 |
209 | oss
210 | https://oss.sonatype.org/
211 | true
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
--------------------------------------------------------------------------------
/src/main/java/com/github/wangji92/dingtalkrobot/DingTalkRobotAppendAutoConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.github.wangji92.dingtalkrobot;
2 |
3 | import com.github.wangji92.dingtalkrobot.core.DingTalkRobotLogbackAppendBootstrap;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
6 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.context.annotation.ComponentScan;
9 | import org.springframework.context.annotation.Configuration;
10 |
11 | /**
12 | * @author 汪小哥
13 | * @date 17-04-2021
14 | */
15 | @Configuration
16 | @ConditionalOnClass(name = "ch.qos.logback.classic.LoggerContext")
17 | @ConditionalOnProperty(prefix = "spring.dingtalk.logback.append", value = "enable", havingValue = "true", matchIfMissing = true)
18 | @ComponentScan(value = "com.github.wangji92.dingtalkrobot")
19 | @Slf4j
20 | public class DingTalkRobotAppendAutoConfiguration {
21 |
22 | @Bean
23 | public DingTalkRobotLogbackAppendBootstrap dingTalkRobotLogbackAlarmBootstrap() {
24 | return new DingTalkRobotLogbackAppendBootstrap();
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/github/wangji92/dingtalkrobot/DingTalkRobotAppendProperties.java:
--------------------------------------------------------------------------------
1 | package com.github.wangji92.dingtalkrobot;
2 |
3 | import ch.qos.logback.core.AsyncAppenderBase;
4 | import com.github.wangji92.dingtalkrobot.core.DingTalkRobotLogbackAppendBootstrap;
5 | import com.google.common.collect.Lists;
6 | import lombok.Data;
7 | import org.springframework.boot.context.properties.ConfigurationProperties;
8 | import org.springframework.boot.logging.LogLevel;
9 | import org.springframework.context.annotation.Configuration;
10 |
11 | import java.util.List;
12 |
13 | /**
14 | * 钉钉告警配置
15 | *
16 | * @author 汪小哥
17 | * @date 17-04-2021
18 | */
19 | @ConfigurationProperties(prefix = "spring.dingtalk.logback.append")
20 | @Data
21 | @Configuration
22 | public class DingTalkRobotAppendProperties {
23 | /**
24 | * 是否启用
25 | */
26 | private boolean enable = false;
27 | /**
28 | * 钉钉机器人的配置
29 | */
30 | private DingTalkRobot robotConfig;
31 |
32 | /**
33 | * 应用配置
34 | */
35 | private ApplicationConfig applicationConfig;
36 |
37 | /**
38 | * 日志配置
39 | */
40 | private LogConfig logConfig;
41 |
42 | /**
43 | * 查看详情
44 | */
45 | private QuickLink quickLinkConfig;
46 |
47 |
48 | @Data
49 | public static class ApplicationConfig {
50 | /**
51 | * 当前环境 not set is Environment=>spring.profiles.active
52 | */
53 | private String env = "";
54 | /**
55 | * 应用名称 not set is Environment=>spring.application.name
56 | */
57 | private String applicationName = "";
58 | }
59 |
60 | @Data
61 | public static class LogConfig {
62 | /**
63 | * 当前level 等级之上的都打印
64 | */
65 | private LogLevel logLevel = LogLevel.ERROR;
66 | /**
67 | * 消息中有关键词才钉钉通知 逗号分割
68 | * {@link DingTalkRobotLogbackAppendBootstrap#buildJaninoEvaluatorFilter()}
69 | * 这里使用的表达式 kewWordExpression : return formattedMessage.contains("keyword1") || formattedMessage.contains("keyword2");
70 | */
71 | private List includeLogMessageKeyWords;
72 |
73 | /**
74 | * 排除掉message 里面的关键字 不打印
75 | */
76 | private List excludeLogMessageKeyWords;
77 |
78 | /**
79 | * 哪些日志名称不打印 包含关键字
80 | */
81 | private List excludeLogName;
82 |
83 | /**
84 | * 消息中过滤 自己定义表达式 和 logKeyWords 冲突 {@literal http://logback.qos.ch/manual/filters.html#EvaluatorFilter}
85 | * return formattedMessage.contains("keyword1") || formattedMessage.contains("keyword12");
86 | */
87 | private String kewWordExpression = "";
88 |
89 | /**
90 | * 添加到哪些 logger name
91 | */
92 | private List appendLoggerNames = Lists.newArrayList("root");
93 |
94 | /**
95 | * mdc 里面哪些需要打印
96 | */
97 | private List mdcList = Lists.newArrayList();
98 |
99 | /**
100 | * blockingQueue长度决定了队列能放多少信息,在默认的配置下,如果blockingQueue放满了,后续想要输出日志的线程会被阻塞,
101 | * 直到Worker线程处理掉队列中的信息为止。
102 | * 根据实际情况适当调整队列长度,可以防止线程被阻塞。
103 | * {@link DingTalkRobotLogbackAppendBootstrap#buildAsyncAppender()}
104 | */
105 | private Integer asyncAppenderQueueSize = 256;
106 |
107 | /**
108 | * 这里可能会丢日志 {@link AsyncAppenderBase#put(Object) offer 方法没有足够空间直接扔掉}
109 | * 如果配置neverBlock=true,当队列满了之后,后面阻塞的线程想要输出的消息就直接被丢弃,从而线程不会阻塞。
110 | * 这个配置用于线程很重要,不能卡顿,而且日志又不是很重要的场景,因为很有可能会丢日志
111 | * {@link DingTalkRobotLogbackAppendBootstrap#buildAsyncAppender()}
112 | */
113 | private Boolean asyncAppenderNeverBlock = true;
114 |
115 | /**
116 | * 提取调用方数据可能相当昂贵。
117 | * 若要提高性能,默认情况下,当事件添加到事件队列时,不会提取与事件关联的调用方数据。
118 | * 默认情况下,只有“廉价”数据,如线程名和 都被复制了。
119 | * {@link DingTalkRobotLogbackAppendBootstrap#buildAsyncAppender()}
120 | */
121 | private Boolean asyncAppenderIncludeCallerData = true;
122 | }
123 |
124 | /**
125 | * 钉钉的配置
126 | */
127 | @Data
128 | public static class DingTalkRobot {
129 | /**
130 | * 钉钉机器人配置 webhook
131 | */
132 | private String webhook;
133 | /**
134 | * 钉钉机器人加签关键字
135 | */
136 | private String signSecret;
137 | /**
138 | * 钉钉发送消息头
139 | */
140 | private String robotTitle = "钉钉日志告警通知";
141 |
142 | /**
143 | * 机器人发送速度限制 [每分钟最多20次] 1/3.5~= 0.2857
144 | */
145 | private Double rateLimiterPermitsPerSecond = 0.2857;
146 | }
147 |
148 | /**
149 | * 打印的日志追加一个详情
150 | */
151 | @Data
152 | public static class QuickLink {
153 | /**
154 | * 点击查看详情
155 | */
156 | private String clickDescription = "点击查看详情";
157 | /**
158 | * 支持变量 ip 或者 app (应用名称)
159 | * https://kaifa.baidu.com/searchPage?wd=[localIp] or [hostname] or other 属性
160 | */
161 | private String clickUrl;
162 | }
163 |
164 |
165 | }
166 |
--------------------------------------------------------------------------------
/src/main/java/com/github/wangji92/dingtalkrobot/core/DingTalkRobotAppendBuilder.java:
--------------------------------------------------------------------------------
1 | package com.github.wangji92.dingtalkrobot.core;
2 |
3 | import ch.qos.logback.classic.LoggerContext;
4 | import com.github.wangji92.dingtalkrobot.DingTalkRobotAppendProperties;
5 | import com.github.wangji92.dingtalkrobot.logback.append.DingTalkRobotAppend;
6 | import com.github.wangji92.dingtalkrobot.logback.layout.DingTalkRobotLayout;
7 | import lombok.extern.slf4j.Slf4j;
8 | import org.springframework.context.ApplicationContext;
9 | import org.springframework.util.Assert;
10 | import org.springframework.util.StringUtils;
11 |
12 | /**
13 | * 初始化构造 DingTalkRobotAppend
14 | *
15 | * @author 汪小哥
16 | * @date 17-04-2021
17 | */
18 | @Slf4j
19 | public class DingTalkRobotAppendBuilder {
20 |
21 | private static final String HTTP = "http";
22 |
23 | private DingTalkRobotAppendProperties dingTalkRobotAppendProperties;
24 |
25 | private ApplicationContext applicationContext;
26 |
27 | private LoggerContext loggerContext;
28 |
29 | public DingTalkRobotAppendBuilder(DingTalkRobotAppendProperties dingTalkRobotAppendProperties, ApplicationContext applicationContext) {
30 | this.dingTalkRobotAppendProperties = dingTalkRobotAppendProperties;
31 | this.applicationContext = applicationContext;
32 | }
33 |
34 | /**
35 | * 构建 DingTalkRobotAppend
36 | *
37 | * @return
38 | */
39 | public DingTalkRobotAppend buildDingTalkRobotAppend() {
40 | this.checkConfig();
41 | DingTalkRobotAppend dingTalkRobotAppend = new DingTalkRobotAppend();
42 | DingTalkRobotAppendProperties.DingTalkRobot robot = dingTalkRobotAppendProperties.getRobotConfig();
43 | dingTalkRobotAppend.setWebhook(robot.getWebhook());
44 | dingTalkRobotAppend.setSignSecret(robot.getSignSecret());
45 | dingTalkRobotAppend.setRateLimiterPermitsPerSecond(dingTalkRobotAppendProperties.getRobotConfig().getRateLimiterPermitsPerSecond());
46 | String title = robot.getRobotTitle();
47 | if (!StringUtils.hasText(title)) {
48 | title = "钉钉日志告警通知";
49 | }
50 | dingTalkRobotAppend.setRobotTitle(title);
51 | dingTalkRobotAppend.setContext(loggerContext);
52 | DingTalkRobotLayout layout = this.buildDingTalkRobotLayout(loggerContext, robot);
53 | layout.setMdcList(dingTalkRobotAppendProperties.getLogConfig().getMdcList());
54 | layout.start();
55 | dingTalkRobotAppend.setLayout(layout);
56 | dingTalkRobotAppend.start();
57 | return dingTalkRobotAppend;
58 | }
59 |
60 |
61 | /**
62 | * 检查配置
63 | */
64 | private void checkConfig() {
65 | Assert.notNull(loggerContext, "logger context must not be null");
66 | Assert.notNull(dingTalkRobotAppendProperties, "dingtalk dingTalkRobotAppendProperties config must not be null");
67 |
68 | Assert.notNull(dingTalkRobotAppendProperties.getRobotConfig(), "dingtalk robot config must not be null");
69 | Assert.hasText(dingTalkRobotAppendProperties.getRobotConfig().getWebhook(), "dingtalk robot config must not be null");
70 | }
71 |
72 | /**
73 | * 构建 DingTalkRobotLayout
74 | *
75 | * @param loggerContext
76 | * @param robot
77 | * @return
78 | */
79 | private DingTalkRobotLayout buildDingTalkRobotLayout(LoggerContext loggerContext, DingTalkRobotAppendProperties.DingTalkRobot robot) {
80 | DingTalkRobotLayout layout = new DingTalkRobotLayout();
81 | layout.setContext(loggerContext);
82 | DingTalkRobotAppendProperties.ApplicationConfig applicationConfig = dingTalkRobotAppendProperties.getApplicationConfig();
83 | if (applicationConfig == null) {
84 | applicationConfig = new DingTalkRobotAppendProperties.ApplicationConfig();
85 | }
86 | String env = applicationConfig.getEnv();
87 | if (!StringUtils.hasText(env)) {
88 | env = applicationContext.getEnvironment().getProperty("spring.profiles.active");
89 | }
90 | layout.setEnv(env);
91 | String app = applicationConfig.getApplicationName();
92 | if (!StringUtils.hasText(env)) {
93 | app = applicationContext.getEnvironment().getProperty("spring.application.name");
94 | }
95 | layout.setApp(app);
96 |
97 | // 快捷链接 方便直接点击进入服务器
98 | DingTalkRobotAppendProperties.QuickLink quickLink = dingTalkRobotAppendProperties.getQuickLinkConfig();
99 | if (quickLink != null && StringUtils.hasText(quickLink.getClickDescription())) {
100 | layout.setClickDescription(quickLink.getClickDescription());
101 | if (StringUtils.hasText(quickLink.getClickUrl()) && quickLink.getClickUrl().contains(HTTP)) {
102 |
103 | layout.setClickUrl(quickLink.getClickUrl());
104 | }
105 | }
106 | return layout;
107 | }
108 |
109 | public DingTalkRobotAppendProperties getDingTalkRobotAppendProperties() {
110 | return dingTalkRobotAppendProperties;
111 | }
112 |
113 | public void setDingTalkRobotAppendProperties(DingTalkRobotAppendProperties dingTalkRobotAppendProperties) {
114 | this.dingTalkRobotAppendProperties = dingTalkRobotAppendProperties;
115 | }
116 |
117 | public ApplicationContext getApplicationContext() {
118 | return applicationContext;
119 | }
120 |
121 | public void setApplicationContext(ApplicationContext applicationContext) {
122 | this.applicationContext = applicationContext;
123 | }
124 |
125 | public LoggerContext getLoggerContext() {
126 | return loggerContext;
127 | }
128 |
129 | public void setLoggerContext(LoggerContext loggerContext) {
130 | this.loggerContext = loggerContext;
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/src/main/java/com/github/wangji92/dingtalkrobot/core/DingTalkRobotSender.java:
--------------------------------------------------------------------------------
1 | package com.github.wangji92.dingtalkrobot.core;
2 |
3 | import com.dingtalk.api.DefaultDingTalkClient;
4 | import com.dingtalk.api.DingTalkClient;
5 | import com.dingtalk.api.request.OapiRobotSendRequest;
6 | import com.dingtalk.api.response.OapiRobotSendResponse;
7 | import com.google.common.util.concurrent.RateLimiter;
8 | import com.taobao.api.ApiException;
9 | import lombok.extern.slf4j.Slf4j;
10 | import org.springframework.util.StringUtils;
11 |
12 | import javax.crypto.Mac;
13 | import javax.crypto.spec.SecretKeySpec;
14 | import java.io.UnsupportedEncodingException;
15 | import java.net.URLEncoder;
16 | import java.nio.charset.StandardCharsets;
17 | import java.security.InvalidKeyException;
18 | import java.security.NoSuchAlgorithmException;
19 | import java.util.Base64;
20 |
21 | /**
22 | * @author 汪小哥
23 | * @date 17-04-2021
24 | */
25 | @Slf4j
26 | public class DingTalkRobotSender {
27 |
28 | /**
29 | * 钉钉机器人配置 webhook
30 | */
31 | private String webhook;
32 | /**
33 | * 钉钉机器人加签关键字
34 | */
35 | private String signSecret;
36 |
37 | /**
38 | * 发送速率 [每分钟最多20次] 1/3.5~= 0.2857
39 | */
40 | private Double rateLimiterPermitsPerSecond = 0.2857;
41 |
42 | /**
43 | * 每个机器人每分钟最多发送20条
44 | */
45 | private RateLimiter rateLimiter = null;
46 |
47 | public DingTalkRobotSender(String webhook, String signSecret, Double rateLimiterPermitsPerSecond) {
48 | this.webhook = webhook;
49 | this.signSecret = signSecret;
50 | if (rateLimiterPermitsPerSecond == null) {
51 | rateLimiterPermitsPerSecond = 0.2857;
52 | }
53 | rateLimiter = RateLimiter.create(rateLimiterPermitsPerSecond);
54 | }
55 |
56 | /**
57 | * 发送钉钉消息
58 | *
59 | * @param sendRequest
60 | */
61 | public void sendToRobot(OapiRobotSendRequest sendRequest) {
62 | try {
63 | //每个机器人每分钟最多发送20条、限流处理一下
64 | rateLimiter.acquire();
65 | Long timestamp = System.currentTimeMillis();
66 | String url = webhook;
67 | if (StringUtils.hasText(signSecret)) {
68 | String sign = getSign(timestamp);
69 | url = url + "×tamp=" + timestamp + "&sign=" + sign;
70 | }
71 | DingTalkClient client = new DefaultDingTalkClient(url);
72 | try {
73 | OapiRobotSendResponse response = client.execute(sendRequest);
74 | if (!response.isSuccess()) {
75 | System.out.println(String.format("send dingtalk errorCode=%s errorMsg=%s", response.getErrcode(), response.getErrmsg()));
76 | }
77 | } catch (ApiException e) {
78 | System.out.println(String.format("send dingtalk api error=%s", e.getMessage()));
79 | }
80 | } catch (Exception e) {
81 | /**
82 | * 这里不能写日志了
83 | * @see ch.qos.logback.core.UnsynchronizedAppenderBase#addError(String)
84 | */
85 | System.out.println(String.format("send dingtalk error last=%s", e.getMessage()));
86 | }
87 | }
88 |
89 | /**
90 | * 签名
91 | *
92 | * @param timestamp
93 | * @return
94 | */
95 | private String getSign(Long timestamp) {
96 | String secret = this.signSecret;
97 | try {
98 | String stringToSign = timestamp + "\n" + secret;
99 | Mac mac = Mac.getInstance("HmacSHA256");
100 | mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
101 | byte[] signData = mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8));
102 | return URLEncoder.encode(new String(Base64.getEncoder().encode(signData)), StandardCharsets.UTF_8.name());
103 | } catch (NoSuchAlgorithmException | UnsupportedEncodingException | InvalidKeyException e) {
104 | e.printStackTrace();
105 | }
106 | return "";
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/main/java/com/github/wangji92/dingtalkrobot/logback/append/DingTalkRobotAppend.java:
--------------------------------------------------------------------------------
1 | package com.github.wangji92.dingtalkrobot.logback.append;
2 |
3 | import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
4 | import ch.qos.logback.classic.spi.ILoggingEvent;
5 | import ch.qos.logback.core.Layout;
6 | import ch.qos.logback.core.UnsynchronizedAppenderBase;
7 | import ch.qos.logback.core.encoder.Encoder;
8 | import ch.qos.logback.core.encoder.LayoutWrappingEncoder;
9 | import com.dingtalk.api.request.OapiRobotSendRequest;
10 | import com.github.wangji92.dingtalkrobot.core.DingTalkRobotSender;
11 |
12 | import java.nio.charset.StandardCharsets;
13 |
14 |
15 | /**
16 | * 实现异步 日志队列
17 | *
18 | * @author 汪小哥
19 | * @date 17-04-2021
20 | */
21 | public class DingTalkRobotAppend extends UnsynchronizedAppenderBase {
22 | /**
23 | * 钉钉机器人配置 webhook
24 | */
25 | private String webhook;
26 | /**
27 | * 钉钉机器人加签关键字
28 | */
29 | private String signSecret;
30 | /**
31 | * 通知标题
32 | */
33 | private String robotTitle;
34 |
35 | /**
36 | * 发送速率 [每分钟最多20次] 1/3.5~= 0.2857
37 | */
38 | private Double rateLimiterPermitsPerSecond = 0.2857;
39 |
40 | /**
41 | * 定义 layout 处理器 Encode
42 | *
43 | * @see PatternLayoutEncoder
44 | * @see LayoutWrappingEncoder
45 | * {@literal http://logback.qos.ch/manual/encoders.html}
46 | */
47 | private Encoder encoder;
48 | /**
49 | * 发送钉钉机器人消息
50 | */
51 | private DingTalkRobotSender dingTalkRobotSender;
52 |
53 | public DingTalkRobotAppend() {
54 | super();
55 | super.setName("dRobot");
56 | }
57 |
58 | @Override
59 | protected void append(ILoggingEvent eventObject) {
60 | if (encoder == null) {
61 | addWarn("encoder is null");
62 | return;
63 | }
64 | byte[] encodeBytes = encoder.encode(eventObject);
65 | if (dingTalkRobotSender != null) {
66 | OapiRobotSendRequest oapiRobotSendRequest = new OapiRobotSendRequest();
67 | oapiRobotSendRequest.setMsgtype("markdown");
68 |
69 | OapiRobotSendRequest.Markdown markdown = new OapiRobotSendRequest.Markdown();
70 | markdown.setText(new String(encodeBytes, StandardCharsets.UTF_8));
71 | markdown.setTitle(robotTitle);
72 |
73 | oapiRobotSendRequest.setMarkdown(markdown);
74 | dingTalkRobotSender.sendToRobot(oapiRobotSendRequest);
75 | }
76 | }
77 |
78 | @Override
79 | public void start() {
80 | if (webhook != null && webhook.length() > 0) {
81 | dingTalkRobotSender = new DingTalkRobotSender(webhook, signSecret,rateLimiterPermitsPerSecond);
82 | super.start();
83 | }
84 | }
85 |
86 | public String getWebhook() {
87 | return webhook;
88 | }
89 |
90 | public void setWebhook(String webhook) {
91 | this.webhook = webhook;
92 | }
93 |
94 | public String getSignSecret() {
95 | return signSecret;
96 | }
97 |
98 | public void setSignSecret(String signSecret) {
99 | this.signSecret = signSecret;
100 | }
101 |
102 |
103 | /**
104 | * 设置 layout
105 | *
106 | * @param layout
107 | */
108 | public void setLayout(Layout layout) {
109 | LayoutWrappingEncoder customLayoutEncoder = new LayoutWrappingEncoder();
110 | customLayoutEncoder.setLayout(layout);
111 | customLayoutEncoder.setContext(context);
112 | this.encoder = customLayoutEncoder;
113 |
114 | }
115 |
116 | public Double getRateLimiterPermitsPerSecond() {
117 | return rateLimiterPermitsPerSecond;
118 | }
119 |
120 | public void setRateLimiterPermitsPerSecond(Double rateLimiterPermitsPerSecond) {
121 | this.rateLimiterPermitsPerSecond = rateLimiterPermitsPerSecond;
122 | }
123 |
124 | public Encoder getEncoder() {
125 | return encoder;
126 | }
127 |
128 | public void setEncoder(Encoder encoder) {
129 | this.encoder = encoder;
130 | }
131 |
132 | public String getRobotTitle() {
133 | return robotTitle;
134 | }
135 |
136 | public void setRobotTitle(String robotTitle) {
137 | this.robotTitle = robotTitle;
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/src/main/java/com/github/wangji92/dingtalkrobot/logback/layout/DingTalkRobotLayout.java:
--------------------------------------------------------------------------------
1 | package com.github.wangji92.dingtalkrobot.logback.layout;
2 |
3 | import ch.qos.logback.classic.pattern.ClassOfCallerConverter;
4 | import ch.qos.logback.classic.pattern.LineOfCallerConverter;
5 | import ch.qos.logback.classic.pattern.MethodOfCallerConverter;
6 | import ch.qos.logback.classic.pattern.ThrowableProxyConverter;
7 | import ch.qos.logback.classic.spi.ILoggingEvent;
8 | import ch.qos.logback.classic.spi.IThrowableProxy;
9 | import ch.qos.logback.core.CoreConstants;
10 | import ch.qos.logback.core.LayoutBase;
11 | import com.github.wangji92.dingtalkrobot.logback.pattern.CenterBracketsTemplateConverter;
12 | import com.github.wangji92.dingtalkrobot.utils.IpUtils;
13 | import com.google.common.collect.Lists;
14 | import org.springframework.util.StringUtils;
15 |
16 | import java.text.SimpleDateFormat;
17 | import java.util.List;
18 | import java.util.Map;
19 |
20 | /**
21 | * 解析处理日志
22 | *
23 | * @author 汪小哥
24 | * @date 17-04-2021
25 | */
26 | public class DingTalkRobotLayout extends LayoutBase {
27 | /**
28 | * 环境
29 | */
30 | private String env;
31 | /**
32 | * 应用名称
33 | */
34 | private String app;
35 | /**
36 | * ip 地址
37 | */
38 | private String ip = "";
39 |
40 | /**
41 | * 钉钉通知 快捷链接
42 | */
43 | private String clickDescription;
44 | /**
45 | * 快捷链接 后面追加ip
46 | */
47 | private String clickUrl;
48 |
49 | /**
50 | * 需要打印的mdc的信息
51 | */
52 | private List mdcList = Lists.newArrayList();
53 |
54 | @Override
55 | public void start() {
56 | lineOfCallerConverter.start();
57 | methodOfCallerConverter.start();
58 | classOfCallerConverter.start();
59 | methodOfCallerConverter.start();
60 | throwableProxyConverter.setOptionList(Lists.newArrayList("5"));
61 | throwableProxyConverter.start();
62 | ip = IpUtils.getIpAddress();
63 |
64 | //处理动态的属性 https://kaifa.baidu.com/searchPage?wd=[localIp] 链接中的动态变量
65 | centerBracketsTemplateConverter.setOptionList(Lists.newArrayList(clickUrl));
66 | centerBracketsTemplateConverter.setContext(getContext());
67 | centerBracketsTemplateConverter.start();
68 | super.start();
69 | }
70 |
71 | private static final ThreadLocal DATE_FORMAT_THREAD_LOCAL = new ThreadLocal() {
72 | @Override
73 | protected SimpleDateFormat initialValue() {
74 | return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
75 | }
76 | };
77 |
78 | private LineOfCallerConverter lineOfCallerConverter = new LineOfCallerConverter();
79 | private MethodOfCallerConverter methodOfCallerConverter = new MethodOfCallerConverter();
80 | private ClassOfCallerConverter classOfCallerConverter = new ClassOfCallerConverter();
81 | private ThrowableProxyConverter throwableProxyConverter = new ThrowableProxyConverter();
82 | private CenterBracketsTemplateConverter centerBracketsTemplateConverter = new CenterBracketsTemplateConverter();
83 |
84 | @Override
85 | public String doLayout(ILoggingEvent event) {
86 | if (!isStarted()) {
87 | return CoreConstants.EMPTY_STRING;
88 | }
89 | StringBuilder sb = new StringBuilder();
90 | if (StringUtils.hasText(this.getPresentationHeader())) {
91 | sb.append("## ").append(this.getPresentationHeader()).append("\n");
92 | }
93 | this.markdownTextAppend(sb, "env", env);
94 | this.markdownTextAppend(sb, "app", app);
95 | this.markdownTextAppend(sb, "ip", ip);
96 | this.markdownTextAppend(sb, "thread", event.getThreadName());
97 | this.markdownTextAppend(sb, "level", event.getLevel().levelStr);
98 | // this.markdownTextAppend(sb, "logger", event.getLoggerName());
99 |
100 | // String classConvert = classOfCallerConverter.convert(event);
101 | // this.markdownTextAppend(sb, "class", classConvert);
102 |
103 | String method = methodOfCallerConverter.convert(event);
104 | this.markdownTextAppend(sb, "method", method);
105 |
106 | String line = lineOfCallerConverter.convert(event);
107 | this.markdownTextAppend(sb, "line", line);
108 |
109 | this.mdcAppend(sb, event);
110 |
111 | this.markdownTextAppend(sb, "message", event.getFormattedMessage());
112 |
113 | IThrowableProxy tp = event.getThrowableProxy();
114 | if (tp != null) {
115 | String stackTrace = throwableProxyConverter.convert(event);
116 | this.markdownTextAppend(sb, "stackTrace", stackTrace);
117 | }
118 |
119 | //增加快捷链接
120 | if (StringUtils.hasText(clickDescription) && StringUtils.hasText(clickUrl)) {
121 | String clickUrlDetail = centerBracketsTemplateConverter.convert(event);
122 | this.markdownTextAppendUrl(sb, clickDescription, clickUrlDetail, clickUrlDetail);
123 | }
124 | return sb.toString();
125 | }
126 |
127 | /**
128 | * md 格式
129 | *
130 | * @param sb
131 | * @param key
132 | * @param value
133 | */
134 | private void markdownTextAppend(StringBuilder sb, String key, String value) {
135 | if (StringUtils.hasText(value)) {
136 | sb.append("- ").append(key).append(": ").append(value).append("\n");
137 | }
138 | }
139 |
140 | /**
141 | * 增加链接
142 | *
143 | * @param sb
144 | * @param key
145 | * @param url
146 | * @param value
147 | */
148 | private void markdownTextAppendUrl(StringBuilder sb, String key, String url, String value) {
149 | String link = String.format("[%s](%s)", value, url);
150 | sb.append("- ").append(key).append(": ").append(link).append("\n");
151 | }
152 |
153 | /**
154 | * mdc 处理
155 | *
156 | * @param sb
157 | * @param event
158 | */
159 | private void mdcAppend(StringBuilder sb, ILoggingEvent event) {
160 | Map mdcPropertyMap = event.getMDCPropertyMap();
161 | for (Map.Entry entry : mdcPropertyMap.entrySet()) {
162 | if (StringUtils.hasText(entry.getKey()) && StringUtils.hasText(entry.getValue()) && mdcList.contains(entry.getKey())) {
163 | this.markdownTextAppend(sb, entry.getKey(), entry.getValue());
164 | }
165 | }
166 | }
167 |
168 | public String getEnv() {
169 | return env;
170 | }
171 |
172 | public void setEnv(String env) {
173 | this.env = env;
174 | }
175 |
176 | public String getApp() {
177 | return app;
178 | }
179 |
180 | public void setApp(String app) {
181 | this.app = app;
182 | }
183 |
184 | public String getClickDescription() {
185 | return clickDescription;
186 | }
187 |
188 | public void setClickDescription(String clickDescription) {
189 | this.clickDescription = clickDescription;
190 | }
191 |
192 | public String getClickUrl() {
193 | return clickUrl;
194 | }
195 |
196 | public void setClickUrl(String clickUrl) {
197 | this.clickUrl = clickUrl;
198 | }
199 |
200 | public List getMdcList() {
201 | return mdcList;
202 | }
203 |
204 | public void setMdcList(List mdcList) {
205 | if (mdcList == null) {
206 | return;
207 | }
208 | this.mdcList = mdcList;
209 | }
210 | }
211 |
--------------------------------------------------------------------------------
/src/main/java/com/github/wangji92/dingtalkrobot/logback/listener/LoggerStartupListener.java:
--------------------------------------------------------------------------------
1 | package com.github.wangji92.dingtalkrobot.logback.listener;
2 |
3 | import ch.qos.logback.classic.Level;
4 | import ch.qos.logback.classic.Logger;
5 | import ch.qos.logback.classic.LoggerContext;
6 | import ch.qos.logback.classic.spi.LoggerContextListener;
7 | import ch.qos.logback.core.spi.ContextAwareBase;
8 | import ch.qos.logback.core.spi.LifeCycle;
9 | import com.github.wangji92.dingtalkrobot.logback.property.LocalIpDefiner;
10 |
11 | /**
12 | * @author 汪小哥
13 | * @date 18-04-2021
14 | */
15 | public class LoggerStartupListener extends ContextAwareBase implements LoggerContextListener, LifeCycle {
16 |
17 | private boolean started = false;
18 |
19 | private LocalIpDefiner localIpDefiner = new LocalIpDefiner();
20 |
21 | @Override
22 | public boolean isResetResistant() {
23 | return false;
24 | }
25 |
26 | @Override
27 | public void onStart(LoggerContext context) {
28 |
29 | }
30 |
31 | @Override
32 | public void onReset(LoggerContext context) {
33 |
34 | }
35 |
36 | @Override
37 | public void onStop(LoggerContext context) {
38 |
39 | }
40 |
41 | @Override
42 | public void onLevelChange(Logger logger, Level level) {
43 |
44 | }
45 |
46 | @Override
47 | public void start() {
48 | if (started) {
49 | return;
50 | }
51 | context.putProperty("localIp", localIpDefiner.getPropertyValue());
52 | started = true;
53 | }
54 |
55 | @Override
56 | public void stop() {
57 |
58 | }
59 |
60 | @Override
61 | public boolean isStarted() {
62 | return started;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/java/com/github/wangji92/dingtalkrobot/logback/pattern/CenterBracketsTemplateConverter.java:
--------------------------------------------------------------------------------
1 | package com.github.wangji92.dingtalkrobot.logback.pattern;
2 |
3 | import ch.qos.logback.classic.pattern.ClassicConverter;
4 | import ch.qos.logback.classic.spi.ILoggingEvent;
5 | import ch.qos.logback.core.Context;
6 | import org.springframework.util.StringUtils;
7 |
8 | import java.util.HashMap;
9 | import java.util.Map;
10 | import java.util.regex.Matcher;
11 | import java.util.regex.Pattern;
12 |
13 | /**
14 | * 中括号中变量处理 比如 https://kaifa.baidu.com/searchPage?w=[localIp]
15 | * https://blog.csdn.net/WuLex/article/details/82116701
16 | * https://xie.infoq.cn/article/73d2aa78bac23f1bd2731ed23
17 | *
18 | * @author 汪小哥
19 | * @date 19-04-2021
20 | */
21 | public class CenterBracketsTemplateConverter extends ClassicConverter {
22 |
23 | private static final String REGEX = "(?<=\\[)([a-zA-Z0-9]*)(?=\\])";
24 |
25 | /**
26 | * 缓存值 第一次处理即可
27 | */
28 | private String convertContentCache = "";
29 |
30 | @Override
31 | public String convert(ILoggingEvent event) {
32 | if (StringUtils.hasText(convertContentCache)) {
33 | return convertContentCache;
34 | }
35 |
36 | if (getFirstOption() == null) {
37 | return "";
38 | }
39 | String firstOption = getFirstOption();
40 | Context context = getContext();
41 | Pattern compile = Pattern.compile(REGEX);
42 | Matcher matcher = compile.matcher(getFirstOption());
43 | Map map = new HashMap<>(3);
44 | while (matcher.find()) {
45 | for (int index = 1; index <= matcher.groupCount(); index++) {
46 | String propertyValue = context.getProperty(matcher.group(index));
47 | if (StringUtils.hasText(propertyValue)) {
48 | map.put(matcher.group(index), propertyValue);
49 | }
50 | }
51 | }
52 | for (Map.Entry keyValue : map.entrySet()) {
53 | firstOption = firstOption.replace("[" + keyValue.getKey() + "]", keyValue.getValue());
54 | }
55 | convertContentCache = firstOption;
56 | return firstOption;
57 | }
58 |
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/com/github/wangji92/dingtalkrobot/logback/property/LocalIpDefiner.java:
--------------------------------------------------------------------------------
1 | package com.github.wangji92.dingtalkrobot.logback.property;
2 |
3 | import ch.qos.logback.core.PropertyDefinerBase;
4 | import com.github.wangji92.dingtalkrobot.utils.IpUtils;
5 |
6 | /**
7 | * how to define value {@literal https://blog.csdn.net/acohi68664/article/details/102178465}
8 | * 然后在logback.xml中,添加 配置,指定属性名(本例中为localIP)及获取属性值的实现类,这样就可以在配置中通过 ${localIp}来引用该属性值了。
9 | *
10 | *
11 | * @author 汪小哥
12 | * @date 18-04-2021
13 | */
14 | public class LocalIpDefiner extends PropertyDefinerBase {
15 | @Override
16 | public String getPropertyValue() {
17 | return IpUtils.getIpAddress();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/github/wangji92/dingtalkrobot/utils/IpUtils.java:
--------------------------------------------------------------------------------
1 | package com.github.wangji92.dingtalkrobot.utils;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 |
5 | import java.net.Inet4Address;
6 | import java.net.InetAddress;
7 | import java.net.NetworkInterface;
8 | import java.util.Enumeration;
9 |
10 | /**
11 | * 获取本机ip
12 | *
13 | * @author jet
14 | * @date 20-11-2019
15 | */
16 | @Slf4j
17 | public class IpUtils {
18 |
19 | /**
20 | * 获取本机Ip
21 | *
22 | * @return
23 | */
24 | public static String getIpAddress() {
25 | try {
26 | Enumeration allNetInterfaces = NetworkInterface.getNetworkInterfaces();
27 | InetAddress ip = null;
28 | while (allNetInterfaces.hasMoreElements()) {
29 | NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
30 | if (netInterface.isLoopback() || netInterface.isVirtual() || !netInterface.isUp()) {
31 | //
32 | } else {
33 | Enumeration addresses = netInterface.getInetAddresses();
34 | while (addresses.hasMoreElements()) {
35 | ip = addresses.nextElement();
36 | if (ip instanceof Inet4Address) {
37 | return ip.getHostAddress();
38 | }
39 | }
40 | }
41 | }
42 | } catch (Exception e) {
43 | log.warn("getIpAddress error", e);
44 | }
45 | return "";
46 |
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/resources/META-INF/spring.factories:
--------------------------------------------------------------------------------
1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.github.wangji92.dingtalkrobot.DingTalkRobotAppendAutoConfiguration
--------------------------------------------------------------------------------
/src/main/resources/com/github/wangji92/dingtalkrobot/logback-dingtalk-robot-base.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
9 |
10 |
11 |
13 |
14 |
16 |
17 |
18 |
20 |
21 |
22 |
25 |
26 |
28 |
29 |
30 |
32 |
34 |
37 |
38 |
39 |
41 |
42 |
43 |
45 |
46 |
47 |
49 |
50 |
51 |
53 |
54 |
55 |
57 |
58 |
59 |
61 |
62 |
63 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/src/main/resources/com/github/wangji92/dingtalkrobot/logback-dingtalk-robot-custom-layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
11 |
12 |
13 |
15 | ${dingTalkRobotWebhook}
16 | ${dingTalkRobotSignSecret}
17 | ${dingTalkRobotTitle}
18 | ${dingTalkRateLimiterPermitsPerSecond:-0.2875}
19 |
20 | ${env}
21 | ${app}
22 | ${dingTalkQuickLinkClickDescription}
23 | ${dingTalkQuickLinkClickUrl}
24 |
25 |
26 |
27 |
28 | ${asyncAppenderIncludeCallerData:-true}
29 | ${asyncAppenderQueueSize:-256}
30 | ${asyncAppenderNeverBlock:-true}
31 |
32 |
33 | ${dingTalkLogLevel:-ERROR}
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | ${dingTalkLogConfigKewWordExpression}
43 |
44 |
45 | ACCEPT
46 |
47 | DENY
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/src/main/resources/com/github/wangji92/dingtalkrobot/logback-dingtalk-robot-pattern-layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
11 |
12 |
13 |
15 | ${dingTalkRobotWebhook}
16 | ${dingTalkRobotSignSecret}
17 | ${dingTalkRobotTitle}
18 |
19 |
20 | ${DINGTALK_ROBOT_LOG_PATTERN}
21 | UTF-8
22 |
23 |
24 |
25 |
26 | ${asyncAppenderIncludeCallerData:-true}
27 | ${asyncAppenderQueueSize:-256}
28 | ${asyncAppenderNeverBlock:-true}
29 |
30 |
31 | ${dingTalkLogLevel:-ERROR}
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | ${dingTalkLogConfigKewWordExpression}
41 |
42 |
43 | ACCEPT
44 |
45 | DENY
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/src/main/resources/example/logback-dingtalk-robot-example.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | ${CONSOLE_LOG_PATTERN}
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/test/java/com/github/wangji92/dingtalkrobot/DingtalkRobotLogbackAlarmSpringBootStartApplicationTests.java:
--------------------------------------------------------------------------------
1 | //package com.github.wangji92.logback;
2 | //
3 | //import org.junit.jupiter.api.Test;
4 | //import org.springframework.boot.test.context.SpringBootTest;
5 | //
6 | //@SpringBootTest
7 | //class DingtalkRobotLogbackappendSpringBootStartApplicationTests {
8 | //
9 | // @Test
10 | // void contextLoads() {
11 | // }
12 | //
13 | //}
14 |
--------------------------------------------------------------------------------