mirror of
https://github.com/hanzoai/otel-collector.git
synced 2026-11-03 02:20:04 +00:00
176 lines
6.1 KiB
Go
176 lines
6.1 KiB
Go
package clickhousetracesexporter
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/ClickHouse/clickhouse-go/v2"
|
|
"go.opentelemetry.io/collector/featuregate"
|
|
)
|
|
|
|
const (
|
|
DurationSortFeature = "DURATION_SORT_FEATURE"
|
|
TimestampSortFeature = "TIMESTAMP_SORT_FEATURE"
|
|
)
|
|
|
|
var durationSortFeatureGate *featuregate.Gate
|
|
var timestampSortFeatureGate *featuregate.Gate
|
|
|
|
func init() {
|
|
durationSortFeatureGate = featuregate.GlobalRegistry().MustRegister(
|
|
DurationSortFeature,
|
|
featuregate.StageBeta,
|
|
featuregate.WithRegisterDescription("It controls use of materialized view which optimizes span duration based sorting for trace list at cost of extra disk usage"),
|
|
)
|
|
timestampSortFeatureGate = featuregate.GlobalRegistry().MustRegister(
|
|
TimestampSortFeature,
|
|
featuregate.StageBeta,
|
|
featuregate.WithRegisterDescription("It controls use of materialized view which optimizes span timestamp based sorting for trace list at cost of extra disk usage"),
|
|
)
|
|
}
|
|
|
|
func initFeatures(db clickhouse.Conn, options *Options) error {
|
|
if durationSortFeatureGate.IsEnabled() {
|
|
err := enableDurationSortFeature(db, options)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
err := disableDurationSortFeature(db, options)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if timestampSortFeatureGate.IsEnabled() {
|
|
err := enableTimestampSortFeature(db, options)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
err := disableTimestampSortFeature(db, options)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func enableDurationSortFeature(db clickhouse.Conn, options *Options) error {
|
|
err := db.Exec(context.Background(), fmt.Sprintf(`CREATE TABLE IF NOT EXISTS %s.%s ON CLUSTER %s(
|
|
timestamp DateTime64(9) CODEC(DoubleDelta, LZ4),
|
|
traceID FixedString(32) CODEC(ZSTD(1)),
|
|
spanID String CODEC(ZSTD(1)),
|
|
parentSpanID String CODEC(ZSTD(1)),
|
|
serviceName LowCardinality(String) CODEC(ZSTD(1)),
|
|
name LowCardinality(String) CODEC(ZSTD(1)),
|
|
kind Int8 CODEC(T64, ZSTD(1)),
|
|
durationNano UInt64 CODEC(T64, ZSTD(1)),
|
|
statusCode Int16 CODEC(T64, ZSTD(1)),
|
|
component LowCardinality(String) CODEC(ZSTD(1)),
|
|
httpMethod LowCardinality(String) CODEC(ZSTD(1)),
|
|
httpUrl LowCardinality(String) CODEC(ZSTD(1)),
|
|
httpCode LowCardinality(String) CODEC(ZSTD(1)),
|
|
httpRoute LowCardinality(String) CODEC(ZSTD(1)),
|
|
httpHost LowCardinality(String) CODEC(ZSTD(1)),
|
|
gRPCCode LowCardinality(String) CODEC(ZSTD(1)),
|
|
gRPCMethod LowCardinality(String) CODEC(ZSTD(1)),
|
|
hasError bool CODEC(T64, ZSTD(1)),
|
|
tagMap Map(LowCardinality(String), String) CODEC(ZSTD(1)),
|
|
rpcSystem LowCardinality(String) CODEC(ZSTD(1)),
|
|
rpcService LowCardinality(String) CODEC(ZSTD(1)),
|
|
rpcMethod LowCardinality(String) CODEC(ZSTD(1)),
|
|
responseStatusCode LowCardinality(String) CODEC(ZSTD(1)),
|
|
stringTagMap Map(String, String) CODEC(ZSTD(1)),
|
|
numberTagMap Map(String, Float64) CODEC(ZSTD(1)),
|
|
boolTagMap Map(String, bool) CODEC(ZSTD(1)),
|
|
INDEX idx_service serviceName TYPE bloom_filter GRANULARITY 4,
|
|
INDEX idx_name name TYPE bloom_filter GRANULARITY 4,
|
|
INDEX idx_kind kind TYPE minmax GRANULARITY 4,
|
|
INDEX idx_duration durationNano TYPE minmax GRANULARITY 1,
|
|
INDEX idx_httpCode httpCode TYPE set(0) GRANULARITY 1,
|
|
INDEX idx_hasError hasError TYPE set(2) GRANULARITY 1,
|
|
INDEX idx_tagMapKeys mapKeys(tagMap) TYPE bloom_filter(0.01) GRANULARITY 64,
|
|
INDEX idx_tagMapValues mapValues(tagMap) TYPE bloom_filter(0.01) GRANULARITY 64,
|
|
INDEX idx_httpRoute httpRoute TYPE bloom_filter GRANULARITY 4,
|
|
INDEX idx_httpUrl httpUrl TYPE bloom_filter GRANULARITY 4,
|
|
INDEX idx_httpHost httpHost TYPE bloom_filter GRANULARITY 4,
|
|
INDEX idx_httpMethod httpMethod TYPE bloom_filter GRANULARITY 4,
|
|
INDEX idx_timestamp timestamp TYPE minmax GRANULARITY 1,
|
|
INDEX idx_rpcMethod rpcMethod TYPE bloom_filter GRANULARITY 4,
|
|
INDEX idx_responseStatusCode responseStatusCode TYPE set(0) GRANULARITY 1,
|
|
) ENGINE MergeTree()
|
|
PARTITION BY toDate(timestamp)
|
|
ORDER BY (durationNano, timestamp)
|
|
TTL toDateTime(timestamp) + INTERVAL 604800 SECOND DELETE
|
|
SETTINGS index_granularity = 8192, ttl_only_drop_parts = 1`, options.primary.TraceDatabase, options.primary.DurationSortTable, options.primary.Cluster))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = db.Exec(context.Background(), fmt.Sprintf(`CREATE MATERIALIZED VIEW IF NOT EXISTS %s.%s ON CLUSTER %s
|
|
TO %s.%s
|
|
AS SELECT
|
|
timestamp,
|
|
traceID,
|
|
spanID,
|
|
parentSpanID,
|
|
serviceName,
|
|
name,
|
|
kind,
|
|
durationNano,
|
|
statusCode,
|
|
component,
|
|
httpMethod,
|
|
httpUrl,
|
|
httpCode,
|
|
httpRoute,
|
|
httpHost,
|
|
gRPCMethod,
|
|
gRPCCode,
|
|
hasError,
|
|
tagMap,
|
|
rpcSystem,
|
|
rpcService,
|
|
rpcMethod,
|
|
responseStatusCode,
|
|
stringTagMap,
|
|
numberTagMap,
|
|
boolTagMap
|
|
FROM %s.%s
|
|
ORDER BY durationNano, timestamp`, options.primary.TraceDatabase, options.primary.DurationSortMVTable, options.primary.Cluster, options.primary.TraceDatabase, options.primary.DurationSortTable, options.primary.TraceDatabase, options.primary.IndexTable))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func disableDurationSortFeature(db clickhouse.Conn, options *Options) error {
|
|
err := db.Exec(context.Background(), fmt.Sprintf(`DROP TABLE IF EXISTS %s.%s ON CLUSTER %s`, options.primary.TraceDatabase, options.primary.DurationSortTable, options.primary.Cluster))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = db.Exec(context.Background(), fmt.Sprintf(`DROP VIEW IF EXISTS %s.%s ON CLUSTER %s`, options.primary.TraceDatabase, options.primary.DurationSortMVTable, options.primary.Cluster))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func enableTimestampSortFeature(db clickhouse.Conn, options *Options) error {
|
|
err := db.Exec(context.Background(), fmt.Sprintf(`ALTER TABLE %s.%s ON CLUSTER %s
|
|
ADD PROJECTION IF NOT EXISTS timestampSort
|
|
( SELECT * ORDER BY timestamp )`, options.primary.TraceDatabase, options.primary.LocalIndexTable, options.primary.Cluster))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func disableTimestampSortFeature(db clickhouse.Conn, options *Options) error {
|
|
err := db.Exec(context.Background(), fmt.Sprintf(`ALTER TABLE %s.%s ON CLUSTER %s
|
|
DROP PROJECTION IF EXISTS timestampSort`, options.primary.TraceDatabase, options.primary.LocalIndexTable, options.primary.Cluster))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|