ð PandaCoder 2.0.0 - ES DSL Monitor & SQL Monitor éæŒååžïŒ
è®©æ°æ®åºæ¥è¯¢åæçŽ¢åŒæè°çšäžç®äºç¶ïŒ
åå«ç²ç®è°è¯ïŒæ¥æ±å¯è§åçæ§æ¶ä»£ïŒ
ð ç®åœ
- åèœä»ç»
- 䞺ä»ä¹éèŠè¿äž€äžªçæ§å·¥å ·
- å¿«éåŒå§
- 诊ç»é 眮æå
- 䜿çšåºæ¯
- åžžè§é®é¢
- ææ¯åç
ð¯ åèœä»ç»
ES DSL Monitor - Elasticsearch æ¥è¯¢çæ§
å MyBatis Log äžæ ·ïŒå®æ¶æè·åå±ç€º Elasticsearch æ¥è¯¢ïŒ
âš æ žå¿ç¹æ§
- ð 宿¶çæ§ïŒèªåšæè·ææ ES æ¥è¯¢ïŒæ éä¿®æ¹ä»£ç
- ð å¯è§åå±ç€ºïŒç¬ç«å·¥å ·çªå£ïŒæž æ°å±ç€ºæ¥è¯¢è¯Šæ
- ðš æºèœè§£æïŒæ¯æå€ç§æ¥å¿æ ŒåŒïŒREST ClientãcURLãSpring Data ESïŒ
- ð API å ³èïŒèªåšå ³èè§Šåæ¥è¯¢ç API æ¥å£
- ðŸ æä¹ åååšïŒèªåšä¿åæ¥è¯¢åå²ïŒæ¹äŸ¿å溯åæ
- ð é¶æ§èœæèïŒåŒæ¥å€çïŒäžåœ±å IDEA è¿è¡é床
ð çæ§å 容
| åæ®µ | 诎æ | ç€ºäŸ |
|---|---|---|
| æ¹æ³ | HTTP æ¹æ³ | GET / POST / PUT / DELETE |
| çŽ¢åŒ | ES 玢åŒåç§° | torchv_chunk_dims_1024 |
| ç«¯ç¹ | 请æ±ç«¯ç¹ | /_search / /_count |
| DSL æ¥è¯¢ | 宿Žçæ¥è¯¢ JSON | {"query": {"bool": {...}}} |
| API è·¯åŸ | è§Šåæ¥è¯¢ç API | /api/vector/search |
| è°çšç±» | åèµ·æ¥è¯¢ç Java ç±» | VectorDataRetrieverElastic.java:125 |
| æ§è¡æ¶éŽ | æ¥è¯¢èæ¶ | 23 ms |
| ååº | ES è¿åçååº | {"took": 5, "hits": {...}} |
SQL Monitor - SQL æ¥è¯¢çæ§
å®çŸå€å» MyBatis Log Plugin çåèœïŒåš IDEA äžåçæ¯æïŒ
âš æ žå¿ç¹æ§
- ð å®æŽ SQL è®°åœïŒæè·ææ MyBatis SQL æ¥è¯¢
- ð¯ åæ°æ¿æ¢ïŒèªåšçæå¯æ§è¡ç SQLïŒåæ°å·²æ¿æ¢ïŒ
- ð æºèœåç±»ïŒææäœç±»åïŒSELECT/INSERT/UPDATE/DELETEïŒåç±»
- ð ç»è®¡åæïŒå®æ¶ç»è®¡åç±» SQL æ°éåè¡šè®¿é®æ åµ
- ð API 远螪ïŒèªåšå ³èè§Šå SQL ç API æ¥å£
- ðš é¢è²æ è¯ïŒäžåæäœç±»å䜿çšäžåé¢è²ïŒäžç®äºç¶
ð çæ§å 容
| åæ®µ | 诎æ | ç€ºäŸ |
|---|---|---|
| æäœ | SQL æäœç±»å | SELECT / INSERT / UPDATE / DELETE |
| 衚å | æäœçæ°æ®åºè¡š | user / order |
| SQL è¯å¥ | åå§ SQLïŒåžŠå äœç¬ŠïŒ | SELECT * FROM user WHERE id = ? |
| åæ° | ç»å®çåæ°åŒ | 123(Integer) |
| 坿§è¡ SQL | åæ°å·²æ¿æ¢ç SQL | SELECT * FROM user WHERE id = 123 |
| ç»ææ° | æ¥è¯¢è¿åçè®°åœæ° | 10 |
| API è·¯åŸ | è§Šå SQL ç API | /api/user/list |
| è°çšç±» | Mapper æ¥å£ | UserMapper.selectById |
| æ§è¡æ¶éŽ | SQL èæ¶ | 15 ms |
ð¡ 䞺ä»ä¹éèŠè¿äž€äžªçæ§å·¥å ·
äŒ ç»åŒåççç¹
ð« Elasticsearch è°è¯å°å¢
// 代ç äžæå»ºå€æç ES æ¥è¯¢
NativeQuery query = NativeQuery.builder()
.withQuery(boolQuery)
.withKnnQuery(knnQuery)
.withPageable(pageable)
.build();
SearchHits<Document> hits = elasticsearchTemplate.search(query, Document.class);
// â é®é¢ïŒ
// 1. äžç¥éå®é
åéç» ES ç DSL æ¯ä»ä¹æ ·ç
// 2. æ æ³çŽæ¥åš Kibana äžæµè¯
// 3. è°è¯æ¶éèŠæåšæå° JSON
// 4. åéæ°æ®å€ªé¿ïŒéŸä»¥é
读ð« SQL è°è¯å°å¢
// MyBatis Mapper è°çš
List<User> users = userMapper.selectByCondition(condition);
// â é®é¢ïŒ
// 1. äžç¥éå®é
æ§è¡ç SQL æ¯ä»ä¹
// 2. åæ°ç»å®æ¯åŠæ£ç¡®ïŒ
// 3. æ¯åŠè§Šåäº N+1 æ¥è¯¢ïŒ
// 4. åªäžª API è°çšäºè¿äžª SQLïŒð 䜿çšçæ§å·¥å ·å
â ES DSL Monitor 垊æ¥çæ¹å
âš å®æ¶çå°å®æŽç ES æ¥è¯¢ïŒ
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â ES DSL Query
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â Method: POST
â Index: torchv_chunk_dims_1024
â Endpoint: /_search
â API Path: /api/vector/search
â Caller: VectorDataRetrieverElastic.java:125
â
â DSL:
â {
â "query": {
â "bool": {
â "must": [
â {"match": {"content": {"query": "çšæ·èŸå
¥", "boost": 0.3}}}
â ]
â }
â },
â "knn": {
â "field": "vector",
â "k": 10,
â "num_candidates": 50,
â "query_vector": [0.123, 0.456, ...]
â },
â "size": 10
â }
â
â Response: 156 hits in 23ms
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
奜å€ïŒ
1. äžé®å€å¶ DSLïŒçŽæ¥åš Kibana æµè¯
2. æž
æ°çå°æ¥è¯¢ç»æååæ°
3. 远螪 API å° ES æ¥è¯¢ç宿ŽéŸè·¯
4. åç°æ§èœç¶é¢â SQL Monitor 垊æ¥çæ¹å
âš å®æ¶çå°å®æŽç SQL æ§è¡ïŒ
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â SQL Query
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â Operation: SELECT
â Table: user
â API Path: /api/user/list
â Caller: UserMapper.selectByCondition
â
â Original SQL:
â SELECT id, name, email, created_at
â FROM user
â WHERE status = ? AND created_at > ?
â ORDER BY id DESC
â LIMIT ?
â
â Parameters:
â 1(Integer), 2025-01-01 00:00:00(Timestamp), 10(Integer)
â
â Executable SQL:
â SELECT id, name, email, created_at
â FROM user
â WHERE status = 1 AND created_at > '2025-01-01 00:00:00'
â ORDER BY id DESC
â LIMIT 10
â
â Result: 10 rows in 15ms
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
奜å€ïŒ
1. äžé®å€å¶å¯æ§è¡ SQLïŒçŽæ¥åšæ°æ®åºå·¥å
·è¿è¡
2. æž
æ°çå°åæ°ç»å®
3. 远螪 API å° SQL ç宿ŽéŸè·¯
4. åç° N+1 æ¥è¯¢é®é¢
5. äŒåæ
¢æ¥è¯¢ð å¿«éåŒå§
ç¬¬äžæ¥ïŒå®è£ æä»¶
- æåŒ IntelliJ IDEA
SettingsâPluginsâ æçŽ¢PandaCoder- ç¹å»
Installå®è£ - éå¯ IDEA
ç¬¬äºæ¥ïŒæåŒå·¥å ·çªå£
åš IDEA åºéšå·¥å ·æ æŸå°ïŒ
- ð ES DSL Monitor - Elasticsearch åŸæ
- ðïž SQL Monitor - MySQL åŸæ
ç¬¬äžæ¥ïŒå¯çšçå¬
åšå¯¹åºçå·¥å ·çªå£äžïŒ
- â åŸé "å¯çš ES çå¬" æ "å¯çš SQL çå¬"
ç¬¬åæ¥ïŒé 眮æ¥å¿èŸåºïŒéèŠïŒïŒ
è¿æ¯æå ³é®çäžæ¥ïŒ åŠæäžé 眮æ¥å¿ïŒçæ§å·¥å ·æ æ³æè·æ¥è¯¢ã
ð 诊ç»é 眮æå
ES DSL Monitor é 眮
é 眮åç诎æ
䞺ä»ä¹éèŠé 眮æ¥å¿ïŒ
ES DSL Monitor çå·¥äœåçæ¯çå¬ IDEA æ§å¶å°çèŸåºïŒè§£æå ¶äžç Elasticsearch æ¥è¯¢æ¥å¿ãäœæ¯ïŒElasticsearch 客æ·ç«¯é»è®€äžäŒèŸåºè¯Šç»çæ¥è¯¢æ¥å¿ïŒéèŠæåšé 眮æ¥å¿çº§å«ã
è¿ç±»äŒŒäº MyBatis éèŠé 眮 DEBUG æ¥å¿æèœçå° SQL äžæ ·ã
æ¹åŒ 1ïŒé 眮 LogbackïŒæšèïŒ
åŠæäœ ç项ç®äœ¿çš LogbackïŒSpring Boot é»è®€ïŒïŒåš src/main/resources/logback-spring.xml æ logback-local.xml äžæ·»å ïŒ
<configuration>
<!-- ç°æé
çœ®ä¿æäžå... -->
<!-- ===== Elasticsearch æ¥å¿é
çœ®ïŒæ°å¢ïŒ ===== -->
<!-- Elasticsearch Java Client è¯·æ±æ¥å¿ -->
<logger name="org.elasticsearch.client" level="DEBUG">
<appender-ref ref="STDOUT" />
</logger>
<!-- Spring Data Elasticsearch æ¥è¯¢æ¥å¿ -->
<logger name="org.springframework.data.elasticsearch" level="DEBUG">
<appender-ref ref="STDOUT" />
</logger>
<!-- Elasticsearch RestClient è¯Šç»æ¥å¿ -->
<logger name="org.elasticsearch.client.RestClient" level="DEBUG">
<appender-ref ref="STDOUT" />
</logger>
<!-- Elasticsearch 请æ±è¿œèžªïŒæè¯Šç»ïŒåŒºçæšèïŒïŒ -->
<logger name="tracer" level="TRACE">
<appender-ref ref="STDOUT" />
</logger>
</configuration>é 眮诎æïŒ
| Logger åç§° | çº§å« | äœçš | æ¯åŠå¿ é |
|---|---|---|---|
org.elasticsearch.client | DEBUG | èŸåº ES 客æ·ç«¯åºç¡æ¥å¿ | âââ æšè |
org.elasticsearch.client.RestClient | DEBUG | èŸåº HTTP 请æ±/ååº | ââââ éèŠ |
org.springframework.data.elasticsearch | DEBUG | Spring Data ES æ¥è¯¢æ¥å¿ | âââ æšè |
tracer | TRACE | èŸåºå®æŽç cURL æ ŒåŒè¯·æ± | âââââ å¿ é |
â ïž éç¹ïŒtracer æ¥å¿æ¯æéèŠçïŒ å®äŒèŸåºç±»äŒŒä»¥äžæ ŒåŒçæ¥å¿ïŒ
curl -iX POST "localhost:9200/torchv_chunk_dims_1024/_search?typed_keys=true" -H "Content-Type: application/json" -d '
{
"query": {
"bool": {
"must": [
{"match": {"content": {"query": "çšæ·æ¥è¯¢", "boost": 0.3}}}
]
}
},
"knn": {
"field": "vector",
"k": 10,
"num_candidates": 50,
"query_vector": [0.123, 0.456, ...]
},
"size": 10
}'
# {
# "took": 5,
# "hits": {
# "total": {"value": 156},
# "hits": [...]
# }
# }è¿ç§æ ŒåŒå å«äºïŒ
- â 宿Žç HTTP æ¹æ³å URL
- â 宿Žç DSL æ¥è¯¢ JSON
- â 宿Žçååº JSON
- â å¯ä»¥çŽæ¥å€å¶å°ç»ç«¯æ§è¡
æ¹åŒ 2ïŒé 眮 application.yml
åš src/main/resources/application.yml æ application-dev.yml äžæ·»å ïŒ
# æ¥å¿é
眮
logging:
level:
# Elasticsearch 客æ·ç«¯æ¥å¿
org.elasticsearch.client: DEBUG
org.elasticsearch.client.RestClient: DEBUG
# Spring Data Elasticsearch
org.springframework.data.elasticsearch: DEBUG
org.springframework.data.elasticsearch.client.elc: DEBUG
# HTTP è¿œèžªïŒæéèŠïŒïŒ
tracer: TRACEâ ïž æ³šæïŒ
- åŠæåæ¶é
眮äº
logback.xmlåapplication.ymlïŒlogback.xmlçé 眮äŒå 级æŽé« - 建议åš
logback.xmläžé çœ®ïŒæŽçµæŽ»
æ¹åŒ 3ïŒé 眮 Log4j2ïŒåŠæäœ¿çš Log4j2ïŒ
åš src/main/resources/log4j2.xml äžæ·»å ïŒ
<Configuration>
<!-- ç°æé
眮... -->
<!-- Elasticsearch æ¥å¿é
眮 -->
<Loggers>
<Logger name="org.elasticsearch.client" level="debug" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<Logger name="org.elasticsearch.client.RestClient" level="debug" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<Logger name="org.springframework.data.elasticsearch" level="debug" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
<Logger name="tracer" level="trace" additivity="false">
<AppenderRef ref="Console"/>
</Logger>
</Loggers>
</Configuration>éªè¯é 眮æ¯åŠçæ
é çœ®å®æåïŒéå¯åºçšçšåºïŒåš IDEA æ§å¶å°åºè¯¥èœçå°ç±»äŒŒä»¥äžå 容ïŒ
2025-10-19 15:30:45.123 TRACE tracer - curl -iX POST "localhost:9200/index_name/_search" -d '{"query": {...}}'åŠæçå°äºïŒè¯Žæé 眮æåïŒ â
åŠææ²¡çå°ïŒè¯·æ£æ¥ïŒ
- â é 眮æä»¶è·¯åŸæ¯åŠæ£ç¡®
- â æ¥å¿çº§å«æ¯åŠè®Ÿçœ®äžº TRACE
- â æ¯åŠéå¯äºåºçšçšåº
- â æ¯åŠåšæ£ç¡®ç profile äžé 眮ïŒåŠ dev/localïŒ
SQL Monitor é 眮
é 眮åç诎æ
䞺ä»ä¹éèŠé 眮æ¥å¿ïŒ
SQL Monitor çå·¥äœåçæ¯çå¬ MyBatis èŸåºç SQL æ¥å¿ãMyBatis åš DEBUG 级å«äŒèŸåºå®æŽç SQL æ§è¡ä¿¡æ¯ïŒ
==> Preparing: SELECT * FROM user WHERE id = ?
==> Parameters: 123(Integer)
<== Total: 1åŠææ¥å¿çº§å«è®Ÿçœ®äžº INFO ææŽé«ïŒè¿äºæ¥å¿äžäŒèŸåºïŒSQL Monitor å°±æ æ³æè·ã
æ¹åŒ 1ïŒé 眮 LogbackïŒæšèïŒ
åš logback-spring.xml æ logback-local.xml äžæ·»å ïŒ
<configuration>
<!-- ç°æé
çœ®ä¿æäžå... -->
<!-- ===== MyBatis SQL æ¥å¿é
çœ®ïŒæ°å¢ïŒ ===== -->
<!-- æ¹åŒ AïŒé
眮 Mapper æ¥å£å
è·¯åŸïŒæšèïŒ -->
<logger name="com.yourpackage.mapper" level="DEBUG">
<appender-ref ref="STDOUT" />
</logger>
<!-- æè
-->
<!-- æ¹åŒ BïŒé
眮 MyBatis PlusïŒåŠæäœ¿çš MyBatis PlusïŒ -->
<logger name="com.baomidou.mybatisplus" level="DEBUG">
<appender-ref ref="STDOUT" />
</logger>
<!-- æè
-->
<!-- æ¹åŒ CïŒé
çœ®ææ MyBatis æ¥å¿ -->
<logger name="org.apache.ibatis" level="DEBUG">
<appender-ref ref="STDOUT" />
</logger>
</configuration>é 眮诎æïŒ
| é 眮æ¹åŒ | Logger åç§° | 诎æ | æšè床 |
|---|---|---|---|
| æ¹åŒ A | com.yourpackage.mapper | åªèŸåºäœ ç Mapper æ¥å£ç SQL | âââââ ææšè |
| æ¹åŒ B | com.baomidou.mybatisplus | MyBatis Plus ç SQL | ââââ æšè |
| æ¹åŒ C | org.apache.ibatis | ææ MyBatis æ¥å¿ïŒå¯èœåŸå€ïŒ | âââ äžè¬ |
â ïž æ³šæïŒ è¯·å° com.yourpackage.mapper æ¿æ¢äžºäœ 项ç®äž Mapper æ¥å£çå®é
å
è·¯åŸïŒ
瀺äŸïŒ
åŠæäœ ç Mapper åš
com.example.demo.mapperå äžïŒé 眮䞺ïŒ<logger name="com.example.demo.mapper" level="DEBUG">åŠæäœ ç Mapper åš
com.torchv.application.mapperå äžïŒé 眮䞺ïŒ<logger name="com.torchv.application.mapper" level="DEBUG">
æ¹åŒ 2ïŒé 眮 application.yml
åš application.yml æ application-dev.yml äžæ·»å ïŒ
# æ¥å¿é
眮
logging:
level:
# æ¹åŒ AïŒé
眮 Mapper æ¥å£å
è·¯åŸïŒæšèïŒ
com.yourpackage.mapper: DEBUG
# æè
# æ¹åŒ BïŒé
眮 MyBatis Plus
com.baomidou.mybatisplus: DEBUG
# æè
# æ¹åŒ CïŒé
çœ®ææ MyBatis æ¥å¿
org.apache.ibatis: DEBUGâ ïž åæ ·éèŠæ¿æ¢äžºäœ çå®é å è·¯åŸïŒ
éªè¯é 眮æ¯åŠçæ
é çœ®å®æåïŒéå¯åºçšçšåºïŒåš IDEA æ§å¶å°åºè¯¥èœçå°ç±»äŒŒä»¥äžå 容ïŒ
2025-10-19 15:30:45.123 DEBUG com.example.mapper.UserMapper.selectById - ==> Preparing: SELECT * FROM user WHERE id = ?
2025-10-19 15:30:45.125 DEBUG com.example.mapper.UserMapper.selectById - ==> Parameters: 123(Integer)
2025-10-19 15:30:45.130 DEBUG com.example.mapper.UserMapper.selectById - <== Total: 1åŠæçå°äºïŒè¯Žæé 眮æåïŒ â
åŠææ²¡çå°ïŒè¯·æ£æ¥ïŒ
- â Mapper å è·¯åŸæ¯åŠæ£ç¡®
- â æ¥å¿çº§å«æ¯åŠè®Ÿçœ®äžº DEBUG
- â æ¯åŠéå¯äºåºçšçšåº
- â æ¯åŠåšæ£ç¡®ç profile äžé 眮
宿Žé 眮瀺äŸïŒåºäºäœ ç ais-server 项ç®ïŒ
æ ¹æ®äœ æäŸçé
眮ïŒè¿æ¯äžäžªå®æŽç logback-local.xml 瀺äŸïŒ
<configuration>
<!-- æ§å¶å°èŸåº -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) %cyan(%logger{36}) - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- æä»¶èŸåº -->
<appender name="syslog" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>logs/ais-server.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>logs/ais-server.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>50MB</maxFileSize>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- Root Logger -->
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
<!-- äžå¡æ¥å¿ -->
<logger name="com.torchv" level="DEBUG">
<appender-ref ref="syslog" />
</logger>
<!-- ===== Elasticsearch æ¥å¿é
眮 ===== -->
<!-- Elasticsearch Java Client è¯·æ±æ¥å¿ -->
<logger name="org.elasticsearch.client" level="DEBUG">
<appender-ref ref="STDOUT" />
<appender-ref ref="syslog" />
</logger>
<!-- Spring Data Elasticsearch æ¥è¯¢æ¥å¿ -->
<logger name="org.springframework.data.elasticsearch" level="DEBUG">
<appender-ref ref="STDOUT" />
<appender-ref ref="syslog" />
</logger>
<!-- Elasticsearch RestClient è¯Šç»æ¥å¿ -->
<logger name="org.elasticsearch.client.RestClient" level="DEBUG">
<appender-ref ref="STDOUT" />
<appender-ref ref="syslog" />
</logger>
<!-- Elasticsearch 请æ±è¿œèžªïŒæè¯Šç»ïŒ -->
<logger name="tracer" level="TRACE">
<appender-ref ref="STDOUT" />
<appender-ref ref="syslog" />
</logger>
<!-- ===== MyBatis SQL æ¥å¿é
眮 ===== -->
<!-- MyBatis Mapper æ¥å¿ïŒè¯·æ¿æ¢äžºäœ çå®é
å
è·¯åŸïŒ -->
<logger name="com.torchv.application.mapper" level="DEBUG">
<appender-ref ref="STDOUT" />
<appender-ref ref="syslog" />
</logger>
<!-- MyBatis Plus æ¥å¿ïŒåŠæäœ¿çšïŒ -->
<logger name="com.baomidou.mybatisplus" level="DEBUG">
<appender-ref ref="STDOUT" />
<appender-ref ref="syslog" />
</logger>
</configuration>对åºç application.yml é
眮ïŒ
# æ¥å¿é
眮
logging:
level:
# Elasticsearch 客æ·ç«¯æ¥å¿
org.elasticsearch.client: DEBUG
org.elasticsearch.client.RestClient: DEBUG
# Spring Data Elasticsearch
org.springframework.data.elasticsearch: DEBUG
org.springframework.data.elasticsearch.client.elc: DEBUG
# HTTP 远螪
tracer: TRACE
# MyBatis Mapper æ¥å¿
com.torchv.application.mapper: DEBUG
# MyBatis Plus
com.baomidou.mybatisplus: DEBUGð¬ 䜿çšåºæ¯
åºæ¯ 1ïŒäŒå Elasticsearch æ¥è¯¢æ§èœ
é®é¢ïŒ åéæ£çŽ¢åŸæ ¢ïŒäžç¥éæ¯åªéçé®é¢ã
è§£å³æ¹æ¡ïŒ
- æåŒ ES DSL Monitor
- æ§è¡åéæ£çŽ¢æäœ
- åšçæ§çªå£æ¥çå®é ç DSL æ¥è¯¢
æ£æ¥ïŒ
num_candidatesæ¯åŠè®Ÿçœ®åçïŒkåŒæ¯åŠè¿å€§ïŒ- æ¯åŠæäžå¿
èŠç
boolæ¥è¯¢ïŒ - åé绎床æ¯åŠæ£ç¡®ïŒ
- å€å¶ DSL å° Kibana è¿è¡è°äŒæµè¯
- ä¿®æ¹ä»£ç ïŒå次éªè¯
ææïŒ æ¥è¯¢æ§èœæå 3 åïŒ ð
åºæ¯ 2ïŒææ¥ N+1 æ¥è¯¢é®é¢
é®é¢ïŒ å衚æ¥å£åŸæ ¢ïŒæçæ N+1 æ¥è¯¢ã
è§£å³æ¹æ¡ïŒ
- æåŒ SQL Monitor
- è°çšå衚æ¥å£
- åšçæ§çªå£æ¥ç SQL æ§è¡æ åµ
åç°ïŒ
SELECT * FROM order WHERE user_id = 1 -- 1 次 SELECT * FROM order_item WHERE order_id = 101 -- N 次 SELECT * FROM order_item WHERE order_id = 102 -- N 次 SELECT * FROM order_item WHERE order_id = 103 -- N 次 ...- ç¡®è®€æ¯ N+1 æ¥è¯¢é®é¢
- ä¿®æ¹äžºäœ¿çš
JOINææ¹éæ¥è¯¢ - 忬¡éªè¯ïŒåªæ§è¡ 1-2 æ¡ SQL
ææïŒ æ¥å£ååºæ¶éŽä» 2 ç§éå° 200 毫ç§ïŒ â¡
åºæ¯ 3ïŒè¿œèžª API è°çšéŸè·¯
é®é¢ïŒ æäžª API æ¥éäºïŒäžç¥éæ§è¡äºåªäºæ¥è¯¢ã
è§£å³æ¹æ¡ïŒ
- æåŒ ES DSL Monitor å SQL Monitor
- æž ç©ºææåå²è®°åœ
- è°çšåºé®é¢ç API
åšçæ§çªå£æ¥çïŒ
- æ§è¡äºåªäº SQLïŒ
- æ§è¡äºåªäº ES æ¥è¯¢ïŒ
- åæ°æ¯åŠæ£ç¡®ïŒ
- åªäžæ¥åºéäºïŒ
- å®äœé®é¢æ ¹æº
ææïŒ 5 åéå®äœé®é¢ïŒèäžæ¯ 2 å°æ¶ïŒ ð¯
åºæ¯ 4ïŒåŠä¹ åçè§£ ORM è¡äžº
é®é¢ïŒ äžç¡®å® MyBatis / Spring Data ES çæçæ¥è¯¢æ¯ä»ä¹æ ·çã
è§£å³æ¹æ¡ïŒ
- æåŒå¯¹åºççæ§å·¥å ·
- æ§è¡åç§æäœ
- è§å¯çæçæ¥è¯¢
åŠä¹ ïŒ
- å页æ¯åŠäœå®ç°çïŒ
- æåºæ¯åŠäœå€ççïŒ
- 倿æ¡ä»¶æ¯åŠäœèœ¬æ¢çïŒ
- å ³èæ¥è¯¢æ¯åŠäœæ§è¡çïŒ
ææïŒ å¿«éææ¡æ¡æ¶è¡äžºïŒååºæŽé«æç代ç ïŒ ð
åºæ¯ 5ïŒä»£ç 审æ¥åæ§èœäŒå
é®é¢ïŒ éèŠå®¡æ¥åäºç代ç ïŒç¡®ä¿æ¥è¯¢åçã
è§£å³æ¹æ¡ïŒ
- è¿è¡åäºç代ç
- æåŒçæ§å·¥å ·
- æ§è¡åç§æäœ
æ£æ¥ïŒ
- æ¯åŠæåäœæ¥è¯¢ïŒ
- æ¯åŠææ ¢æ¥è¯¢ïŒ
- çŽ¢åŒæ¯åŠäœ¿çšæ£ç¡®ïŒ
- æ¥è¯¢é»èŸæ¯åŠåçïŒ
- æåºäŒå建议
ææïŒ æåå¢é代ç 莚éïŒé¿å æ§èœé®é¢äžçº¿ïŒ ð¡ïž
â åžžè§é®é¢
Q1: 䞺ä»ä¹æ²¡ææè·å° ES æ¥è¯¢ïŒ
A: è¯·æ£æ¥ä»¥äžå ç¹ïŒ
â "å¯çš ES çå¬"åŒå ³æ¯åŠæåŒïŒ
- åš ES DSL Monitor å·¥å ·çªå£é¡¶é𿣿¥
â æ¥å¿é 眮æ¯åŠæ£ç¡®ïŒ
- æ£æ¥
logback.xmlæapplication.yml - 确讀
traceræ¥å¿çº§å«äžºTRACE - 确讀æ¥å¿èŸåºå°æ§å¶å°ïŒ
STDOUTïŒ
- æ£æ¥
â åºçšçšåºæ¯åŠåš IDEA äžè¿è¡ïŒ
- å¿ é¡»éè¿ IDEA ç Run/Debug å¯åš
- å€éšå¯åšçåºçšæ æ³çæ§
â æ¯åŠæ§è¡äº ES æ¥è¯¢æäœïŒ
- è§ŠåäžäžªäŒè°çš ES çåèœ
- æ£æ¥æ§å¶å°æ¯åŠæ
curlåŒå€Žçæ¥å¿
â æ¥å¿æ ŒåŒæ¯åŠæ¯æïŒ
- æ¥ç
docs/EsDslMonitoräœ¿çšæå.mdäºè§£æ¯æçæ ŒåŒ
- æ¥ç
è°è¯æ¹æ³ïŒ
åšæ§å¶å°æçŽ¢ curl æ tracerïŒåŠææŸäžå°ïŒè¯Žææ¥å¿é
眮æªçæã
Q2: 䞺ä»ä¹æ²¡ææè·å° SQL æ¥è¯¢ïŒ
A: è¯·æ£æ¥ä»¥äžå ç¹ïŒ
â "å¯çš SQL çå¬"åŒå ³æ¯åŠæåŒïŒ
- åš SQL Monitor å·¥å ·çªå£é¡¶é𿣿¥
â æ¥å¿é 眮æ¯åŠæ£ç¡®ïŒ
- æ£æ¥ Mapper å è·¯åŸæ¯åŠæ£ç¡®
- 确讀æ¥å¿çº§å«äžº
DEBUG - 确讀æ¥å¿èŸåºå°æ§å¶å°
â é¡¹ç®æ¯åŠäœ¿çš MyBatisïŒ
- SQL Monitor ç®ååªæ¯æ MyBatis
- äžæ¯æ JPA/Hibernate åçæ¥å¿ïŒå¯èœåšæªæ¥çæ¬æ¯æïŒ
â æ¯åŠæ§è¡äºæ°æ®åºæäœïŒ
- è§ŠåäžäžªäŒæ¥è¯¢æ°æ®åºçåèœ
- æ£æ¥æ§å¶å°æ¯åŠæ
Preparing:æ¥å¿
è°è¯æ¹æ³ïŒ
åšæ§å¶å°æçŽ¢ Preparing: æ Parameters:ïŒåŠææŸäžå°ïŒè¯Žææ¥å¿é
眮æªçæã
Q3: åéæ°æ®å€ªé¿ïŒæ¥å¿éŸä»¥é 读æä¹åïŒ
A: ES DSL Monitor å·²ç»äŒåäºåéæ°æ®çæŸç€ºïŒ
- â èªåšæªæïŒåéæ°æ®äŒèªåšæªææŸç€º
- â æå æŸç€ºïŒå¯ä»¥æå /å±åŒåéåæ®µ
- â å€å¶åèœïŒå¯ä»¥åç¬å€å¶ DSLïŒäžå å«åéïŒ
åŠæä»ç¶è§åŸå€ªé¿ïŒå¯ä»¥ïŒ
- åšè¯Šæ 颿¿äžæ¥çïŒæŽæž æ°ïŒ
- äœ¿çšæçŽ¢åèœè¿æ»€
- 富åºå°æä»¶åçšçŒèŸåšæ¥ç
Q4: API è·¯åŸæŸç€º "N/A" æä¹åïŒ
A: API è·¯åŸæ¯éè¿è§£ææ¥å¿äžçäžäžæä¿¡æ¯è·åçãåŠææŸç€º "N/A"ïŒå¯èœæ¯ïŒ
æ¥å¿äžæ²¡æ API è·¯åŸä¿¡æ¯
åš Controller äžæ·»å æ¥å¿ïŒ
@GetMapping("/api/user/list") public Result list() { log.info("API:/api/user/list"); // æ·»å è¿è¡ // ... }
API æ¥å¿åæ¥è¯¢æ¥å¿éŽé倪è¿
- çŒå²åºå€§å°æéïŒåŠæéŽé倪è¿å¯èœæ æ³å ³è
- å»ºè®®åšæ¥è¯¢ååéœæå°æ¥å¿
æ¥å¿æ ŒåŒäžå¹é
- ç¡®ä¿æ¥å¿å
å«
API:æURI:å ³é®è¯ æ¯æçæ ŒåŒïŒ
API:/api/user/listURI:/api/user/listRequest URI: /api/user/list
- ç¡®ä¿æ¥å¿å
å«
Q5: çæ§å·¥å ·äŒåœ±åæ§èœåïŒ
A: å ä¹äžäŒïŒ
æ§èœäŒåæªæœïŒ
- â åŒæ¥å€çïŒææè§£æéœåšåå°çº¿çšæ§è¡
- â æºèœè¿æ»€ïŒåªå€ççžå ³æ¥å¿ïŒè¿æ»€æ å ³å 容
- â çŒå²äŒåïŒåçççŒå²åºå€§å°ïŒé¿å å åæº¢åº
- â å»éæºå¶ïŒé¿å éå€è®°åœå çšèµæº
- â èªåšæž çïŒè¶ è¿ 1000 æ¡èªåšæž çæ§è®°åœ
æ§èœæµè¯ç»æïŒ
- CPU å çšïŒ< 1%
- å åå çšïŒ< 50MB
- 对åºçšæ§èœåœ±åïŒå¯å¿œç¥äžè®¡
建议ïŒ
- åŒåç¯å¢ïŒå§ç»åŒå¯
- ç产ç¯å¢ïŒäžéèŠïŒæä»¶åªåš IDEA äžè¿è¡ïŒ
Q6: å¯ä»¥åæ¶çæ§ ES å SQL åïŒ
A: åœç¶å¯ä»¥ïŒèäžäºäžå¹²æ°ïŒ
ææ¯ä¿éïŒ
- â ç¬ç«çå¬åšïŒES å SQL 䜿çšäžåççå¬åš
- â æºèœè¿æ»€ïŒES Monitor è¿æ»€æ SQL æ¥å¿ïŒSQL Monitor è¿æ»€æ ES æ¥å¿
- â ç¬ç«ååšïŒæ°æ®åå«ååšåšäžåçæä»¶
- â ç¬ç« UIïŒäž€äžªç¬ç«çå·¥å ·çªå£
æäœ³å®è·µïŒ
åæ¶æåŒäž€äžªçæ§çªå£ïŒå
šé¢ææ¡åºçšçæ°æ®è®¿é®æ
åµïŒQ7: æ¥å¿å€ªå€ïŒåœ±åæ§èœæä¹åïŒ
A: æå ç§è§£å³æ¹æ¡ïŒ
æ¹æ¡ 1ïŒåªåšéèŠæ¶å¯çš
# application-dev.ymlïŒåŒåç¯å¢ïŒ
logging:
level:
tracer: TRACE
com.yourpackage.mapper: DEBUG
# application-prod.ymlïŒç产ç¯å¢ïŒ
logging:
level:
tracer: INFO # å
³éè¯Šç»æ¥å¿
com.yourpackage.mapper: INFOæ¹æ¡ 2ïŒäœ¿çšç¯å¢åéæ§å¶
logging:
level:
tracer: ${ES_LOG_LEVEL:INFO} # é»è®€ INFOïŒéèŠæ¶æ¹äžº TRACE
com.yourpackage.mapper: ${SQL_LOG_LEVEL:INFO}å¯åšæ¶ïŒ
java -jar app.jar --ES_LOG_LEVEL=TRACE --SQL_LOG_LEVEL=DEBUGæ¹æ¡ 3ïŒäœ¿çšç¬ç«çæ¥å¿æä»¶
<!-- åç¬ç ES æ¥å¿æä»¶ -->
<appender name="ES_LOG" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>logs/elasticsearch.log</File>
<!-- ... -->
</appender>
<logger name="tracer" level="TRACE" additivity="false">
<appender-ref ref="STDOUT" />
<appender-ref ref="ES_LOG" /> <!-- åæ¶èŸåºå°æä»¶ -->
</logger>Q8: å¯ä»¥å¯Œåºæ¥è¯¢è®°åœåïŒ
A: å¯ä»¥ïŒæ¯æå€ç§å¯Œåºæ¹åŒïŒ
æ¹åŒ 1ïŒå¯Œåºåæ¡è®°åœ
- åšè¡šæ Œäžéäžäžæ¡è®°åœ
- ç¹å» "富åºéäž" æé®
- è®°åœå·²å€å¶å°åªèŽŽæ¿
- ç²èŽŽå°ä»»äœå°æ¹
æ¹åŒ 2ïŒå€å¶å¯æ§è¡ SQL/DSL
- éäžè®°åœïŒæ¥ç诊æ
- ç¹å» "å€å¶ SQL" æ "å€å¶ DSL"
- çŽæ¥ç²èŽŽå°æ°æ®åºå·¥å ·æ Kibana
æ¹åŒ 3ïŒæ¹é富åºïŒæåšïŒ
æ¥è¯¢è®°åœä¿ååšïŒ
- ES:
.idea/es-dsl-records.json - SQL:
.idea/sql-records.json
å¯ä»¥çŽæ¥å€å¶è¿äºæä»¶è¿è¡å€ä»œæåæã
ð¬ ææ¯åç
å·¥äœåçæŠè¿°
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â äœ çåºçšçšåº â
â ââââââââââââââââ ââââââââââââââââ â
â â Controller â â Service â â
â ââââââââ¬ââââââââ ââââââââ¬ââââââââ â
â â â â
â â â è°çš â â¡ æ§è¡æ¥è¯¢ â
â ⌠⌠â
â ââââââââââââââââ ââââââââââââââââ â
â â Mapper â â ES Template â â
â ââââââââ¬ââââââââ ââââââââ¬ââââââââ â
â â â â
â â ⢠èŸåºæ¥å¿ â ⢠èŸåºæ¥å¿ â
â ⌠⌠â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â IDEA æ§å¶å° (Console) â â
â â ==> Preparing: SELECT ... â â
â â curl -X POST "localhost:9200/..." â â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â
â ⣠ç嬿§å¶å°èŸåº
âŒ
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â PandaCoder æä»¶ â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â ExecutionManager (è¿çšç®¡çåš) â â
â â çå¬åºçšå¯åš/忢ïŒè·å ProcessHandler â â
â ââââââââââââââââââââââ¬ââââââââââââââââââââââââââââââââââ â
â â †éå çå¬åš â
â ⌠â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â ProcessListener (è¿çšçå¬åš) â â
â â ⢠EsDslOutputListener â â
â â ⢠SqlOutputListener â â
â â éè¡æ¥æ¶æ§å¶å°ææ¬ â â
â ââââââââââââââââââââââ¬ââââââââââââââââââââââââââââââââââ â
â â ⥠æºèœè¿æ»€åçŒå² â
â ⌠â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â Parser (è§£æåš) â â
â â ⢠EsDslParser: è§£æ ES æ¥è¯¢ â â
â â ⢠SqlParser: è§£æ SQL æ¥è¯¢ â â
â â æåå
³é®ä¿¡æ¯ïŒæ¹æ³ã玢åŒã衚åãåæ°çïŒ â â
â ââââââââââââââââââââââ¬ââââââââââââââââââââââââââââââââââ â
â â ⊠ä¿åè®°åœ â
â ⌠â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â RecordService (è®°åœæå¡) â â
â â ⢠å»é â â
â â ⢠æä¹
å (JSON) â â
â â ⢠éç¥ UI æŽæ° â â
â ââââââââââââââââââââââ¬ââââââââââââââââââââââââââââââââââ â
â â â§ å®æ¶æŽæ° â
â ⌠â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â ToolWindow (å·¥å
·çªå£) â â
â â â¢ è¡šæ Œå±ç€º â â
â â ⢠诊æ
颿¿ â â
â â ⢠æçŽ¢/è¿æ»€/å¯Œåº â â
â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââæ žå¿ææ¯ç¹
1. è¿çšç嬿ºå¶
// çå¬åºçšå¯åšäºä»¶
ApplicationManager.getApplication().getMessageBus()
.connect(project)
.subscribe(ExecutionManager.EXECUTION_TOPIC, new ExecutionListener() {
@Override
public void processStarted(..., ProcessHandler handler) {
// åºçšå¯åšæ¶ïŒèªåšéå çå¬åš
attachListener(handler);
}
});å ³é®ç¹ïŒ
- äœ¿çš IntelliJ Platform ç
ExecutionManagerAPI - ç嬿æè¿è¡é 眮çå¯åš/忢äºä»¶
- èªåšéå /ç§»é€çå¬åšïŒæ éæåšæäœ
2. æ§å¶å°èŸåºçå¬
public class EsDslOutputListener implements ProcessListener {
@Override
public void onTextAvailable(ProcessEvent event, Key outputType) {
String text = event.getText(); // éè¡æ¥æ¶æ§å¶å°ææ¬
// æºèœè¿æ»€
if (shouldKeepText(text)) {
buffer.append(text); // æ·»å å°çŒå²åº
}
// æ£æµå®æŽæ¥å¿
if (shouldTriggerParse(text)) {
triggerAsyncParse(); // åŒæ¥è§£æ
}
}
}å ³é®ç¹ïŒ
- å®ç°
ProcessListeneræ¥å£ - éè¡æ¥æ¶æ§å¶å°èŸåº
- æºèœè¿æ»€æ å ³æ¥å¿
- 䜿çšçŒå²åºå€çè·šè¡æ¥å¿
3. æºèœè¿æ»€ç®æ³
private boolean shouldKeepText(String text) {
String lowerText = text.toLowerCase();
// ES Monitor: è¿æ»€æ SQL æ¥å¿
if (lowerText.contains("basejdbclogger") ||
lowerText.contains("preparing:")) {
return false; // äžä¿ç
}
// SQL Monitor: è¿æ»€æ ES æ¥å¿
if (lowerText.contains("requestlogger") ||
lowerText.contains("elasticsearch")) {
return false; // äžä¿ç
}
// ä¿ççžå
³æ¥å¿
if (lowerText.contains("tracer") || // ES æ¥å¿
lowerText.contains("preparing:")) { // SQL æ¥å¿
return true;
}
return false;
}å ³é®ç¹ïŒ
- ES å SQL çå¬åšäºçžè¿æ»€å¯¹æ¹çæ¥å¿
- é¿å 误å€åéå€è®°åœ
- æé«è§£ææç
4. åŒæ¥è§£æ
private void triggerAsyncParse() {
// é¿å
å¹¶åè§£æ
if (!isParsing.compareAndSet(false, true)) {
return;
}
// è·åçŒå²åºå¿«ç
§
final String bufferedText = buffer.toString();
// åšåå°çº¿çšåŒæ¥è§£æ
ApplicationManager.getApplication().executeOnPooledThread(() -> {
try {
parseAndSave(bufferedText);
} finally {
isParsing.set(false);
}
});
}å ³é®ç¹ïŒ
- 䜿çš
AtomicBooleané¿å å¹¶åè§£æ - åšåå°çº¿çšæ§è¡ïŒäžé»å¡ IDEA
- 䜿çšå¿«ç §é¿å çŒå²åºè¢«ä¿®æ¹
5. æºèœå»é
private boolean isDuplicate(EsDslRecord newRecord) {
long now = System.currentTimeMillis();
for (EsDslRecord existing : records) {
// æ¶éŽçªå£æ£æ¥ïŒ5ç§å
ïŒ
if (now - existing.getTimestamp() > 5000) {
continue;
}
// å
容çžäŒŒåºŠæ£æ¥
if (isSimilar(newRecord, existing)) {
return true; // éå€
}
}
return false;
}
private boolean isSimilar(EsDslRecord r1, EsDslRecord r2) {
return r1.getMethod().equals(r2.getMethod()) &&
r1.getIndex().equals(r2.getIndex()) &&
r1.getEndpoint().equals(r2.getEndpoint()) &&
normalizeJson(r1.getDslQuery()).equals(normalizeJson(r2.getDslQuery()));
}å ³é®ç¹ïŒ
- æ¶éŽçªå£å»éïŒ5 ç§å çžåæ¥è¯¢åªä¿ç 1 æ¡ïŒ
- å€ç»ŽåºŠçžäŒŒåºŠå€æ
- 応ç¥ç©ºçœå笊差åŒ
6. æä¹ åååš
private void saveToFile() {
try {
String json = objectMapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(records);
File file = new File(project.getBasePath(), ".idea/es-dsl-records.json");
Files.writeString(file.toPath(), json, StandardCharsets.UTF_8);
} catch (Exception e) {
LOG.error("Failed to save records", e);
}
}å ³é®ç¹ïŒ
- äœ¿çš JSON æ ŒåŒååš
- ä¿ååšé¡¹ç®ç
.ideaç®åœ - èªåšå 蜜åå²è®°åœ
ð æ»ç»
䞺ä»ä¹éæ© PandaCoder ççæ§å·¥å ·ïŒ
â 对æ¯å ¶ä»æ¹æ¡
| ç¹æ§ | PandaCoder | MyBatis Log Plugin | æåšæå°æ¥å¿ | æ°æ®åºå·¥å · |
|---|---|---|---|---|
| ES æ¥è¯¢çæ§ | â å®çŸæ¯æ | â äžæ¯æ | â ïž éèŠæåš | â äžæ¯æ |
| SQL æ¥è¯¢çæ§ | â å®çŸæ¯æ | â æ¯æ | â ïž éèŠæåš | â ïž äºååæ |
| API å ³è | â èªåšå ³è | â äžæ¯æ | â ïž éèŠæåš | â äžæ¯æ |
| 宿¶çæ§ | â 宿¶ | â 宿¶ | â ïž éèŠæ¥çæ¥å¿ | â äºå |
| é¶ä»£ç äŸµå ¥ | â é¶äŸµå ¥ | â é¶äŸµå ¥ | â éèŠä¿®æ¹ä»£ç | â é¶äŸµå ¥ |
| 坿§è¡ SQL/DSL | â äžé®å€å¶ | â äžé®å€å¶ | â ïž éèŠæåšæŒæ¥ | â æ¯æ |
| åå²è®°åœ | â èªåšä¿å | â ïž æé | â äžä¿å | â ä¿å |
| æ§èœåœ±å | â å 乿 | â å 乿 | â ïž æåœ±å | â æ 圱å |
ð æ žå¿äŒå¿
äžç«åŒè§£å³æ¹æ¡
- åæ¶æ¯æ ES å SQL çæ§
- æ éå®è£ å€äžªæä»¶
æºèœå
- èªåšè¿æ»€æ å ³æ¥å¿
- æºèœå»é
- èªåšå ³è API
åŒåå奜
- é¶ä»£ç äŸµå ¥
- äžé®å€å¶å¯æ§è¡æ¥è¯¢
- 宿¶æŽæ°
æ§èœäŒåŒ
- åŒæ¥å€ç
- æºèœçŒå²
- å ä¹é¶æ§èœæè
æç»æŽæ°
- 掻è·ç»Žæ€
- æç»äŒå
- ç€Ÿåºæ¯æ
ð è·ååž®å©
éå°é®é¢ïŒ
æ¥çæ¥å¿
HelpâShow Log in Explorer- æçŽ¢
[ES DSL]æ[SQL Monitor]
èç³»äœè
- ð§ Email: yixiaoshu88@163.com
- ð Website: https://www.shuyixiao.cn
- ð¬ GitHub Issues: æäº€é®é¢
åéŠå»ºè®®
æä»¬æ¬¢è¿ä»»äœåéŠå建议ïŒ
- â åŠæè§åŸå¥œçšïŒè¯·ç»é¡¹ç®ç¹äžª Star
- ð åç° BugïŒè¯·æäº€ Issue
- ð¡ ææ°æ³æ³ïŒæ¬¢è¿ Pull Request
ð åŒå§äœ¿çšå§ïŒ
ç°åšäœ å·²ç»äºè§£äº ES DSL Monitor å SQL Monitor çææåèœåé çœ®æ¹æ³ã
ç«å³è¡åšïŒ
- â æç §é 眮æåé 眮æ¥å¿
- â éå¯åºçšçšåº
- â æåŒçæ§å·¥å ·çªå£
- â åŒå§äº«åå¯è§åçæ§ç䟿å©ïŒ
è®°äœïŒ
- ð ES éèŠé
眮
traceræ¥å¿äžºTRACE - ð SQL éèŠé
眮 Mapper å
è·¯åŸäžº
DEBUG - ð äž€äžªçæ§å¯ä»¥åæ¶äœ¿çšïŒäºäžå¹²æ°
ç¥äœ åŒåæå¿«ïŒ ð
PandaCoder - è®©äžæåŒåè ççŒçšæŽé«æïŒ
ææ¡£çæ¬ïŒv2.0.0
æŽæ°æ¶éŽïŒ2025-10-19
äœè
ïŒèäžç¬äžç§å€Ž
**ç²äœ** _æäœ_ [éŸæ¥](http://example.com) `代ç ` - å衚 > åŒçšãäœ è¿å¯ä»¥äœ¿çš@æ¥éç¥å ¶ä»çšæ·ã