diff --git a/Cargo.lock b/Cargo.lock
index 88b66acc55ec..d78802ff087b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2243,6 +2243,7 @@ dependencies = [
"common-tracing",
"derive_more",
"futures",
+ "lazy_static",
"log",
"logcall",
"minitrace",
@@ -2428,11 +2429,8 @@ dependencies = [
"anyhow",
"common-exception",
"lazy_static",
- "log",
"metrics",
"metrics-exporter-prometheus",
- "once_cell",
- "parking_lot 0.12.1",
"procfs",
"prometheus-client",
"prometheus-parse",
@@ -2445,6 +2443,8 @@ name = "common-openai"
version = "0.1.0"
dependencies = [
"common-exception",
+ "common-metrics",
+ "lazy_static",
"log",
"metrics",
"openai_api_rust",
@@ -2920,7 +2920,6 @@ dependencies = [
"common-pipeline-sources",
"common-sql",
"common-storage",
- "databend-query",
"ethnum",
"futures",
"log",
@@ -3662,7 +3661,6 @@ dependencies = [
"common-meta-sled-store",
"common-meta-store",
"common-meta-types",
- "common-metrics",
"common-storage",
"common-tracing",
"databend-meta",
@@ -3875,6 +3873,7 @@ dependencies = [
"itertools 0.10.5",
"jsonb",
"jwt-simple",
+ "lazy_static",
"log",
"lz4",
"maplit",
@@ -3890,6 +3889,7 @@ dependencies = [
"ordered-float 3.7.0",
"p256 0.13.0",
"parking_lot 0.12.1",
+ "parquet",
"paste",
"petgraph",
"pin-project-lite",
@@ -8296,7 +8296,6 @@ dependencies = [
"hyper",
"log",
"md-5",
- "metrics",
"minitrace",
"moka",
"once_cell",
diff --git a/Cargo.toml b/Cargo.toml
index b1987c7be1d9..a28467126363 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -108,7 +108,6 @@ members = [
sled = { git = "https://github.com/datafuse-extras/sled", tag = "v0.34.7-datafuse.1", default-features = false }
opendal = { version = "0.39", features = [
"layers-minitrace",
- "layers-metrics",
"services-ipfs",
"services-moka",
"services-redis",
diff --git a/docs/doc/13-sql-reference/99-ansi-sql.md b/docs/doc/13-sql-reference/99-ansi-sql.md
index 25beb5c1e079..7967c20450a6 100644
--- a/docs/doc/13-sql-reference/99-ansi-sql.md
+++ b/docs/doc/13-sql-reference/99-ansi-sql.md
@@ -95,7 +95,7 @@ Databend aims to conform to the SQL standard, with particular support for ISO/IE
| E121-17 | WITH HOLD cursors | No | |
| **E131** | **Null value support (nulls in lieu of values)** | Yes | |
| **E141** | **Basic integrity constraints** | No | |
-| E141-01 | NOT NULL constraints | Yes | Default in Databend: All columns are non-nullable (NOT NULL). |
+| E141-01 | NOT NULL constraints | Yes | Default in Databend: All columns are nullable. |
| E141-02 | UNIQUE constraint of NOT NULL columns | No | |
| E141-03 | PRIMARY KEY constraints | No | |
| E141-04 | Basic FOREIGN KEY constraint with the NO ACTION default for both referential delete action and referential update action | No | |
diff --git a/docs/doc/14-sql-commands/00-ddl/50-udf/_category_.json b/docs/doc/14-sql-commands/00-ddl/50-udf/_category_.json
index fccc400f3f6b..0b9b999caf48 100644
--- a/docs/doc/14-sql-commands/00-ddl/50-udf/_category_.json
+++ b/docs/doc/14-sql-commands/00-ddl/50-udf/_category_.json
@@ -1,7 +1,3 @@
{
- "label": "User-Defined Function",
- "link": {
- "type": "generated-index",
- "slug": "/sql-commands/ddl/udf"
- }
+ "label": "User-Defined Function"
}
\ No newline at end of file
diff --git a/docs/doc/14-sql-commands/00-ddl/50-udf/ddl-alter-function.md b/docs/doc/14-sql-commands/00-ddl/50-udf/ddl-alter-function.md
index 1a727c2b02d2..a196a7689aa9 100644
--- a/docs/doc/14-sql-commands/00-ddl/50-udf/ddl-alter-function.md
+++ b/docs/doc/14-sql-commands/00-ddl/50-udf/ddl-alter-function.md
@@ -3,22 +3,33 @@ title: ALTER FUNCTION
description:
Modifies the properties for an existing user-defined function.
---
+import FunctionDescription from '@site/src/components/FunctionDescription';
+
+
+
+Alters a user-defined function.
## Syntax
```sql
-CREATE FUNCTION AS ([ argname ]) -> ''
+-- Alter UDF created with lambda expression
+ALTER FUNCTION [IF NOT EXISTS]
+ AS () ->
+ [DESC='']
+
+-- Alter UDF created with UDF server
+ALTER FUNCTION [IF NOT EXISTS]
+ AS () RETURNS LANGUAGE
+ HANDLER = '' ADDRESS = ''
+ [DESC='']
```
## Examples
```sql
+CREATE FUNCTION a_plus_3 AS (a) -> a+3+3;
ALTER FUNCTION a_plus_3 AS (a) -> a+3;
-SELECT a_plus_3(2);
-+---------+
-| (2 + 3) |
-+---------+
-| 5 |
-+---------+
-```
+CREATE FUNCTION gcd (INT, INT) RETURNS INT LANGUAGE python HANDLER = 'gcd' ADDRESS = 'http://0.0.0.0:8815';
+ALTER FUNCTION gcd (INT, INT) RETURNS INT LANGUAGE python HANDLER = 'gcd_new' ADDRESS = 'http://0.0.0.0:8815';
+```
\ No newline at end of file
diff --git a/docs/doc/14-sql-commands/00-ddl/50-udf/ddl-create-function.md b/docs/doc/14-sql-commands/00-ddl/50-udf/ddl-create-function.md
index 6e3d91a01412..303eff27943b 100644
--- a/docs/doc/14-sql-commands/00-ddl/50-udf/ddl-create-function.md
+++ b/docs/doc/14-sql-commands/00-ddl/50-udf/ddl-create-function.md
@@ -3,20 +3,44 @@ title: CREATE FUNCTION
description:
Create a new user-defined scalar function.
---
+import FunctionDescription from '@site/src/components/FunctionDescription';
+
-## CREATE FUNCTION
-
-Creates a new UDF (user-defined function), the UDF can contain an SQL expression.
+Creates a user-defined function.
## Syntax
```sql
-CREATE FUNCTION [ IF NOT EXISTS ] AS ([ argname ]) -> ''
+-- Create with lambda expression
+CREATE FUNCTION [IF NOT EXISTS]
+ AS () ->
+ [DESC='']
+
+
+-- Create with UDF server
+CREATE FUNCTION [IF NOT EXISTS]
+ AS () RETURNS LANGUAGE
+ HANDLER = '' ADDRESS = ''
+ [DESC='']
```
+| Parameter | Description |
+|-----------------------|---------------------------------------------------------------------------------------------------|
+| `` | The name of the function. |
+| `` | The lambda expression or code snippet defining the function's behavior. |
+| `DESC=''` | Description of the UDF.|
+| `<`| A list of input parameter names. Separated by comma.|
+| `<`| A list of input parameter types. Separated by comma.|
+| `` | The return type of the function. |
+| `LANGUAGE` | Specifies the language used to write the function. Available values: `python`. |
+| `HANDLER = ''` | Specifies the name of the function's handler. |
+| `ADDRESS = ''` | Specifies the address of the UDF server. |
+
## Examples
+### Creating UDF with Lambda Expression
+
```sql
CREATE FUNCTION a_plus_3 AS (a) -> a+3;
@@ -53,3 +77,89 @@ DROP FUNCTION get_v2;
DROP TABLE json_table;
```
+
+### Creating UDF with UDF Server (Python)
+
+This example demonstrates how to enable and configure a UDF server in Python:
+
+1. Enable UDF server support by adding the following parameters to the [query] section in the [databend-query.toml](https://github.com/datafuselabs/databend/blob/main/scripts/distribution/configs/databend-query.toml) configuration file.
+
+```toml title='databend-query.toml'
+[query]
+...
+enable_udf_server = true
+# List the allowed UDF server addresses, separating multiple addresses with commas.
+# For example, ['http://0.0.0.0:8815', 'http://example.com']
+udf_server_allow_list = ['http://0.0.0.0:8815']
+...
+```
+
+2. Define your function. This code defines and runs a UDF server in Python, which exposes a custom function *gcd* for calculating the greatest common divisor of two integers and allows remote execution of this function:
+
+:::note
+The SDK package is not yet available. Prior to its release, please download the 'udf.py' file from https://github.com/datafuselabs/databend/blob/main/tests/udf-server/udf.py and ensure it is saved in the same directory as this Python script. This step is essential for the code to function correctly.
+:::
+
+```python title='udf_server.py'
+from udf import *
+
+@udf(
+ input_types=["INT", "INT"],
+ result_type="INT",
+ skip_null=True,
+)
+def gcd(x: int, y: int) -> int:
+ while y != 0:
+ (x, y) = (y, x % y)
+ return x
+
+if __name__ == '__main__':
+ # create a UDF server listening at '0.0.0.0:8815'
+ server = UdfServer("0.0.0.0:8815")
+ # add defined functions
+ server.add_function(gcd)
+ # start the UDF server
+ server.serve()
+```
+
+`@udf` is a decorator used for defining UDFs in Databend, supporting the following parameters:
+
+| Parameter | Description |
+|--------------|-----------------------------------------------------------------------------------------------------|
+| input_types | A list of strings or Arrow data types that specify the input data types. |
+| result_type | A string or an Arrow data type that specifies the return value type. |
+| name | An optional string specifying the function name. If not provided, the original name will be used. |
+| io_threads | Number of I/O threads used per data chunk for I/O bound functions. |
+| skip_null | A boolean value specifying whether to skip NULL values. If set to True, NULL values will not be passed to the function, and the corresponding return value is set to NULL. Default is False. |
+
+This table illustrates the correspondence between Databend data types and their corresponding Python equivalents:
+
+| Databend Type | Python Type |
+|-----------------------|-----------------------|
+| BOOLEAN | bool |
+| TINYINT (UNSIGNED) | int |
+| SMALLINT (UNSIGNED) | int |
+| INT (UNSIGNED) | int |
+| BIGINT (UNSIGNED) | int |
+| FLOAT | float |
+| DOUBLE | float |
+| DECIMAL | decimal.Decimal |
+| DATE | datetime.date |
+| TIMESTAMP | datetime.datetime |
+| VARCHAR | str |
+| VARIANT | any |
+| MAP(K,V) | dict |
+| ARRAY(T) | list[T] |
+| TUPLE(T...) | tuple(T...) |
+
+3. Run the Python file to start the UDF server:
+
+```shell
+python3 udf_server.py
+```
+
+4. Register the function *gcd* with the [CREATE FUNCTION](ddl-create-function.md) in Databend:
+
+```sql
+CREATE FUNCTION gcd (INT, INT) RETURNS INT LANGUAGE python HANDLER = 'gcd' ADDRESS = 'http://0.0.0.0:8815';
+```
\ No newline at end of file
diff --git a/docs/doc/14-sql-commands/00-ddl/50-udf/ddl-drop-function.md b/docs/doc/14-sql-commands/00-ddl/50-udf/ddl-drop-function.md
index b93365d5f630..5650295b770d 100644
--- a/docs/doc/14-sql-commands/00-ddl/50-udf/ddl-drop-function.md
+++ b/docs/doc/14-sql-commands/00-ddl/50-udf/ddl-drop-function.md
@@ -4,12 +4,12 @@ description:
Drop an existing user-defined function.
---
-Drop an existing user-defined function.
+Drops a user-defined function.
## Syntax
```sql
-DROP FUNCTION [IF EXISTS]
+DROP FUNCTION [IF EXISTS]
```
## Examples
@@ -19,4 +19,4 @@ DROP FUNCTION a_plus_3;
SELECT a_plus_3(2);
ERROR 1105 (HY000): Code: 2602, Text = Unknown Function a_plus_3 (while in analyze select projection).
-```
+```
\ No newline at end of file
diff --git a/docs/doc/14-sql-commands/00-ddl/50-udf/index.md b/docs/doc/14-sql-commands/00-ddl/50-udf/index.md
new file mode 100644
index 000000000000..27ceaed90510
--- /dev/null
+++ b/docs/doc/14-sql-commands/00-ddl/50-udf/index.md
@@ -0,0 +1,125 @@
+---
+title: User-Defined Function
+---
+import IndexOverviewList from '@site/src/components/IndexOverviewList';
+
+## What are UDFs?
+
+User-Defined Functions (UDFs) enable you to define their own custom operations to process data within Databend. They are typically written using lambda expressions or implemented via a UDF server with programming languages such as Python and are executed as part of Databend's query processing pipeline. Advantages of using UDFs include:
+
+- Customized Data Transformations: UDFs empower you to perform data transformations that may not be achievable through built-in Databend functions alone. This customization is particularly valuable for handling unique data formats or business logic.
+
+- Performance Optimization: UDFs provide the flexibility to define and fine-tune your own custom functions, enabling you to optimize data processing to meet precise performance requirements. This means you can tailor the code for maximum efficiency, ensuring that your data processing tasks run as efficiently as possible.
+
+- Code Reusability: UDFs can be reused across multiple queries, saving time and effort in coding and maintaining data processing logic.
+
+## Managing UDFs
+
+To manage UDFs in Databend, use the following commands:
+
+
+
+## Usage Examples
+
+This section demonstrates two UDF implementation methods within Databend: one by creating UDFs with lambda expressions and the other by utilizing UDF servers in conjunction with Python. For additional examples of defining UDFs in various programming languages, see [CREATE FUNCTION](ddl-create-function.md).
+
+### UDF Implementation with Lambda Expression
+
+This example implements a UDF named *a_plus_3* using a lambda expression:
+
+```sql
+CREATE FUNCTION a_plus_3 AS (a) -> a+3;
+
+SELECT a_plus_3(2);
++---------+
+| (2 + 3) |
++---------+
+| 5 |
++---------+
+```
+
+### UDF Implementation via UDF Server
+
+This example demonstrates how to enable and configure a UDF server in Python:
+
+1. Enable UDF server support by adding the following parameters to the [query] section in the [databend-query.toml](https://github.com/datafuselabs/databend/blob/main/scripts/distribution/configs/databend-query.toml) configuration file.
+
+```toml title='databend-query.toml'
+[query]
+...
+enable_udf_server = true
+# List the allowed UDF server addresses, separating multiple addresses with commas.
+# For example, ['http://0.0.0.0:8815', 'http://example.com']
+udf_server_allow_list = ['http://0.0.0.0:8815']
+...
+```
+
+2. Define your function. This code defines and runs a UDF server in Python, which exposes a custom function *gcd* for calculating the greatest common divisor of two integers and allows remote execution of this function:
+
+:::note
+The SDK package is not yet available. Prior to its release, please download the 'udf.py' file from https://github.com/datafuselabs/databend/blob/main/tests/udf-server/udf.py and ensure it is saved in the same directory as this Python script. This step is essential for the code to function correctly.
+:::
+
+```python title='udf_server.py'
+from udf import *
+
+@udf(
+ input_types=["INT", "INT"],
+ result_type="INT",
+ skip_null=True,
+)
+def gcd(x: int, y: int) -> int:
+ while y != 0:
+ (x, y) = (y, x % y)
+ return x
+
+if __name__ == '__main__':
+ # create a UDF server listening at '0.0.0.0:8815'
+ server = UdfServer("0.0.0.0:8815")
+ # add defined functions
+ server.add_function(gcd)
+ # start the UDF server
+ server.serve()
+```
+
+`@udf` is a decorator used for defining UDFs in Databend, supporting the following parameters:
+
+| Parameter | Description |
+|--------------|-----------------------------------------------------------------------------------------------------|
+| input_types | A list of strings or Arrow data types that specify the input data types. |
+| result_type | A string or an Arrow data type that specifies the return value type. |
+| name | An optional string specifying the function name. If not provided, the original name will be used. |
+| io_threads | Number of I/O threads used per data chunk for I/O bound functions. |
+| skip_null | A boolean value specifying whether to skip NULL values. If set to True, NULL values will not be passed to the function, and the corresponding return value is set to NULL. Default is False. |
+
+This table illustrates the correspondence between Databend data types and their corresponding Python equivalents:
+
+| Databend Type | Python Type |
+|-----------------------|-----------------------|
+| BOOLEAN | bool |
+| TINYINT (UNSIGNED) | int |
+| SMALLINT (UNSIGNED) | int |
+| INT (UNSIGNED) | int |
+| BIGINT (UNSIGNED) | int |
+| FLOAT | float |
+| DOUBLE | float |
+| DECIMAL | decimal.Decimal |
+| DATE | datetime.date |
+| TIMESTAMP | datetime.datetime |
+| VARCHAR | str |
+| VARIANT | any |
+| MAP(K,V) | dict |
+| ARRAY(T) | list[T] |
+| TUPLE(T...) | tuple(T...) |
+
+3. Run the Python file to start the UDF server:
+
+```shell
+python3 udf_server.py
+```
+
+4. Register the function *gcd* with the [CREATE FUNCTION](ddl-create-function.md) in Databend:
+
+```sql
+CREATE FUNCTION gcd (INT, INT) RETURNS INT LANGUAGE python HANDLER = 'gcd' ADDRESS = 'http://0.0.0.0:8815';
+```
\ No newline at end of file
diff --git a/docs/doc/14-sql-commands/10-dml/dml-copy-into-table.md b/docs/doc/14-sql-commands/10-dml/dml-copy-into-table.md
index 5448cf61f869..53f14d49bc95 100644
--- a/docs/doc/14-sql-commands/10-dml/dml-copy-into-table.md
+++ b/docs/doc/14-sql-commands/10-dml/dml-copy-into-table.md
@@ -184,10 +184,14 @@ externalLocation ::=
Specify a list of one or more files names (separated by commas) to be loaded.
-### PATTERN = 'regex_pattern'
+### PATTERN = ''
A [PCRE2](https://www.pcre.org/current/doc/html/)-based regular expression pattern string, enclosed in single quotes, specifying the file names to match. Click [here](#loading-data-with-pattern-matching) to see an example. For PCRE2 syntax, see http://www.pcre.org/current/doc/html/pcre2syntax.html.
+:::note
+Suppose there is a file `@//`, to include it, `` needs to match `^$`.
+:::
+
### FILE_FORMAT
See [Input & Output File Formats](../../13-sql-reference/50-file-format-options.md).
diff --git a/docs/doc/15-sql-functions/112-table-functions/list_stage.md b/docs/doc/15-sql-functions/112-table-functions/list_stage.md
index e5ddaeaff1ef..9843e95ea0d7 100644
--- a/docs/doc/15-sql-functions/112-table-functions/list_stage.md
+++ b/docs/doc/15-sql-functions/112-table-functions/list_stage.md
@@ -36,10 +36,15 @@ externalStage ::= @[/]
userStage ::= @~[/]
```
+### PATTERN
+
+See [COPY INTO table](/14-sql-commands/10-dml/dml-copy-into-table.md).
+
+
## Examples
```sql
-SELECT * FROM list_stage(location => '@my_stage/', pattern => '.log');
+SELECT * FROM list_stage(location => '@my_stage/', pattern => '.*[.]log');
+----------------+------+------------------------------------+-------------------------------+---------+
| name | size | md5 | last_modified | creator |
+----------------+------+------------------------------------+-------------------------------+---------+
diff --git a/scripts/setup/rust-tools.txt b/scripts/setup/rust-tools.txt
index 1df282bb138f..5d68657a1398 100644
--- a/scripts/setup/rust-tools.txt
+++ b/scripts/setup/rust-tools.txt
@@ -2,3 +2,4 @@ cargo-audit@0.17.6
cargo-machete@0.5.0
taplo-cli@0.8.1
typos-cli@1.16.3
+nextest@0.9.58
diff --git a/src/binaries/Cargo.toml b/src/binaries/Cargo.toml
index 9351051caa44..29eb0819ff1a 100644
--- a/src/binaries/Cargo.toml
+++ b/src/binaries/Cargo.toml
@@ -27,12 +27,6 @@ io-uring = [
"common-meta-raft-store/io-uring",
]
-enable-histogram-metrics = [
- "default",
- "common-metrics/enable-histogram",
- "databend-query/enable-histogram-metrics",
-]
-
[dependencies]
# Workspace dependencies
common-base = { path = "../common/base" }
@@ -48,7 +42,6 @@ common-meta-raft-store = { path = "../meta/raft-store" }
common-meta-sled-store = { path = "../meta/sled-store" }
common-meta-store = { path = "../meta/store" }
common-meta-types = { path = "../meta/types" }
-common-metrics = { path = "../common/metrics" }
common-storage = { path = "../common/storage" }
common-tracing = { path = "../common/tracing" }
databend-meta = { path = "../meta/service" }
diff --git a/src/binaries/meta/entry.rs b/src/binaries/meta/entry.rs
index 4633971fac0f..c4a52325b958 100644
--- a/src/binaries/meta/entry.rs
+++ b/src/binaries/meta/entry.rs
@@ -31,7 +31,6 @@ use common_meta_types::Cmd;
use common_meta_types::LogEntry;
use common_meta_types::MetaAPIError;
use common_meta_types::Node;
-use common_metrics::init_default_metrics_recorder;
use common_tracing::init_logging;
use common_tracing::set_panic_hook;
use databend_meta::api::GrpcServer;
@@ -91,7 +90,6 @@ pub async fn entry(conf: Config) -> anyhow::Result<()> {
}
init_sled_db(conf.raft_config.raft_dir.clone());
- init_default_metrics_recorder();
let single_or_join = if conf.raft_config.single {
"single".to_string()
diff --git a/src/binaries/query/entry.rs b/src/binaries/query/entry.rs
index 37ddd5be1eb5..5d0e3758c2a9 100644
--- a/src/binaries/query/entry.rs
+++ b/src/binaries/query/entry.rs
@@ -25,7 +25,6 @@ use common_config::QUERY_SEMVER;
use common_exception::ErrorCode;
use common_exception::Result;
use common_meta_client::MIN_METASRV_SEMVER;
-use common_metrics::init_default_metrics_recorder;
use common_tracing::set_panic_hook;
use databend_query::api::HttpService;
use databend_query::api::RpcService;
@@ -59,7 +58,6 @@ pub async fn run_cmd(conf: &InnerConfig) -> Result {
}
pub async fn init_services(conf: &InnerConfig) -> Result<()> {
- init_default_metrics_recorder();
set_panic_hook();
set_alloc_error_hook();
diff --git a/src/common/metrics/Cargo.toml b/src/common/metrics/Cargo.toml
index f1e2838a3e75..d1094050673a 100644
--- a/src/common/metrics/Cargo.toml
+++ b/src/common/metrics/Cargo.toml
@@ -19,11 +19,8 @@ common-exception = { path = "../exception" }
# Crates.io dependencies
lazy_static = { workspace = true }
-log = { workspace = true }
metrics = "0.20.1"
metrics-exporter-prometheus = { version = "0.11.0", default-features = false }
-once_cell = "1.15.0"
-parking_lot = "0.12.1"
prometheus-client = { workspace = true }
prometheus-parse = "0.2.3"
serde = { workspace = true }
diff --git a/src/common/metrics/src/dump.rs b/src/common/metrics/src/dump.rs
index 1d9df2501f91..cfa86df54614 100644
--- a/src/common/metrics/src/dump.rs
+++ b/src/common/metrics/src/dump.rs
@@ -16,7 +16,9 @@ use std::collections::HashMap;
use common_exception::ErrorCode;
use common_exception::Result;
-use metrics_exporter_prometheus::PrometheusHandle;
+use prometheus_client::registry::Registry;
+
+use crate::render_prometheus_metrics;
#[derive(Debug)]
pub struct MetricSample {
@@ -86,8 +88,8 @@ pub struct SummaryCount {
pub count: f64,
}
-pub fn dump_metric_samples(handle: PrometheusHandle) -> Result> {
- let text = handle.render();
+pub fn dump_metric_samples(registry: &Registry) -> Result> {
+ let text = render_prometheus_metrics(registry);
let lines = text.lines().map(|s| Ok(s.to_owned()));
let mut samples = prometheus_parse::Scrape::parse(lines)
.map_err(|err| ErrorCode::Internal(format!("Dump prometheus metrics failed: {:?}", err)))?
@@ -95,8 +97,13 @@ pub fn dump_metric_samples(handle: PrometheusHandle) -> Result
.into_iter()
.map(|s| {
let value: MetricValue = s.value.into();
+ let metric_name = s
+ .metric
+ .strip_prefix("databend_")
+ .map(|s| s.to_string())
+ .unwrap_or(s.metric);
MetricSample {
- name: s.metric,
+ name: metric_name,
value,
labels: (*s.labels).clone(),
}
diff --git a/src/common/metrics/src/lib.rs b/src/common/metrics/src/lib.rs
index f4295cf632b4..066ee962b0b3 100644
--- a/src/common/metrics/src/lib.rs
+++ b/src/common/metrics/src/lib.rs
@@ -17,9 +17,9 @@
pub mod counter;
mod dump;
pub mod histogram;
-mod recorder;
pub mod registry;
-mod reset;
+
+pub type VecLabels = Vec<(&'static str, String)>;
pub use dump::dump_metric_samples;
pub use dump::HistogramCount;
@@ -31,18 +31,6 @@ pub use prometheus_client::metrics::counter::Counter;
pub use prometheus_client::metrics::family::Family;
pub use prometheus_client::metrics::gauge::Gauge;
pub use prometheus_client::metrics::histogram::Histogram;
-pub use recorder::init_default_metrics_recorder;
-pub use recorder::label_counter;
-pub use recorder::label_counter_with_val;
-pub use recorder::label_counter_with_val_and_labels;
-pub use recorder::label_decrement_gauge_with_val_and_labels;
-pub use recorder::label_gauge;
-pub use recorder::label_gauge_with_val_and_labels;
-pub use recorder::label_histogram_with_val;
-pub use recorder::label_increment_gauge_with_val_and_labels;
-pub use recorder::try_handle;
-pub use recorder::LABEL_KEY_CLUSTER;
-pub use recorder::LABEL_KEY_TENANT;
pub use registry::load_global_prometheus_registry;
pub use registry::register_counter;
pub use registry::register_counter_family;
@@ -52,4 +40,5 @@ pub use registry::register_histogram_family_in_milliseconds;
pub use registry::register_histogram_family_in_seconds;
pub use registry::register_histogram_in_milliseconds;
pub use registry::register_histogram_in_seconds;
-pub use reset::reset_metrics;
+pub use registry::render_prometheus_metrics;
+pub use registry::reset_global_prometheus_registry;
diff --git a/src/common/metrics/src/recorder.rs b/src/common/metrics/src/recorder.rs
deleted file mode 100644
index 8addaf0da91e..000000000000
--- a/src/common/metrics/src/recorder.rs
+++ /dev/null
@@ -1,313 +0,0 @@
-// Copyright 2021 Datafuse Labs
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-use std::mem::ManuallyDrop;
-use std::sync::Arc;
-use std::sync::Once;
-
-use log::warn;
-use metrics::counter;
-use metrics::decrement_gauge;
-use metrics::gauge;
-use metrics::histogram;
-use metrics::increment_gauge;
-use metrics::Counter;
-use metrics::CounterFn;
-use metrics::Gauge;
-use metrics::GaugeFn;
-use metrics::Histogram;
-use metrics::HistogramFn;
-use metrics::Key;
-use metrics::KeyName;
-use metrics::Recorder;
-use metrics::SharedString;
-use metrics::Unit;
-use metrics_exporter_prometheus::PrometheusBuilder;
-use metrics_exporter_prometheus::PrometheusHandle;
-use metrics_exporter_prometheus::PrometheusRecorder;
-use once_cell::sync::Lazy;
-use parking_lot::RwLock;
-
-static PROMETHEUS_HANDLE: Lazy>>> =
- Lazy::new(|| Arc::new(RwLock::new(None)));
-
-pub const LABEL_KEY_TENANT: &str = "tenant";
-pub const LABEL_KEY_CLUSTER: &str = "cluster_name";
-
-#[inline]
-pub fn label_histogram_with_val(
- name: &'static str,
- labels: &Vec<(&'static str, String)>,
- val: f64,
-) {
- histogram!(name, val, labels);
-}
-
-#[inline]
-pub fn label_counter_with_val_and_labels(
- name: &'static str,
- labels: &Vec<(&'static str, String)>,
- val: u64,
-) {
- counter!(name, val, labels);
-}
-
-#[inline]
-pub fn label_gauge_with_val_and_labels(
- name: &'static str,
- labels: &Vec<(&'static str, String)>,
- val: f64,
-) {
- gauge!(name, val, labels);
-}
-
-#[inline]
-pub fn label_increment_gauge_with_val_and_labels(
- name: &'static str,
- labels: &Vec<(&'static str, String)>,
- val: f64,
-) {
- increment_gauge!(name, val, labels);
-}
-
-#[inline]
-pub fn label_decrement_gauge_with_val_and_labels(
- name: &'static str,
- labels: &Vec<(&'static str, String)>,
- val: f64,
-) {
- decrement_gauge!(name, val, labels);
-}
-
-#[inline]
-pub fn label_counter(name: &'static str, tenant_id: &str, cluster_id: &str) {
- label_counter_with_val(name, 1, tenant_id, cluster_id)
-}
-
-#[inline]
-pub fn label_counter_with_val(name: &'static str, val: u64, tenant_id: &str, cluster_id: &str) {
- let labels = [
- (LABEL_KEY_TENANT, tenant_id.to_string()),
- (LABEL_KEY_CLUSTER, cluster_id.to_string()),
- ];
- counter!(name, val, &labels);
-}
-
-#[inline]
-pub fn label_gauge(name: &'static str, val: f64, tenant_id: &str, cluster_id: &str) {
- let labels = [
- (LABEL_KEY_TENANT, tenant_id.to_string()),
- (LABEL_KEY_CLUSTER, cluster_id.to_string()),
- ];
- gauge!(name, val, &labels);
-}
-
-pub fn init_default_metrics_recorder() {
- static START: Once = Once::new();
- START.call_once(init_prometheus_recorder)
-}
-
-/// Init prometheus recorder.
-fn init_prometheus_recorder() {
- let recorder = ClearableRecorder::create();
- let mut h = PROMETHEUS_HANDLE.as_ref().write();
- *h = Some(recorder.clone());
- unsafe {
- metrics::clear_recorder();
- }
- match metrics::set_boxed_recorder(Box::new(recorder)) {
- Ok(_) => (),
- Err(err) => warn!("Install prometheus recorder failed, cause: {}", err),
- };
-}
-
-pub fn try_handle() -> Option {
- let read_guard = PROMETHEUS_HANDLE.as_ref().read();
- read_guard.as_ref().map(ClearableRecorder::handle)
-}
-
-pub fn try_get_record() -> Option {
- let read_guard = PROMETHEUS_HANDLE.as_ref().read();
- read_guard.as_ref().cloned()
-}
-
-struct CounterFnWrap {
- pub counter: ManuallyDrop,
- pub holder: ManuallyDrop>,
-}
-
-impl Drop for CounterFnWrap {
- fn drop(&mut self) {
- unsafe {
- ManuallyDrop::drop(&mut self.counter);
- ManuallyDrop::drop(&mut self.holder);
- }
- }
-}
-
-impl CounterFn for CounterFnWrap {
- fn increment(&self, value: u64) {
- self.counter.increment(value)
- }
-
- fn absolute(&self, value: u64) {
- self.counter.absolute(value)
- }
-}
-
-struct GaugeFnWrap {
- pub gauge: ManuallyDrop,
- pub holder: ManuallyDrop>,
-}
-
-impl Drop for GaugeFnWrap {
- fn drop(&mut self) {
- unsafe {
- ManuallyDrop::drop(&mut self.gauge);
- ManuallyDrop::drop(&mut self.holder);
- }
- }
-}
-
-impl GaugeFn for GaugeFnWrap {
- fn increment(&self, value: f64) {
- self.gauge.increment(value)
- }
-
- fn decrement(&self, value: f64) {
- self.gauge.decrement(value)
- }
-
- fn set(&self, value: f64) {
- self.gauge.set(value)
- }
-}
-
-struct HistogramFnWrap {
- pub histogram: std::mem::ManuallyDrop,
- pub holder: ManuallyDrop>,
-}
-
-impl Drop for HistogramFnWrap {
- fn drop(&mut self) {
- unsafe {
- ManuallyDrop::drop(&mut self.histogram);
- ManuallyDrop::drop(&mut self.holder);
- }
- }
-}
-
-impl HistogramFn for HistogramFnWrap {
- fn record(&self, value: f64) {
- self.histogram.record(value)
- }
-}
-
-// It will be ensured that the recorder will be destroyed after all counters, gauge, histogram are destroyed
-struct ArcRecorder {
- pub inner: Arc,
-}
-
-impl Recorder for ArcRecorder {
- #[inline]
- fn describe_counter(&self, key: KeyName, unit: Option, description: SharedString) {
- self.inner.describe_counter(key, unit, description)
- }
-
- #[inline]
- fn describe_gauge(&self, key: KeyName, unit: Option, description: SharedString) {
- self.inner.describe_gauge(key, unit, description)
- }
-
- #[inline]
- fn describe_histogram(&self, key: KeyName, unit: Option, description: SharedString) {
- self.inner.describe_histogram(key, unit, description)
- }
-
- fn register_counter(&self, key: &Key) -> Counter {
- Counter::from_arc(Arc::new(CounterFnWrap {
- counter: ManuallyDrop::new(self.inner.register_counter(key)),
- holder: ManuallyDrop::new(self.inner.clone()),
- }))
- }
-
- fn register_gauge(&self, key: &Key) -> Gauge {
- Gauge::from_arc(Arc::new(GaugeFnWrap {
- gauge: ManuallyDrop::new(self.inner.register_gauge(key)),
- holder: ManuallyDrop::new(self.inner.clone()),
- }))
- }
-
- fn register_histogram(&self, key: &Key) -> Histogram {
- Histogram::from_arc(Arc::new(HistogramFnWrap {
- histogram: ManuallyDrop::new(self.inner.register_histogram(key)),
- holder: ManuallyDrop::new(self.inner.clone()),
- }))
- }
-}
-
-// TODO: use atomic refactor rwlock
-#[derive(Clone)]
-pub struct ClearableRecorder {
- inner: Arc>>,
-}
-
-impl ClearableRecorder {
- pub fn create() -> ClearableRecorder {
- let recorder = PrometheusBuilder::new().build_recorder();
- ClearableRecorder {
- inner: Arc::new(RwLock::new(ArcRecorder {
- inner: Arc::new(recorder),
- })),
- }
- }
-
- pub fn clear(&self) {
- let mut inner = self.inner.write();
- let recorder = PrometheusBuilder::new().build_recorder();
- *inner = ArcRecorder {
- inner: Arc::new(recorder),
- };
- }
-
- pub fn handle(&self) -> PrometheusHandle {
- self.inner.read().inner.handle()
- }
-}
-
-impl Recorder for ClearableRecorder {
- fn describe_counter(&self, key: KeyName, unit: Option, description: SharedString) {
- self.inner.read().describe_counter(key, unit, description)
- }
-
- fn describe_gauge(&self, key: KeyName, unit: Option, description: SharedString) {
- self.inner.read().describe_gauge(key, unit, description)
- }
-
- fn describe_histogram(&self, key: KeyName, unit: Option, description: SharedString) {
- self.inner.read().describe_histogram(key, unit, description)
- }
-
- fn register_counter(&self, key: &Key) -> Counter {
- self.inner.read().register_counter(key)
- }
-
- fn register_gauge(&self, key: &Key) -> Gauge {
- self.inner.read().register_gauge(key)
- }
-
- fn register_histogram(&self, key: &Key) -> Histogram {
- self.inner.read().register_histogram(key)
- }
-}
diff --git a/src/common/metrics/src/registry.rs b/src/common/metrics/src/registry.rs
index 160e52e4d205..a7de87108e80 100644
--- a/src/common/metrics/src/registry.rs
+++ b/src/common/metrics/src/registry.rs
@@ -16,6 +16,7 @@ use std::sync::Mutex;
use std::sync::MutexGuard;
use lazy_static::lazy_static;
+use prometheus_client::encoding::text::encode as prometheus_encode;
use prometheus_client::encoding::EncodeLabelSet;
use prometheus_client::metrics::counter::Counter;
use prometheus_client::metrics::family::Family;
@@ -27,13 +28,28 @@ use crate::histogram::BUCKET_MILLISECONDS;
use crate::histogram::BUCKET_SECONDS;
lazy_static! {
- pub static ref REGISTRY: Mutex = Mutex::new(Registry::default());
+ pub static ref REGISTRY: Mutex = Mutex::new(Registry::with_prefix("databend"));
}
pub fn load_global_prometheus_registry() -> MutexGuard<'static, Registry> {
REGISTRY.lock().unwrap()
}
+pub fn reset_global_prometheus_registry() {
+ // TODO(liyz): do nothing yet. This function would be trivial once prometheus_client
+ // supports iterating metrics. However it's not supported yet. I've raised an issue about
+ // this: https://github.com/prometheus/client_rust/issues/163 . If this feature request
+ // got denied, we can still wrap a customized Registry which record the metrics by itself.
+}
+
+pub fn render_prometheus_metrics(registry: &Registry) -> String {
+ let mut text = String::new();
+ match prometheus_encode(&mut text, registry) {
+ Ok(_) => text,
+ Err(err) => format!("Failed to encode metrics: {}", err),
+ }
+}
+
pub fn register_counter(name: &str) -> Counter {
let counter = Counter::default();
let mut registry = load_global_prometheus_registry();
diff --git a/src/common/metrics/tests/it/main.rs b/src/common/metrics/tests/it/main.rs
index 24383d744620..60dab279f8e2 100644
--- a/src/common/metrics/tests/it/main.rs
+++ b/src/common/metrics/tests/it/main.rs
@@ -14,40 +14,38 @@
use std::collections::HashMap;
+use common_exception::ErrorCode;
use common_metrics::dump_metric_samples;
-use common_metrics::init_default_metrics_recorder;
-use common_metrics::try_handle;
+use common_metrics::load_global_prometheus_registry;
+use common_metrics::register_counter;
+use common_metrics::register_histogram_in_milliseconds;
use common_metrics::MetricValue;
#[tokio::test(flavor = "multi_thread")]
async fn test_dump_metric_samples() -> common_exception::Result<()> {
- init_default_metrics_recorder();
- metrics::counter!("test.test1_count", 1);
- metrics::counter!("test.test2_count", 2);
+ let counter1 = register_counter("test_test1_count");
+ let counter2 = register_counter("test_test2_count");
+ let histogram1 = register_histogram_in_milliseconds("test_test_query_usedtime");
+ counter1.inc();
+ counter2.inc_by(2);
+ histogram1.observe(2.0);
- #[cfg(feature = "enable_histogram")]
- metrics::histogram!("test.test_query_usedtime", 2.0);
-
- let handle = crate::try_handle().unwrap();
- let samples = dump_metric_samples(handle)
+ let registry = load_global_prometheus_registry();
+ let samples = dump_metric_samples(®istry)
.unwrap()
.into_iter()
.map(|s| (s.name.clone(), s))
.collect::>();
assert_eq!(
- MetricValue::Counter(1.0),
- samples.get("test_test1_count").unwrap().value
+ MetricValue::Untyped(1.0),
+ samples.get("test_test1_count_total").unwrap().value
);
- #[cfg(feature = "enable_histogram")]
- {
- use common_exception::ErrorCode;
- let summaries = match &samples.get("test_test_query_usedtime").unwrap().value {
- MetricValue::Summary(summaries) => summaries,
- _ => return Err(ErrorCode::Internal("test failed")),
- };
- assert_eq!(7, summaries.len());
- }
+ let histogram = match &samples.get("test_test_query_usedtime").unwrap().value {
+ MetricValue::Histogram(histogram) => histogram,
+ _ => return Err(ErrorCode::Internal("test failed")),
+ };
+ assert_eq!(16, histogram.len());
Ok(())
}
diff --git a/src/common/openai/Cargo.toml b/src/common/openai/Cargo.toml
index c9f3526b7c0c..72f2b7508246 100644
--- a/src/common/openai/Cargo.toml
+++ b/src/common/openai/Cargo.toml
@@ -15,10 +15,12 @@ test = false
[dependencies]
# Workspace dependencies
common-exception = { path = "../exception" }
+common-metrics = { path = "../metrics" }
# GitHub dependencies
# Crates.io dependencies
+lazy_static = { workspace = true }
log = { workspace = true }
metrics = "0.20.1"
openai_api_rust = { git = "https://github.com/datafuse-extras/openai-api", rev = "819a0ed" }
diff --git a/src/common/openai/src/metrics.rs b/src/common/openai/src/metrics.rs
index 4391e0c81e04..e3fcc44d77ea 100644
--- a/src/common/openai/src/metrics.rs
+++ b/src/common/openai/src/metrics.rs
@@ -12,20 +12,34 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+use common_metrics::register_counter;
+use common_metrics::Counter;
+use lazy_static::lazy_static;
use metrics::counter;
+lazy_static! {
+ static ref OPENAI_COMPLETION_COUNT: Counter = register_counter("openai_completion_count");
+ static ref OPENAI_COMPLETION_TOKEN: Counter = register_counter("openai_completion_token");
+ static ref OPENAI_EMBEDDING_COUNT: Counter = register_counter("openai_embedding_count");
+ static ref OPENAI_EMBEDDING_TOKEN: Counter = register_counter("openai_embedding_token");
+}
+
pub fn metrics_completion_count(c: u32) {
counter!("openai_completion_count", c.into());
+ OPENAI_COMPLETION_COUNT.inc_by(c as u64);
}
pub fn metrics_completion_token(c: u32) {
counter!("openai_completion_token", c.into());
+ OPENAI_COMPLETION_TOKEN.inc_by(c as u64);
}
pub fn metrics_embedding_count(c: u32) {
counter!("openai_embedding_count", c.into());
+ OPENAI_EMBEDDING_COUNT.inc_by(c as u64);
}
pub fn metrics_embedding_token(c: u32) {
counter!("openai_embedding_token", c.into());
+ OPENAI_EMBEDDING_TOKEN.inc_by(c as u64);
}
diff --git a/src/common/metrics/src/reset.rs b/src/common/storage/src/metrics/common.rs
similarity index 56%
rename from src/common/metrics/src/reset.rs
rename to src/common/storage/src/metrics/common.rs
index a81804819852..2596ceaf82b7 100644
--- a/src/common/metrics/src/reset.rs
+++ b/src/common/storage/src/metrics/common.rs
@@ -12,15 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-use common_exception::Result;
+use common_metrics::register_counter;
+use common_metrics::Counter;
+use lazy_static::lazy_static;
-use crate::recorder::try_get_record;
+lazy_static! {
+ static ref OMIT_FILTER_ROWGROUPS: Counter = register_counter("omit_filter_rowgroups");
+ static ref OMIT_FILTER_ROWS: Counter = register_counter("omit_filter_rows");
+}
-/// Reset gauge metrics to 0.
-pub fn reset_metrics() -> Result<()> {
- if let Some(recorder) = try_get_record() {
- recorder.clear();
- }
+pub fn metrics_inc_omit_filter_rowgroups(c: u64) {
+ OMIT_FILTER_ROWGROUPS.inc_by(c);
+}
- Ok(())
+pub fn metrics_inc_omit_filter_rows(c: u64) {
+ OMIT_FILTER_ROWS.inc_by(c);
}
diff --git a/src/common/storage/src/metrics/copy.rs b/src/common/storage/src/metrics/copy.rs
index e9d3dee16a52..8fc777afd766 100644
--- a/src/common/storage/src/metrics/copy.rs
+++ b/src/common/storage/src/metrics/copy.rs
@@ -17,76 +17,52 @@ use common_metrics::register_histogram_in_milliseconds;
use common_metrics::Counter;
use common_metrics::Histogram;
use lazy_static::lazy_static;
-use metrics::increment_gauge;
-
-macro_rules! key {
- ($key: literal) => {
- concat!("query_", $key)
- };
-}
lazy_static! {
- static ref COPY_PURGE_FILE_COUNTER: Counter = register_counter("copy_purge_file_counter");
+ static ref COPY_PURGE_FILE_COUNTER: Counter = register_counter("query_copy_purge_file_counter");
static ref COPY_PURGE_FILE_COST_MILLISECONDS: Histogram =
- register_histogram_in_milliseconds("copy_purge_file_cost_milliseconds");
- static ref COPY_READ_PART_COUNTER: Counter = register_counter("copy_read_part_counter");
- static ref COPY_READ_SIZE_BYTES: Counter = register_counter("copy_read_size_bytes");
+ register_histogram_in_milliseconds("query_copy_purge_file_cost_milliseconds");
+ static ref COPY_READ_PART_COUNTER: Counter = register_counter("query_copy_read_part_counter");
+ static ref COPY_READ_SIZE_BYTES: Counter = register_counter("query_copy_read_size_bytes");
static ref COPY_READ_PART_COST_MILLISECONDS: Histogram =
- register_histogram_in_milliseconds("copy_read_part_cost_milliseconds");
+ register_histogram_in_milliseconds("query_copy_read_part_cost_milliseconds");
static ref FILTER_OUT_COPIED_FILES_REQUEST_MILLISECONDS: Histogram =
- register_histogram_in_milliseconds("filter_out_copied_files_request_milliseconds");
+ register_histogram_in_milliseconds("query_filter_out_copied_files_request_milliseconds");
static ref FILTER_OUT_COPIED_FILES_ENTIRE_MILLISECONDS: Histogram =
- register_histogram_in_milliseconds("filter_out_copied_files_entire_milliseconds");
+ register_histogram_in_milliseconds("query_filter_out_copied_files_entire_milliseconds");
static ref COLLECT_FILES_GET_ALL_SOURCE_FILES_MILLISECONDS: Histogram =
- register_histogram_in_milliseconds("collect_files_get_all_source_files_milliseconds");
+ register_histogram_in_milliseconds("query_collect_files_get_all_source_files_milliseconds");
}
/// COPY
pub fn metrics_inc_copy_purge_files_counter(c: u32) {
- increment_gauge!(key!("copy_purge_file_counter"), c as f64);
COPY_PURGE_FILE_COUNTER.inc_by(c as u64);
}
pub fn metrics_inc_copy_purge_files_cost_milliseconds(c: u32) {
- increment_gauge!(key!("copy_purge_file_cost_milliseconds"), c as f64);
COPY_PURGE_FILE_COST_MILLISECONDS.observe(c as f64);
}
pub fn metrics_inc_copy_read_part_counter() {
- increment_gauge!(key!("copy_read_part_counter"), 1.0);
COPY_READ_PART_COUNTER.inc();
}
pub fn metrics_inc_copy_read_size_bytes(c: u64) {
- increment_gauge!(key!("copy_read_size_bytes"), c as f64);
COPY_READ_SIZE_BYTES.inc_by(c);
}
pub fn metrics_inc_copy_read_part_cost_milliseconds(c: u64) {
- increment_gauge!(key!("copy_read_part_cost_milliseconds"), c as f64);
COPY_READ_PART_COST_MILLISECONDS.observe(c as f64);
}
pub fn metrics_inc_filter_out_copied_files_request_milliseconds(c: u64) {
- increment_gauge!(
- key!("filter_out_copied_files_request_milliseconds"),
- c as f64
- );
FILTER_OUT_COPIED_FILES_REQUEST_MILLISECONDS.observe(c as f64);
}
pub fn metrics_inc_filter_out_copied_files_entire_milliseconds(c: u64) {
- increment_gauge!(
- key!("filter_out_copied_files_entire_milliseconds"),
- c as f64
- );
FILTER_OUT_COPIED_FILES_ENTIRE_MILLISECONDS.observe(c as f64);
}
pub fn metrics_inc_collect_files_get_all_source_files_milliseconds(c: u64) {
- increment_gauge!(
- key!("collect_files_get_all_source_files_milliseconds"),
- c as f64
- );
COLLECT_FILES_GET_ALL_SOURCE_FILES_MILLISECONDS.observe(c as f64);
}
diff --git a/src/common/storage/src/metrics/merge_into.rs b/src/common/storage/src/metrics/merge_into.rs
index 9a236bea2b87..a295afbed8ec 100644
--- a/src/common/storage/src/metrics/merge_into.rs
+++ b/src/common/storage/src/metrics/merge_into.rs
@@ -15,7 +15,6 @@
use common_metrics::register_counter;
use common_metrics::Counter;
use lazy_static::lazy_static;
-use metrics::increment_gauge;
macro_rules! key {
($key: literal) => {
@@ -34,21 +33,17 @@ lazy_static! {
}
pub fn metrics_inc_merge_into_replace_blocks_counter(c: u32) {
- increment_gauge!(key!("merge_into_replace_blocks_counter"), c as f64);
MERGE_INTO_REPLACE_BLOCKS_COUNTER.inc_by(c as u64);
}
pub fn metrics_inc_merge_into_append_blocks_counter(c: u32) {
- increment_gauge!(key!("merge_into_append_blocks_counter"), c as f64);
MERGE_INTO_APPEND_BLOCKS_COUNTER.inc_by(c as u64);
}
pub fn metrics_inc_merge_into_matched_rows(c: u32) {
- increment_gauge!(key!("merge_into_matched_rows"), c as f64);
MERGE_INTO_MATCHED_ROWS.inc_by(c as u64);
}
pub fn metrics_inc_merge_into_unmatched_rows(c: u32) {
- increment_gauge!(key!("merge_into_unmatched_rows"), c as f64);
MERGE_INTO_UNMATCHED_ROWS.inc_by(c as u64);
}
diff --git a/src/common/storage/src/metrics/mod.rs b/src/common/storage/src/metrics/mod.rs
index 890e46a7413d..7d5d075ca8d4 100644
--- a/src/common/storage/src/metrics/mod.rs
+++ b/src/common/storage/src/metrics/mod.rs
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+pub mod common;
pub mod copy;
pub mod merge_into;
mod storage_metrics;
diff --git a/src/common/storage/src/operator.rs b/src/common/storage/src/operator.rs
index 044e93faacfe..b2320fe823e5 100644
--- a/src/common/storage/src/operator.rs
+++ b/src/common/storage/src/operator.rs
@@ -41,7 +41,6 @@ use common_meta_app::storage::StorageWebhdfsConfig;
use log::warn;
use opendal::layers::ImmutableIndexLayer;
use opendal::layers::LoggingLayer;
-use opendal::layers::MetricsLayer;
use opendal::layers::MinitraceLayer;
use opendal::layers::RetryLayer;
use opendal::layers::TimeoutLayer;
@@ -106,12 +105,11 @@ pub fn build_operator(builder: B) -> Result {
)
// Add retry
.layer(RetryLayer::new().with_jitter())
- // Add metrics
- .layer(MetricsLayer)
// Add logging
.layer(LoggingLayer::default())
// Add tracing
.layer(MinitraceLayer)
+ // TODO(liyz): add PrometheusClientLayer
.finish();
Ok(op)
diff --git a/src/common/storage/src/stage.rs b/src/common/storage/src/stage.rs
index fb809a3eaa8d..fdf714284494 100644
--- a/src/common/storage/src/stage.rs
+++ b/src/common/storage/src/stage.rs
@@ -92,7 +92,7 @@ pub struct StageFilesInfo {
impl StageFilesInfo {
fn get_pattern(&self) -> Result