ð 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
äœè
ïŒèäžç¬äžçŠ¿é