-
Notifications
You must be signed in to change notification settings - Fork 2.7k
[clickhouse] Implement FindTraceIDs for ClickHouse Storage For Primitive Parameters #7648
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
1391e4f
a1454f8
a8f84ea
82900ce
403b85b
9a92d85
21a8841
6bf0612
c5c14d3
8475124
cedff6f
b55e348
76a9276
9381a59
13dd013
7019e2e
2499aa6
843370f
342e4c6
07fe36a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,13 @@ import ( | |
| "go.opentelemetry.io/collector/config/configoptional" | ||
| ) | ||
|
|
||
| const ( | ||
| defaultProtocol = "native" | ||
| defaultDatabase = "jaeger" | ||
| defaultSearchDepth = 100 | ||
| defaultMaxSearchDepth = 10000 | ||
| ) | ||
|
|
||
| type Configuration struct { | ||
| // Protocol is the protocol to use to connect to ClickHouse. | ||
| // Supported values are "native" and "http". Default is "native". | ||
|
|
@@ -25,6 +32,13 @@ type Configuration struct { | |
| DialTimeout time.Duration `mapstructure:"dial_timeout"` | ||
| // CreateSchema, if set to true, will create the ClickHouse schema if it does not exist. | ||
| CreateSchema bool `mapstructure:"create_schema"` | ||
| // DefaultSearchDepth is the default search depth for queries. | ||
| // This is the maximum number of trace IDs that will be returned when searching for traces | ||
| // if a limit is not specified in the query. | ||
| DefaultSearchDepth int `mapstructure:"default_search_depth"` | ||
| // MaxSearchDepth is the maximum allowed search depth for queries. | ||
| // This limits the number of trace IDs that can be returned when searching for traces. | ||
| MaxSearchDepth int `mapstructure:"max_search_depth"` | ||
| // TODO: add more settings | ||
| } | ||
|
|
||
|
|
@@ -37,3 +51,18 @@ func (cfg *Configuration) Validate() error { | |
| _, err := govalidator.ValidateStruct(cfg) | ||
| return err | ||
| } | ||
|
|
||
| func (cfg *Configuration) applyDefaults() { | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @yurishkuro For a lot of the ClickHouse configurations - the driver has its own defaults. Should we let the driver handle those or do we want to define our own?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we already expose them in config? when we do it makes sense to default to driver's defaults in most cases. |
||
| if cfg.Protocol == "" { | ||
| cfg.Protocol = "native" | ||
| } | ||
| if cfg.Database == "" { | ||
| cfg.Database = defaultDatabase | ||
| } | ||
| if cfg.DefaultSearchDepth == 0 { | ||
| cfg.DefaultSearchDepth = defaultSearchDepth | ||
| } | ||
| if cfg.MaxSearchDepth == 0 { | ||
| cfg.MaxSearchDepth = defaultMaxSearchDepth | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -5,10 +5,12 @@ package tracestore | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "context" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "encoding/hex" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "fmt" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "iter" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/ClickHouse/clickhouse-go/v2/lib/driver" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "go.opentelemetry.io/collector/pdata/pcommon" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "go.opentelemetry.io/collector/pdata/ptrace" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/jaegertracing/jaeger/internal/storage/v2/api/tracestore" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -18,17 +20,27 @@ import ( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var _ tracestore.Reader = (*Reader)(nil) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type ReaderConfig struct { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // DefaultSearchDepth is the default number of trace IDs to return when searching for traces. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // This value is used when the SearchDepth field in TraceQueryParams is not set. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| DefaultSearchDepth int | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // MaxSearchDepth is the maximum number of trace IDs that can be returned when searching for traces. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // This value is used to limit the SearchDepth field in TraceQueryParams. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MaxSearchDepth int | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type Reader struct { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| conn driver.Conn | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| conn driver.Conn | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| config ReaderConfig | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // NewReader returns a new Reader instance that uses the given ClickHouse connection | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // to read trace data. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // The provided connection is used exclusively for reading traces, meaning it is safe | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // to enable instrumentation on the connection without risk of recursively generating traces. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func NewReader(conn driver.Conn) *Reader { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return &Reader{conn: conn} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func NewReader(conn driver.Conn, cfg ReaderConfig) *Reader { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return &Reader{conn: conn, config: cfg} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func (r *Reader) GetTraces( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -129,9 +141,60 @@ func (*Reader) FindTraces( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| panic("not implemented") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func (*Reader) FindTraceIDs( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| context.Context, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tracestore.TraceQueryParams, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func (r *Reader) FindTraceIDs( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ctx context.Context, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| query tracestore.TraceQueryParams, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) iter.Seq2[[]tracestore.FoundTraceID, error] { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| panic("not implemented") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return func(yield func([]tracestore.FoundTraceID, error) bool) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| q := sql.SearchTraceIDs | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| args := []any{} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if query.ServiceName != "" { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| q += " AND service_name = ?" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| args = append(args, query.ServiceName) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if query.OperationName != "" { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| q += " AND name = ?" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| args = append(args, query.OperationName) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| q += " LIMIT ?" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if query.SearchDepth > 0 { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest we introduce a default value if not specified , as well as a max value which user input cannot exceed (expose both in the config)
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if query.SearchDepth > r.config.MaxSearchDepth { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| yield(nil, fmt.Errorf("search depth %d exceeds maximum allowed %d", query.SearchDepth, r.config.MaxSearchDepth)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| args = append(args, query.SearchDepth) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| args = append(args, r.config.DefaultSearchDepth) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| rows, err := r.conn.Query(ctx, q, args...) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| yield(nil, fmt.Errorf("failed to query trace IDs: %w", err)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| defer rows.Close() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for rows.Next() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var traceID string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err := rows.Scan(&traceID); err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !yield(nil, fmt.Errorf("failed to scan row: %w", err)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| b, err := hex.DecodeString(traceID) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !yield(nil, fmt.Errorf("failed to decode trace ID: %w", err)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !yield([]tracestore.FoundTraceID{{TraceID: pcommon.TraceID(b)}}, nil) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we should be returning timestamps with found trace IDs, this was one critical requirement why we added them to the GetTraces API because in CH finding trace by ID is not cheap without time range.
Comment on lines
+187
to
+195
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Type conversion error: Cannot convert Fix by copying the slice into a fixed-size array: b, err := hex.DecodeString(traceID)
if err != nil {
if !yield(nil, fmt.Errorf("failed to decode trace ID: %w", err)) {
return
}
continue
}
var traceIDArray [16]byte
if len(b) != 16 {
if !yield(nil, fmt.Errorf("invalid trace ID length: expected 16 bytes, got %d", len(b))) {
return
}
continue
}
copy(traceIDArray[:], b)
if !yield([]tracestore.FoundTraceID{{TraceID: pcommon.TraceID(traceIDArray)}}, nil) {
return
}
Suggested change
Spotted by Graphite Agent |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yurishkuro Thoughts on these values?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
defaultSearchDepth could be 1000