From a30381fd45fb9020e865d8e5fd23332d8b5bc5ea Mon Sep 17 00:00:00 2001 From: actiontech-zihan Date: Wed, 22 Apr 2026 11:29:00 +0000 Subject: [PATCH 1/2] i18n: add Oracle slow log locale entries #2745 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增 ApMetaOracleSlowLog 国际化条目,用于 Oracle 慢日志扫描任务类型描述。 在 message_zh.go、active.en.toml、active.zh.toml 三个文件中分别添加 中英文翻译。 --- sqle/locale/active.en.toml | 1 + sqle/locale/active.zh.toml | 1 + sqle/locale/message_zh.go | 1 + 3 files changed, 3 insertions(+) diff --git a/sqle/locale/active.en.toml b/sqle/locale/active.en.toml index ca5b953d6..3c923a530 100644 --- a/sqle/locale/active.en.toml +++ b/sqle/locale/active.en.toml @@ -34,6 +34,7 @@ ApMetaMySQLTopSQL = "MySQL TOP SQL" ApMetaObForOracleTopSQL = "OceanBase For Oracle TOP SQL" ApMetaOceanBaseForMySQLFullCollect = "Full Collect" ApMetaOceanBaseForMySQLSlowLog = "OceanBase For MySQL slow log" +ApMetaOracleSlowLog = "Oracle slow log" ApMetaOracleTopSQL = "Oracle TOP SQL" ApMetaPerformanceCollect = "Performance metrics" ApMetaPerformanceCollectTips = "Performance metric collection will incur significant performance overhead, so please enable it with caution. Once enabled, the system will continuously collect performance data (such as QPS, number of connections, etc.) for this data source and generate performance trend charts, which will be displayed on the Performance Insights page." diff --git a/sqle/locale/active.zh.toml b/sqle/locale/active.zh.toml index db04148b0..48bada572 100644 --- a/sqle/locale/active.zh.toml +++ b/sqle/locale/active.zh.toml @@ -34,6 +34,7 @@ ApMetaMySQLTopSQL = "MySQL TOP SQL" ApMetaObForOracleTopSQL = "OceanBase For Oracle TOP SQL" ApMetaOceanBaseForMySQLFullCollect = "全量采集" ApMetaOceanBaseForMySQLSlowLog = "慢日志" +ApMetaOracleSlowLog = "Oracle慢日志" ApMetaOracleTopSQL = "Oracle TOP SQL" ApMetaPerformanceCollect = "数据源性能指标" ApMetaPerformanceCollectTips = "性能指标采集将产生较大性能开销,请谨慎开启。开启后,系统将持续采集该数据源的性能数据(如QPS、连接数等),并生成性能趋势图表,体现在性能洞察页面。" diff --git a/sqle/locale/message_zh.go b/sqle/locale/message_zh.go index 18a24b878..1bb62334c 100644 --- a/sqle/locale/message_zh.go +++ b/sqle/locale/message_zh.go @@ -405,6 +405,7 @@ var ( ApMetaBaiduRdsMySQLSlowLog = &i18n.Message{ID: "ApMetaBaiduRdsMySQLSlowLog", Other: "百度云RDS MySQL慢日志"} ApMetaHuaweiRdsMySQLSlowLog = &i18n.Message{ID: "ApMetaHuaweiRdsMySQLSlowLog", Other: "华为云RDS MySQL慢日志"} ApMetaOracleTopSQL = &i18n.Message{ID: "ApMetaOracleTopSQL", Other: "Oracle TOP SQL"} + ApMetaOracleSlowLog = &i18n.Message{ID: "ApMetaOracleSlowLog", Other: "Oracle慢日志"} ApMetaAllAppExtract = &i18n.Message{ID: "ApMetaAllAppExtract", Other: "应用程序SQL抓取"} ApMetaTiDBAuditLog = &i18n.Message{ID: "ApMetaTiDBAuditLog", Other: "TiDB审计日志"} ApMetaSlowLog = &i18n.Message{ID: "ApMetaSlowLog", Other: "慢日志"} From 2e2ffa07e60880c29317ee7193ac232dbc6353f5 Mon Sep 17 00:00:00 2001 From: actiontech-zihan Date: Wed, 22 Apr 2026 11:29:09 +0000 Subject: [PATCH 2/2] feat(oracle): add slow log query template and QuerySlowSQLs method #2745 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在 perf.go 中新增 DynPerformanceViewSQLAreaSlowLogTpl 查询模板, 基于 V$SQLAREA JOIN DBA_USERS,按平均执行时间阈值过滤慢 SQL, 包含 EXECUTIONS > 0 防除零保护。 在 db.go 中新增 QuerySlowSQLs 方法,参考 QueryTopSQLs 实现模式, 支持采集时间窗口、慢 SQL 阈值(微秒)、用户黑名单过滤和 Top N 限制。 复用已有的 DynPerformanceSQLArea 结构体。 --- sqle/pkg/oracle/db.go | 45 +++++++++++++++++++++++++++++++++++++++++ sqle/pkg/oracle/perf.go | 25 +++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/sqle/pkg/oracle/db.go b/sqle/pkg/oracle/db.go index ab0cb3dfc..623d3cc2a 100644 --- a/sqle/pkg/oracle/db.go +++ b/sqle/pkg/oracle/db.go @@ -110,3 +110,48 @@ func (o *DB) QueryTopSQLs(ctx context.Context, collectIntervalMinute string, top } return ret, nil } + +func (o *DB) QuerySlowSQLs(ctx context.Context, collectIntervalMinute string, topN int, slowSQLThresholdMicroseconds int64, notInUsers []string) ([]*DynPerformanceSQLArea, error) { + var notInUsersStr string + if len(notInUsers) > 0 { + var notInUsersFormatted []string + var notInUserSqlTpl = `AND u.username NOT IN (%v)` + for _, user := range notInUsers { + notInUsersFormatted = append(notInUsersFormatted, fmt.Sprintf("'%s'", user)) + } + notInUsersStr = strings.Join(notInUsersFormatted, ",") + notInUsersStr = fmt.Sprintf(notInUserSqlTpl, notInUsersStr) + } + if topN == 0 { + topN = 100 + } + + query := fmt.Sprintf(DynPerformanceViewSQLAreaSlowLogTpl, collectIntervalMinute, slowSQLThresholdMicroseconds, notInUsersStr, topN) + rows, err := o.db.QueryContext(ctx, query) + if err != nil { + return nil, errors.Wrapf(err, "failed to query %s", query) + } + defer rows.Close() + + var ret []*DynPerformanceSQLArea + for rows.Next() { + res := DynPerformanceSQLArea{} + if err := rows.Scan( + &res.SQLFullText, + &res.Executions, + &res.ElapsedTime, + &res.UserIOWaitTime, + &res.CPUTime, + &res.DiskReads, + &res.BufferGets, + &res.UserName, + ); err != nil { + return nil, errors.Wrapf(err, "failed to scan %s", query) + } + ret = append(ret, &res) + } + if err := rows.Err(); err != nil { + return nil, errors.Wrapf(err, "failed to iterate %s", query) + } + return ret, nil +} diff --git a/sqle/pkg/oracle/perf.go b/sqle/pkg/oracle/perf.go index bc9d7c0d1..6be55e1f5 100644 --- a/sqle/pkg/oracle/perf.go +++ b/sqle/pkg/oracle/perf.go @@ -38,6 +38,31 @@ SELECT * FROM ( %v ORDER BY %v DESC ) +WHERE + rownum <= %v +` + DynPerformanceViewSQLAreaSlowLogTpl = ` +SELECT * FROM ( + SELECT + s.sql_fulltext, + s.executions, + s.elapsed_time, + s.user_io_wait_time, + s.cpu_time, + s.disk_reads, + s.buffer_gets, + u.username + FROM + V$SQLAREA s + JOIN + DBA_USERS u ON s.parsing_user_id = u.user_id + WHERE + last_active_time >= SYSDATE - INTERVAL '%v' MINUTE + AND s.EXECUTIONS > 0 + AND s.elapsed_time / s.executions > %v + %v + ORDER BY s.elapsed_time / s.executions DESC +) WHERE rownum <= %v `