├── .gitignore ├── LICENSE ├── README.md ├── autoconfigure ├── pom.xml └── storage-scouter-udp-conf │ ├── pom.xml │ └── src │ └── main │ ├── java │ └── zipkin │ │ └── autoconfigure │ │ └── storage │ │ └── scouter │ │ ├── ZipkinScouterStorageAutoConfiguration.java │ │ └── ZipkinScouterStorageProperties.java │ └── resources │ ├── META-INF │ └── spring.factories │ └── zipkin-server-scouter.yml ├── pom.xml └── storage-scouter-udp ├── pom.xml └── src ├── main └── java │ └── zipkin2 │ └── storage │ └── scouter │ ├── ScouterConstants.java │ └── udp │ ├── ScouterConfig.java │ ├── ScouterUDPStorage.java │ └── net │ ├── DataProxy.java │ ├── DataUdpAgent.java │ └── UDPDataSendThread.java └── test └── java └── zipkin2 └── storage └── scouter ├── ScouterConstantsTest.java └── udp └── net └── DataProxyTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | 25 | # intellij 26 | *.iml 27 | 28 | target/ 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # zipkin-scouter 2 | Zipkin Scouter UDP storage and other zipkin-scouter integrations. 3 | * Supported scouter collector version : `v2.5+` 4 | 5 | ## Server integration 6 | In order to integrate with zipkin-server, you need to use properties 7 | launcher to load your collector (or sender) alongside the zipkin-server 8 | process. 9 | 10 | To integrate a module with a Zipkin server, you need to: 11 | * add a module jar to the `loader.path` 12 | * enable the profile associated with that module 13 | * launch Zipkin with `PropertiesLauncher` 14 | 15 | Each module will also have different minimum variables that need to be set. 16 | 17 | 18 | ## Example integrating the Scouter Collector by Zipkin-Scouter-Storage 19 | 20 | Here's an example of integrating the scouter Collector. 21 | 22 | ### Step 1: Download zipkin-server jar 23 | Download the [latest released server](https://search.maven.org/remote_content?g=io.zipkin&a=zipkin-server&v=2.12.9&c=exec) as zipkin.jar: 24 | 25 | ``` 26 | cd /tmp 27 | wget -O zipkin.jar 'https://search.maven.org/remote_content?g=io.zipkin.java&a=zipkin-server&v=2.12.9&c=exec' 28 | ``` 29 | 30 | ### Step 2: Download the latest zipkin-storage-scouter jar 31 | Download the [latest released Scouter module](https://search.maven.org/remote_content?g=io.github.scouter-project&a=zipkin-autoconfigure-storage-scouter-udp&v=LATEST&c=module) as zipkin-storage-scouter.jar: 32 | 33 | ``` 34 | cd /tmp 35 | wget -O zipkin-storage-scouter.jar 'https://search.maven.org/remote_content?g=io.github.scouter-project&a=zipkin-autoconfigure-storage-scouter-udp&v=LATEST&c=module' 36 | ``` 37 | 38 | ### Step 3: Run the server with the "scouter" profile active 39 | When you enable the "scouter" profile, you can configure scouter with 40 | short environment variables similar to other [Zipkin integrations](https://github.com/openzipkin/zipkin/blob/master/zipkin-server/README.md#elasticsearch-storage). 41 | 42 | ``` bash 43 | cd /tmp 44 | SCOUTER_COLLECTOR_ADDR=127.0.0.1 \ 45 | SCOUTER_COLLECTOR_PORT=6100 \ 46 | SCOUTER_SERVICE_MAPS_OJB_TYPE= \ 47 | STORAGE_TYPE=scouter \ 48 | java -Dloader.path='zipkin-storage-scouter.jar,zipkin-storage-scouter.jar!lib' -Dspring.profiles.active=scouter -cp zipkin.jar org.springframework.boot.loader.PropertiesLauncher 49 | ``` 50 | * **NOTE:** Make sure the parameters are defined in the same line or use environment variables ** 51 | 52 | * Configures 53 | * `STORAGE_TYPE=scouter` : **required**. All others are optional. 54 | * `SCOUTER_COLLECTOR_ADDR` (default: 127.0.0.1) : Scouter collector IP 55 | * `SCOUTER_COLLECTOR_PORT` (default: 6100) : Scounter collector Port 56 | * `SCOUTER_UDP_PACKET_MAX_BYTES` (default: 60000) : should be smaller than OS UDP diagram size. 57 | * `SCOUTER_TAG_MAP_TEXT1` : tag mapping to scouter xlog's predefined column `text1` (default: `spring.instance_id`) (comma separated multi-tags supported.) 58 | * `SCOUTER_TAG_MAP_TEXT2` : tag mapping to scouter xlog's predefined column `text2` (comma separated multi-tags supported.) 59 | * `SCOUTER_TAG_MAP_TEXT3` : tag mapping to scouter xlog's predefined column `text3` (comma separated multi-tags supported.) 60 | * `SCOUTER_TAG_MAP_TEXT4` : tag mapping to scouter xlog's predefined column `text4` (comma separated multi-tags supported.) 61 | * `SCOUTER_TAG_MAP_TEXT5` : tag mapping to scouter xlog's predefined column `text5` (comma separated multi-tags supported.) 62 | * `SCOUTER_TAG_MAP_LOGIN` : tag mapping to scouter xlog's predefined dictionary encoded column `login` (just single first matching tag of comma separated tags is used for the column.) 63 | * `SCOUTER_TAG_MAP_DESC` : tag mapping to scouter xlog's predefined dictionary encoded column `desc` (just single first matching tag of comma separated tags is used for the column.) 64 | * `SCOUTER_SERVICE_MAPS_OJB_TYPE` : map a zipkin's local endpoint service name to a scouter objType (ex: system1:OrderSystem,system2:CustomerSystem ...). It use the same name of service name with preceding $z. 65 | * `SCOUTER_DEBUG` (default: false) : Debug option 66 | 67 | ### Limitation 68 | This currently only supports sending to a Scouter collector, not reading back spans from the service. 69 | Spans can be shown in the Scouter's XLog view. 70 | 71 | ### Scouter Links 72 | - [Scouter GitHub](https://github.com/scouter-project/scouter) 73 | 74 | ### Scouter Paper Links 75 | - [Scouter Paper Homepage](https://github.com/scouter-project/scouter) 76 | - **Scouter Paper showcase** : [scouter paper overview (youtube)](https://www.youtube.com/watch?v=NjJ0dGhdIbU) 77 | 78 | -------------------------------------------------------------------------------- /autoconfigure/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 4.0.0 20 | 21 | 22 | io.github.scouter-project 23 | zipkin-scouter-parent 24 | 1.2.0 25 | 26 | 27 | zipkin-autoconfigure-scouter 28 | pom 29 | 30 | Zipkin Scouter Autoconfigure(Parent) 31 | Zipkin Scouter Autoconfigure(Parent) 32 | https://github.com/scouter-project/zipkin-scouter 33 | 34 | 35 | ${project.basedir}/.. 36 | 37 | 1.8 38 | java18 39 | 40 | 41 | 42 | storage-scouter-udp-conf 43 | 44 | 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-autoconfigure 49 | ${spring-boot.version} 50 | provided 51 | 52 | 53 | org.springframework.boot 54 | spring-boot-test 55 | ${spring-boot.version} 56 | test 57 | 58 | 59 | 60 | 61 | 62 | 63 | org.springframework.boot 64 | spring-boot-maven-plugin 65 | 66 | 67 | 68 | io.zipkin.zipkin2,io.zipkin.reporter2,org.springframework.boot,org.springframework,com.fasterxml.jackson.core,com.google.auto.value,com.google.guava 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /autoconfigure/storage-scouter-udp-conf/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 4.0.0 20 | 21 | 22 | io.github.scouter-project 23 | zipkin-autoconfigure-scouter 24 | 1.2.0 25 | 26 | 27 | zipkin-autoconfigure-storage-scouter-udp 28 | Auto Configuration: Scouter UDP 29 | 30 | 31 | ${project.basedir}/../.. 32 | 33 | 34 | 35 | 36 | io.github.scouter-project 37 | zipkin-storage-scouter-udp 38 | 39 | 40 | 41 | 42 | 43 | 44 | true 45 | src/main/resources 46 | 47 | 48 | 49 | 50 | org.apache.maven.plugins 51 | maven-compiler-plugin 52 | 3.1 53 | 54 | 1.8 55 | 1.8 56 | 57 | 58 | 59 | org.apache.maven.plugins 60 | maven-jar-plugin 61 | 3.0.2 62 | 63 | 64 | maven-assembly-plugin 65 | 66 | 67 | package 68 | 69 | single 70 | 71 | 72 | 73 | 74 | zipkin-storage-scouter 75 | false 76 | 77 | jar-with-dependencies 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /autoconfigure/storage-scouter-udp-conf/src/main/java/zipkin/autoconfigure/storage/scouter/ZipkinScouterStorageAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * @https://github.com/scouter-project/scouter 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | package zipkin.autoconfigure.storage.scouter; 20 | 21 | import org.springframework.beans.factory.annotation.Value; 22 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 23 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 24 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 25 | import org.springframework.context.annotation.Bean; 26 | import org.springframework.context.annotation.Configuration; 27 | import zipkin2.storage.StorageComponent; 28 | 29 | @Configuration 30 | @EnableConfigurationProperties(ZipkinScouterStorageProperties.class) 31 | @ConditionalOnProperty(name = "zipkin.storage.type", havingValue = "scouter") 32 | @ConditionalOnMissingBean(StorageComponent.class) 33 | public class ZipkinScouterStorageAutoConfiguration { 34 | 35 | @Bean 36 | @ConditionalOnMissingBean 37 | StorageComponent storage(ZipkinScouterStorageProperties properties, 38 | @Value("${zipkin.storage.strict-trace-id:true}") boolean strictTraceId) { 39 | 40 | return properties.toBuilder().strictTraceId(strictTraceId).build(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /autoconfigure/storage-scouter-udp-conf/src/main/java/zipkin/autoconfigure/storage/scouter/ZipkinScouterStorageProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * @https://github.com/scouter-project/scouter 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | package zipkin.autoconfigure.storage.scouter; 20 | 21 | import org.springframework.boot.context.properties.ConfigurationProperties; 22 | import zipkin2.storage.scouter.udp.ScouterConfig; 23 | import zipkin2.storage.scouter.udp.ScouterUDPStorage; 24 | 25 | import java.io.Serializable; 26 | import java.util.Map; 27 | import java.util.logging.Logger; 28 | 29 | @ConfigurationProperties("zipkin.storage.scouter") 30 | public class ZipkinScouterStorageProperties implements Serializable { 31 | private static final long serialVersionUID = 0L; 32 | private static final Logger logger = Logger.getLogger(ZipkinScouterStorageProperties.class.getName()); 33 | 34 | /** 35 | * Scouter Collector UDP address; defaults to localhost:6100 36 | */ 37 | private boolean debug; 38 | private String scouterCollectorAddress; 39 | private int scouterCollectorPort; 40 | private int scouterUdpPacketMaxBytes; 41 | private Map tagMap; 42 | private String serviceMapsToObjType; 43 | 44 | public boolean isDebug() { 45 | return debug; 46 | } 47 | public void setDebug(boolean debug) { 48 | this.debug = debug; 49 | } 50 | 51 | public String getScouterCollectorAddress() { 52 | return scouterCollectorAddress; 53 | } 54 | public void setScouterCollectorAddress(String scouterCollectorAddress) { 55 | this.scouterCollectorAddress = scouterCollectorAddress; 56 | } 57 | 58 | public int getScouterCollectorPort() { 59 | return scouterCollectorPort; 60 | } 61 | public void setScouterCollectorPort(int scouterCollectorPort) { 62 | this.scouterCollectorPort = scouterCollectorPort; 63 | } 64 | 65 | public int getScouterUdpPacketMaxBytes() { 66 | return scouterUdpPacketMaxBytes; 67 | } 68 | public void setScouterUdpPacketMaxBytes(int scouterUdpPacketMaxBytes) { 69 | this.scouterUdpPacketMaxBytes = scouterUdpPacketMaxBytes; 70 | } 71 | 72 | public Map getTagMap() { 73 | return tagMap; 74 | } 75 | 76 | public void setTagMap(Map tagMap) { 77 | this.tagMap = tagMap; 78 | } 79 | 80 | public String getServiceMapsToObjType() { 81 | return serviceMapsToObjType; 82 | } 83 | 84 | public void setServiceMapsToObjType(String serviceMapsToObjType) { 85 | this.serviceMapsToObjType = serviceMapsToObjType; 86 | } 87 | 88 | public ScouterUDPStorage.Builder toBuilder() { 89 | logger.info("[zipkin-scouter-storage] loading."); 90 | ScouterConfig config = new ScouterConfig(debug, scouterCollectorAddress, scouterCollectorPort, scouterUdpPacketMaxBytes, tagMap, serviceMapsToObjType); 91 | logger.info("[zipkin-scouter-storage] config " + config.toString()); 92 | ScouterUDPStorage.Builder builder = ScouterUDPStorage.newBuilder(); 93 | if (scouterCollectorAddress != null) builder.config(config); 94 | return builder; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /autoconfigure/storage-scouter-udp-conf/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 2 | zipkin.autoconfigure.storage.scouter.ZipkinScouterStorageAutoConfiguration 3 | -------------------------------------------------------------------------------- /autoconfigure/storage-scouter-udp-conf/src/main/resources/zipkin-server-scouter.yml: -------------------------------------------------------------------------------- 1 | # When enabled, this allows shorter env properties (ex -Dspring.profiles.active=scouter) 2 | zipkin: 3 | storage: 4 | scouter: 5 | debug: ${SCOUTER_DEBUG:false} 6 | # Scouter collector address 7 | scouter-collector-address: ${SCOUTER_COLLECTOR_ADDR:127.0.0.1} 8 | # Scouter collector port 9 | scouter-collector-port: ${SCOUTER_COLLECTOR_PORT:6100} 10 | scouter-udp-packet-max-bytes: ${SCOUTER_UDP_PACKET_MAX_BYTES:60000} 11 | tag-map: 12 | # tag mapping from zipkin to scouter xlog column. (comma separated multi-tags supported.) 13 | text1: ${SCOUTER_TAG_MAP_TEXT1:spring.instance_id} 14 | text2: ${SCOUTER_TAG_MAP_TEXT2:} 15 | text3: ${SCOUTER_TAG_MAP_TEXT3:} 16 | text4: ${SCOUTER_TAG_MAP_TEXT4:} 17 | text5: ${SCOUTER_TAG_MAP_TEXT5:} 18 | # tag mapping from zipkin to scouter xlog dictionary encoded column(login or desc). (just single first matching tag of comma separated tags is used for the column.) 19 | login: ${SCOUTER_TAG_MAP_LOGIN:} 20 | desc: ${SCOUTER_TAG_MAP_DESC:} 21 | # map a service to scouter objType (ex: system1:system1,system2:system2 ...). default use the same name of the zipkin local endpoint service name with preceding $z. 22 | service-maps-to-obj-type: ${SCOUTER_SERVICE_MAPS_OJB_TYPE:} 23 | 24 | 25 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | io.github.scouter-project 8 | zipkin-scouter-parent 9 | 1.2.0 10 | pom 11 | 12 | Zipkin Scouter (Parent) 13 | Zipkin Scouter (Parent) 14 | https://github.com/scouter-project/zipkin-scouter 15 | 16 | 17 | storage-scouter-udp 18 | autoconfigure 19 | 20 | 21 | 22 | 23 | The Apache Software License, Version 2.0 24 | http://www.apache.org/licenses/LICENSE-2.0.txt 25 | repo 26 | A business-friendly OSS license 27 | 28 | 29 | 30 | 31 | 32 | gunlee01 33 | Gunhee Lee 34 | gunlee01@gmail.com 35 | https://github.com/gunlee01 36 | 37 | PMC 38 | developer 39 | 40 | +8 41 | 42 | 43 | 44 | 45 | github.com 46 | https://github.com/scouter-project/zipkin-scouter/issues 47 | 48 | 49 | 50 | scm:git:git@github.com:scouter-project/zipkin-scouter.git 51 | scm:git:git@github.com:scouter-project/zipkin-scouter.git 52 | git@github.com:scouter-project/zipkin-scouter.git 53 | HEAD 54 | 55 | 56 | 57 | UTF-8 58 | UTF-8 59 | 60 | 1.8 61 | java18 62 | ${project.basedir} 63 | 64 | 2.11.7 65 | 1.7.25 66 | 2.11.1 67 | 68 | 2.0.5.RELEASE 69 | 2.5.0 70 | 71 | 72 | 73 | 74 | ossrh 75 | https://oss.sonatype.org/content/repositories/snapshots 76 | 77 | 78 | ossrh 79 | https://oss.sonatype.org/service/local/staging/deploy/maven2 80 | 81 | 82 | 83 | 84 | 85 | 86 | io.zipkin.zipkin2 87 | zipkin 88 | ${zipkin.version} 89 | 90 | 91 | io.zipkin.zipkin2 92 | zipkin-collector 93 | ${zipkin.version} 94 | 95 | 96 | io.github.scouter-project 97 | scouter-common 98 | ${scouter.version} 99 | 100 | 101 | io.github.scouter-project 102 | zipkin-storage-scouter-udp 103 | ${project.version} 104 | 105 | 106 | io.github.scouter-project 107 | zipkin-autoconfigure-scouter 108 | ${project.version} 109 | 110 | 111 | io.github.scouter-project 112 | zipkin-autoconfigure-storage-scouter-udp 113 | ${project.version} 114 | 115 | 116 | junit 117 | junit 118 | 4.13.1 119 | 120 | 121 | 122 | 123 | 124 | 125 | io.github.scouter-project 126 | scouter-common 127 | 128 | 129 | io.zipkin.zipkin2 130 | zipkin 131 | 132 | 133 | junit 134 | junit 135 | test 136 | 137 | 138 | org.assertj 139 | assertj-core 140 | 3.11.1 141 | test 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | org.springframework.boot 150 | spring-boot-maven-plugin 151 | ${spring-boot.version} 152 | 153 | 154 | 155 | repackage 156 | 157 | 158 | 159 | 160 | 161 | zipkin 162 | 163 | module 164 | 165 | 166 | 167 | io.zipkin.layout 168 | zipkin-layout-factory 169 | 0.0.2 170 | 171 | 172 | 173 | 174 | org.apache.maven.plugins 175 | maven-source-plugin 176 | 3.0.1 177 | 178 | 179 | attach-sources 180 | 181 | jar-no-fork 182 | 183 | 184 | 185 | 186 | 187 | org.apache.maven.plugins 188 | maven-javadoc-plugin 189 | 190 | -Xdoclint:none 191 | 192 | 193 | 194 | attach-javadocs 195 | 196 | jar 197 | 198 | 199 | 200 | 201 | 202 | org.sonatype.plugins 203 | nexus-staging-maven-plugin 204 | 1.6.7 205 | true 206 | 207 | ossrh 208 | https://oss.sonatype.org/ 209 | true 210 | 211 | 212 | 213 | org.apache.maven.plugins 214 | maven-gpg-plugin 215 | 1.5 216 | 217 | 218 | sign-artifacts 219 | verify 220 | 221 | sign 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | org.apache.maven.plugins 231 | maven-source-plugin 232 | 233 | 234 | org.apache.maven.plugins 235 | maven-javadoc-plugin 236 | 237 | 238 | org.sonatype.plugins 239 | nexus-staging-maven-plugin 240 | 241 | 242 | org.apache.maven.plugins 243 | maven-gpg-plugin 244 | 245 | 246 | 247 | 248 | 249 | -------------------------------------------------------------------------------- /storage-scouter-udp/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 4.0.0 20 | 21 | 22 | io.github.scouter-project 23 | zipkin-scouter-parent 24 | 1.2.0 25 | 26 | 27 | zipkin-storage-scouter-udp 28 | Zipkin Storage: Scouter UDP 29 | 30 | 31 | ${project.basedir}/.. 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | src/main/resources 42 | true 43 | 44 | 45 | 46 | 47 | org.apache.maven.plugins 48 | maven-compiler-plugin 49 | 3.1 50 | 51 | 1.8 52 | 1.8 53 | 54 | 55 | 56 | org.apache.maven.plugins 57 | maven-jar-plugin 58 | 3.0.2 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /storage-scouter-udp/src/main/java/zipkin2/storage/scouter/ScouterConstants.java: -------------------------------------------------------------------------------- 1 | package zipkin2.storage.scouter; 2 | 3 | import scouter.util.StringUtil; 4 | import zipkin2.storage.scouter.udp.ScouterConfig; 5 | 6 | import java.util.Map; 7 | 8 | /** 9 | * @author Gun Lee (gunlee01@gmail.com) on 31/10/2018 10 | */ 11 | public class ScouterConstants { 12 | public static final String OBJ_PREFIX = "ZIPKIN/"; 13 | public static final String OBJ_TYPE_PREFIX = "z$"; 14 | public static final String UNKNOWN = "UNKNOWN"; 15 | 16 | public static String toScouterObjName(String name) { 17 | if (StringUtil.isNotEmpty(name)) { 18 | return OBJ_PREFIX + name; 19 | } else { 20 | return OBJ_PREFIX + UNKNOWN; 21 | } 22 | } 23 | 24 | public static String toScouterObjType(String name, ScouterConfig conf) { 25 | if (StringUtil.isNotEmpty(name)) { 26 | Map serviceToType = conf.getServiceToObjTypeMap(); 27 | return OBJ_TYPE_PREFIX + serviceToType.getOrDefault(name, name); 28 | } else { 29 | return "zipkin"; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /storage-scouter-udp/src/main/java/zipkin2/storage/scouter/udp/ScouterConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * @https://github.com/scouter-project/scouter 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | package zipkin2.storage.scouter.udp; 20 | 21 | import scouter.util.StringUtil; 22 | 23 | import java.util.HashMap; 24 | import java.util.Map; 25 | import java.util.stream.Stream; 26 | 27 | import static java.util.stream.Collectors.toMap; 28 | 29 | public final class ScouterConfig { 30 | boolean debug; 31 | String address; 32 | int port; 33 | int udpPacketMaxBytes; 34 | String loginTag; 35 | String descTag; 36 | String text1Tag; 37 | String text2Tag; 38 | String text3Tag; 39 | String text4Tag; 40 | String text5Tag; 41 | Map seviceToObjTypeMap = new HashMap<>(); 42 | 43 | public ScouterConfig(boolean debug, String address, int port, int udpPacketMaxBytes, 44 | Map tagMap, String serviceMapsToObjType) { 45 | this.debug = debug; 46 | this.address = address; 47 | this.port = port; 48 | this.udpPacketMaxBytes = udpPacketMaxBytes; 49 | this.loginTag = tagMap.get("login"); 50 | this.descTag = tagMap.get("desc"); 51 | this.text1Tag = tagMap.get("text1"); 52 | this.text2Tag = tagMap.get("text2"); 53 | this.text3Tag = tagMap.get("text3"); 54 | this.text4Tag = tagMap.get("text4"); 55 | this.text5Tag = tagMap.get("text5"); 56 | 57 | if (StringUtil.isNotEmpty(serviceMapsToObjType)) { 58 | seviceToObjTypeMap = Stream.of(serviceMapsToObjType.split(",")) 59 | .map(str -> str.split(":")) 60 | .collect(toMap(kv -> kv[0], kv -> kv[1])); 61 | } 62 | } 63 | 64 | public boolean isDebug() { 65 | return debug; 66 | } 67 | 68 | public String getAddress() { 69 | return address; 70 | } 71 | 72 | public int getPort() { 73 | return port; 74 | } 75 | 76 | public int getUdpPacketMaxBytes() { 77 | return udpPacketMaxBytes; 78 | } 79 | 80 | public Map getServiceToObjTypeMap() { 81 | return seviceToObjTypeMap; 82 | } 83 | 84 | public String getLoginTag() { 85 | return loginTag; 86 | } 87 | 88 | public String getDescTag() { 89 | return descTag; 90 | } 91 | 92 | public String getText1Tag() { 93 | return text1Tag; 94 | } 95 | 96 | public String getText2Tag() { 97 | return text2Tag; 98 | } 99 | 100 | public String getText3Tag() { 101 | return text3Tag; 102 | } 103 | 104 | public String getText4Tag() { 105 | return text4Tag; 106 | } 107 | 108 | public String getText5Tag() { 109 | return text5Tag; 110 | } 111 | 112 | @Override 113 | public String toString() { 114 | return "ScouterConfig{" + 115 | "address='" + address + '\'' + 116 | ", port=" + port + 117 | ", udpPacketMaxBytes=" + udpPacketMaxBytes + 118 | ", debug=" + debug + 119 | ", loginTag='" + loginTag + '\'' + 120 | ", descTag='" + descTag + '\'' + 121 | ", text1Tag='" + text1Tag + '\'' + 122 | ", text2Tag='" + text2Tag + '\'' + 123 | ", text3Tag='" + text3Tag + '\'' + 124 | ", text4Tag='" + text4Tag + '\'' + 125 | ", text5Tag='" + text5Tag + '\'' + 126 | ", seviceToObjTypeMap=" + seviceToObjTypeMap + 127 | '}'; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /storage-scouter-udp/src/main/java/zipkin2/storage/scouter/udp/ScouterUDPStorage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2018 the original author or authors. 3 | * @https://github.com/scouter-project/scouter 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | */ 18 | 19 | package zipkin2.storage.scouter.udp; 20 | 21 | import zipkin2.Call; 22 | import zipkin2.Callback; 23 | import zipkin2.DependencyLink; 24 | import zipkin2.Span; 25 | import zipkin2.storage.QueryRequest; 26 | import zipkin2.storage.SpanConsumer; 27 | import zipkin2.storage.SpanStore; 28 | import zipkin2.storage.StorageComponent; 29 | import zipkin2.storage.scouter.udp.net.DataProxy; 30 | 31 | import java.io.IOException; 32 | import java.net.DatagramSocket; 33 | import java.util.HashMap; 34 | import java.util.List; 35 | import java.util.logging.Level; 36 | import java.util.logging.Logger; 37 | 38 | public final class ScouterUDPStorage extends StorageComponent implements SpanStore, SpanConsumer { 39 | private static final Logger logger = Logger.getLogger(ScouterUDPStorage.class.getName()); 40 | private static ScouterConfig config; 41 | 42 | public static Builder newBuilder() { 43 | return new Builder(); 44 | } 45 | 46 | private volatile DatagramSocket socket; 47 | private volatile boolean closeCalled; 48 | 49 | private ScouterUDPStorage(ScouterConfig config) { 50 | this.config = config; 51 | } 52 | 53 | public static ScouterConfig getConfig() { 54 | return config; 55 | } 56 | 57 | @Override 58 | public SpanStore spanStore() { 59 | return this; 60 | } 61 | 62 | @Override 63 | public SpanConsumer spanConsumer() { 64 | return this; 65 | } 66 | 67 | @Override 68 | public Call accept(List spans) { 69 | if (config.isDebug()) { 70 | logger.info("SPANS received : " + spans); 71 | } 72 | if (closeCalled) throw new IllegalStateException("closed"); 73 | if (spans.isEmpty()) return Call.create(null); 74 | return new UDPCall(spans); 75 | } 76 | 77 | @Override 78 | public synchronized void close() { 79 | if (closeCalled) return; 80 | DatagramSocket socket = this.socket; 81 | if (socket != null) socket.close(); 82 | closeCalled = true; 83 | } 84 | 85 | @Override 86 | public Call>> getTraces(QueryRequest queryRequest) { 87 | throw new UnsupportedOperationException("This is collector-only at the moment"); 88 | } 89 | 90 | @Override 91 | public Call> getTrace(String s) { 92 | throw new UnsupportedOperationException("This is collector-only at the moment"); 93 | } 94 | 95 | @Override 96 | public Call> getServiceNames() { 97 | throw new UnsupportedOperationException("This is collector-only at the moment"); 98 | } 99 | 100 | @Override 101 | public Call> getSpanNames(String s) { 102 | throw new UnsupportedOperationException("This is collector-only at the moment"); 103 | } 104 | 105 | @Override 106 | public Call> getDependencies(long l, long l1) { 107 | throw new UnsupportedOperationException("This is collector-only at the moment"); 108 | } 109 | 110 | public static final class Builder extends StorageComponent.Builder { 111 | ScouterConfig config; 112 | 113 | /** 114 | * Ignored as Scouter doesn't accept 64-bit trace IDs. downgrade the ID in scouter. 115 | */ 116 | @Override 117 | public Builder strictTraceId(boolean strictTraceId) { 118 | return this; 119 | } 120 | 121 | /** 122 | * Ignored as Scouter doesn't expose storage options 123 | */ 124 | @Override 125 | public Builder searchEnabled(boolean searchEnabled) { 126 | return this; 127 | } 128 | 129 | /** 130 | * Defaults to the env variable 131 | */ 132 | public Builder config(ScouterConfig config) { 133 | if (config == null) throw new IllegalArgumentException("config == null"); 134 | this.config = config; 135 | return this; 136 | } 137 | 138 | @Override 139 | public ScouterUDPStorage build() { 140 | if (config == null) { 141 | config = new ScouterConfig(false, "127.0.0.1", 6100, 60000, new HashMap<>(), null); 142 | } 143 | 144 | return new ScouterUDPStorage(config); 145 | } 146 | 147 | Builder() { 148 | } 149 | } 150 | 151 | @Override 152 | public final String toString() { 153 | return "ScouterUDPStorage{address=" + config.getAddress() + ":" + config.getPort() + "}"; 154 | } 155 | 156 | 157 | static class UDPCall extends Call.Base { 158 | private static final Logger logger = Logger.getLogger(UDPCall.class.getName()); 159 | private final List spans; 160 | 161 | UDPCall(List spans) { 162 | this.spans = spans; 163 | } 164 | 165 | @Override 166 | protected Void doExecute() throws IOException { 167 | DataProxy.sendSpanContainer(spans, config); 168 | return null; 169 | } 170 | 171 | @Override 172 | protected void doEnqueue(Callback callback) { 173 | try { 174 | doExecute(); 175 | callback.onSuccess(null); 176 | 177 | } catch (IOException | RuntimeException | Error e) { 178 | logger.log(Level.WARNING, e.getMessage(), e); 179 | propagateIfFatal(e); 180 | callback.onError(e); 181 | } 182 | } 183 | 184 | @Override 185 | public Call clone() { 186 | return new UDPCall(spans); 187 | } 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /storage-scouter-udp/src/main/java/zipkin2/storage/scouter/udp/net/DataProxy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 the original author or authors. 3 | * @https://github.com/scouter-project/scouter 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package zipkin2.storage.scouter.udp.net; 18 | 19 | import scouter.io.DataOutputX; 20 | import scouter.lang.TextTypes; 21 | import scouter.lang.pack.ObjectPack; 22 | import scouter.lang.pack.Pack; 23 | import scouter.lang.pack.SpanContainerPack; 24 | import scouter.lang.pack.SpanPack; 25 | import scouter.lang.pack.SpanTypes; 26 | import scouter.lang.pack.TextPack; 27 | import scouter.lang.pack.XLogPack; 28 | import scouter.lang.pack.XLogTypes; 29 | import scouter.lang.value.ListValue; 30 | import scouter.lang.value.MapValue; 31 | import scouter.util.HashUtil; 32 | import scouter.util.IntIntLinkedMap; 33 | import scouter.util.IntLinkedSet; 34 | import scouter.util.IntLongLinkedMap; 35 | import scouter.util.StringUtil; 36 | import zipkin2.Annotation; 37 | import zipkin2.Endpoint; 38 | import zipkin2.Span; 39 | import zipkin2.internal.HexCodec; 40 | import zipkin2.storage.scouter.ScouterConstants; 41 | import zipkin2.storage.scouter.udp.ScouterConfig; 42 | 43 | import java.io.IOException; 44 | import java.util.Arrays; 45 | import java.util.List; 46 | import java.util.Map; 47 | import java.util.logging.Logger; 48 | import java.util.regex.Pattern; 49 | import java.util.stream.Collectors; 50 | 51 | public class DataProxy { 52 | private static final Logger logger = Logger.getLogger(DataProxy.class.getName()); 53 | private static UDPDataSendThread udpCollect = UDPDataSendThread.getInstance(); 54 | private static IntIntLinkedMap sqlHash = new IntIntLinkedMap().setMax(5000); 55 | private static final Pattern WHITE_SPACE = Pattern.compile("\\s\\s+"); 56 | 57 | private static int getSqlHash(String sql) { 58 | if (sql.length() < 100) 59 | return HashUtil.hash(sql); 60 | int id = sql.hashCode(); 61 | int hash = sqlHash.get(id); 62 | if (hash == 0) { 63 | hash = HashUtil.hash(sql); 64 | sqlHash.put(id, hash); 65 | } 66 | return hash; 67 | } 68 | 69 | private static IntLinkedSet sqlText = new IntLinkedSet().setMax(10000); 70 | 71 | public static int sendSqlText(String sql) { 72 | int hash = getSqlHash(sql); 73 | if (sqlText.contains(hash)) { 74 | return hash; 75 | } 76 | sqlText.put(hash); 77 | sendDirect(new TextPack(TextTypes.SQL, hash, sql)); 78 | return hash; 79 | } 80 | 81 | private static IntLinkedSet serviceName = new IntLinkedSet().setMax(10000); 82 | 83 | public static int sendServiceName(String service) { 84 | int hash = HashUtil.hash(service); 85 | sendServiceName(hash, service); 86 | return hash; 87 | } 88 | 89 | public static void sendServiceName(int hash, String service) { 90 | if (serviceName.contains(hash)) { 91 | return; 92 | } 93 | serviceName.put(hash); 94 | udpCollect.add(new TextPack(TextTypes.SERVICE, hash, service)); 95 | } 96 | 97 | private static IntLinkedSet descTable = new IntLinkedSet().setMax(1000); 98 | 99 | public static int sendDesc(String desc) { 100 | int hash = HashUtil.hash(desc); 101 | if (descTable.contains(hash)) { 102 | return hash; 103 | } 104 | descTable.put(hash); 105 | udpCollect.add(new TextPack(TextTypes.DESC, hash, desc)); 106 | return hash; 107 | } 108 | 109 | private static IntLinkedSet loginTable = new IntLinkedSet().setMax(10000); 110 | 111 | public static int sendLogin(String loginName) { 112 | int hash = HashUtil.hash(loginName); 113 | if (loginTable.contains(hash)) { 114 | return hash; 115 | } 116 | loginTable.put(hash); 117 | udpCollect.add(new TextPack(TextTypes.LOGIN, hash, loginName)); 118 | return hash; 119 | } 120 | 121 | private static IntLinkedSet objNameSet = new IntLinkedSet().setMax(10000); 122 | 123 | private static IntLongLinkedMap objSentMap = new IntLongLinkedMap().setMax(1000); 124 | 125 | public static void registerZipkinObj(Span span, ScouterConfig conf) { 126 | String objName = ScouterConstants.toScouterObjName(span.localServiceName()); 127 | int objHash = HashUtil.hash(objName); 128 | 129 | long registered = objSentMap.get(objHash); 130 | long now = System.currentTimeMillis(); 131 | if (registered != 0 && now - registered < 30 * 1000) { 132 | return; 133 | } 134 | 135 | ObjectPack p = new ObjectPack(); 136 | p.objType = ScouterConstants.toScouterObjType(span.localServiceName(), conf); 137 | p.objName = objName; 138 | p.objHash = objHash; 139 | if (span.localEndpoint() != null) { 140 | p.address = span.localEndpoint().ipv4() + ":" + span.localEndpoint().portAsInt(); 141 | } 142 | p.tags.put(scouter.lang.constants.ScouterConstants.TAG_OBJ_DETECTED_TYPE, "zipkin"); 143 | p.tags.put(ObjectPack.TAG_KEY_DEAD_TIME, 300 * 1000); 144 | 145 | objSentMap.put(objHash, now); 146 | sendHeartBeat(p); 147 | 148 | if (conf.isDebug()) { 149 | logger.info("Object heartbeat: " + p); 150 | } 151 | } 152 | 153 | public static void sendHeartBeat(ObjectPack p) { 154 | udpCollect.add(p); 155 | } 156 | 157 | public static int sendObjName(String objName) { 158 | if (objName == null) { 159 | return 0; 160 | } 161 | int hash = HashUtil.hash(objName); 162 | sendObjName(hash, objName); 163 | return hash; 164 | } 165 | 166 | public static void sendObjName(int hash, String objName) { 167 | if (objName == null) { 168 | return; 169 | } 170 | if (objNameSet.contains(hash)) { 171 | return; 172 | } 173 | objNameSet.put(hash); 174 | udpCollect.add(new TextPack(TextTypes.OBJECT, hash, objName)); 175 | } 176 | 177 | private static IntLinkedSet errText = new IntLinkedSet().setMax(10000); 178 | 179 | public static int sendError(String message) { 180 | int hash = HashUtil.hash(message); 181 | if (errText.contains(hash)) { 182 | return hash; 183 | } 184 | errText.put(hash); 185 | udpCollect.add(new TextPack(TextTypes.ERROR, hash, message)); 186 | return hash; 187 | } 188 | 189 | private static IntLinkedSet hashMessage = new IntLinkedSet().setMax(10000); 190 | 191 | public static int sendHashedMessage(String text) { 192 | int hash = HashUtil.hash(text); 193 | if (hashMessage.contains(hash)) { 194 | return hash; 195 | } 196 | hashMessage.put(hash); 197 | udpCollect.add(new TextPack(TextTypes.HASH_MSG, hash, text)); 198 | return hash; 199 | } 200 | 201 | public static void reset() { 202 | serviceName.clear(); 203 | errText.clear(); 204 | sqlText.clear(); 205 | hashMessage.clear(); 206 | } 207 | 208 | public static void sendXLog(XLogPack p) { 209 | sendDirect(p); 210 | } 211 | 212 | static DataUdpAgent udpNet = DataUdpAgent.getInstance(); 213 | 214 | public static void sendDirect(Pack p) { 215 | try { 216 | udpNet.write(new DataOutputX().writePack(p).toByteArray()); 217 | } catch (IOException e) { 218 | } 219 | } 220 | 221 | private static void sendDirect(List buff) { 222 | switch (buff.size()) { 223 | case 0: 224 | return; 225 | case 1: 226 | udpNet.write(buff.get(0)); 227 | break; 228 | default: 229 | udpNet.write(buff); 230 | break; 231 | } 232 | } 233 | 234 | public static void sendSpanContainer(final List spans, final ScouterConfig conf) { 235 | int udpMaxBytes = conf.getUdpPacketMaxBytes(); 236 | if (spans == null || spans.size() == 0) 237 | return; 238 | 239 | Map> spansById = spans.stream() 240 | .collect(Collectors.groupingBy(Span::traceId)); 241 | 242 | for (Map.Entry> entry : spansById.entrySet()) { 243 | SpanContainerPack containerPack = new SpanContainerPack(); 244 | containerPack.gxid = HexCodec.lowerHexToUnsignedLong(entry.getKey()); 245 | containerPack.spanCount = entry.getValue().size(); 246 | 247 | List spanList = entry.getValue(); 248 | spanList.forEach(span -> DataProxy.registerZipkinObj(span, conf)); 249 | 250 | List spanPacks = spanList.stream() 251 | .map(DataProxy::makeSpanPack).collect(Collectors.toList()); 252 | 253 | if (conf.isDebug()) { 254 | spanPacks.forEach(pack -> logger.info("SpanPack generated: " + pack.toString())); 255 | } 256 | 257 | List spansBytesList = SpanPack.toBytesList(spanPacks, udpMaxBytes); 258 | for (byte[] spansBytes : spansBytesList) { 259 | containerPack.spans = spansBytes; 260 | sendDirect(containerPack); 261 | } 262 | 263 | for (SpanPack spanPack : spanPacks) { 264 | if (SpanTypes.isXLoggable(spanPack.spanType)) { 265 | XLogPack xlogPack = makeXLogPack(spanPack, conf); 266 | if (conf.isDebug()) { 267 | logger.info("XLog generated: " + xlogPack); 268 | } 269 | sendXLog(xlogPack); 270 | } 271 | } 272 | } 273 | } 274 | 275 | private static SpanPack makeSpanPack(Span span) { 276 | SpanPack pack = new SpanPack(); 277 | 278 | pack.gxid = HexCodec.lowerHexToUnsignedLong(span.traceId()); 279 | pack.txid = HexCodec.lowerHexToUnsignedLong(span.id()); 280 | pack.caller = span.parentId() != null ? HexCodec.lowerHexToUnsignedLong(span.parentId()) : 0L; 281 | 282 | pack.timestamp = span.timestampAsLong() / 1000; 283 | pack.elapsed = (int) (span.durationAsLong() / 1000); 284 | 285 | pack.spanType = SpanTypes.UNKNOWN; 286 | if (span.kind() != null) { 287 | switch (span.kind()) { 288 | case SERVER: 289 | pack.spanType = SpanTypes.SERVER; 290 | break; 291 | case CLIENT: 292 | pack.spanType = SpanTypes.CLIENT; 293 | break; 294 | case PRODUCER: 295 | pack.spanType = SpanTypes.PRODUCER; 296 | break; 297 | case CONSUMER: 298 | pack.spanType = SpanTypes.CONSUMER; 299 | break; 300 | } 301 | } 302 | 303 | String error = span.tags().get("error"); 304 | if (StringUtil.isNotEmpty(error)) { 305 | pack.error = sendError(error); 306 | } 307 | 308 | Endpoint localEndPoint = span.localEndpoint(); 309 | Endpoint remoteEndPoint = span.remoteEndpoint(); 310 | 311 | pack.objHash = sendObjName(ScouterConstants.toScouterObjName(span.localServiceName())); 312 | pack.localEndpointServiceName = sendObjName(span.localServiceName()); 313 | pack.remoteEndpointServiceName = sendObjName(span.remoteServiceName()); 314 | pack.localEndpointIp = localEndPoint != null ? localEndPoint.ipv4Bytes() : null; 315 | pack.remoteEndpointIp = remoteEndPoint != null ? remoteEndPoint.ipv4Bytes() : null; 316 | pack.localEndpointPort = localEndPoint != null ? (short) localEndPoint.portAsInt() : 0; 317 | pack.remoteEndpointPort = remoteEndPoint != null ? (short) remoteEndPoint.portAsInt() : 0; 318 | 319 | Boolean spanDebug = span.debug(); 320 | Boolean spanShared = span.shared(); 321 | pack.debug = spanDebug != null ? spanDebug : false; 322 | pack.shared = spanShared != null ? spanShared : false; 323 | 324 | pack.annotationTimestamps = new ListValue(); 325 | pack.annotationValues = new ListValue(); 326 | for (Annotation annotation : span.annotations()) { 327 | pack.annotationTimestamps.add(annotation.timestamp() / 1000); 328 | pack.annotationValues.add(annotation.value()); 329 | } 330 | 331 | pack.tags = MapValue.ofStringValueMap(span.tags()); 332 | 333 | String serviceName = StringUtil.emptyToDefault(span.name(), "").trim(); 334 | if (pack.spanType == SpanTypes.CLIENT) { 335 | if (pack.tags.getText("sql.query") != null) { 336 | //serviceName = pack.tags.getText("sql.query").replaceAll("[\r\n]+", " "); 337 | serviceName = WHITE_SPACE.matcher(pack.tags.getText("sql.query")).replaceAll(" "); 338 | } else if (pack.tags.getText("http.path") != null) { 339 | serviceName = pack.tags.getText("http.method") + " " + pack.tags.getText("http.path"); 340 | } 341 | } 342 | pack.name = sendServiceName(serviceName); 343 | 344 | return pack; 345 | } 346 | 347 | public static XLogPack makeXLogPack(SpanPack pack, ScouterConfig conf) { 348 | XLogPack xlog = new XLogPack(); 349 | xlog.endTime = pack.timestamp + pack.elapsed; 350 | xlog.objHash = pack.objHash; 351 | xlog.service = pack.name; 352 | xlog.txid = pack.txid; 353 | xlog.gxid = pack.gxid; 354 | xlog.caller = pack.caller; 355 | xlog.elapsed = pack.elapsed; 356 | xlog.error = pack.error; 357 | xlog.xType = XLogTypes.ZIPKIN_SPAN; 358 | 359 | String loginColumnString = map1stMatchingTagNames(pack, conf.getLoginTag()); 360 | if (StringUtil.isNotEmpty(loginColumnString)) { 361 | xlog.login = sendLogin(loginColumnString); 362 | } 363 | String descColumnString = map1stMatchingTagNames(pack, conf.getDescTag()); 364 | if (StringUtil.isNotEmpty(descColumnString)) { 365 | xlog.desc = sendLogin(descColumnString); 366 | } 367 | 368 | xlog.text1 = mapTagNames(pack, conf.getText1Tag()); 369 | xlog.text2 = mapTagNames(pack, conf.getText2Tag()); 370 | xlog.text3 = mapTagNames(pack, conf.getText3Tag()); 371 | xlog.text4 = mapTagNames(pack, conf.getText4Tag()); 372 | xlog.text5 = mapTagNames(pack, conf.getText5Tag()); 373 | 374 | return xlog; 375 | } 376 | 377 | protected static String map1stMatchingTagNames(SpanPack pack, String tagNames) { 378 | if (StringUtil.isEmpty(tagNames)) { 379 | return null; 380 | } 381 | return Arrays.stream(tagNames.split(",")) 382 | .map(tag -> pack.tags.getText(tag)) 383 | .filter(StringUtil::isNotEmpty) 384 | .findFirst().orElse(null); 385 | } 386 | 387 | protected static String mapTagNames(SpanPack pack, String tagNames) { 388 | if (StringUtil.isEmpty(tagNames)) { 389 | return null; 390 | } 391 | return Arrays.stream(tagNames.split(",")) 392 | .map(tag -> pack.tags.getText(tag)) 393 | .filter(StringUtil::isNotEmpty) 394 | .collect(Collectors.joining(",")); 395 | } 396 | } 397 | -------------------------------------------------------------------------------- /storage-scouter-udp/src/main/java/zipkin2/storage/scouter/udp/net/DataUdpAgent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 the original author or authors. 3 | * @https://github.com/scouter-project/scouter 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package zipkin2.storage.scouter.udp.net; 18 | 19 | import scouter.io.DataInputX; 20 | import scouter.io.DataOutputX; 21 | import scouter.net.NetCafe; 22 | import scouter.util.KeyGen; 23 | import zipkin2.storage.scouter.udp.ScouterConfig; 24 | import zipkin2.storage.scouter.udp.ScouterUDPStorage; 25 | 26 | import java.io.IOException; 27 | import java.net.DatagramPacket; 28 | import java.net.DatagramSocket; 29 | import java.net.InetAddress; 30 | import java.util.List; 31 | import java.util.logging.Level; 32 | import java.util.logging.Logger; 33 | 34 | public class DataUdpAgent { 35 | private static final Logger logger = Logger.getLogger(DataUdpAgent.class.getName()); 36 | private static DataUdpAgent inst; 37 | 38 | InetAddress serverHost; 39 | int serverPort; 40 | private DatagramSocket datagram; 41 | 42 | private DataUdpAgent() { 43 | setTarget(); 44 | openDatagramSocket(); 45 | } 46 | 47 | private void setTarget() { 48 | ScouterConfig config = ScouterUDPStorage.getConfig(); 49 | if (config != null) { 50 | String host = config.getAddress(); 51 | int port = config.getPort(); 52 | try { 53 | serverHost = InetAddress.getByName(host); 54 | serverPort = port; 55 | } catch (Exception e) { 56 | logger.log(Level.WARNING, e.getMessage(), e); 57 | } 58 | } 59 | } 60 | protected void close(DatagramSocket d) { 61 | if (d != null) { 62 | try { 63 | d.close(); 64 | } catch (Exception e) { 65 | } 66 | } 67 | } 68 | private void openDatagramSocket() { 69 | try { 70 | datagram = new DatagramSocket(); 71 | } catch (Exception e) { 72 | logger.log(Level.SEVERE, e.getMessage(), e); 73 | } 74 | } 75 | 76 | public static synchronized DataUdpAgent getInstance() { 77 | if (inst == null) { 78 | inst = new DataUdpAgent(); 79 | } 80 | return inst; 81 | } 82 | 83 | ScouterConfig config = ScouterUDPStorage.getConfig(); 84 | 85 | public boolean write(byte[] p) { 86 | try { 87 | if (serverHost == null) 88 | return false; 89 | if (p.length > config.getUdpPacketMaxBytes()) { 90 | return writeMTU(p, config.getUdpPacketMaxBytes()); 91 | } 92 | DataOutputX out = new DataOutputX(); 93 | out.write(NetCafe.CAFE); 94 | out.write(p); 95 | byte[] buff = out.toByteArray(); 96 | DatagramPacket packet = new DatagramPacket(buff, buff.length); 97 | packet.setAddress(serverHost); 98 | packet.setPort(serverPort); 99 | datagram.send(packet); 100 | return true; 101 | 102 | } catch (IOException e) { 103 | logger.log(Level.WARNING, "A120: UDP writing error. " + e.getMessage()); 104 | return false; 105 | } 106 | } 107 | 108 | private boolean writeMTU(byte[] data, int packetSize) { 109 | try { 110 | if (serverHost == null) 111 | return false; 112 | long pkid = KeyGen.next(); 113 | int total = data.length / packetSize; 114 | int remainder = data.length % packetSize; 115 | if (remainder > 0) 116 | total++; 117 | int num = 0; 118 | for (num = 0; num < data.length / packetSize; num++) { 119 | writeMTU(pkid, total, num, packetSize, DataInputX.get(data, num * packetSize, packetSize)); 120 | } 121 | if (remainder > 0) { 122 | writeMTU(pkid, total, num, remainder, DataInputX.get(data, data.length - remainder, remainder)); 123 | } 124 | return true; 125 | 126 | } catch (IOException e) { 127 | logger.log(Level.WARNING, "A121: UDP writing error.(MTU) " + e.getMessage()); 128 | return false; 129 | } 130 | } 131 | 132 | private void writeMTU(long pkid, int total, int num, int packetSize, byte[] data) throws IOException { 133 | DataOutputX out = new DataOutputX(); 134 | out.write(NetCafe.CAFE_MTU); 135 | out.writeInt(0); 136 | out.writeLong(pkid); 137 | out.writeShort(total); 138 | out.writeShort(num); 139 | out.writeBlob(data); 140 | byte[] buff = out.toByteArray(); 141 | DatagramPacket packet = new DatagramPacket(buff, buff.length); 142 | packet.setAddress(serverHost); 143 | packet.setPort(serverPort); 144 | datagram.send(packet); 145 | } 146 | 147 | public void close() { 148 | if (datagram != null) 149 | datagram.close(); 150 | datagram = null; 151 | } 152 | 153 | public boolean write(List p) { 154 | try { 155 | if (serverHost == null) 156 | return false; 157 | DataOutputX buffer = new DataOutputX(); 158 | int bufferCount = 0; 159 | for (int i = 0; i < p.size(); i++) { 160 | byte[] b = p.get(i); 161 | if (b.length > config.getUdpPacketMaxBytes()) { 162 | writeMTU(b, config.getUdpPacketMaxBytes()); 163 | 164 | } else if (b.length + buffer.getWriteSize() > config.getUdpPacketMaxBytes()) { 165 | sendList(bufferCount, buffer.toByteArray()); 166 | buffer = new DataOutputX(); 167 | bufferCount = 1; 168 | buffer.write(b); 169 | 170 | } else { 171 | bufferCount++; 172 | buffer.write(b); 173 | } 174 | } 175 | 176 | if (buffer.getWriteSize() > 0) { 177 | sendList(bufferCount, buffer.toByteArray()); 178 | } 179 | return true; 180 | } catch (IOException e) { 181 | logger.log(Level.WARNING, "A123: UDP writing error." + e.getMessage()); 182 | return false; 183 | } 184 | } 185 | 186 | private void sendList(int bufferCount, byte[] buffer) throws IOException { 187 | DataOutputX outter = new DataOutputX(); 188 | outter.write(NetCafe.CAFE_N); 189 | outter.writeShort(bufferCount); 190 | outter.write(buffer); 191 | byte[] buff = outter.toByteArray(); 192 | DatagramPacket packet = new DatagramPacket(buff, buff.length); 193 | packet.setAddress(serverHost); 194 | packet.setPort(serverPort); 195 | datagram.send(packet); 196 | } 197 | 198 | public boolean debugWrite(String ip, int port, int length) { 199 | try { 200 | DataOutputX out = new DataOutputX(); 201 | out.write("TEST".getBytes()); 202 | if (length > 4) { 203 | out.write(new byte[length - 4]); 204 | } 205 | byte[] buff = out.toByteArray(); 206 | DatagramPacket packet = new DatagramPacket(buff, buff.length); 207 | packet.setAddress(InetAddress.getByName(ip)); 208 | packet.setPort(port); 209 | datagram.send(packet); 210 | logger.info( "A124: Sent " + length + " bytes to " + ip + ":" + port); 211 | return true; 212 | 213 | } catch (IOException e) { 214 | logger.info( "A124: Sent " + length + " bytes to " + ip + ":" + port); 215 | 216 | logger.log(Level.WARNING, "A125: UDP writing error.(MTU) " + e.getMessage()); 217 | return false; 218 | } 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /storage-scouter-udp/src/main/java/zipkin2/storage/scouter/udp/net/UDPDataSendThread.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 the original author or authors. 3 | * @https://github.com/scouter-project/scouter 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package zipkin2.storage.scouter.udp.net; 19 | 20 | import scouter.io.DataOutputX; 21 | import scouter.lang.pack.Pack; 22 | import scouter.util.Queue; 23 | import scouter.util.ThreadUtil; 24 | import zipkin2.storage.scouter.udp.ScouterConfig; 25 | import zipkin2.storage.scouter.udp.ScouterUDPStorage; 26 | 27 | import java.util.ArrayList; 28 | import java.util.List; 29 | 30 | public class UDPDataSendThread extends Thread { 31 | 32 | private static UDPDataSendThread instance = null; 33 | ScouterConfig config = ScouterUDPStorage.getConfig(); 34 | 35 | public final static synchronized UDPDataSendThread getInstance() { 36 | if (instance == null) { 37 | instance = new UDPDataSendThread(); 38 | instance.setDaemon(true); 39 | instance.setName(ThreadUtil.getName(instance)); 40 | instance.start(); 41 | } 42 | return instance; 43 | } 44 | 45 | protected UDPDataSendThread() { 46 | } 47 | 48 | private Queue queue = new Queue(1024); 49 | 50 | public int getQueueSize() { 51 | return queue.size(); 52 | } 53 | 54 | public boolean add(Pack p) { 55 | try { 56 | byte[] b = new DataOutputX().writePack(p).toByteArray(); 57 | Object ok = queue.push(b); 58 | return ok != null; 59 | } catch (Exception e) { 60 | } 61 | return false; 62 | } 63 | 64 | public boolean isQueueOk() { 65 | return queue.size() < 1000; 66 | } 67 | 68 | public void shutdown() { 69 | running = false; 70 | } 71 | 72 | private boolean running = true; 73 | 74 | public void run() { 75 | DataUdpAgent udp = DataUdpAgent.getInstance(); 76 | 77 | while (running) { 78 | int size = queue.size(); 79 | switch (size) { 80 | case 0: 81 | ThreadUtil.sleep(100); 82 | break; 83 | case 1: 84 | udp.write(queue.pop()); 85 | break; 86 | default: 87 | send(udp, size); 88 | break; 89 | } 90 | 91 | } 92 | } 93 | 94 | private void send(DataUdpAgent udp, int size) { 95 | List buff = new ArrayList(); 96 | int bytes = 0; 97 | for (int k = 0; k < size; k++) { 98 | byte[] b = queue.pop(); 99 | if (bytes + b.length >= config.getUdpPacketMaxBytes()) { 100 | send(udp, buff); 101 | bytes = 0; 102 | buff.clear(); 103 | } 104 | bytes += b.length; 105 | buff.add(b); 106 | } 107 | send(udp, buff); 108 | } 109 | 110 | public void send(DataUdpAgent udp, List buff) { 111 | switch (buff.size()) { 112 | case 0: 113 | break; 114 | case 1: 115 | udp.write(buff.get(0)); 116 | break; 117 | default: 118 | udp.write(buff); 119 | break; 120 | } 121 | } 122 | 123 | } -------------------------------------------------------------------------------- /storage-scouter-udp/src/test/java/zipkin2/storage/scouter/ScouterConstantsTest.java: -------------------------------------------------------------------------------- 1 | package zipkin2.storage.scouter; 2 | 3 | import org.junit.Test; 4 | import zipkin2.storage.scouter.udp.ScouterConfig; 5 | 6 | import java.util.HashMap; 7 | 8 | import static org.junit.Assert.*; 9 | 10 | /** 11 | * @author Gun Lee (gunlee01@gmail.com) on 10/11/2018 12 | */ 13 | public class ScouterConstantsTest { 14 | 15 | @Test 16 | public void toScouterObjName() { 17 | String name = "test-name"; 18 | String expected = "ZIPKIN/test-name"; 19 | 20 | assertEquals(expected, ScouterConstants.toScouterObjName(name)); 21 | } 22 | 23 | @Test 24 | public void toScouterObjType() { 25 | ScouterConfig config = new ScouterConfig(false, "localhost", 6100, 60000, 26 | new HashMap<>(), "s1:xxs1,s2:xxs2"); 27 | 28 | assertEquals("z$nomap", ScouterConstants.toScouterObjType("nomap", config)); 29 | assertEquals("z$xxs1", ScouterConstants.toScouterObjType("s1", config)); 30 | assertEquals("z$xxs2", ScouterConstants.toScouterObjType("s2", config)); 31 | } 32 | } -------------------------------------------------------------------------------- /storage-scouter-udp/src/test/java/zipkin2/storage/scouter/udp/net/DataProxyTest.java: -------------------------------------------------------------------------------- 1 | package zipkin2.storage.scouter.udp.net; 2 | 3 | import org.junit.Test; 4 | import scouter.lang.pack.SpanPack; 5 | import scouter.lang.value.MapValue; 6 | 7 | import static org.hamcrest.CoreMatchers.is; 8 | import static org.junit.Assert.*; 9 | 10 | /** 11 | * @author Gun Lee (gunlee01@gmail.com) on 11/11/2018 12 | */ 13 | public class DataProxyTest { 14 | static SpanPack pack = new SpanPack(); 15 | static { 16 | pack.tags = new MapValue(); 17 | pack.tags.put("tag1", "tv1"); 18 | pack.tags.put("tag2", "tv2"); 19 | pack.tags.put("tag3", "tv3"); 20 | } 21 | 22 | @Test 23 | public void map1stMatchingTagNames_no_matching() { 24 | assertNull(DataProxy.map1stMatchingTagNames(pack, "tagX")); 25 | assertNull(DataProxy.map1stMatchingTagNames(pack, "tagY")); 26 | assertNull(DataProxy.map1stMatchingTagNames(pack, "tagX,tagY")); 27 | } 28 | 29 | @Test 30 | public void map1stMatchingTagNames_matching() { 31 | assertThat(DataProxy.map1stMatchingTagNames(pack, "tag1"), is(pack.tags.getText("tag1"))); 32 | assertThat(DataProxy.map1stMatchingTagNames(pack, "tag2"), is(pack.tags.getText("tag2"))); 33 | assertThat(DataProxy.map1stMatchingTagNames(pack, "tag1,tag2"), is(pack.tags.getText("tag1"))); 34 | assertThat(DataProxy.map1stMatchingTagNames(pack, "tag2,tag1"), is(pack.tags.getText("tag2"))); 35 | assertThat(DataProxy.map1stMatchingTagNames(pack, "tagX,tag1"), is(pack.tags.getText("tag1"))); 36 | assertThat(DataProxy.map1stMatchingTagNames(pack, "tagX,tag2,tag3"), is(pack.tags.getText("tag2"))); 37 | } 38 | 39 | @Test 40 | public void mapTagNames_no_matching() { 41 | assertThat(DataProxy.mapTagNames(pack, "tagX"), is("")); 42 | assertThat(DataProxy.mapTagNames(pack, "tagY"), is("")); 43 | assertThat(DataProxy.mapTagNames(pack, "tagX,tagY"), is("")); 44 | } 45 | 46 | @Test 47 | public void mapTagNames_matching() { 48 | assertThat(DataProxy.mapTagNames(pack, "tag1"), is("tv1")); 49 | assertThat(DataProxy.mapTagNames(pack, "tag2"), is("tv2")); 50 | assertThat(DataProxy.mapTagNames(pack, "tag1,tag2"), is("tv1,tv2")); 51 | assertThat(DataProxy.mapTagNames(pack, "tagX,tag1,tag2"), is("tv1,tv2")); 52 | assertThat(DataProxy.mapTagNames(pack, "tagX,tag1,tagX,tag2"), is("tv1,tv2")); 53 | assertThat(DataProxy.mapTagNames(pack, "tagX,tag1,tagX,tag2,tag3,tagX"), is("tv1,tv2,tv3")); 54 | } 55 | } --------------------------------------------------------------------------------