Skip to content

Commit 600f503

Browse files
authored
fix: only support one spanset temporarily (#106)
* fix: only support one spanset temporarily * chore: fix ut
1 parent 8a0786b commit 600f503

File tree

10 files changed

+125
-152
lines changed

10 files changed

+125
-152
lines changed

.github/workflows/prcheck.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ jobs:
3535
run: cargo binstall -y cargo-sort
3636
- name: run checkers
3737
run: |
38-
cargo sort -c
38+
cargo sort -c -w
3939
cargo fmt -- --check
4040
cargo clippy -- -D warnings
4141
cargo test

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ ordered-float = { version = "4.2.2" }
2323
humantime = { version = "2.1.0" }
2424
chrono = { version = "0.4.38", features = ["serde"] }
2525
pretty_assertions = "1.4.0"
26+
opentelemetry-proto = { version = "0.7.0", features = ["full"] }
2627

2728
[dependencies]
2829
anyhow = "1.0.86"
@@ -45,7 +46,7 @@ logql = { path = "logql" }
4546
moka = { version = "0.12.8", features = ["default", "sync"] }
4647
opentelemetry = { version = "0.24.0", features = ["metrics"] }
4748
opentelemetry-prometheus = "0.17.0"
48-
opentelemetry-proto = { version = "0.7.0", features = ["full"] }
49+
opentelemetry-proto = { workspace = true }
4950
opentelemetry-semantic-conventions = { version = "0.16.0" }
5051
opentelemetry_sdk = { version = "0.24.1", features = ["metrics"] }
5152
ordered-float = { version = "4.2.2" }

common/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ rust-version = "1.76.0"
66
authors = ["caibirdme <[email protected]>"]
77

88
[dependencies]
9-
chrono = {workspace=true}
10-
anyhow = { version = "1.0.86"}
9+
anyhow = { version = "1.0.86" }
10+
chrono = { workspace = true }

logql/Cargo.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,9 @@ rust-version = "1.76.0"
66
authors = ["caibirdme <[email protected]>"]
77

88
[dependencies]
9-
nom = { workspace = true }
109
humantime-serde = { workspace = true }
1110
itertools = { workspace = true }
12-
11+
nom = { workspace = true }
1312

1413
[dev-dependencies]
15-
pretty_assertions = { workspace = true }
14+
pretty_assertions = { workspace = true }

sqlbuilder/Cargo.toml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ authors = ["caibirdme <[email protected]>"]
77

88
[dependencies]
99
chrono ={ workspace = true }
10-
ordered-float = {workspace = true}
11-
common = {path = "../common"}
12-
logql = {path = "../logql"}
13-
traceql = {path = "../traceql"}
10+
common = { path = "../common" }
1411
itertools = { workspace = true }
12+
logql = { path = "../logql" }
13+
opentelemetry-proto = { workspace = true }
14+
ordered-float = { workspace = true }
15+
traceql = { path = "../traceql" }

sqlbuilder/src/trace.rs

Lines changed: 52 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ use super::builder::{
33
TableSchema,
44
};
55
use itertools::Itertools as _;
6+
use opentelemetry_proto::tonic::trace::v1::status::StatusCode as PBStatusCode;
67
use traceql::{
78
ComparisonOperator, Expression, FieldExpr, FieldType, FieldValue,
8-
IntrisincField, LogicalOperator, SpanSet,
9+
IntrisincField, LogicalOperator, SpanSet, StatusCode,
910
};
1011

12+
#[allow(dead_code)]
1113
enum SubQuery<T: TableSchema, C: QueryConverter> {
1214
Basic(QueryPlan<T, C>),
1315
And(Box<SubQuery<T, C>>, Box<SubQuery<T, C>>),
@@ -31,7 +33,7 @@ where
3133
{
3234
match expr {
3335
Expression::SpanSet(spanset) => {
34-
let selection = spanset_to_qp(spanset);
36+
let selection = spanset_to_selection(spanset);
3537
let mut qp = QueryPlan::new(
3638
converter.clone(),
3739
schema.clone(),
@@ -49,26 +51,19 @@ where
4951
qp.projection = vec![schema.trace_key().to_string()];
5052
SubQuery::Basic(qp)
5153
}
52-
Expression::Logical(left, op, right) => {
53-
let l =
54-
Self::new(converter.clone(), left, schema.clone(), spans);
55-
let r =
56-
Self::new(converter.clone(), right, schema.clone(), spans);
57-
match op {
58-
LogicalOperator::And => {
59-
SubQuery::And(Box::new(l), Box::new(r))
60-
}
61-
LogicalOperator::Or => {
62-
SubQuery::Or(Box::new(l), Box::new(r))
63-
}
64-
}
54+
Expression::Logical(_, _, _) => {
55+
unimplemented!("logical expression")
6556
}
6657
}
6758
}
6859
fn as_sql(&self) -> String {
6960
match self {
7061
SubQuery::Basic(qp) => {
71-
format!("sub.{} IN ({})", qp.schema.trace_key(), qp.as_sql())
62+
format!(
63+
"sub.{} GLOBAL IN ({})",
64+
qp.schema.trace_key(),
65+
qp.as_sql()
66+
)
7267
}
7368
SubQuery::And(l, r) => {
7469
let l_sql = l.as_sql();
@@ -84,7 +79,7 @@ where
8479
}
8580
}
8681

87-
fn spanset_to_qp(spanset: &SpanSet) -> Selection {
82+
fn spanset_to_selection(spanset: &SpanSet) -> Selection {
8883
match spanset {
8984
SpanSet::Expr(expr) => {
9085
// expand unscoped into (resource or span)
@@ -98,16 +93,16 @@ fn spanset_to_qp(spanset: &SpanSet) -> Selection {
9893
operator: expr.operator,
9994
});
10095
return Selection::LogicalOr(
101-
Box::new(spanset_to_qp(&left)),
102-
Box::new(spanset_to_qp(&right)),
96+
Box::new(spanset_to_selection(&left)),
97+
Box::new(spanset_to_selection(&right)),
10398
);
10499
}
105100
let c = field_expr_to_condition(expr);
106101
Selection::Unit(c)
107102
}
108103
SpanSet::Logical(left, op, right) => {
109-
let l = spanset_to_qp(left);
110-
let r = spanset_to_qp(right);
104+
let l = spanset_to_selection(left);
105+
let r = spanset_to_selection(right);
111106
match op {
112107
LogicalOperator::And => {
113108
Selection::LogicalAnd(Box::new(l), Box::new(r))
@@ -167,12 +162,22 @@ fn construct_condition(
167162
}
168163
}
169164

165+
fn convert_status_code(s: StatusCode) -> PBStatusCode {
166+
match s {
167+
StatusCode::Err => PBStatusCode::Error,
168+
StatusCode::Ok => PBStatusCode::Ok,
169+
StatusCode::Unset => PBStatusCode::Unset,
170+
}
171+
}
172+
170173
fn field_expr_to_condition(expr: &FieldExpr) -> Condition {
171174
match &expr.kv {
172175
FieldType::Intrinsic(intrisinc) => match intrisinc {
173176
IntrisincField::Status(status) => construct_condition(
174177
Column::Raw("StatusCode".to_string()),
175-
PlaceValue::Integer((*status).into()),
178+
PlaceValue::String(
179+
convert_status_code(*status).as_str_name().to_string(),
180+
),
176181
expr.operator,
177182
),
178183
IntrisincField::Duraion(d) => construct_condition(
@@ -253,7 +258,7 @@ where
253258
}
254259
pub fn as_sql(&self) -> String {
255260
let mut sql = format!(
256-
"SELECT * FROM {} sp WHERE sp.{} IN (SELECT {} FROM (",
261+
"SELECT * FROM {} sp WHERE sp.{} GLOBAL IN (SELECT {} FROM (",
257262
self.schema.table(),
258263
self.schema.span_id_key(),
259264
self.schema.span_id_key(),
@@ -270,3 +275,27 @@ where
270275
sql
271276
}
272277
}
278+
279+
pub fn single_spanset_query<T, C>(
280+
spanset: &SpanSet,
281+
schema: T,
282+
projection: Vec<String>,
283+
converter: C,
284+
) -> String
285+
where
286+
T: TableSchema,
287+
C: QueryConverter,
288+
{
289+
let selection = spanset_to_selection(spanset);
290+
QueryPlan::new(
291+
converter,
292+
schema,
293+
projection,
294+
Some(selection),
295+
vec![],
296+
vec![],
297+
vec![],
298+
Some(500),
299+
)
300+
.as_sql()
301+
}

src/storage/ck/trace.rs

Lines changed: 51 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ use opentelemetry_proto::tonic::trace::v1::{
1111
};
1212
use reqwest::Client;
1313
use serde_json::Value as JSONValue;
14-
use sqlbuilder::{builder::TableSchema, trace::ComplexQuery};
14+
use sqlbuilder::{builder::TableSchema, trace::single_spanset_query};
1515
use std::collections::HashMap;
1616
use traceql::*;
17-
use tracing::error;
17+
use tracing::{error, warn};
1818

1919
#[derive(Clone)]
2020
pub struct CKTraceQuerier {
@@ -67,25 +67,40 @@ impl TraceStorage for CKTraceQuerier {
6767
expr: &Expression,
6868
_opt: QueryLimits,
6969
) -> Result<Vec<SpanItem>> {
70-
let converter = CKLogConverter::new(self.schema.clone(), true);
71-
let sql =
72-
ComplexQuery::new(expr, self.schema.clone(), converter).as_sql();
73-
let mut results = vec![];
74-
let rows =
75-
send_query(self.client.clone(), self.ck_cfg.common.clone(), sql)
70+
match expr {
71+
Expression::Logical(_, _, _) => {
72+
warn!("Search span does not support logical expression");
73+
return Ok(vec![]);
74+
}
75+
Expression::SpanSet(sp) => {
76+
let converter = CKLogConverter::new(self.schema.clone(), true);
77+
let sql = single_spanset_query(
78+
sp,
79+
self.schema.clone(),
80+
self.schema.projection(),
81+
converter,
82+
);
83+
let mut results = vec![];
84+
let rows = send_query(
85+
self.client.clone(),
86+
self.ck_cfg.common.clone(),
87+
sql,
88+
)
7689
.await
7790
.map_err(|e| {
7891
error!("Query trace error: {:?}", e);
7992
e
8093
})?;
81-
for row in rows {
82-
let record = TraceRecord::try_from(row).map_err(|e| {
83-
error!("Convert trace record error: {:?}", e);
84-
e
85-
})?;
86-
results.push(record.into());
94+
for row in rows {
95+
let record = TraceRecord::try_from(row).map_err(|e| {
96+
error!("Convert trace record error: {:?}", e);
97+
e
98+
})?;
99+
results.push(record.into());
100+
}
101+
Ok(results)
102+
}
87103
}
88-
Ok(results)
89104
}
90105
}
91106

@@ -372,7 +387,7 @@ impl TableSchema for TraceTable {
372387
mod tests {
373388
use super::*;
374389
use pretty_assertions::assert_eq;
375-
use sqlparser::{dialect::AnsiDialect, parser::Parser};
390+
use sqlparser::{dialect::ClickHouseDialect, parser::Parser};
376391
use std::{fs, path::PathBuf};
377392
use traceql::parse_traceql;
378393

@@ -396,21 +411,26 @@ mod tests {
396411
);
397412
for (name, tc) in cases {
398413
let expr = parse_traceql(&tc.input).unwrap();
399-
let sql = ComplexQuery::new(
400-
&expr,
401-
schema.clone(),
402-
CKLogConverter::new(schema.clone(), true),
403-
)
404-
.as_sql();
405-
let actual_ast = Parser::parse_sql(&AnsiDialect {}, &sql).unwrap();
406-
let expect_ast =
407-
Parser::parse_sql(&AnsiDialect {}, &tc.expect).unwrap();
408-
assert_eq!(
409-
expect_ast[0].to_string(),
410-
actual_ast[0].to_string(),
411-
"case: {}",
412-
name
413-
);
414+
if let Expression::SpanSet(sp) = expr {
415+
let converter = CKLogConverter::new(schema.clone(), true);
416+
let sql = single_spanset_query(
417+
&sp,
418+
schema.clone(),
419+
schema.projection(),
420+
converter,
421+
);
422+
let actual_ast =
423+
Parser::parse_sql(&ClickHouseDialect {}, &sql).unwrap();
424+
let expect_ast =
425+
Parser::parse_sql(&ClickHouseDialect {}, &tc.expect)
426+
.unwrap();
427+
assert_eq!(
428+
expect_ast[0].to_string(),
429+
actual_ast[0].to_string(),
430+
"case: {}",
431+
name
432+
);
433+
}
414434
}
415435
}
416436
}

0 commit comments

Comments
 (0)