From 5041f3150646608857959f5b451094ca449a9253 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Mon, 28 Oct 2024 16:16:00 +0530 Subject: [PATCH 01/55] Embeded template file in binary and added query construction and execution for initialize database Signed-off-by: Alok Kumar Singh --- cmd/jaeger/config-cassandra.yaml | 12 ++ pkg/cassandra/config/config.go | 16 +- plugin/storage/cassandra/factory.go | 14 ++ plugin/storage/cassandra/schema/schema.go | 201 ++++++++++++++++++ .../storage/cassandra/schema/schema_test.go | 22 ++ .../schema/v004-go-tmpl-test.cql.tmpl | 84 ++++++++ .../cassandra/schema/v004-go-tmpl.cql.tmpl | 200 +++++++++++++++++ 7 files changed, 548 insertions(+), 1 deletion(-) create mode 100644 plugin/storage/cassandra/schema/schema.go create mode 100644 plugin/storage/cassandra/schema/schema_test.go create mode 100644 plugin/storage/cassandra/schema/v004-go-tmpl-test.cql.tmpl create mode 100644 plugin/storage/cassandra/schema/v004-go-tmpl.cql.tmpl diff --git a/cmd/jaeger/config-cassandra.yaml b/cmd/jaeger/config-cassandra.yaml index 3ead38258c2..d78d1f78f3f 100644 --- a/cmd/jaeger/config-cassandra.yaml +++ b/cmd/jaeger/config-cassandra.yaml @@ -34,6 +34,12 @@ extensions: cassandra: schema: keyspace: "jaeger_v1_dc1" + datacenter: "test" + trace_ttl: 172800 + dependencies_ttl: 172800 + replication_factor: 1 + cas_version: 4 + compaction_window: "1m" connection: auth: basic: @@ -45,6 +51,12 @@ extensions: cassandra: schema: keyspace: "jaeger_v1_dc1" + datacenter: "test" + trace_ttl: 172800 + dependencies_ttl: 172800 + replication_factor: 1 + cas_version: 4 + compaction_window: "1m" connection: auth: basic: diff --git a/pkg/cassandra/config/config.go b/pkg/cassandra/config/config.go index 6bab9c75da4..23fa3b0767a 100644 --- a/pkg/cassandra/config/config.go +++ b/pkg/cassandra/config/config.go @@ -51,6 +51,18 @@ type Connection struct { ProtoVersion int `mapstructure:"proto_version"` } +type SchemaConfig struct { + Datacenter string `mapstructure:"datacenter" valid:"optional"` + TraceTTL int `mapstructure:"trace_ttl" valid:"optional"` + DependenciesTTL int `mapstructure:"dependencies_ttl" valid:"optional"` + ReplicationFactor int `mapstructure:"replication_factor" valid:"optional"` + CasVersion int `mapstructure:"cas_version" valid:"optional"` + CompactionWindow string `mapstructure:"compaction_window" valid:"optional"` + Replication string `mapstructure:"replication" valid:"optional"` + CompactionWindowSize int `mapstructure:"compaction_window_size" valid:"optional"` + CompactionWindowUnit string `mapstructure:"compaction_window_unit" valid:"optional"` +} + type Schema struct { // Keyspace contains the namespace where Jaeger data will be stored. Keyspace string `mapstructure:"keyspace"` @@ -58,6 +70,7 @@ type Schema struct { // while connecting to the Cassandra Cluster. This is useful for connecting to clusters, like Azure Cosmos DB, // that do not support SnappyCompression. DisableCompression bool `mapstructure:"disable_compression"` + SchemaConfig } type Query struct { @@ -150,7 +163,8 @@ func (c *Configuration) NewSession() (cassandra.Session, error) { // NewCluster creates a new gocql cluster from the configuration func (c *Configuration) NewCluster() (*gocql.ClusterConfig, error) { cluster := gocql.NewCluster(c.Connection.Servers...) - cluster.Keyspace = c.Schema.Keyspace + // Removing this, since keyspace would be created post builing connection + // cluster.Keyspace = c.Schema.Keyspace cluster.NumConns = c.Connection.ConnectionsPerHost cluster.ConnectTimeout = c.Connection.Timeout cluster.ReconnectInterval = c.Connection.ReconnectInterval diff --git a/plugin/storage/cassandra/factory.go b/plugin/storage/cassandra/factory.go index 4654a2a2c82..fca10dcc2bc 100644 --- a/plugin/storage/cassandra/factory.go +++ b/plugin/storage/cassandra/factory.go @@ -24,6 +24,7 @@ import ( cLock "github.com/jaegertracing/jaeger/plugin/pkg/distributedlock/cassandra" cDepStore "github.com/jaegertracing/jaeger/plugin/storage/cassandra/dependencystore" cSamplingStore "github.com/jaegertracing/jaeger/plugin/storage/cassandra/samplingstore" + "github.com/jaegertracing/jaeger/plugin/storage/cassandra/schema" cSpanStore "github.com/jaegertracing/jaeger/plugin/storage/cassandra/spanstore" "github.com/jaegertracing/jaeger/plugin/storage/cassandra/spanstore/dbmodel" "github.com/jaegertracing/jaeger/storage" @@ -131,6 +132,10 @@ func (f *Factory) configureFromOptions(o *Options) { } } +func (f *Factory) initializeDB(session cassandra.Session, cfg *config.Schema) error { + return schema.GenerateSchemaIfNotPresent(session, cfg) +} + // Initialize implements storage.Factory func (f *Factory) Initialize(metricsFactory metrics.Factory, logger *zap.Logger) error { f.primaryMetricsFactory = metricsFactory.Namespace(metrics.NSOptions{Name: "cassandra", Tags: nil}) @@ -143,12 +148,21 @@ func (f *Factory) Initialize(metricsFactory metrics.Factory, logger *zap.Logger) } f.primarySession = primarySession + // After creating a session, execute commands to initialize the setup if not already present + if err := f.initializeDB(primarySession, &f.Options.Primary.Schema); err != nil { + return err + } + if f.archiveConfig != nil { archiveSession, err := f.archiveConfig.NewSession() if err != nil { return err } f.archiveSession = archiveSession + + if err := f.initializeDB(archiveSession, &f.Options.Primary.Schema); err != nil { + return err + } } else { logger.Info("Cassandra archive storage configuration is empty, skipping") } diff --git a/plugin/storage/cassandra/schema/schema.go b/plugin/storage/cassandra/schema/schema.go new file mode 100644 index 00000000000..27c88c38984 --- /dev/null +++ b/plugin/storage/cassandra/schema/schema.go @@ -0,0 +1,201 @@ +// Copyright (c) 2024 The Jaeger Authors. +// SPDX-License-Identifier: Apache-2.0 + +package schema + +import ( + "bytes" + "embed" + "fmt" + "regexp" + "strconv" + "text/template" + + "github.com/jaegertracing/jaeger/pkg/cassandra" + "github.com/jaegertracing/jaeger/pkg/cassandra/config" +) + +//go:embed v004-go-tmpl.cql.tmpl +//go:embed v004-go-tmpl-test.cql.tmpl +var schemaFile embed.FS + +func DefaultSchemaConfig() config.Schema { + return config.Schema{ + Keyspace: "jaeger_v2_test", + SchemaConfig: config.SchemaConfig{ + Datacenter: "test", + TraceTTL: 172800, + DependenciesTTL: 0, + ReplicationFactor: 1, + CasVersion: 4, + }, + } +} + +func applyDefaults(cfg *config.Schema) { + defaultSchema := DefaultSchemaConfig() + + if cfg.Keyspace == "" { + cfg.Keyspace = defaultSchema.Keyspace + } + + if cfg.Datacenter == "" { + cfg.Datacenter = defaultSchema.Datacenter + } + + if cfg.TraceTTL == 0 { + cfg.TraceTTL = defaultSchema.TraceTTL + } + + if cfg.ReplicationFactor == 0 { + cfg.ReplicationFactor = defaultSchema.ReplicationFactor + } + + if cfg.CasVersion == 0 { + cfg.CasVersion = 4 + } +} + +// Applies defaults for the configs and contructs other optional parameters from it +func constructCompleteSchemaConfig(cfg *config.Schema) error { + applyDefaults(cfg) + + cfg.Replication = fmt.Sprintf("{'class': 'NetworkTopologyStrategy', '%s': '%v' }", cfg.Datacenter, cfg.ReplicationFactor) + + if cfg.CompactionWindow != "" { + isMatch, err := regexp.MatchString("^[0-9]+[mhd]$", cfg.CompactionWindow) + if err != nil { + return err + } + + if !isMatch { + return fmt.Errorf("Invalid compaction window size format. Please use numeric value followed by 'm' for minutes, 'h' for hours, or 'd' for days") + } + + cfg.CompactionWindowSize, err = strconv.Atoi(cfg.CompactionWindow[:len(cfg.CompactionWindow)-1]) + if err != nil { + return err + } + + cfg.CompactionWindowUnit = cfg.CompactionWindow[len(cfg.CompactionWindow)-1:] + } else { + traceTTLMinutes := cfg.TraceTTL / 60 + + cfg.CompactionWindowSize = (traceTTLMinutes + 30 - 1) / 30 + cfg.CompactionWindowUnit = "m" + } + + switch cfg.CompactionWindowUnit { + case `m`: + cfg.CompactionWindowUnit = `MINUTES` + case `h`: + cfg.CompactionWindowUnit = `HOURS` + case `d`: + cfg.CompactionWindowUnit = `DAYS` + default: + return fmt.Errorf("Invalid compaction window unit. If can be among {m|h|d}") + } + + return nil +} + +func getQueryFileAsBytes(fileName string, cfg *config.Schema) ([]byte, error) { + tmpl, err := template.ParseFS(schemaFile, fileName) + if err != nil { + return nil, err + } + + var result bytes.Buffer + err = tmpl.Execute(&result, cfg) + if err != nil { + return nil, err + } + + return result.Bytes(), nil +} + +func getQueriesFromBytes(queryFile []byte) ([]string, error) { + lines := bytes.Split(queryFile, []byte("\n")) + + var extractedLines [][]byte + + for _, line := range lines { + // Remove any comments, if at the end of the line + commentIndex := bytes.Index(line, []byte(`--`)) + if commentIndex != -1 { + // remove everything after comment + line = line[0:commentIndex] + } + + if len(line) == 0 { + continue + } + + extractedLines = append(extractedLines, bytes.TrimSpace(line)) + } + + var queries []string + + // Construct individual queries strings + var queryString string + for _, line := range extractedLines { + queryString += string(line) + if bytes.HasSuffix(line, []byte(";")) { + queries = append(queries, queryString) + queryString = "" + } + } + + if len(queryString) > 0 { + return nil, fmt.Errorf(`Invalid template`) + } + + return queries, nil +} + +func getCassandraQueriesFromQueryStrings(session cassandra.Session, queries []string) []cassandra.Query { + var casQueries []cassandra.Query + + for _, query := range queries { + casQueries = append(casQueries, session.Query(query)) + } + + return casQueries +} + +func contructSchemaQueries(session cassandra.Session, cfg *config.Schema) ([]cassandra.Query, error) { + err := constructCompleteSchemaConfig(cfg) + if err != nil { + return nil, err + } + + queryFile, err := getQueryFileAsBytes(`v004-go-tmpl.cql.tmpl`, cfg) + if err != nil { + return nil, err + } + + queryStrings, err := getQueriesFromBytes(queryFile) + if err != nil { + return nil, err + } + + casQueries := getCassandraQueriesFromQueryStrings(session, queryStrings) + + return casQueries, nil +} + +func GenerateSchemaIfNotPresent(session cassandra.Session, cfg *config.Schema) error { + casQueries, err := contructSchemaQueries(session, cfg) + if err != nil { + return err + } + + for _, query := range casQueries { + err := query.Exec() + if err != nil { + return err + } + } + + return nil +} diff --git a/plugin/storage/cassandra/schema/schema_test.go b/plugin/storage/cassandra/schema/schema_test.go new file mode 100644 index 00000000000..a2f6821891c --- /dev/null +++ b/plugin/storage/cassandra/schema/schema_test.go @@ -0,0 +1,22 @@ +// Copyright (c) 2024 The Jaeger Authors. +// SPDX-License-Identifier: Apache-2.0 + +package schema + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestTemplateRendering(t *testing.T) { + cfg := DefaultSchemaConfig() + res, err := getQueryFileAsBytes(`v004-go-tmpl-test.cql.tmpl`, &cfg) + require.NoError(t, err) + + queryStrings, err := getQueriesFromBytes(res) + require.NoError(t, err) + + assert.Equal(t, 9, len(queryStrings)) +} diff --git a/plugin/storage/cassandra/schema/v004-go-tmpl-test.cql.tmpl b/plugin/storage/cassandra/schema/v004-go-tmpl-test.cql.tmpl new file mode 100644 index 00000000000..5f37104959f --- /dev/null +++ b/plugin/storage/cassandra/schema/v004-go-tmpl-test.cql.tmpl @@ -0,0 +1,84 @@ +-- There are total 9 queries here + +CREATE KEYSPACE IF NOT EXISTS {{.Keyspace}} WITH replication = {{.Replication}}; + +CREATE TYPE IF NOT EXISTS {{.Keyspace}}.keyvalue ( + key text, + value_type text, + value_string text, + value_bool boolean, + value_long bigint, + value_double double, + value_binary blob +); + +CREATE TYPE IF NOT EXISTS {{.Keyspace}}.log ( + ts bigint, -- microseconds since epoch + fields frozen>> +); + +CREATE TYPE IF NOT EXISTS {{.Keyspace}}.span_ref ( + ref_type text, + trace_id blob, + span_id bigint +); + +CREATE TYPE IF NOT EXISTS {{.Keyspace}}.process ( + service_name text, + tags frozen>> +); + +CREATE TABLE IF NOT EXISTS {{.Keyspace}}.service_names ( + service_name text, + PRIMARY KEY (service_name) +) + WITH compaction = { + 'min_threshold': '4', + 'max_threshold': '32', + 'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy' + } + AND default_time_to_live = {{.TraceTTL}} + AND speculative_retry = 'NONE' + AND gc_grace_seconds = 10800; -- 3 hours of downtime acceptable on nodes + +-- a bucketing strategy may have to be added for tag queries +-- we can make this table even better by adding a timestamp to it +CREATE TABLE IF NOT EXISTS {{.Keyspace}}.tag_index ( + service_name text, + tag_key text, + tag_value text, + start_time bigint, -- microseconds since epoch + trace_id blob, + span_id bigint, + PRIMARY KEY ((service_name, tag_key, tag_value), start_time, trace_id, span_id) +) + WITH CLUSTERING ORDER BY (start_time DESC) + AND compaction = { + 'compaction_window_size': '1', + 'compaction_window_unit': 'HOURS', + 'class': 'org.apache.cassandra.db.compaction.TimeWindowCompactionStrategy' + } + AND default_time_to_live = {{.TraceTTL}} + AND speculative_retry = 'NONE' + AND gc_grace_seconds = 10800; -- 3 hours of downtime acceptable on nodes + +CREATE TYPE IF NOT EXISTS {{.Keyspace}}.dependency ( + parent text, + child text, + call_count bigint, + source text +); + +-- compaction strategy is intentionally different as compared to other tables due to the size of dependencies data +CREATE TABLE IF NOT EXISTS {{.Keyspace}}.dependencies_v2 ( + ts_bucket timestamp, + ts timestamp, + dependencies list>, + PRIMARY KEY (ts_bucket, ts) +) WITH CLUSTERING ORDER BY (ts DESC) + AND compaction = { + 'min_threshold': '4', + 'max_threshold': '32', + 'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy' + } + AND default_time_to_live = {{.DependenciesTTL}}; \ No newline at end of file diff --git a/plugin/storage/cassandra/schema/v004-go-tmpl.cql.tmpl b/plugin/storage/cassandra/schema/v004-go-tmpl.cql.tmpl new file mode 100644 index 00000000000..5a08e3f9dc0 --- /dev/null +++ b/plugin/storage/cassandra/schema/v004-go-tmpl.cql.tmpl @@ -0,0 +1,200 @@ +CREATE KEYSPACE IF NOT EXISTS {{.Keyspace}} WITH replication = {{.Replication}}; + +CREATE TYPE IF NOT EXISTS {{.Keyspace}}.keyvalue ( + key text, + value_type text, + value_string text, + value_bool boolean, + value_long bigint, + value_double double, + value_binary blob +); + +CREATE TYPE IF NOT EXISTS {{.Keyspace}}.log ( + ts bigint, -- microseconds since epoch + fields frozen>> +); + +CREATE TYPE IF NOT EXISTS {{.Keyspace}}.span_ref ( + ref_type text, + trace_id blob, + span_id bigint +); + +CREATE TYPE IF NOT EXISTS {{.Keyspace}}.process ( + service_name text, + tags frozen>> +); + +-- Notice we have span_hash. This exists only for zipkin backwards compat. Zipkin allows spans with the same ID. +-- Note: Cassandra re-orders non-PK columns alphabetically, so the table looks differently in CQLSH "describe table". +-- start_time is bigint instead of timestamp as we require microsecond precision +CREATE TABLE IF NOT EXISTS {{.Keyspace}}.traces ( + trace_id blob, + span_id bigint, + span_hash bigint, + parent_id bigint, + operation_name text, + flags int, + start_time bigint, -- microseconds since epoch + duration bigint, -- microseconds + tags list>, + logs list>, + refs list>, + process frozen, + PRIMARY KEY (trace_id, span_id, span_hash) +) + WITH compaction = { + 'compaction_window_size': '{{.CompactionWindowSize}}', + 'compaction_window_unit': '{{.CompactionWindowUnit}}', + 'class': 'org.apache.cassandra.db.compaction.TimeWindowCompactionStrategy' + } + AND default_time_to_live = {{.TraceTTL}} + AND speculative_retry = 'NONE' + AND gc_grace_seconds = 10800; -- 3 hours of downtime acceptable on nodes + +CREATE TABLE IF NOT EXISTS {{.Keyspace}}.service_names ( + service_name text, + PRIMARY KEY (service_name) +) + WITH compaction = { + 'min_threshold': '4', + 'max_threshold': '32', + 'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy' + } + AND default_time_to_live = {{.TraceTTL}} + AND speculative_retry = 'NONE' + AND gc_grace_seconds = 10800; -- 3 hours of downtime acceptable on nodes + +CREATE TABLE IF NOT EXISTS {{.Keyspace}}.operation_names_v2 ( + service_name text, + span_kind text, + operation_name text, + PRIMARY KEY ((service_name), span_kind, operation_name) +) + WITH compaction = { + 'min_threshold': '4', + 'max_threshold': '32', + 'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy' + } + AND default_time_to_live = {{.TraceTTL}} + AND speculative_retry = 'NONE' + AND gc_grace_seconds = 10800; -- 3 hours of downtime acceptable on nodes + +-- index of trace IDs by service + operation names, sorted by span start_time. +CREATE TABLE IF NOT EXISTS {{.Keyspace}}.service_operation_index ( + service_name text, + operation_name text, + start_time bigint, -- microseconds since epoch + trace_id blob, + PRIMARY KEY ((service_name, operation_name), start_time) +) WITH CLUSTERING ORDER BY (start_time DESC) + AND compaction = { + 'compaction_window_size': '1', + 'compaction_window_unit': 'HOURS', + 'class': 'org.apache.cassandra.db.compaction.TimeWindowCompactionStrategy' + } + AND default_time_to_live = {{.TraceTTL}} + AND speculative_retry = 'NONE' + AND gc_grace_seconds = 10800; -- 3 hours of downtime acceptable on nodes + +CREATE TABLE IF NOT EXISTS {{.Keyspace}}.service_name_index ( + service_name text, + bucket int, + start_time bigint, -- microseconds since epoch + trace_id blob, + PRIMARY KEY ((service_name, bucket), start_time) +) WITH CLUSTERING ORDER BY (start_time DESC) + AND compaction = { + 'compaction_window_size': '1', + 'compaction_window_unit': 'HOURS', + 'class': 'org.apache.cassandra.db.compaction.TimeWindowCompactionStrategy' + } + AND default_time_to_live = {{.TraceTTL}} + AND speculative_retry = 'NONE' + AND gc_grace_seconds = 10800; -- 3 hours of downtime acceptable on nodes + +CREATE TABLE IF NOT EXISTS {{.Keyspace}}.duration_index ( + service_name text, -- service name + operation_name text, -- operation name, or blank for queries without span name + bucket timestamp, -- time bucket, - the start_time of the given span rounded to an hour + duration bigint, -- span duration, in microseconds + start_time bigint, -- microseconds since epoch + trace_id blob, + PRIMARY KEY ((service_name, operation_name, bucket), duration, start_time, trace_id) +) WITH CLUSTERING ORDER BY (duration DESC, start_time DESC) + AND compaction = { + 'compaction_window_size': '1', + 'compaction_window_unit': 'HOURS', + 'class': 'org.apache.cassandra.db.compaction.TimeWindowCompactionStrategy' + } + AND default_time_to_live = {{.TraceTTL}} + AND speculative_retry = 'NONE' + AND gc_grace_seconds = 10800; -- 3 hours of downtime acceptable on nodes + +-- a bucketing strategy may have to be added for tag queries +-- we can make this table even better by adding a timestamp to it +CREATE TABLE IF NOT EXISTS {{.Keyspace}}.tag_index ( + service_name text, + tag_key text, + tag_value text, + start_time bigint, -- microseconds since epoch + trace_id blob, + span_id bigint, + PRIMARY KEY ((service_name, tag_key, tag_value), start_time, trace_id, span_id) +) + WITH CLUSTERING ORDER BY (start_time DESC) + AND compaction = { + 'compaction_window_size': '1', + 'compaction_window_unit': 'HOURS', + 'class': 'org.apache.cassandra.db.compaction.TimeWindowCompactionStrategy' + } + AND default_time_to_live = {{.TraceTTL}} + AND speculative_retry = 'NONE' + AND gc_grace_seconds = 10800; -- 3 hours of downtime acceptable on nodes + +CREATE TYPE IF NOT EXISTS {{.Keyspace}}.dependency ( + parent text, + child text, + call_count bigint, + source text +); + +-- compaction strategy is intentionally different as compared to other tables due to the size of dependencies data +CREATE TABLE IF NOT EXISTS {{.Keyspace}}.dependencies_v2 ( + ts_bucket timestamp, + ts timestamp, + dependencies list>, + PRIMARY KEY (ts_bucket, ts) +) WITH CLUSTERING ORDER BY (ts DESC) + AND compaction = { + 'min_threshold': '4', + 'max_threshold': '32', + 'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy' + } + AND default_time_to_live = {{.DependenciesTTL}}; + +-- adaptive sampling tables +-- ./plugin/storage/cassandra/samplingstore/storage.go +CREATE TABLE IF NOT EXISTS {{.Keyspace}}.operation_throughput ( + bucket int, + ts timeuuid, + throughput text, + PRIMARY KEY(bucket, ts) +) WITH CLUSTERING ORDER BY (ts desc); + +CREATE TABLE IF NOT EXISTS {{.Keyspace}}.sampling_probabilities ( + bucket int, + ts timeuuid, + hostname text, + probabilities text, + PRIMARY KEY(bucket, ts) +) WITH CLUSTERING ORDER BY (ts desc); + +-- distributed lock +-- ./plugin/pkg/distributedlock/cassandra/lock.go +CREATE TABLE IF NOT EXISTS {{.Keyspace}}.leases ( + name text, + owner text, + PRIMARY KEY (name) +); \ No newline at end of file From 30db1708dae1bb2a3906ac6e15c232e5e0a9b096 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Mon, 28 Oct 2024 16:45:50 +0530 Subject: [PATCH 02/55] Removed unnecessary SchemaConfig struct Signed-off-by: Alok Kumar Singh --- pkg/cassandra/config/config.go | 31 +++++++++++-------- plugin/storage/cassandra/schema/schema.go | 22 ++++++------- .../storage/cassandra/schema/schema_test.go | 2 +- 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/pkg/cassandra/config/config.go b/pkg/cassandra/config/config.go index 23fa3b0767a..450d7c9171b 100644 --- a/pkg/cassandra/config/config.go +++ b/pkg/cassandra/config/config.go @@ -51,18 +51,6 @@ type Connection struct { ProtoVersion int `mapstructure:"proto_version"` } -type SchemaConfig struct { - Datacenter string `mapstructure:"datacenter" valid:"optional"` - TraceTTL int `mapstructure:"trace_ttl" valid:"optional"` - DependenciesTTL int `mapstructure:"dependencies_ttl" valid:"optional"` - ReplicationFactor int `mapstructure:"replication_factor" valid:"optional"` - CasVersion int `mapstructure:"cas_version" valid:"optional"` - CompactionWindow string `mapstructure:"compaction_window" valid:"optional"` - Replication string `mapstructure:"replication" valid:"optional"` - CompactionWindowSize int `mapstructure:"compaction_window_size" valid:"optional"` - CompactionWindowUnit string `mapstructure:"compaction_window_unit" valid:"optional"` -} - type Schema struct { // Keyspace contains the namespace where Jaeger data will be stored. Keyspace string `mapstructure:"keyspace"` @@ -70,7 +58,24 @@ type Schema struct { // while connecting to the Cassandra Cluster. This is useful for connecting to clusters, like Azure Cosmos DB, // that do not support SnappyCompression. DisableCompression bool `mapstructure:"disable_compression"` - SchemaConfig + //Datacenter is the name for network topology + Datacenter string `mapstructure:"datacenter" valid:"optional"` + // TraceTTL is Time To Live (TTL) for the trace data in seconds + TraceTTL int `mapstructure:"trace_ttl" valid:"optional"` + // DependenciesTTL is Time To Live (TTL) for dependencies data in seconds + DependenciesTTL int `mapstructure:"dependencies_ttl" valid:"optional"` + // Replication factor for the db + ReplicationFactor int `mapstructure:"replication_factor" valid:"optional"` + // CasVersion is version of cassandra used + CasVersion int `mapstructure:"cas_version" valid:"optional"` + // CompactionWindow of format "^[0-9]+[mhd]$" tells the compaction window of the db + CompactionWindow string `mapstructure:"compaction_window" valid:"optional"` + // Replication is the replication strategy used + Replication string `mapstructure:"replication" valid:"optional"` + // CompactionWindowSize is the numberical part of CompactionWindow. Extracted from CompactionWindow + CompactionWindowSize int `mapstructure:"compaction_window_size" valid:"optional"` + // CompactionWindowUnit is the time unit of the CompactionWindow. Extracted from CompactionWindow + CompactionWindowUnit string `mapstructure:"compaction_window_unit" valid:"optional"` } type Query struct { diff --git a/plugin/storage/cassandra/schema/schema.go b/plugin/storage/cassandra/schema/schema.go index 27c88c38984..f8d69e7d1f8 100644 --- a/plugin/storage/cassandra/schema/schema.go +++ b/plugin/storage/cassandra/schema/schema.go @@ -19,21 +19,19 @@ import ( //go:embed v004-go-tmpl-test.cql.tmpl var schemaFile embed.FS -func DefaultSchemaConfig() config.Schema { +func DefaultSchema() config.Schema { return config.Schema{ - Keyspace: "jaeger_v2_test", - SchemaConfig: config.SchemaConfig{ - Datacenter: "test", - TraceTTL: 172800, - DependenciesTTL: 0, - ReplicationFactor: 1, - CasVersion: 4, - }, + Keyspace: "jaeger_v2_test", + Datacenter: "test", + TraceTTL: 172800, + DependenciesTTL: 0, + ReplicationFactor: 1, + CasVersion: 4, } } func applyDefaults(cfg *config.Schema) { - defaultSchema := DefaultSchemaConfig() + defaultSchema := DefaultSchema() if cfg.Keyspace == "" { cfg.Keyspace = defaultSchema.Keyspace @@ -57,7 +55,7 @@ func applyDefaults(cfg *config.Schema) { } // Applies defaults for the configs and contructs other optional parameters from it -func constructCompleteSchemaConfig(cfg *config.Schema) error { +func constructCompleteSchema(cfg *config.Schema) error { applyDefaults(cfg) cfg.Replication = fmt.Sprintf("{'class': 'NetworkTopologyStrategy', '%s': '%v' }", cfg.Datacenter, cfg.ReplicationFactor) @@ -164,7 +162,7 @@ func getCassandraQueriesFromQueryStrings(session cassandra.Session, queries []st } func contructSchemaQueries(session cassandra.Session, cfg *config.Schema) ([]cassandra.Query, error) { - err := constructCompleteSchemaConfig(cfg) + err := constructCompleteSchema(cfg) if err != nil { return nil, err } diff --git a/plugin/storage/cassandra/schema/schema_test.go b/plugin/storage/cassandra/schema/schema_test.go index a2f6821891c..6f4afdef979 100644 --- a/plugin/storage/cassandra/schema/schema_test.go +++ b/plugin/storage/cassandra/schema/schema_test.go @@ -11,7 +11,7 @@ import ( ) func TestTemplateRendering(t *testing.T) { - cfg := DefaultSchemaConfig() + cfg := DefaultSchema() res, err := getQueryFileAsBytes(`v004-go-tmpl-test.cql.tmpl`, &cfg) require.NoError(t, err) From ce0c375844a07a5628bcd1dee8aaa29a88b6f431 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Mon, 28 Oct 2024 16:56:11 +0530 Subject: [PATCH 03/55] Added new schema configs in default config generator Signed-off-by: Alok Kumar Singh --- pkg/cassandra/config/config.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pkg/cassandra/config/config.go b/pkg/cassandra/config/config.go index 450d7c9171b..34676f19fe7 100644 --- a/pkg/cassandra/config/config.go +++ b/pkg/cassandra/config/config.go @@ -104,7 +104,13 @@ type BasicAuthenticator struct { func DefaultConfiguration() Configuration { return Configuration{ Schema: Schema{ - Keyspace: "jaeger_v1_test", + Keyspace: "jaeger_v1_test", + Datacenter: "test", + TraceTTL: 172800, + DependenciesTTL: 172800, + ReplicationFactor: 1, + CasVersion: 4, + CompactionWindow: "1m", }, Connection: Connection{ Servers: []string{"127.0.0.1"}, From 810ab1c5262c3716fe17bfe9bf8f80027fd5fcf2 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Mon, 28 Oct 2024 18:37:25 +0530 Subject: [PATCH 04/55] Revert Keyspace removal Signed-off-by: Alok Kumar Singh --- pkg/cassandra/config/config.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/cassandra/config/config.go b/pkg/cassandra/config/config.go index 34676f19fe7..8a3761141e5 100644 --- a/pkg/cassandra/config/config.go +++ b/pkg/cassandra/config/config.go @@ -174,8 +174,7 @@ func (c *Configuration) NewSession() (cassandra.Session, error) { // NewCluster creates a new gocql cluster from the configuration func (c *Configuration) NewCluster() (*gocql.ClusterConfig, error) { cluster := gocql.NewCluster(c.Connection.Servers...) - // Removing this, since keyspace would be created post builing connection - // cluster.Keyspace = c.Schema.Keyspace + cluster.Keyspace = c.Schema.Keyspace cluster.NumConns = c.Connection.ConnectionsPerHost cluster.ConnectTimeout = c.Connection.Timeout cluster.ReconnectInterval = c.Connection.ReconnectInterval From 0d6383fbdb471e48cf58fddac8d60d6b15541134 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Tue, 29 Oct 2024 12:31:54 +0530 Subject: [PATCH 05/55] Bug fix while creating queries Signed-off-by: Alok Kumar Singh --- plugin/storage/cassandra/schema/schema.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/storage/cassandra/schema/schema.go b/plugin/storage/cassandra/schema/schema.go index f8d69e7d1f8..b9c1fd1cf14 100644 --- a/plugin/storage/cassandra/schema/schema.go +++ b/plugin/storage/cassandra/schema/schema.go @@ -137,7 +137,7 @@ func getQueriesFromBytes(queryFile []byte) ([]string, error) { // Construct individual queries strings var queryString string for _, line := range extractedLines { - queryString += string(line) + queryString += string(line) + "\n" if bytes.HasSuffix(line, []byte(";")) { queries = append(queries, queryString) queryString = "" From 207945f7b1310eaa195bd8e766a721d170872b8c Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Tue, 29 Oct 2024 13:01:13 +0530 Subject: [PATCH 06/55] Improving test Signed-off-by: Alok Kumar Singh --- .../storage/cassandra/schema/schema_test.go | 52 ++++++++++++++++++- .../schema/v004-go-tmpl-test.cql.tmpl | 43 +-------------- 2 files changed, 51 insertions(+), 44 deletions(-) diff --git a/plugin/storage/cassandra/schema/schema_test.go b/plugin/storage/cassandra/schema/schema_test.go index 6f4afdef979..a478798344d 100644 --- a/plugin/storage/cassandra/schema/schema_test.go +++ b/plugin/storage/cassandra/schema/schema_test.go @@ -10,7 +10,7 @@ import ( "github.com/stretchr/testify/require" ) -func TestTemplateRendering(t *testing.T) { +func TestQueryCreationFromTemplate(t *testing.T) { cfg := DefaultSchema() res, err := getQueryFileAsBytes(`v004-go-tmpl-test.cql.tmpl`, &cfg) require.NoError(t, err) @@ -18,5 +18,53 @@ func TestTemplateRendering(t *testing.T) { queryStrings, err := getQueriesFromBytes(res) require.NoError(t, err) - assert.Equal(t, 9, len(queryStrings)) + expOutputQueries := []string{ + `CREATE TYPE IF NOT EXISTS jaeger_v2_test.keyvalue ( +key text, +value_type text, +value_string text, +value_bool boolean, +value_long bigint, +value_double double, +value_binary blob +); +`, + `CREATE TYPE IF NOT EXISTS jaeger_v2_test.log ( +ts bigint, +fields frozen>> +); +`, + `CREATE TABLE IF NOT EXISTS jaeger_v2_test.service_names ( +service_name text, +PRIMARY KEY (service_name) +) +WITH compaction = { +'min_threshold': '4', +'max_threshold': '32', +'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy' +} +AND default_time_to_live = 172800 +AND speculative_retry = 'NONE' +AND gc_grace_seconds = 10800; +`, + `CREATE TABLE IF NOT EXISTS jaeger_v2_test.dependencies_v2 ( +ts_bucket timestamp, +ts timestamp, +dependencies list>, +PRIMARY KEY (ts_bucket, ts) +) WITH CLUSTERING ORDER BY (ts DESC) +AND compaction = { +'min_threshold': '4', +'max_threshold': '32', +'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy' +} +AND default_time_to_live = 0; +`, + } + + assert.Equal(t, len(expOutputQueries), len(queryStrings)) + + for i := range expOutputQueries { + assert.Equal(t, expOutputQueries[i], queryStrings[i]) + } } diff --git a/plugin/storage/cassandra/schema/v004-go-tmpl-test.cql.tmpl b/plugin/storage/cassandra/schema/v004-go-tmpl-test.cql.tmpl index 5f37104959f..d8192d0c2ed 100644 --- a/plugin/storage/cassandra/schema/v004-go-tmpl-test.cql.tmpl +++ b/plugin/storage/cassandra/schema/v004-go-tmpl-test.cql.tmpl @@ -1,6 +1,4 @@ --- There are total 9 queries here - -CREATE KEYSPACE IF NOT EXISTS {{.Keyspace}} WITH replication = {{.Replication}}; +-- There are total 4 queries here CREATE TYPE IF NOT EXISTS {{.Keyspace}}.keyvalue ( key text, @@ -17,17 +15,6 @@ CREATE TYPE IF NOT EXISTS {{.Keyspace}}.log ( fields frozen>> ); -CREATE TYPE IF NOT EXISTS {{.Keyspace}}.span_ref ( - ref_type text, - trace_id blob, - span_id bigint -); - -CREATE TYPE IF NOT EXISTS {{.Keyspace}}.process ( - service_name text, - tags frozen>> -); - CREATE TABLE IF NOT EXISTS {{.Keyspace}}.service_names ( service_name text, PRIMARY KEY (service_name) @@ -41,34 +28,6 @@ CREATE TABLE IF NOT EXISTS {{.Keyspace}}.service_names ( AND speculative_retry = 'NONE' AND gc_grace_seconds = 10800; -- 3 hours of downtime acceptable on nodes --- a bucketing strategy may have to be added for tag queries --- we can make this table even better by adding a timestamp to it -CREATE TABLE IF NOT EXISTS {{.Keyspace}}.tag_index ( - service_name text, - tag_key text, - tag_value text, - start_time bigint, -- microseconds since epoch - trace_id blob, - span_id bigint, - PRIMARY KEY ((service_name, tag_key, tag_value), start_time, trace_id, span_id) -) - WITH CLUSTERING ORDER BY (start_time DESC) - AND compaction = { - 'compaction_window_size': '1', - 'compaction_window_unit': 'HOURS', - 'class': 'org.apache.cassandra.db.compaction.TimeWindowCompactionStrategy' - } - AND default_time_to_live = {{.TraceTTL}} - AND speculative_retry = 'NONE' - AND gc_grace_seconds = 10800; -- 3 hours of downtime acceptable on nodes - -CREATE TYPE IF NOT EXISTS {{.Keyspace}}.dependency ( - parent text, - child text, - call_count bigint, - source text -); - -- compaction strategy is intentionally different as compared to other tables due to the size of dependencies data CREATE TABLE IF NOT EXISTS {{.Keyspace}}.dependencies_v2 ( ts_bucket timestamp, From 985f65b1a43d9452994a8a9113e6d7fc12413d68 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Tue, 29 Oct 2024 14:38:50 +0530 Subject: [PATCH 07/55] Created new struct for derived params Signed-off-by: Alok Kumar Singh --- pkg/cassandra/config/config.go | 6 -- plugin/storage/cassandra/schema/schema.go | 97 +++++++++++-------- .../storage/cassandra/schema/schema_test.go | 4 +- 3 files changed, 58 insertions(+), 49 deletions(-) diff --git a/pkg/cassandra/config/config.go b/pkg/cassandra/config/config.go index 8a3761141e5..16a676d4175 100644 --- a/pkg/cassandra/config/config.go +++ b/pkg/cassandra/config/config.go @@ -70,12 +70,6 @@ type Schema struct { CasVersion int `mapstructure:"cas_version" valid:"optional"` // CompactionWindow of format "^[0-9]+[mhd]$" tells the compaction window of the db CompactionWindow string `mapstructure:"compaction_window" valid:"optional"` - // Replication is the replication strategy used - Replication string `mapstructure:"replication" valid:"optional"` - // CompactionWindowSize is the numberical part of CompactionWindow. Extracted from CompactionWindow - CompactionWindowSize int `mapstructure:"compaction_window_size" valid:"optional"` - // CompactionWindowUnit is the time unit of the CompactionWindow. Extracted from CompactionWindow - CompactionWindowUnit string `mapstructure:"compaction_window_unit" valid:"optional"` } type Query struct { diff --git a/plugin/storage/cassandra/schema/schema.go b/plugin/storage/cassandra/schema/schema.go index b9c1fd1cf14..837cef28dab 100644 --- a/plugin/storage/cassandra/schema/schema.go +++ b/plugin/storage/cassandra/schema/schema.go @@ -19,92 +19,107 @@ import ( //go:embed v004-go-tmpl-test.cql.tmpl var schemaFile embed.FS -func DefaultSchema() config.Schema { - return config.Schema{ - Keyspace: "jaeger_v2_test", - Datacenter: "test", - TraceTTL: 172800, - DependenciesTTL: 0, - ReplicationFactor: 1, - CasVersion: 4, +type TemplateParams struct { + config.Schema + // Replication is the replication strategy used + Replication string `mapstructure:"replication" valid:"optional"` + // CompactionWindowSize is the numberical part of CompactionWindow. Extracted from CompactionWindow + CompactionWindowSize int `mapstructure:"compaction_window_size" valid:"optional"` + // CompactionWindowUnit is the time unit of the CompactionWindow. Extracted from CompactionWindow + CompactionWindowUnit string `mapstructure:"compaction_window_unit" valid:"optional"` +} + +func DefaultParams() TemplateParams { + return TemplateParams{ + Schema: config.Schema{ + Keyspace: "jaeger_v2_test", + Datacenter: "test", + TraceTTL: 172800, + DependenciesTTL: 0, + ReplicationFactor: 1, + CasVersion: 4, + }, } } -func applyDefaults(cfg *config.Schema) { - defaultSchema := DefaultSchema() +func applyDefaults(params *TemplateParams) { + defaultSchema := DefaultParams() - if cfg.Keyspace == "" { - cfg.Keyspace = defaultSchema.Keyspace + if params.Keyspace == "" { + params.Keyspace = defaultSchema.Keyspace } - if cfg.Datacenter == "" { - cfg.Datacenter = defaultSchema.Datacenter + if params.Datacenter == "" { + params.Datacenter = defaultSchema.Datacenter } - if cfg.TraceTTL == 0 { - cfg.TraceTTL = defaultSchema.TraceTTL + if params.TraceTTL == 0 { + params.TraceTTL = defaultSchema.TraceTTL } - if cfg.ReplicationFactor == 0 { - cfg.ReplicationFactor = defaultSchema.ReplicationFactor + if params.ReplicationFactor == 0 { + params.ReplicationFactor = defaultSchema.ReplicationFactor } - if cfg.CasVersion == 0 { - cfg.CasVersion = 4 + if params.CasVersion == 0 { + params.CasVersion = 4 } } // Applies defaults for the configs and contructs other optional parameters from it -func constructCompleteSchema(cfg *config.Schema) error { - applyDefaults(cfg) +func constructTemplateParams(cfg config.Schema) (TemplateParams, error) { + params := TemplateParams{ + Schema: config.Schema{}, + } + applyDefaults(¶ms) - cfg.Replication = fmt.Sprintf("{'class': 'NetworkTopologyStrategy', '%s': '%v' }", cfg.Datacenter, cfg.ReplicationFactor) + params.Replication = fmt.Sprintf("{'class': 'NetworkTopologyStrategy', '%s': '%v' }", params.Datacenter, params.ReplicationFactor) if cfg.CompactionWindow != "" { - isMatch, err := regexp.MatchString("^[0-9]+[mhd]$", cfg.CompactionWindow) + isMatch, err := regexp.MatchString("^[0-9]+[mhd]$", params.CompactionWindow) if err != nil { - return err + return TemplateParams{}, err } if !isMatch { - return fmt.Errorf("Invalid compaction window size format. Please use numeric value followed by 'm' for minutes, 'h' for hours, or 'd' for days") + return TemplateParams{}, fmt.Errorf("Invalid compaction window size format. Please use numeric value followed by 'm' for minutes, 'h' for hours, or 'd' for days") } - cfg.CompactionWindowSize, err = strconv.Atoi(cfg.CompactionWindow[:len(cfg.CompactionWindow)-1]) + params.CompactionWindowSize, err = strconv.Atoi(params.CompactionWindow[:len(params.CompactionWindow)-1]) if err != nil { - return err + return TemplateParams{}, err } - cfg.CompactionWindowUnit = cfg.CompactionWindow[len(cfg.CompactionWindow)-1:] + params.CompactionWindowUnit = params.CompactionWindow[len(params.CompactionWindow)-1:] } else { traceTTLMinutes := cfg.TraceTTL / 60 - cfg.CompactionWindowSize = (traceTTLMinutes + 30 - 1) / 30 - cfg.CompactionWindowUnit = "m" + params.CompactionWindowSize = (traceTTLMinutes + 30 - 1) / 30 + params.CompactionWindowUnit = "m" } - switch cfg.CompactionWindowUnit { + switch params.CompactionWindowUnit { case `m`: - cfg.CompactionWindowUnit = `MINUTES` + params.CompactionWindowUnit = `MINUTES` case `h`: - cfg.CompactionWindowUnit = `HOURS` + params.CompactionWindowUnit = `HOURS` case `d`: - cfg.CompactionWindowUnit = `DAYS` + params.CompactionWindowUnit = `DAYS` default: - return fmt.Errorf("Invalid compaction window unit. If can be among {m|h|d}") + return TemplateParams{}, fmt.Errorf("Invalid compaction window unit. If can be among {m|h|d}") } - return nil + return params, nil } -func getQueryFileAsBytes(fileName string, cfg *config.Schema) ([]byte, error) { +func getQueryFileAsBytes(fileName string, params TemplateParams) ([]byte, error) { tmpl, err := template.ParseFS(schemaFile, fileName) if err != nil { return nil, err } var result bytes.Buffer - err = tmpl.Execute(&result, cfg) + err = tmpl.Execute(&result, params) if err != nil { return nil, err } @@ -162,12 +177,12 @@ func getCassandraQueriesFromQueryStrings(session cassandra.Session, queries []st } func contructSchemaQueries(session cassandra.Session, cfg *config.Schema) ([]cassandra.Query, error) { - err := constructCompleteSchema(cfg) + params, err := constructTemplateParams(*cfg) if err != nil { return nil, err } - queryFile, err := getQueryFileAsBytes(`v004-go-tmpl.cql.tmpl`, cfg) + queryFile, err := getQueryFileAsBytes(`v004-go-tmpl.cql.tmpl`, params) if err != nil { return nil, err } diff --git a/plugin/storage/cassandra/schema/schema_test.go b/plugin/storage/cassandra/schema/schema_test.go index a478798344d..729837fd47a 100644 --- a/plugin/storage/cassandra/schema/schema_test.go +++ b/plugin/storage/cassandra/schema/schema_test.go @@ -11,8 +11,8 @@ import ( ) func TestQueryCreationFromTemplate(t *testing.T) { - cfg := DefaultSchema() - res, err := getQueryFileAsBytes(`v004-go-tmpl-test.cql.tmpl`, &cfg) + params := DefaultParams() + res, err := getQueryFileAsBytes(`v004-go-tmpl-test.cql.tmpl`, params) require.NoError(t, err) queryStrings, err := getQueriesFromBytes(res) From 1c3050305b0d18f71356e6ae0d842e643e2e6085 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Tue, 29 Oct 2024 14:48:50 +0530 Subject: [PATCH 08/55] Remove fields from yaml file Signed-off-by: Alok Kumar Singh --- cmd/jaeger/config-cassandra.yaml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/cmd/jaeger/config-cassandra.yaml b/cmd/jaeger/config-cassandra.yaml index d78d1f78f3f..3ead38258c2 100644 --- a/cmd/jaeger/config-cassandra.yaml +++ b/cmd/jaeger/config-cassandra.yaml @@ -34,12 +34,6 @@ extensions: cassandra: schema: keyspace: "jaeger_v1_dc1" - datacenter: "test" - trace_ttl: 172800 - dependencies_ttl: 172800 - replication_factor: 1 - cas_version: 4 - compaction_window: "1m" connection: auth: basic: @@ -51,12 +45,6 @@ extensions: cassandra: schema: keyspace: "jaeger_v1_dc1" - datacenter: "test" - trace_ttl: 172800 - dependencies_ttl: 172800 - replication_factor: 1 - cas_version: 4 - compaction_window: "1m" connection: auth: basic: From e4ab709ae546f3706da9374a5b30e51524d5e863 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Tue, 19 Nov 2024 21:45:46 +0530 Subject: [PATCH 09/55] Added integration test Signed-off-by: Alok Kumar Singh --- pkg/cassandra/config/config.go | 53 ++++++++++++++++++- .../schema => pkg/cassandra/config}/schema.go | 35 ++++++------ .../cassandra/config}/schema_test.go | 12 ++--- .../config}/v004-go-tmpl-test.cql.tmpl | 0 .../cassandra/config}/v004-go-tmpl.cql.tmpl | 0 plugin/storage/cassandra/factory.go | 14 ----- scripts/cassandra-integration-test.sh | 22 ++++++-- 7 files changed, 94 insertions(+), 42 deletions(-) rename {plugin/storage/cassandra/schema => pkg/cassandra/config}/schema.go (83%) rename {plugin/storage/cassandra/schema => pkg/cassandra/config}/schema_test.go (82%) rename {plugin/storage/cassandra/schema => pkg/cassandra/config}/v004-go-tmpl-test.cql.tmpl (100%) rename {plugin/storage/cassandra/schema => pkg/cassandra/config}/v004-go-tmpl.cql.tmpl (100%) diff --git a/pkg/cassandra/config/config.go b/pkg/cassandra/config/config.go index 16a676d4175..6c167493c69 100644 --- a/pkg/cassandra/config/config.go +++ b/pkg/cassandra/config/config.go @@ -58,7 +58,7 @@ type Schema struct { // while connecting to the Cassandra Cluster. This is useful for connecting to clusters, like Azure Cosmos DB, // that do not support SnappyCompression. DisableCompression bool `mapstructure:"disable_compression"` - //Datacenter is the name for network topology + // Datacenter is the name for network topology Datacenter string `mapstructure:"datacenter" valid:"optional"` // TraceTTL is Time To Live (TTL) for the trace data in seconds TraceTTL int `mapstructure:"trace_ttl" valid:"optional"` @@ -98,7 +98,7 @@ type BasicAuthenticator struct { func DefaultConfiguration() Configuration { return Configuration{ Schema: Schema{ - Keyspace: "jaeger_v1_test", + Keyspace: "jaeger_v1_dc1", Datacenter: "test", TraceTTL: 172800, DependenciesTTL: 172800, @@ -124,6 +124,31 @@ func (c *Configuration) ApplyDefaults(source *Configuration) { if c.Schema.Keyspace == "" { c.Schema.Keyspace = source.Schema.Keyspace } + + if c.Schema.Datacenter == "" { + c.Schema.Datacenter = source.Schema.Datacenter + } + + if c.Schema.TraceTTL == 0 { + c.Schema.TraceTTL = source.Schema.TraceTTL + } + + if c.Schema.DependenciesTTL == 0 { + c.Schema.DependenciesTTL = source.Schema.DependenciesTTL + } + + if c.Schema.ReplicationFactor == 0 { + c.Schema.ReplicationFactor = source.Schema.ReplicationFactor + } + + if c.Schema.CasVersion == 0 { + c.Schema.CasVersion = source.Schema.CasVersion + } + + if c.Schema.CompactionWindow == "" { + c.Schema.CompactionWindow = source.Schema.CompactionWindow + } + if c.Connection.ConnectionsPerHost == 0 { c.Connection.ConnectionsPerHost = source.Connection.ConnectionsPerHost } @@ -152,8 +177,32 @@ type SessionBuilder interface { NewSession() (cassandra.Session, error) } +func (c *Configuration) newSessionPrerequisites() error { + cluster, err := c.NewCluster() + if err != nil { + return err + } + + cluster.Keyspace = "" + + session, err := cluster.CreateSession() + if err != nil { + return err + } + + wSession := gocqlw.WrapCQLSession(session) + defer wSession.Close() + + return GenerateSchemaIfNotPresent(wSession, &c.Schema) +} + // NewSession creates a new Cassandra session func (c *Configuration) NewSession() (cassandra.Session, error) { + err := c.newSessionPrerequisites() + if err != nil { + return nil, err + } + cluster, err := c.NewCluster() if err != nil { return nil, err diff --git a/plugin/storage/cassandra/schema/schema.go b/pkg/cassandra/config/schema.go similarity index 83% rename from plugin/storage/cassandra/schema/schema.go rename to pkg/cassandra/config/schema.go index 837cef28dab..b8c0b8c11b5 100644 --- a/plugin/storage/cassandra/schema/schema.go +++ b/pkg/cassandra/config/schema.go @@ -1,18 +1,18 @@ // Copyright (c) 2024 The Jaeger Authors. // SPDX-License-Identifier: Apache-2.0 -package schema +package config import ( "bytes" "embed" + "errors" "fmt" "regexp" "strconv" "text/template" "github.com/jaegertracing/jaeger/pkg/cassandra" - "github.com/jaegertracing/jaeger/pkg/cassandra/config" ) //go:embed v004-go-tmpl.cql.tmpl @@ -20,7 +20,7 @@ import ( var schemaFile embed.FS type TemplateParams struct { - config.Schema + Schema // Replication is the replication strategy used Replication string `mapstructure:"replication" valid:"optional"` // CompactionWindowSize is the numberical part of CompactionWindow. Extracted from CompactionWindow @@ -31,8 +31,8 @@ type TemplateParams struct { func DefaultParams() TemplateParams { return TemplateParams{ - Schema: config.Schema{ - Keyspace: "jaeger_v2_test", + Schema: Schema{ + Keyspace: "jaeger_v1_dc1", Datacenter: "test", TraceTTL: 172800, DependenciesTTL: 0, @@ -67,30 +67,31 @@ func applyDefaults(params *TemplateParams) { } // Applies defaults for the configs and contructs other optional parameters from it -func constructTemplateParams(cfg config.Schema) (TemplateParams, error) { +func constructTemplateParams(cfg Schema) (TemplateParams, error) { params := TemplateParams{ - Schema: config.Schema{}, + Schema: cfg, } applyDefaults(¶ms) - params.Replication = fmt.Sprintf("{'class': 'NetworkTopologyStrategy', '%s': '%v' }", params.Datacenter, params.ReplicationFactor) + params.Replication = fmt.Sprintf("{'class': 'NetworkTopologyStrategy', 'replication_factor': '%v' }", params.ReplicationFactor) - if cfg.CompactionWindow != "" { - isMatch, err := regexp.MatchString("^[0-9]+[mhd]$", params.CompactionWindow) + if params.CompactionWindow != "" { + var err error + isMatch, err := regexp.MatchString("[0-9]+[mhd]", params.CompactionWindow) if err != nil { return TemplateParams{}, err } if !isMatch { - return TemplateParams{}, fmt.Errorf("Invalid compaction window size format. Please use numeric value followed by 'm' for minutes, 'h' for hours, or 'd' for days") + return TemplateParams{}, fmt.Errorf("invalid compaction window size format: %s. Please use numeric value followed by 'm' for minutes, 'h' for hours, or 'd' for days", cfg.CompactionWindow) } - params.CompactionWindowSize, err = strconv.Atoi(params.CompactionWindow[:len(params.CompactionWindow)-1]) + params.CompactionWindowSize, err = strconv.Atoi(params.CompactionWindow[0 : len(params.CompactionWindow)-1]) if err != nil { return TemplateParams{}, err } - params.CompactionWindowUnit = params.CompactionWindow[len(params.CompactionWindow)-1:] + params.CompactionWindowUnit = params.CompactionWindow[len(params.CompactionWindow)-1 : len(params.CompactionWindow)] } else { traceTTLMinutes := cfg.TraceTTL / 60 @@ -106,7 +107,7 @@ func constructTemplateParams(cfg config.Schema) (TemplateParams, error) { case `d`: params.CompactionWindowUnit = `DAYS` default: - return TemplateParams{}, fmt.Errorf("Invalid compaction window unit. If can be among {m|h|d}") + return TemplateParams{}, errors.New("Invalid compaction window unit. If can be among {m|h|d}") } return params, nil @@ -160,7 +161,7 @@ func getQueriesFromBytes(queryFile []byte) ([]string, error) { } if len(queryString) > 0 { - return nil, fmt.Errorf(`Invalid template`) + return nil, errors.New(`Invalid template`) } return queries, nil @@ -176,7 +177,7 @@ func getCassandraQueriesFromQueryStrings(session cassandra.Session, queries []st return casQueries } -func contructSchemaQueries(session cassandra.Session, cfg *config.Schema) ([]cassandra.Query, error) { +func contructSchemaQueries(session cassandra.Session, cfg *Schema) ([]cassandra.Query, error) { params, err := constructTemplateParams(*cfg) if err != nil { return nil, err @@ -197,7 +198,7 @@ func contructSchemaQueries(session cassandra.Session, cfg *config.Schema) ([]cas return casQueries, nil } -func GenerateSchemaIfNotPresent(session cassandra.Session, cfg *config.Schema) error { +func GenerateSchemaIfNotPresent(session cassandra.Session, cfg *Schema) error { casQueries, err := contructSchemaQueries(session, cfg) if err != nil { return err diff --git a/plugin/storage/cassandra/schema/schema_test.go b/pkg/cassandra/config/schema_test.go similarity index 82% rename from plugin/storage/cassandra/schema/schema_test.go rename to pkg/cassandra/config/schema_test.go index 729837fd47a..84b53789fcf 100644 --- a/plugin/storage/cassandra/schema/schema_test.go +++ b/pkg/cassandra/config/schema_test.go @@ -1,7 +1,7 @@ // Copyright (c) 2024 The Jaeger Authors. // SPDX-License-Identifier: Apache-2.0 -package schema +package config import ( "testing" @@ -19,7 +19,7 @@ func TestQueryCreationFromTemplate(t *testing.T) { require.NoError(t, err) expOutputQueries := []string{ - `CREATE TYPE IF NOT EXISTS jaeger_v2_test.keyvalue ( + `CREATE TYPE IF NOT EXISTS jaeger_v1_dc1.keyvalue ( key text, value_type text, value_string text, @@ -29,12 +29,12 @@ value_double double, value_binary blob ); `, - `CREATE TYPE IF NOT EXISTS jaeger_v2_test.log ( + `CREATE TYPE IF NOT EXISTS jaeger_v1_dc1.log ( ts bigint, -fields frozen>> +fields frozen>> ); `, - `CREATE TABLE IF NOT EXISTS jaeger_v2_test.service_names ( + `CREATE TABLE IF NOT EXISTS jaeger_v1_dc1.service_names ( service_name text, PRIMARY KEY (service_name) ) @@ -47,7 +47,7 @@ AND default_time_to_live = 172800 AND speculative_retry = 'NONE' AND gc_grace_seconds = 10800; `, - `CREATE TABLE IF NOT EXISTS jaeger_v2_test.dependencies_v2 ( + `CREATE TABLE IF NOT EXISTS jaeger_v1_dc1.dependencies_v2 ( ts_bucket timestamp, ts timestamp, dependencies list>, diff --git a/plugin/storage/cassandra/schema/v004-go-tmpl-test.cql.tmpl b/pkg/cassandra/config/v004-go-tmpl-test.cql.tmpl similarity index 100% rename from plugin/storage/cassandra/schema/v004-go-tmpl-test.cql.tmpl rename to pkg/cassandra/config/v004-go-tmpl-test.cql.tmpl diff --git a/plugin/storage/cassandra/schema/v004-go-tmpl.cql.tmpl b/pkg/cassandra/config/v004-go-tmpl.cql.tmpl similarity index 100% rename from plugin/storage/cassandra/schema/v004-go-tmpl.cql.tmpl rename to pkg/cassandra/config/v004-go-tmpl.cql.tmpl diff --git a/plugin/storage/cassandra/factory.go b/plugin/storage/cassandra/factory.go index fca10dcc2bc..4654a2a2c82 100644 --- a/plugin/storage/cassandra/factory.go +++ b/plugin/storage/cassandra/factory.go @@ -24,7 +24,6 @@ import ( cLock "github.com/jaegertracing/jaeger/plugin/pkg/distributedlock/cassandra" cDepStore "github.com/jaegertracing/jaeger/plugin/storage/cassandra/dependencystore" cSamplingStore "github.com/jaegertracing/jaeger/plugin/storage/cassandra/samplingstore" - "github.com/jaegertracing/jaeger/plugin/storage/cassandra/schema" cSpanStore "github.com/jaegertracing/jaeger/plugin/storage/cassandra/spanstore" "github.com/jaegertracing/jaeger/plugin/storage/cassandra/spanstore/dbmodel" "github.com/jaegertracing/jaeger/storage" @@ -132,10 +131,6 @@ func (f *Factory) configureFromOptions(o *Options) { } } -func (f *Factory) initializeDB(session cassandra.Session, cfg *config.Schema) error { - return schema.GenerateSchemaIfNotPresent(session, cfg) -} - // Initialize implements storage.Factory func (f *Factory) Initialize(metricsFactory metrics.Factory, logger *zap.Logger) error { f.primaryMetricsFactory = metricsFactory.Namespace(metrics.NSOptions{Name: "cassandra", Tags: nil}) @@ -148,21 +143,12 @@ func (f *Factory) Initialize(metricsFactory metrics.Factory, logger *zap.Logger) } f.primarySession = primarySession - // After creating a session, execute commands to initialize the setup if not already present - if err := f.initializeDB(primarySession, &f.Options.Primary.Schema); err != nil { - return err - } - if f.archiveConfig != nil { archiveSession, err := f.archiveConfig.NewSession() if err != nil { return err } f.archiveSession = archiveSession - - if err := f.initializeDB(archiveSession, &f.Options.Primary.Schema); err != nil { - return err - } } else { logger.Info("Cassandra archive storage configuration is empty, skipping") } diff --git a/scripts/cassandra-integration-test.sh b/scripts/cassandra-integration-test.sh index 9f5e295bc3c..429c90cb2fa 100755 --- a/scripts/cassandra-integration-test.sh +++ b/scripts/cassandra-integration-test.sh @@ -11,13 +11,25 @@ success="false" timeout=600 end_time=$((SECONDS + timeout)) +SKIP_APPLY_SCHEMA="false" + +while getopts "s" opt; do + case "${opt}" in + s) + SKIP_APPLY_SCHEMA="true" + ;; + *) + ;; + esac +done + usage() { echo $"Usage: $0 " exit 1 } check_arg() { - if [ ! $# -eq 3 ]; then + if [ ! $# -ge 3 ]; then echo "ERROR: need exactly three arguments, " usage fi @@ -98,8 +110,12 @@ run_integration_test() { healthcheck_cassandra "${major_version}" - apply_schema "$schema_version" "$primaryKeyspace" - apply_schema "$schema_version" "$archiveKeyspace" + healthcheck_cassandra "${major_version}" + + if [ "${SKIP_APPLY_SCHEMA}" = "true" ]; then + apply_schema "$schema_version" "$primaryKeyspace" + apply_schema "$schema_version" "$archiveKeyspace" + fi if [ "${jaegerVersion}" = "v1" ]; then STORAGE=cassandra make storage-integration-test From c329bba4d9dabb5e6b290b3bd740556a7adad3fd Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Tue, 19 Nov 2024 21:47:06 +0530 Subject: [PATCH 10/55] Rebase fixes Signed-off-by: Alok Kumar Singh --- scripts/cassandra-integration-test.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/cassandra-integration-test.sh b/scripts/cassandra-integration-test.sh index 429c90cb2fa..25e951bf1df 100755 --- a/scripts/cassandra-integration-test.sh +++ b/scripts/cassandra-integration-test.sh @@ -110,8 +110,6 @@ run_integration_test() { healthcheck_cassandra "${major_version}" - healthcheck_cassandra "${major_version}" - if [ "${SKIP_APPLY_SCHEMA}" = "true" ]; then apply_schema "$schema_version" "$primaryKeyspace" apply_schema "$schema_version" "$archiveKeyspace" From e3c604569ae4e0143cae098fc37222ed636b4648 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Tue, 19 Nov 2024 22:22:52 +0530 Subject: [PATCH 11/55] Minor changes in integration script Signed-off-by: Alok Kumar Singh --- scripts/cassandra-integration-test.sh | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/scripts/cassandra-integration-test.sh b/scripts/cassandra-integration-test.sh index 25e951bf1df..97597adcaf8 100755 --- a/scripts/cassandra-integration-test.sh +++ b/scripts/cassandra-integration-test.sh @@ -14,22 +14,25 @@ end_time=$((SECONDS + timeout)) SKIP_APPLY_SCHEMA="false" while getopts "s" opt; do - case "${opt}" in - s) + case "${opt}" in + s) SKIP_APPLY_SCHEMA="true" - ;; + ;; *) - ;; - esac + ;; + esac done +# remove flags, leave only positional args +shift $((OPTIND - 1)) + usage() { echo $"Usage: $0 " exit 1 } check_arg() { - if [ ! $# -ge 3 ]; then + if [ ! $# -eq 3 ]; then echo "ERROR: need exactly three arguments, " usage fi @@ -110,7 +113,7 @@ run_integration_test() { healthcheck_cassandra "${major_version}" - if [ "${SKIP_APPLY_SCHEMA}" = "true" ]; then + if [ "${SKIP_APPLY_SCHEMA}" = "false" ]; then apply_schema "$schema_version" "$primaryKeyspace" apply_schema "$schema_version" "$archiveKeyspace" fi From 492e15e7dcd7d26a0d47cbe4683c83b1cadfeaad Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Tue, 19 Nov 2024 22:33:03 +0530 Subject: [PATCH 12/55] removed test Signed-off-by: Alok Kumar Singh --- pkg/cassandra/config/schema.go | 1 - pkg/cassandra/config/schema_test.go | 70 ------------------- .../config/v004-go-tmpl-test.cql.tmpl | 43 ------------ 3 files changed, 114 deletions(-) delete mode 100644 pkg/cassandra/config/schema_test.go delete mode 100644 pkg/cassandra/config/v004-go-tmpl-test.cql.tmpl diff --git a/pkg/cassandra/config/schema.go b/pkg/cassandra/config/schema.go index b8c0b8c11b5..329f37da39f 100644 --- a/pkg/cassandra/config/schema.go +++ b/pkg/cassandra/config/schema.go @@ -16,7 +16,6 @@ import ( ) //go:embed v004-go-tmpl.cql.tmpl -//go:embed v004-go-tmpl-test.cql.tmpl var schemaFile embed.FS type TemplateParams struct { diff --git a/pkg/cassandra/config/schema_test.go b/pkg/cassandra/config/schema_test.go deleted file mode 100644 index 84b53789fcf..00000000000 --- a/pkg/cassandra/config/schema_test.go +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) 2024 The Jaeger Authors. -// SPDX-License-Identifier: Apache-2.0 - -package config - -import ( - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestQueryCreationFromTemplate(t *testing.T) { - params := DefaultParams() - res, err := getQueryFileAsBytes(`v004-go-tmpl-test.cql.tmpl`, params) - require.NoError(t, err) - - queryStrings, err := getQueriesFromBytes(res) - require.NoError(t, err) - - expOutputQueries := []string{ - `CREATE TYPE IF NOT EXISTS jaeger_v1_dc1.keyvalue ( -key text, -value_type text, -value_string text, -value_bool boolean, -value_long bigint, -value_double double, -value_binary blob -); -`, - `CREATE TYPE IF NOT EXISTS jaeger_v1_dc1.log ( -ts bigint, -fields frozen>> -); -`, - `CREATE TABLE IF NOT EXISTS jaeger_v1_dc1.service_names ( -service_name text, -PRIMARY KEY (service_name) -) -WITH compaction = { -'min_threshold': '4', -'max_threshold': '32', -'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy' -} -AND default_time_to_live = 172800 -AND speculative_retry = 'NONE' -AND gc_grace_seconds = 10800; -`, - `CREATE TABLE IF NOT EXISTS jaeger_v1_dc1.dependencies_v2 ( -ts_bucket timestamp, -ts timestamp, -dependencies list>, -PRIMARY KEY (ts_bucket, ts) -) WITH CLUSTERING ORDER BY (ts DESC) -AND compaction = { -'min_threshold': '4', -'max_threshold': '32', -'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy' -} -AND default_time_to_live = 0; -`, - } - - assert.Equal(t, len(expOutputQueries), len(queryStrings)) - - for i := range expOutputQueries { - assert.Equal(t, expOutputQueries[i], queryStrings[i]) - } -} diff --git a/pkg/cassandra/config/v004-go-tmpl-test.cql.tmpl b/pkg/cassandra/config/v004-go-tmpl-test.cql.tmpl deleted file mode 100644 index d8192d0c2ed..00000000000 --- a/pkg/cassandra/config/v004-go-tmpl-test.cql.tmpl +++ /dev/null @@ -1,43 +0,0 @@ --- There are total 4 queries here - -CREATE TYPE IF NOT EXISTS {{.Keyspace}}.keyvalue ( - key text, - value_type text, - value_string text, - value_bool boolean, - value_long bigint, - value_double double, - value_binary blob -); - -CREATE TYPE IF NOT EXISTS {{.Keyspace}}.log ( - ts bigint, -- microseconds since epoch - fields frozen>> -); - -CREATE TABLE IF NOT EXISTS {{.Keyspace}}.service_names ( - service_name text, - PRIMARY KEY (service_name) -) - WITH compaction = { - 'min_threshold': '4', - 'max_threshold': '32', - 'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy' - } - AND default_time_to_live = {{.TraceTTL}} - AND speculative_retry = 'NONE' - AND gc_grace_seconds = 10800; -- 3 hours of downtime acceptable on nodes - --- compaction strategy is intentionally different as compared to other tables due to the size of dependencies data -CREATE TABLE IF NOT EXISTS {{.Keyspace}}.dependencies_v2 ( - ts_bucket timestamp, - ts timestamp, - dependencies list>, - PRIMARY KEY (ts_bucket, ts) -) WITH CLUSTERING ORDER BY (ts DESC) - AND compaction = { - 'min_threshold': '4', - 'max_threshold': '32', - 'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy' - } - AND default_time_to_live = {{.DependenciesTTL}}; \ No newline at end of file From 44c39dc9957a52f2db9e167bbb28ce87654a708a Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Wed, 20 Nov 2024 19:52:20 +0530 Subject: [PATCH 13/55] Updated fields with time.Duration type and added validators and tests Signed-off-by: Alok Kumar Singh --- pkg/cassandra/config/config.go | 35 ++++++--- pkg/cassandra/config/config_test.go | 16 ++++ pkg/cassandra/config/schema.go | 86 +++------------------- pkg/cassandra/config/v004-go-tmpl.cql.tmpl | 18 ++--- scripts/cassandra-integration-test.sh | 2 + 5 files changed, 63 insertions(+), 94 deletions(-) diff --git a/pkg/cassandra/config/config.go b/pkg/cassandra/config/config.go index 6c167493c69..e81df152a22 100644 --- a/pkg/cassandra/config/config.go +++ b/pkg/cassandra/config/config.go @@ -60,16 +60,16 @@ type Schema struct { DisableCompression bool `mapstructure:"disable_compression"` // Datacenter is the name for network topology Datacenter string `mapstructure:"datacenter" valid:"optional"` - // TraceTTL is Time To Live (TTL) for the trace data in seconds - TraceTTL int `mapstructure:"trace_ttl" valid:"optional"` - // DependenciesTTL is Time To Live (TTL) for dependencies data in seconds - DependenciesTTL int `mapstructure:"dependencies_ttl" valid:"optional"` + // TraceTTL is Time To Live (TTL) for the trace data + TraceTTL time.Duration `mapstructure:"trace_ttl" valid:"optional,cassandraTTLValidation"` + // DependenciesTTL is Time To Live (TTL) for dependencies data + DependenciesTTL time.Duration `mapstructure:"dependencies_ttl" valid:"optional,cassandraTTLValidation"` // Replication factor for the db ReplicationFactor int `mapstructure:"replication_factor" valid:"optional"` // CasVersion is version of cassandra used CasVersion int `mapstructure:"cas_version" valid:"optional"` // CompactionWindow of format "^[0-9]+[mhd]$" tells the compaction window of the db - CompactionWindow string `mapstructure:"compaction_window" valid:"optional"` + CompactionWindow time.Duration `mapstructure:"compaction_window" valid:"optional,isDurationGreaterThanOrEqualMinute"` } type Query struct { @@ -100,11 +100,11 @@ func DefaultConfiguration() Configuration { Schema: Schema{ Keyspace: "jaeger_v1_dc1", Datacenter: "test", - TraceTTL: 172800, - DependenciesTTL: 172800, + TraceTTL: 172800 * time.Second, + DependenciesTTL: 172800 * time.Second, ReplicationFactor: 1, CasVersion: 4, - CompactionWindow: "1m", + CompactionWindow: time.Minute, }, Connection: Connection{ Servers: []string{"127.0.0.1"}, @@ -145,7 +145,7 @@ func (c *Configuration) ApplyDefaults(source *Configuration) { c.Schema.CasVersion = source.Schema.CasVersion } - if c.Schema.CompactionWindow == "" { + if c.Schema.CompactionWindow == 0 { c.Schema.CompactionWindow = source.Schema.CompactionWindow } @@ -278,6 +278,23 @@ func (c *Configuration) String() string { } func (c *Configuration) Validate() error { + govalidator.CustomTypeTagMap.Set("cassandraTTLValidation", func(i interface{}, _ interface{}) bool { + duration, ok := i.(time.Duration) + if !ok { + return false + } + // Either set to no-expiry using 0 or if set should be greater than or equal to second + return duration == 0 || duration >= time.Second + }) + + govalidator.CustomTypeTagMap.Set("isDurationGreaterThanOrEqualMinute", func(i interface{}, _ interface{}) bool { + duration, ok := i.(time.Duration) + if !ok { + return false + } + return duration >= time.Minute + }) + _, err := govalidator.ValidateStruct(c) return err } diff --git a/pkg/cassandra/config/config_test.go b/pkg/cassandra/config/config_test.go index 8d532f65c60..3aedabf08b3 100644 --- a/pkg/cassandra/config/config_test.go +++ b/pkg/cassandra/config/config_test.go @@ -5,6 +5,7 @@ package config import ( "testing" + "time" "github.com/gocql/gocql" "github.com/stretchr/testify/assert" @@ -94,3 +95,18 @@ func TestToString(t *testing.T) { s := cfg.String() assert.Contains(t, s, "Keyspace:test") } + +func TestConfigSchemaValidation(t *testing.T) { + cfg := DefaultConfiguration() + err := cfg.Validate() + require.NoError(t, err) + + cfg.Schema.TraceTTL = time.Millisecond + err = cfg.Validate() + require.Error(t, err) + + cfg.Schema.TraceTTL = time.Second + cfg.Schema.CompactionWindow = time.Minute - 1 + err = cfg.Validate() + require.Error(t, err) +} diff --git a/pkg/cassandra/config/schema.go b/pkg/cassandra/config/schema.go index 329f37da39f..4756f27a9ea 100644 --- a/pkg/cassandra/config/schema.go +++ b/pkg/cassandra/config/schema.go @@ -8,9 +8,8 @@ import ( "embed" "errors" "fmt" - "regexp" - "strconv" "text/template" + "time" "github.com/jaegertracing/jaeger/pkg/cassandra" ) @@ -23,46 +22,13 @@ type TemplateParams struct { // Replication is the replication strategy used Replication string `mapstructure:"replication" valid:"optional"` // CompactionWindowSize is the numberical part of CompactionWindow. Extracted from CompactionWindow - CompactionWindowSize int `mapstructure:"compaction_window_size" valid:"optional"` + CompactionWindowInMinutes int64 `mapstructure:"compaction_window_size"` // CompactionWindowUnit is the time unit of the CompactionWindow. Extracted from CompactionWindow - CompactionWindowUnit string `mapstructure:"compaction_window_unit" valid:"optional"` -} - -func DefaultParams() TemplateParams { - return TemplateParams{ - Schema: Schema{ - Keyspace: "jaeger_v1_dc1", - Datacenter: "test", - TraceTTL: 172800, - DependenciesTTL: 0, - ReplicationFactor: 1, - CasVersion: 4, - }, - } -} + CompactionWindowUnit string `mapstructure:"compaction_window_unit"` -func applyDefaults(params *TemplateParams) { - defaultSchema := DefaultParams() + TraceTTLInSeconds int64 - if params.Keyspace == "" { - params.Keyspace = defaultSchema.Keyspace - } - - if params.Datacenter == "" { - params.Datacenter = defaultSchema.Datacenter - } - - if params.TraceTTL == 0 { - params.TraceTTL = defaultSchema.TraceTTL - } - - if params.ReplicationFactor == 0 { - params.ReplicationFactor = defaultSchema.ReplicationFactor - } - - if params.CasVersion == 0 { - params.CasVersion = 4 - } + DependenciesTTLInSeconds int64 } // Applies defaults for the configs and contructs other optional parameters from it @@ -70,44 +36,12 @@ func constructTemplateParams(cfg Schema) (TemplateParams, error) { params := TemplateParams{ Schema: cfg, } - applyDefaults(¶ms) params.Replication = fmt.Sprintf("{'class': 'NetworkTopologyStrategy', 'replication_factor': '%v' }", params.ReplicationFactor) - - if params.CompactionWindow != "" { - var err error - isMatch, err := regexp.MatchString("[0-9]+[mhd]", params.CompactionWindow) - if err != nil { - return TemplateParams{}, err - } - - if !isMatch { - return TemplateParams{}, fmt.Errorf("invalid compaction window size format: %s. Please use numeric value followed by 'm' for minutes, 'h' for hours, or 'd' for days", cfg.CompactionWindow) - } - - params.CompactionWindowSize, err = strconv.Atoi(params.CompactionWindow[0 : len(params.CompactionWindow)-1]) - if err != nil { - return TemplateParams{}, err - } - - params.CompactionWindowUnit = params.CompactionWindow[len(params.CompactionWindow)-1 : len(params.CompactionWindow)] - } else { - traceTTLMinutes := cfg.TraceTTL / 60 - - params.CompactionWindowSize = (traceTTLMinutes + 30 - 1) / 30 - params.CompactionWindowUnit = "m" - } - - switch params.CompactionWindowUnit { - case `m`: - params.CompactionWindowUnit = `MINUTES` - case `h`: - params.CompactionWindowUnit = `HOURS` - case `d`: - params.CompactionWindowUnit = `DAYS` - default: - return TemplateParams{}, errors.New("Invalid compaction window unit. If can be among {m|h|d}") - } + params.CompactionWindowInMinutes = int64(params.CompactionWindow / time.Minute) + params.CompactionWindowUnit = "MINUTES" + params.TraceTTLInSeconds = int64(params.TraceTTL / time.Second) + params.DependenciesTTLInSeconds = int64(params.DependenciesTTL / time.Second) return params, nil } @@ -160,7 +94,7 @@ func getQueriesFromBytes(queryFile []byte) ([]string, error) { } if len(queryString) > 0 { - return nil, errors.New(`Invalid template`) + return nil, errors.New(`invalid template`) } return queries, nil diff --git a/pkg/cassandra/config/v004-go-tmpl.cql.tmpl b/pkg/cassandra/config/v004-go-tmpl.cql.tmpl index 5a08e3f9dc0..0ef226b4891 100644 --- a/pkg/cassandra/config/v004-go-tmpl.cql.tmpl +++ b/pkg/cassandra/config/v004-go-tmpl.cql.tmpl @@ -45,11 +45,11 @@ CREATE TABLE IF NOT EXISTS {{.Keyspace}}.traces ( PRIMARY KEY (trace_id, span_id, span_hash) ) WITH compaction = { - 'compaction_window_size': '{{.CompactionWindowSize}}', + 'compaction_window_size': '{{.CompactionWindowInMinutes}}', 'compaction_window_unit': '{{.CompactionWindowUnit}}', 'class': 'org.apache.cassandra.db.compaction.TimeWindowCompactionStrategy' } - AND default_time_to_live = {{.TraceTTL}} + AND default_time_to_live = {{.TraceTTLInSeconds}} AND speculative_retry = 'NONE' AND gc_grace_seconds = 10800; -- 3 hours of downtime acceptable on nodes @@ -62,7 +62,7 @@ CREATE TABLE IF NOT EXISTS {{.Keyspace}}.service_names ( 'max_threshold': '32', 'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy' } - AND default_time_to_live = {{.TraceTTL}} + AND default_time_to_live = {{.TraceTTLInSeconds}} AND speculative_retry = 'NONE' AND gc_grace_seconds = 10800; -- 3 hours of downtime acceptable on nodes @@ -77,7 +77,7 @@ CREATE TABLE IF NOT EXISTS {{.Keyspace}}.operation_names_v2 ( 'max_threshold': '32', 'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy' } - AND default_time_to_live = {{.TraceTTL}} + AND default_time_to_live = {{.TraceTTLInSeconds}} AND speculative_retry = 'NONE' AND gc_grace_seconds = 10800; -- 3 hours of downtime acceptable on nodes @@ -94,7 +94,7 @@ CREATE TABLE IF NOT EXISTS {{.Keyspace}}.service_operation_index ( 'compaction_window_unit': 'HOURS', 'class': 'org.apache.cassandra.db.compaction.TimeWindowCompactionStrategy' } - AND default_time_to_live = {{.TraceTTL}} + AND default_time_to_live = {{.TraceTTLInSeconds}} AND speculative_retry = 'NONE' AND gc_grace_seconds = 10800; -- 3 hours of downtime acceptable on nodes @@ -110,7 +110,7 @@ CREATE TABLE IF NOT EXISTS {{.Keyspace}}.service_name_index ( 'compaction_window_unit': 'HOURS', 'class': 'org.apache.cassandra.db.compaction.TimeWindowCompactionStrategy' } - AND default_time_to_live = {{.TraceTTL}} + AND default_time_to_live = {{.TraceTTLInSeconds}} AND speculative_retry = 'NONE' AND gc_grace_seconds = 10800; -- 3 hours of downtime acceptable on nodes @@ -128,7 +128,7 @@ CREATE TABLE IF NOT EXISTS {{.Keyspace}}.duration_index ( 'compaction_window_unit': 'HOURS', 'class': 'org.apache.cassandra.db.compaction.TimeWindowCompactionStrategy' } - AND default_time_to_live = {{.TraceTTL}} + AND default_time_to_live = {{.TraceTTLInSeconds}} AND speculative_retry = 'NONE' AND gc_grace_seconds = 10800; -- 3 hours of downtime acceptable on nodes @@ -149,7 +149,7 @@ CREATE TABLE IF NOT EXISTS {{.Keyspace}}.tag_index ( 'compaction_window_unit': 'HOURS', 'class': 'org.apache.cassandra.db.compaction.TimeWindowCompactionStrategy' } - AND default_time_to_live = {{.TraceTTL}} + AND default_time_to_live = {{.TraceTTLInSeconds}} AND speculative_retry = 'NONE' AND gc_grace_seconds = 10800; -- 3 hours of downtime acceptable on nodes @@ -172,7 +172,7 @@ CREATE TABLE IF NOT EXISTS {{.Keyspace}}.dependencies_v2 ( 'max_threshold': '32', 'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy' } - AND default_time_to_live = {{.DependenciesTTL}}; + AND default_time_to_live = {{.DependenciesTTLInSeconds}}; -- adaptive sampling tables -- ./plugin/storage/cassandra/samplingstore/storage.go diff --git a/scripts/cassandra-integration-test.sh b/scripts/cassandra-integration-test.sh index 97597adcaf8..601d0f94871 100755 --- a/scripts/cassandra-integration-test.sh +++ b/scripts/cassandra-integration-test.sh @@ -113,6 +113,8 @@ run_integration_test() { healthcheck_cassandra "${major_version}" + read -n 1 + if [ "${SKIP_APPLY_SCHEMA}" = "false" ]; then apply_schema "$schema_version" "$primaryKeyspace" apply_schema "$schema_version" "$archiveKeyspace" From dfc0c437f9cfd3c135ce1542f685acc52cba5484 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Wed, 20 Nov 2024 19:53:54 +0530 Subject: [PATCH 14/55] minor changes in script Signed-off-by: Alok Kumar Singh --- scripts/cassandra-integration-test.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/cassandra-integration-test.sh b/scripts/cassandra-integration-test.sh index 601d0f94871..97597adcaf8 100755 --- a/scripts/cassandra-integration-test.sh +++ b/scripts/cassandra-integration-test.sh @@ -113,8 +113,6 @@ run_integration_test() { healthcheck_cassandra "${major_version}" - read -n 1 - if [ "${SKIP_APPLY_SCHEMA}" = "false" ]; then apply_schema "$schema_version" "$primaryKeyspace" apply_schema "$schema_version" "$archiveKeyspace" From cb8ae19114771471c8286649605c2db5f46df81a Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Wed, 20 Nov 2024 21:21:39 +0530 Subject: [PATCH 15/55] Addressed comments Signed-off-by: Alok Kumar Singh --- pkg/cassandra/config/config.go | 10 +++++----- pkg/cassandra/config/schema.go | 7 +++---- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/pkg/cassandra/config/config.go b/pkg/cassandra/config/config.go index e81df152a22..6532a3e90f0 100644 --- a/pkg/cassandra/config/config.go +++ b/pkg/cassandra/config/config.go @@ -60,15 +60,15 @@ type Schema struct { DisableCompression bool `mapstructure:"disable_compression"` // Datacenter is the name for network topology Datacenter string `mapstructure:"datacenter" valid:"optional"` - // TraceTTL is Time To Live (TTL) for the trace data + // TraceTTL is Time To Live (TTL) for the trace data. Should at least be 1 second TraceTTL time.Duration `mapstructure:"trace_ttl" valid:"optional,cassandraTTLValidation"` - // DependenciesTTL is Time To Live (TTL) for dependencies data + // DependenciesTTL is Time To Live (TTL) for dependencies data. Should at least be 1 second DependenciesTTL time.Duration `mapstructure:"dependencies_ttl" valid:"optional,cassandraTTLValidation"` // Replication factor for the db ReplicationFactor int `mapstructure:"replication_factor" valid:"optional"` // CasVersion is version of cassandra used CasVersion int `mapstructure:"cas_version" valid:"optional"` - // CompactionWindow of format "^[0-9]+[mhd]$" tells the compaction window of the db + // CompactionWindow of format tells the compaction window of the db. Should atleast be 1 minute CompactionWindow time.Duration `mapstructure:"compaction_window" valid:"optional,isDurationGreaterThanOrEqualMinute"` } @@ -100,8 +100,8 @@ func DefaultConfiguration() Configuration { Schema: Schema{ Keyspace: "jaeger_v1_dc1", Datacenter: "test", - TraceTTL: 172800 * time.Second, - DependenciesTTL: 172800 * time.Second, + TraceTTL: 2 * 24 * time.Hour, + DependenciesTTL: 2 * 24 * time.Hour, ReplicationFactor: 1, CasVersion: 4, CompactionWindow: time.Minute, diff --git a/pkg/cassandra/config/schema.go b/pkg/cassandra/config/schema.go index 4756f27a9ea..cd333399fd6 100644 --- a/pkg/cassandra/config/schema.go +++ b/pkg/cassandra/config/schema.go @@ -21,17 +21,16 @@ type TemplateParams struct { Schema // Replication is the replication strategy used Replication string `mapstructure:"replication" valid:"optional"` - // CompactionWindowSize is the numberical part of CompactionWindow. Extracted from CompactionWindow + // CompactionWindowInMinutes is constructed from CompactionWindow for using in template CompactionWindowInMinutes int64 `mapstructure:"compaction_window_size"` // CompactionWindowUnit is the time unit of the CompactionWindow. Extracted from CompactionWindow CompactionWindowUnit string `mapstructure:"compaction_window_unit"` - + // TraceTTLInSeconds is constructed from TraceTTL for using in template TraceTTLInSeconds int64 - + // DependenciesTTLInSeconds is constructed from DependenciesTTL for using in template DependenciesTTLInSeconds int64 } -// Applies defaults for the configs and contructs other optional parameters from it func constructTemplateParams(cfg Schema) (TemplateParams, error) { params := TemplateParams{ Schema: cfg, From c3d0fbdefc1f03a834f12c9c82d9ac1afc062c5d Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Thu, 21 Nov 2024 23:47:08 +0530 Subject: [PATCH 16/55] Addressed comments Signed-off-by: Alok Kumar Singh --- pkg/cassandra/config/config.go | 9 ++++++--- pkg/cassandra/config/schema.go | 9 +++------ pkg/cassandra/config/v004-go-tmpl.cql.tmpl | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pkg/cassandra/config/config.go b/pkg/cassandra/config/config.go index 6532a3e90f0..1f3824acf4d 100644 --- a/pkg/cassandra/config/config.go +++ b/pkg/cassandra/config/config.go @@ -58,6 +58,8 @@ type Schema struct { // while connecting to the Cassandra Cluster. This is useful for connecting to clusters, like Azure Cosmos DB, // that do not support SnappyCompression. DisableCompression bool `mapstructure:"disable_compression"` + // CreateSchema tells if the schema ahould be created during session initialization based on the configs provided + CreateSchema bool `mapstructure:"create" valid:"optional"` // Datacenter is the name for network topology Datacenter string `mapstructure:"datacenter" valid:"optional"` // TraceTTL is Time To Live (TTL) for the trace data. Should at least be 1 second @@ -98,6 +100,7 @@ type BasicAuthenticator struct { func DefaultConfiguration() Configuration { return Configuration{ Schema: Schema{ + CreateSchema: false, Keyspace: "jaeger_v1_dc1", Datacenter: "test", TraceTTL: 2 * 24 * time.Hour, @@ -178,10 +181,10 @@ type SessionBuilder interface { } func (c *Configuration) newSessionPrerequisites() error { - cluster, err := c.NewCluster() - if err != nil { - return err + if !c.Schema.CreateSchema { + return nil } + cluster, err := c.NewCluster() cluster.Keyspace = "" diff --git a/pkg/cassandra/config/schema.go b/pkg/cassandra/config/schema.go index cd333399fd6..73497572a37 100644 --- a/pkg/cassandra/config/schema.go +++ b/pkg/cassandra/config/schema.go @@ -19,12 +19,10 @@ var schemaFile embed.FS type TemplateParams struct { Schema - // Replication is the replication strategy used - Replication string `mapstructure:"replication" valid:"optional"` + // Replication is the replication strategy used. Ex: "{'class': 'NetworkTopologyStrategy', 'replication_factor': '1' }" + Replication string // CompactionWindowInMinutes is constructed from CompactionWindow for using in template - CompactionWindowInMinutes int64 `mapstructure:"compaction_window_size"` - // CompactionWindowUnit is the time unit of the CompactionWindow. Extracted from CompactionWindow - CompactionWindowUnit string `mapstructure:"compaction_window_unit"` + CompactionWindowInMinutes int64 // TraceTTLInSeconds is constructed from TraceTTL for using in template TraceTTLInSeconds int64 // DependenciesTTLInSeconds is constructed from DependenciesTTL for using in template @@ -38,7 +36,6 @@ func constructTemplateParams(cfg Schema) (TemplateParams, error) { params.Replication = fmt.Sprintf("{'class': 'NetworkTopologyStrategy', 'replication_factor': '%v' }", params.ReplicationFactor) params.CompactionWindowInMinutes = int64(params.CompactionWindow / time.Minute) - params.CompactionWindowUnit = "MINUTES" params.TraceTTLInSeconds = int64(params.TraceTTL / time.Second) params.DependenciesTTLInSeconds = int64(params.DependenciesTTL / time.Second) diff --git a/pkg/cassandra/config/v004-go-tmpl.cql.tmpl b/pkg/cassandra/config/v004-go-tmpl.cql.tmpl index 0ef226b4891..41ea7494274 100644 --- a/pkg/cassandra/config/v004-go-tmpl.cql.tmpl +++ b/pkg/cassandra/config/v004-go-tmpl.cql.tmpl @@ -46,7 +46,7 @@ CREATE TABLE IF NOT EXISTS {{.Keyspace}}.traces ( ) WITH compaction = { 'compaction_window_size': '{{.CompactionWindowInMinutes}}', - 'compaction_window_unit': '{{.CompactionWindowUnit}}', + 'compaction_window_unit': 'MINUTES', 'class': 'org.apache.cassandra.db.compaction.TimeWindowCompactionStrategy' } AND default_time_to_live = {{.TraceTTLInSeconds}} From 728a1399b73ef70d847596aaa15fa99c8b2f41c4 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh <62210712+akstron@users.noreply.github.com> Date: Thu, 21 Nov 2024 23:50:16 +0530 Subject: [PATCH 17/55] Update pkg/cassandra/config/schema.go Co-authored-by: Yuri Shkuro Signed-off-by: Alok Kumar Singh <62210712+akstron@users.noreply.github.com> --- pkg/cassandra/config/schema.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/cassandra/config/schema.go b/pkg/cassandra/config/schema.go index 73497572a37..25a2469d8d7 100644 --- a/pkg/cassandra/config/schema.go +++ b/pkg/cassandra/config/schema.go @@ -134,8 +134,7 @@ func GenerateSchemaIfNotPresent(session cassandra.Session, cfg *Schema) error { } for _, query := range casQueries { - err := query.Exec() - if err != nil { + if err := query.Exec(); err != nil { return err } } From 1b6683d1ab471d506e087115d42e85f4508e5f81 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh <62210712+akstron@users.noreply.github.com> Date: Thu, 21 Nov 2024 23:50:41 +0530 Subject: [PATCH 18/55] Update pkg/cassandra/config/config.go Co-authored-by: Yuri Shkuro Signed-off-by: Alok Kumar Singh <62210712+akstron@users.noreply.github.com> --- pkg/cassandra/config/config.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkg/cassandra/config/config.go b/pkg/cassandra/config/config.go index 1f3824acf4d..261add21b51 100644 --- a/pkg/cassandra/config/config.go +++ b/pkg/cassandra/config/config.go @@ -201,8 +201,7 @@ func (c *Configuration) newSessionPrerequisites() error { // NewSession creates a new Cassandra session func (c *Configuration) NewSession() (cassandra.Session, error) { - err := c.newSessionPrerequisites() - if err != nil { + if err := c.newSessionPrerequisites(); err != nil { return nil, err } From ce11cc1c447d178e5ac8423d9087db3b39728975 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Thu, 21 Nov 2024 23:51:47 +0530 Subject: [PATCH 19/55] Addressed comments Signed-off-by: Alok Kumar Singh --- pkg/cassandra/config/config.go | 2 +- pkg/cassandra/config/schema.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/cassandra/config/config.go b/pkg/cassandra/config/config.go index 261add21b51..7e139d9c39e 100644 --- a/pkg/cassandra/config/config.go +++ b/pkg/cassandra/config/config.go @@ -196,7 +196,7 @@ func (c *Configuration) newSessionPrerequisites() error { wSession := gocqlw.WrapCQLSession(session) defer wSession.Close() - return GenerateSchemaIfNotPresent(wSession, &c.Schema) + return generateSchemaIfNotPresent(wSession, &c.Schema) } // NewSession creates a new Cassandra session diff --git a/pkg/cassandra/config/schema.go b/pkg/cassandra/config/schema.go index 25a2469d8d7..2bad1bc0643 100644 --- a/pkg/cassandra/config/schema.go +++ b/pkg/cassandra/config/schema.go @@ -127,7 +127,7 @@ func contructSchemaQueries(session cassandra.Session, cfg *Schema) ([]cassandra. return casQueries, nil } -func GenerateSchemaIfNotPresent(session cassandra.Session, cfg *Schema) error { +func generateSchemaIfNotPresent(session cassandra.Session, cfg *Schema) error { casQueries, err := contructSchemaQueries(session, cfg) if err != nil { return err From de1c563395b768227ea7d70541a69dcfc68b2b86 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Thu, 21 Nov 2024 23:57:02 +0530 Subject: [PATCH 20/55] Removed unused CasVersion Signed-off-by: Alok Kumar Singh --- pkg/cassandra/config/config.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pkg/cassandra/config/config.go b/pkg/cassandra/config/config.go index 7e139d9c39e..07607cb2b25 100644 --- a/pkg/cassandra/config/config.go +++ b/pkg/cassandra/config/config.go @@ -68,8 +68,6 @@ type Schema struct { DependenciesTTL time.Duration `mapstructure:"dependencies_ttl" valid:"optional,cassandraTTLValidation"` // Replication factor for the db ReplicationFactor int `mapstructure:"replication_factor" valid:"optional"` - // CasVersion is version of cassandra used - CasVersion int `mapstructure:"cas_version" valid:"optional"` // CompactionWindow of format tells the compaction window of the db. Should atleast be 1 minute CompactionWindow time.Duration `mapstructure:"compaction_window" valid:"optional,isDurationGreaterThanOrEqualMinute"` } @@ -106,7 +104,6 @@ func DefaultConfiguration() Configuration { TraceTTL: 2 * 24 * time.Hour, DependenciesTTL: 2 * 24 * time.Hour, ReplicationFactor: 1, - CasVersion: 4, CompactionWindow: time.Minute, }, Connection: Connection{ @@ -144,10 +141,6 @@ func (c *Configuration) ApplyDefaults(source *Configuration) { c.Schema.ReplicationFactor = source.Schema.ReplicationFactor } - if c.Schema.CasVersion == 0 { - c.Schema.CasVersion = source.Schema.CasVersion - } - if c.Schema.CompactionWindow == 0 { c.Schema.CompactionWindow = source.Schema.CompactionWindow } From edabe22c134358c7fa6b43e89d40ab92f30c7774 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Fri, 22 Nov 2024 22:40:38 +0530 Subject: [PATCH 21/55] Addressed validation comments Signed-off-by: Alok Kumar Singh --- pkg/cassandra/config/config.go | 38 +++++++++++++++++----------------- pkg/cassandra/config/schema.go | 25 +++++++++------------- 2 files changed, 29 insertions(+), 34 deletions(-) diff --git a/pkg/cassandra/config/config.go b/pkg/cassandra/config/config.go index 07607cb2b25..3b75d66e1d8 100644 --- a/pkg/cassandra/config/config.go +++ b/pkg/cassandra/config/config.go @@ -6,6 +6,7 @@ package config import ( "context" + "errors" "fmt" "time" @@ -63,13 +64,13 @@ type Schema struct { // Datacenter is the name for network topology Datacenter string `mapstructure:"datacenter" valid:"optional"` // TraceTTL is Time To Live (TTL) for the trace data. Should at least be 1 second - TraceTTL time.Duration `mapstructure:"trace_ttl" valid:"optional,cassandraTTLValidation"` + TraceTTL time.Duration `mapstructure:"trace_ttl" valid:"optional"` // DependenciesTTL is Time To Live (TTL) for dependencies data. Should at least be 1 second - DependenciesTTL time.Duration `mapstructure:"dependencies_ttl" valid:"optional,cassandraTTLValidation"` + DependenciesTTL time.Duration `mapstructure:"dependencies_ttl" valid:"optional"` // Replication factor for the db ReplicationFactor int `mapstructure:"replication_factor" valid:"optional"` // CompactionWindow of format tells the compaction window of the db. Should atleast be 1 minute - CompactionWindow time.Duration `mapstructure:"compaction_window" valid:"optional,isDurationGreaterThanOrEqualMinute"` + CompactionWindow time.Duration `mapstructure:"compaction_window" valid:"optional"` } type Query struct { @@ -272,23 +273,22 @@ func (c *Configuration) String() string { return fmt.Sprintf("%+v", *c) } +func isValidTTL(duration time.Duration) bool { + return duration == 0 || duration >= time.Second +} + func (c *Configuration) Validate() error { - govalidator.CustomTypeTagMap.Set("cassandraTTLValidation", func(i interface{}, _ interface{}) bool { - duration, ok := i.(time.Duration) - if !ok { - return false - } - // Either set to no-expiry using 0 or if set should be greater than or equal to second - return duration == 0 || duration >= time.Second - }) - - govalidator.CustomTypeTagMap.Set("isDurationGreaterThanOrEqualMinute", func(i interface{}, _ interface{}) bool { - duration, ok := i.(time.Duration) - if !ok { - return false - } - return duration >= time.Minute - }) + if !isValidTTL(c.Schema.TraceTTL) { + return errors.New("trace_ttl can either be 0 or greater than or equal to 1 second") + } + + if !isValidTTL(c.Schema.DependenciesTTL) { + return errors.New("dependencies_ttl can either be 0 or greater than or equal to 1 second") + } + + if c.Schema.CompactionWindow < time.Minute { + return errors.New("compaction_window should at least be 1 minute") + } _, err := govalidator.ValidateStruct(c) return err diff --git a/pkg/cassandra/config/schema.go b/pkg/cassandra/config/schema.go index 2bad1bc0643..ecb9f459201 100644 --- a/pkg/cassandra/config/schema.go +++ b/pkg/cassandra/config/schema.go @@ -18,7 +18,8 @@ import ( var schemaFile embed.FS type TemplateParams struct { - Schema + // Keyspace in which tables and types will be created for storage + Keyspace string // Replication is the replication strategy used. Ex: "{'class': 'NetworkTopologyStrategy', 'replication_factor': '1' }" Replication string // CompactionWindowInMinutes is constructed from CompactionWindow for using in template @@ -29,17 +30,14 @@ type TemplateParams struct { DependenciesTTLInSeconds int64 } -func constructTemplateParams(cfg Schema) (TemplateParams, error) { - params := TemplateParams{ - Schema: cfg, +func constructTemplateParams(cfg Schema) TemplateParams { + return TemplateParams{ + Keyspace: cfg.Keyspace, + Replication: fmt.Sprintf("{'class': 'NetworkTopologyStrategy', 'replication_factor': '%v' }", cfg.ReplicationFactor), + CompactionWindowInMinutes: int64(cfg.CompactionWindow / time.Minute), + TraceTTLInSeconds: int64(cfg.TraceTTL / time.Second), + DependenciesTTLInSeconds: int64(cfg.DependenciesTTL / time.Second), } - - params.Replication = fmt.Sprintf("{'class': 'NetworkTopologyStrategy', 'replication_factor': '%v' }", params.ReplicationFactor) - params.CompactionWindowInMinutes = int64(params.CompactionWindow / time.Minute) - params.TraceTTLInSeconds = int64(params.TraceTTL / time.Second) - params.DependenciesTTLInSeconds = int64(params.DependenciesTTL / time.Second) - - return params, nil } func getQueryFileAsBytes(fileName string, params TemplateParams) ([]byte, error) { @@ -107,10 +105,7 @@ func getCassandraQueriesFromQueryStrings(session cassandra.Session, queries []st } func contructSchemaQueries(session cassandra.Session, cfg *Schema) ([]cassandra.Query, error) { - params, err := constructTemplateParams(*cfg) - if err != nil { - return nil, err - } + params := constructTemplateParams(*cfg) queryFile, err := getQueryFileAsBytes(`v004-go-tmpl.cql.tmpl`, params) if err != nil { From d0e197672a7d4a652f705c426b85c777c745d092 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Tue, 26 Nov 2024 21:51:23 +0530 Subject: [PATCH 22/55] Created helper function for session created and updated tests Signed-off-by: Alok Kumar Singh --- pkg/cassandra/config/config.go | 48 ++++++++++++++---------- plugin/storage/cassandra/factory_test.go | 12 +----- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/pkg/cassandra/config/config.go b/pkg/cassandra/config/config.go index 3b75d66e1d8..101d362c5eb 100644 --- a/pkg/cassandra/config/config.go +++ b/pkg/cassandra/config/config.go @@ -174,40 +174,44 @@ type SessionBuilder interface { NewSession() (cassandra.Session, error) } -func (c *Configuration) newSessionPrerequisites() error { +// createSession creates session from a configuration +func createSession(c *Configuration) (cassandra.Session, error) { + cluster, err := c.NewCluster() + if err != nil { + return nil, err + } + + session, err := cluster.CreateSession() + if err != nil { + return nil, err + } + + return gocqlw.WrapCQLSession(session), nil +} + +// newSessionPrerequisites creates tables and types before creating a session +func newSessionPrerequisites(c Configuration) error { if !c.Schema.CreateSchema { return nil } - cluster, err := c.NewCluster() - cluster.Keyspace = "" + c.Schema.Keyspace = "" - session, err := cluster.CreateSession() + session, err := createSession(&c) if err != nil { return err } - wSession := gocqlw.WrapCQLSession(session) - defer wSession.Close() - - return generateSchemaIfNotPresent(wSession, &c.Schema) + return generateSchemaIfNotPresent(session, &c.Schema) } // NewSession creates a new Cassandra session func (c *Configuration) NewSession() (cassandra.Session, error) { - if err := c.newSessionPrerequisites(); err != nil { + if err := newSessionPrerequisites(*c); err != nil { return nil, err } - cluster, err := c.NewCluster() - if err != nil { - return nil, err - } - session, err := cluster.CreateSession() - if err != nil { - return nil, err - } - return gocqlw.WrapCQLSession(session), nil + return createSession(c) } // NewCluster creates a new gocql cluster from the configuration @@ -278,6 +282,11 @@ func isValidTTL(duration time.Duration) bool { } func (c *Configuration) Validate() error { + _, err := govalidator.ValidateStruct(c) + if err != nil { + return err + } + if !isValidTTL(c.Schema.TraceTTL) { return errors.New("trace_ttl can either be 0 or greater than or equal to 1 second") } @@ -290,6 +299,5 @@ func (c *Configuration) Validate() error { return errors.New("compaction_window should at least be 1 minute") } - _, err := govalidator.ValidateStruct(c) - return err + return nil } diff --git a/plugin/storage/cassandra/factory_test.go b/plugin/storage/cassandra/factory_test.go index 9a2fcc486cf..aec6bdbd5d5 100644 --- a/plugin/storage/cassandra/factory_test.go +++ b/plugin/storage/cassandra/factory_test.go @@ -194,11 +194,7 @@ func TestNewFactoryWithConfig(t *testing.T) { t.Run("valid configuration", func(t *testing.T) { opts := &Options{ Primary: NamespaceConfig{ - Configuration: cassandraCfg.Configuration{ - Connection: cassandraCfg.Connection{ - Servers: []string{"localhost:9200"}, - }, - }, + Configuration: cassandraCfg.DefaultConfiguration(), }, } f := NewFactory() @@ -216,11 +212,7 @@ func TestNewFactoryWithConfig(t *testing.T) { expErr := errors.New("made-up error") opts := &Options{ Primary: NamespaceConfig{ - Configuration: cassandraCfg.Configuration{ - Connection: cassandraCfg.Connection{ - Servers: []string{"localhost:9200"}, - }, - }, + Configuration: cassandraCfg.DefaultConfiguration(), }, } f := NewFactory() From d8479b5ec9e2ed65425d27f64694356ecdef5de4 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Tue, 26 Nov 2024 22:40:21 +0530 Subject: [PATCH 23/55] Added schema unit tests Signed-off-by: Alok Kumar Singh --- pkg/cassandra/config/schema_test.go | 54 +++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 pkg/cassandra/config/schema_test.go diff --git a/pkg/cassandra/config/schema_test.go b/pkg/cassandra/config/schema_test.go new file mode 100644 index 00000000000..f3db1da4d71 --- /dev/null +++ b/pkg/cassandra/config/schema_test.go @@ -0,0 +1,54 @@ +package config + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestQueryGenerationFromBytes(t *testing.T) { + queriesAsString := ` +query1 -- comment (this should be removed) +query1-continue +query1-finished; -- + + +query2; +query-3 query-3-continue query-3-finished; +` + expGeneratedQueries := []string{`query1 +query1-continue +query1-finished; +`, + `query2; +`, + `query-3 query-3-continue query-3-finished; +`, + } + + queriesAsBytes := []byte(queriesAsString) + queries, err := getQueriesFromBytes(queriesAsBytes) + require.NoError(t, err) + + require.Equal(t, len(expGeneratedQueries), len(queries)) + + for i := range len(expGeneratedQueries) { + require.Equal(t, expGeneratedQueries[i], queries[i]) + } +} + +func TestInvalidQueryTemplate(t *testing.T) { + queriesAsString := ` + query1 -- comment (this should be removed) + query1-continue + query1-finished; -- + + + query2; + query-3 query-3-continue query-3-finished -- missing semicolon + ` + + queriesAsBytes := []byte(queriesAsString) + _, err := getQueriesFromBytes(queriesAsBytes) + require.ErrorContains(t, err, "invalid template") +} From 02b6159b15d32d433ecb3b17203f902c6e260c8e Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh <62210712+akstron@users.noreply.github.com> Date: Tue, 26 Nov 2024 22:40:57 +0530 Subject: [PATCH 24/55] Update pkg/cassandra/config/config.go Co-authored-by: Yuri Shkuro Signed-off-by: Alok Kumar Singh <62210712+akstron@users.noreply.github.com> --- pkg/cassandra/config/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cassandra/config/config.go b/pkg/cassandra/config/config.go index 101d362c5eb..25206b57a69 100644 --- a/pkg/cassandra/config/config.go +++ b/pkg/cassandra/config/config.go @@ -100,7 +100,7 @@ func DefaultConfiguration() Configuration { return Configuration{ Schema: Schema{ CreateSchema: false, - Keyspace: "jaeger_v1_dc1", + Keyspace: "jaeger_dc1", Datacenter: "test", TraceTTL: 2 * 24 * time.Hour, DependenciesTTL: 2 * 24 * time.Hour, From 73d276a9b26123d40a61e889e05b67fde5772a8a Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh <62210712+akstron@users.noreply.github.com> Date: Tue, 26 Nov 2024 22:41:07 +0530 Subject: [PATCH 25/55] Update pkg/cassandra/config/config.go Co-authored-by: Yuri Shkuro Signed-off-by: Alok Kumar Singh <62210712+akstron@users.noreply.github.com> --- pkg/cassandra/config/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cassandra/config/config.go b/pkg/cassandra/config/config.go index 25206b57a69..1229957c14d 100644 --- a/pkg/cassandra/config/config.go +++ b/pkg/cassandra/config/config.go @@ -101,7 +101,7 @@ func DefaultConfiguration() Configuration { Schema: Schema{ CreateSchema: false, Keyspace: "jaeger_dc1", - Datacenter: "test", + Datacenter: "dc1", TraceTTL: 2 * 24 * time.Hour, DependenciesTTL: 2 * 24 * time.Hour, ReplicationFactor: 1, From 57349a88f122d0624f71721b10057b79ce41b3f3 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh <62210712+akstron@users.noreply.github.com> Date: Tue, 26 Nov 2024 22:41:43 +0530 Subject: [PATCH 26/55] Update pkg/cassandra/config/config.go Co-authored-by: Yuri Shkuro Signed-off-by: Alok Kumar Singh <62210712+akstron@users.noreply.github.com> --- pkg/cassandra/config/config.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/cassandra/config/config.go b/pkg/cassandra/config/config.go index 1229957c14d..12ecc17c56d 100644 --- a/pkg/cassandra/config/config.go +++ b/pkg/cassandra/config/config.go @@ -190,7 +190,9 @@ func createSession(c *Configuration) (cassandra.Session, error) { } // newSessionPrerequisites creates tables and types before creating a session -func newSessionPrerequisites(c Configuration) error { +func (c *Configuration) newSessionPrerequisites() error { + cfg := *c // clone because we need to connect without specifying a keyspace + cfg.Schema.Keyspace = "" if !c.Schema.CreateSchema { return nil } From 84b52e1ebf2046528e33616adb47b87010304c47 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Tue, 26 Nov 2024 22:44:46 +0530 Subject: [PATCH 27/55] Fixed build Signed-off-by: Alok Kumar Singh --- pkg/cassandra/config/config.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/cassandra/config/config.go b/pkg/cassandra/config/config.go index 12ecc17c56d..e07b4c02ef0 100644 --- a/pkg/cassandra/config/config.go +++ b/pkg/cassandra/config/config.go @@ -191,15 +191,15 @@ func createSession(c *Configuration) (cassandra.Session, error) { // newSessionPrerequisites creates tables and types before creating a session func (c *Configuration) newSessionPrerequisites() error { - cfg := *c // clone because we need to connect without specifying a keyspace - cfg.Schema.Keyspace = "" + cfg := *c // clone because we need to connect without specifying a keyspace + cfg.Schema.Keyspace = "" if !c.Schema.CreateSchema { return nil } c.Schema.Keyspace = "" - session, err := createSession(&c) + session, err := createSession(c) if err != nil { return err } @@ -209,7 +209,7 @@ func (c *Configuration) newSessionPrerequisites() error { // NewSession creates a new Cassandra session func (c *Configuration) NewSession() (cassandra.Session, error) { - if err := newSessionPrerequisites(*c); err != nil { + if err := c.newSessionPrerequisites(); err != nil { return nil, err } From 9c2f05b42aed6bc5ce4156fba1d2a6d0f4ce21d3 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Tue, 26 Nov 2024 22:46:27 +0530 Subject: [PATCH 28/55] formatting fixes Signed-off-by: Alok Kumar Singh --- pkg/cassandra/config/schema_test.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/cassandra/config/schema_test.go b/pkg/cassandra/config/schema_test.go index f3db1da4d71..37560f3fb9c 100644 --- a/pkg/cassandra/config/schema_test.go +++ b/pkg/cassandra/config/schema_test.go @@ -16,7 +16,8 @@ query1-finished; -- query2; query-3 query-3-continue query-3-finished; ` - expGeneratedQueries := []string{`query1 + expGeneratedQueries := []string{ + `query1 query1-continue query1-finished; `, @@ -42,8 +43,8 @@ func TestInvalidQueryTemplate(t *testing.T) { query1 -- comment (this should be removed) query1-continue query1-finished; -- - - + + query2; query-3 query-3-continue query-3-finished -- missing semicolon ` From 2c8de884f73d97a99674a567e54fcf802c1f5861 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Wed, 27 Nov 2024 21:51:52 +0530 Subject: [PATCH 29/55] test fix Signed-off-by: Alok Kumar Singh --- pkg/cassandra/config/config_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/cassandra/config/config_test.go b/pkg/cassandra/config/config_test.go index 3aedabf08b3..3f218592916 100644 --- a/pkg/cassandra/config/config_test.go +++ b/pkg/cassandra/config/config_test.go @@ -44,6 +44,9 @@ func TestValidate_DoesNotReturnErrorWhenRequiredFieldsSet(t *testing.T) { Connection: Connection{ Servers: []string{"localhost:9200"}, }, + Schema: Schema{ + CompactionWindow: time.Minute, + }, } err := cfg.Validate() From eeb1951418ee846a1ee853016cddc54698487569 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Thu, 28 Nov 2024 21:31:22 +0530 Subject: [PATCH 30/55] Added test in workflow Signed-off-by: Alok Kumar Singh --- .github/workflows/ci-e2e-cassandra.yml | 3 + .../internal/integration/cassandra_test.go | 71 ++++++++++++++++++- pkg/cassandra/config/config.go | 9 ++- scripts/cassandra-integration-test.sh | 15 +--- 4 files changed, 78 insertions(+), 20 deletions(-) diff --git a/.github/workflows/ci-e2e-cassandra.yml b/.github/workflows/ci-e2e-cassandra.yml index 72a930156c9..23d81303ac4 100644 --- a/.github/workflows/ci-e2e-cassandra.yml +++ b/.github/workflows/ci-e2e-cassandra.yml @@ -22,6 +22,7 @@ jobs: fail-fast: false matrix: jaeger-version: [v1, v2] + skip-apply-schema: [true, false] version: - distribution: cassandra major: 4.x @@ -45,6 +46,8 @@ jobs: - name: Run cassandra integration tests id: test-execution run: bash scripts/cassandra-integration-test.sh ${{ matrix.version.major }} ${{ matrix.version.schema }} ${{ matrix.jaeger-version }} + env: + SKIP_APPLY_SCHEMA: ${{ matrix.skip-apply-schema }} - name: Upload coverage to codecov uses: ./.github/actions/upload-codecov diff --git a/cmd/jaeger/internal/integration/cassandra_test.go b/cmd/jaeger/internal/integration/cassandra_test.go index a78f66b3ec9..c56e552a96d 100644 --- a/cmd/jaeger/internal/integration/cassandra_test.go +++ b/cmd/jaeger/internal/integration/cassandra_test.go @@ -4,15 +4,84 @@ package integration import ( + "os" + "path/filepath" "testing" "github.com/jaegertracing/jaeger/plugin/storage/integration" + "github.com/stretchr/testify/require" + "gopkg.in/yaml.v3" ) +func addCreateSchemaConfig(t *testing.T, configFile string) string { + data, err := os.ReadFile(configFile) + require.NoError(t, err) + var config map[string]any + err = yaml.Unmarshal(data, &config) + require.NoError(t, err) + + extensionsAny, ok := config["extensions"] + require.True(t, ok) + + extensions, ok := extensionsAny.(map[string]any) + require.True(t, ok) + + jaegerStorageAny, ok := extensions["jaeger_storage"] + require.True(t, ok) + + jaegerStorage, ok := jaegerStorageAny.(map[string]any) + require.True(t, ok) + + backendsAny, ok := jaegerStorage["backends"] + require.True(t, ok) + + backends, ok := backendsAny.(map[string]any) + require.True(t, ok) + + for _, storageName := range []string{"some_storage", "another_storage"} { + storageAny, ok := backends[storageName] + require.True(t, ok) + + storage, ok := storageAny.(map[string]any) + require.True(t, ok) + + cassandraAny, ok := storage["cassandra"] + require.True(t, ok) + + cassandra, ok := cassandraAny.(map[string]any) + require.True(t, ok) + + schemaAny, ok := cassandra["schema"] + require.True(t, ok) + + schema, ok := schemaAny.(map[string]any) + require.True(t, ok) + + schema["create"] = true + } + + newData, err := yaml.Marshal(config) + require.NoError(t, err) + tempFile := filepath.Join(t.TempDir(), "config-cassandra.yaml") + err = os.WriteFile(tempFile, newData, 0o600) + require.NoError(t, err) + + t.Logf("Transformed configuration file %s to %s", configFile, tempFile) + return tempFile +} + func TestCassandraStorage(t *testing.T) { integration.SkipUnlessEnv(t, "cassandra") + + configFile := "../../config-cassandra.yaml" + + if os.Getenv("SKIP_APPLY_SCHEMA") == "true" { + // update config file with create = true, to allow schema creation on fly + configFile = addCreateSchemaConfig(t, configFile) + } + s := &E2EStorageIntegration{ - ConfigFile: "../../config-cassandra.yaml", + ConfigFile: configFile, StorageIntegration: integration.StorageIntegration{ CleanUp: purge, GetDependenciesReturnsSource: true, diff --git a/pkg/cassandra/config/config.go b/pkg/cassandra/config/config.go index e07b4c02ef0..2c861a6a436 100644 --- a/pkg/cassandra/config/config.go +++ b/pkg/cassandra/config/config.go @@ -191,20 +191,19 @@ func createSession(c *Configuration) (cassandra.Session, error) { // newSessionPrerequisites creates tables and types before creating a session func (c *Configuration) newSessionPrerequisites() error { - cfg := *c // clone because we need to connect without specifying a keyspace - cfg.Schema.Keyspace = "" if !c.Schema.CreateSchema { return nil } - c.Schema.Keyspace = "" + cfg := *c // clone because we need to connect without specifying a keyspace + cfg.Schema.Keyspace = "" - session, err := createSession(c) + session, err := createSession(&cfg) if err != nil { return err } - return generateSchemaIfNotPresent(session, &c.Schema) + return generateSchemaIfNotPresent(session, &cfg.Schema) } // NewSession creates a new Cassandra session diff --git a/scripts/cassandra-integration-test.sh b/scripts/cassandra-integration-test.sh index 97597adcaf8..40fd4b3b00f 100755 --- a/scripts/cassandra-integration-test.sh +++ b/scripts/cassandra-integration-test.sh @@ -11,20 +11,7 @@ success="false" timeout=600 end_time=$((SECONDS + timeout)) -SKIP_APPLY_SCHEMA="false" - -while getopts "s" opt; do - case "${opt}" in - s) - SKIP_APPLY_SCHEMA="true" - ;; - *) - ;; - esac -done - -# remove flags, leave only positional args -shift $((OPTIND - 1)) +SKIP_APPLY_SCHEMA=${SKIP_APPLY_SCHEMA:-"false"} usage() { echo $"Usage: $0 " From 601365dc66cb8e7cf9be0d9a2adec84dc00115c8 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Thu, 28 Nov 2024 21:32:27 +0530 Subject: [PATCH 31/55] fmt fixes Signed-off-by: Alok Kumar Singh --- cmd/jaeger/internal/integration/cassandra_test.go | 3 ++- pkg/cassandra/config/schema_test.go | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/cmd/jaeger/internal/integration/cassandra_test.go b/cmd/jaeger/internal/integration/cassandra_test.go index c56e552a96d..c851ef839af 100644 --- a/cmd/jaeger/internal/integration/cassandra_test.go +++ b/cmd/jaeger/internal/integration/cassandra_test.go @@ -8,9 +8,10 @@ import ( "path/filepath" "testing" - "github.com/jaegertracing/jaeger/plugin/storage/integration" "github.com/stretchr/testify/require" "gopkg.in/yaml.v3" + + "github.com/jaegertracing/jaeger/plugin/storage/integration" ) func addCreateSchemaConfig(t *testing.T, configFile string) string { diff --git a/pkg/cassandra/config/schema_test.go b/pkg/cassandra/config/schema_test.go index 37560f3fb9c..9b614a136aa 100644 --- a/pkg/cassandra/config/schema_test.go +++ b/pkg/cassandra/config/schema_test.go @@ -1,3 +1,6 @@ +// Copyright (c) 2024 The Jaeger Authors. +// SPDX-License-Identifier: Apache-2.0 + package config import ( From 4aeaad7738c70ee6e76b94d83c6717b291004d1e Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Thu, 28 Nov 2024 21:46:20 +0530 Subject: [PATCH 32/55] create schema bug fix Signed-off-by: Alok Kumar Singh --- pkg/cassandra/config/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cassandra/config/config.go b/pkg/cassandra/config/config.go index 2c861a6a436..0af10d76739 100644 --- a/pkg/cassandra/config/config.go +++ b/pkg/cassandra/config/config.go @@ -203,7 +203,7 @@ func (c *Configuration) newSessionPrerequisites() error { return err } - return generateSchemaIfNotPresent(session, &cfg.Schema) + return generateSchemaIfNotPresent(session, &c.Schema) } // NewSession creates a new Cassandra session From 0167cb6ffdf31c7abbe2d09dae767921b40c7b35 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Thu, 28 Nov 2024 22:20:02 +0530 Subject: [PATCH 33/55] exclude v1 run with skip-apply-schema as true Signed-off-by: Alok Kumar Singh --- .github/workflows/ci-e2e-cassandra.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci-e2e-cassandra.yml b/.github/workflows/ci-e2e-cassandra.yml index 23d81303ac4..4b50c269e64 100644 --- a/.github/workflows/ci-e2e-cassandra.yml +++ b/.github/workflows/ci-e2e-cassandra.yml @@ -30,6 +30,9 @@ jobs: - distribution: cassandra major: 5.x schema: v004 + exclude: + - jaeger-version: v1 + skip-apply-schema: true name: ${{ matrix.version.distribution }} ${{ matrix.version.major }} ${{ matrix.jaeger-version }} steps: - name: Harden Runner From 07b99da5fa389e2bd12623b8560454883fb8ce1e Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Thu, 28 Nov 2024 22:37:03 +0530 Subject: [PATCH 34/55] Added schemaCreator and comments in workflow Signed-off-by: Alok Kumar Singh --- .github/workflows/ci-e2e-cassandra.yml | 1 + pkg/cassandra/config/config.go | 7 +++- pkg/cassandra/config/schema.go | 45 +++++++++++++++----------- pkg/cassandra/config/schema_test.go | 7 ++-- 4 files changed, 37 insertions(+), 23 deletions(-) diff --git a/.github/workflows/ci-e2e-cassandra.yml b/.github/workflows/ci-e2e-cassandra.yml index 4b50c269e64..d80bbed256e 100644 --- a/.github/workflows/ci-e2e-cassandra.yml +++ b/.github/workflows/ci-e2e-cassandra.yml @@ -31,6 +31,7 @@ jobs: major: 5.x schema: v004 exclude: + # Exclude v1 as create schema on fly is available for v2 only - jaeger-version: v1 skip-apply-schema: true name: ${{ matrix.version.distribution }} ${{ matrix.version.major }} ${{ matrix.jaeger-version }} diff --git a/pkg/cassandra/config/config.go b/pkg/cassandra/config/config.go index 0af10d76739..fa6d6b3b274 100644 --- a/pkg/cassandra/config/config.go +++ b/pkg/cassandra/config/config.go @@ -203,7 +203,12 @@ func (c *Configuration) newSessionPrerequisites() error { return err } - return generateSchemaIfNotPresent(session, &c.Schema) + sc := schemaCreator{ + session: session, + schema: c.Schema, + } + + return sc.createSchemaIfNotPresent() } // NewSession creates a new Cassandra session diff --git a/pkg/cassandra/config/schema.go b/pkg/cassandra/config/schema.go index ecb9f459201..34dc7df305e 100644 --- a/pkg/cassandra/config/schema.go +++ b/pkg/cassandra/config/schema.go @@ -30,17 +30,22 @@ type TemplateParams struct { DependenciesTTLInSeconds int64 } -func constructTemplateParams(cfg Schema) TemplateParams { +type schemaCreator struct { + session cassandra.Session + schema Schema +} + +func (sc *schemaCreator) constructTemplateParams() TemplateParams { return TemplateParams{ - Keyspace: cfg.Keyspace, - Replication: fmt.Sprintf("{'class': 'NetworkTopologyStrategy', 'replication_factor': '%v' }", cfg.ReplicationFactor), - CompactionWindowInMinutes: int64(cfg.CompactionWindow / time.Minute), - TraceTTLInSeconds: int64(cfg.TraceTTL / time.Second), - DependenciesTTLInSeconds: int64(cfg.DependenciesTTL / time.Second), + Keyspace: sc.schema.Keyspace, + Replication: fmt.Sprintf("{'class': 'NetworkTopologyStrategy', 'replication_factor': '%v' }", sc.schema.ReplicationFactor), + CompactionWindowInMinutes: int64(sc.schema.CompactionWindow / time.Minute), + TraceTTLInSeconds: int64(sc.schema.TraceTTL / time.Second), + DependenciesTTLInSeconds: int64(sc.schema.DependenciesTTL / time.Second), } } -func getQueryFileAsBytes(fileName string, params TemplateParams) ([]byte, error) { +func (sc *schemaCreator) getQueryFileAsBytes(fileName string, params TemplateParams) ([]byte, error) { tmpl, err := template.ParseFS(schemaFile, fileName) if err != nil { return nil, err @@ -55,7 +60,7 @@ func getQueryFileAsBytes(fileName string, params TemplateParams) ([]byte, error) return result.Bytes(), nil } -func getQueriesFromBytes(queryFile []byte) ([]string, error) { +func (sc *schemaCreator) getQueriesFromBytes(queryFile []byte) ([]string, error) { lines := bytes.Split(queryFile, []byte("\n")) var extractedLines [][]byte @@ -68,11 +73,13 @@ func getQueriesFromBytes(queryFile []byte) ([]string, error) { line = line[0:commentIndex] } - if len(line) == 0 { + trimmedLine := bytes.TrimSpace(line) + + if len(trimmedLine) == 0 { continue } - extractedLines = append(extractedLines, bytes.TrimSpace(line)) + extractedLines = append(extractedLines, trimmedLine) } var queries []string @@ -94,36 +101,36 @@ func getQueriesFromBytes(queryFile []byte) ([]string, error) { return queries, nil } -func getCassandraQueriesFromQueryStrings(session cassandra.Session, queries []string) []cassandra.Query { +func (sc *schemaCreator) getCassandraQueriesFromQueryStrings(queries []string) []cassandra.Query { var casQueries []cassandra.Query for _, query := range queries { - casQueries = append(casQueries, session.Query(query)) + casQueries = append(casQueries, sc.session.Query(query)) } return casQueries } -func contructSchemaQueries(session cassandra.Session, cfg *Schema) ([]cassandra.Query, error) { - params := constructTemplateParams(*cfg) +func (sc *schemaCreator) contructSchemaQueries() ([]cassandra.Query, error) { + params := sc.constructTemplateParams() - queryFile, err := getQueryFileAsBytes(`v004-go-tmpl.cql.tmpl`, params) + queryFile, err := sc.getQueryFileAsBytes(`v004-go-tmpl.cql.tmpl`, params) if err != nil { return nil, err } - queryStrings, err := getQueriesFromBytes(queryFile) + queryStrings, err := sc.getQueriesFromBytes(queryFile) if err != nil { return nil, err } - casQueries := getCassandraQueriesFromQueryStrings(session, queryStrings) + casQueries := sc.getCassandraQueriesFromQueryStrings(queryStrings) return casQueries, nil } -func generateSchemaIfNotPresent(session cassandra.Session, cfg *Schema) error { - casQueries, err := contructSchemaQueries(session, cfg) +func (sc *schemaCreator) createSchemaIfNotPresent() error { + casQueries, err := sc.contructSchemaQueries() if err != nil { return err } diff --git a/pkg/cassandra/config/schema_test.go b/pkg/cassandra/config/schema_test.go index 9b614a136aa..b5bebb06e5d 100644 --- a/pkg/cassandra/config/schema_test.go +++ b/pkg/cassandra/config/schema_test.go @@ -30,8 +30,9 @@ query1-finished; `, } + sc := schemaCreator{} queriesAsBytes := []byte(queriesAsString) - queries, err := getQueriesFromBytes(queriesAsBytes) + queries, err := sc.getQueriesFromBytes(queriesAsBytes) require.NoError(t, err) require.Equal(t, len(expGeneratedQueries), len(queries)) @@ -51,8 +52,8 @@ func TestInvalidQueryTemplate(t *testing.T) { query2; query-3 query-3-continue query-3-finished -- missing semicolon ` - + sc := schemaCreator{} queriesAsBytes := []byte(queriesAsString) - _, err := getQueriesFromBytes(queriesAsBytes) + _, err := sc.getQueriesFromBytes(queriesAsBytes) require.ErrorContains(t, err, "invalid template") } From 04ec76fd49b28b2a4c21eade6bd550a3fd17ccb9 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Thu, 28 Nov 2024 23:22:30 +0530 Subject: [PATCH 35/55] ci changes Signed-off-by: Alok Kumar Singh --- .github/workflows/ci-e2e-cassandra.yml | 2 +- cmd/jaeger/config-cassandra.yaml | 2 + .../internal/integration/cassandra_test.go | 71 +------------------ 3 files changed, 4 insertions(+), 71 deletions(-) diff --git a/.github/workflows/ci-e2e-cassandra.yml b/.github/workflows/ci-e2e-cassandra.yml index d80bbed256e..fd38e9603ac 100644 --- a/.github/workflows/ci-e2e-cassandra.yml +++ b/.github/workflows/ci-e2e-cassandra.yml @@ -34,7 +34,7 @@ jobs: # Exclude v1 as create schema on fly is available for v2 only - jaeger-version: v1 skip-apply-schema: true - name: ${{ matrix.version.distribution }} ${{ matrix.version.major }} ${{ matrix.jaeger-version }} + name: ${{ matrix.version.distribution }} ${{ matrix.version.major }} ${{ matrix.jaeger-version }} ${{ matrix.skip-apply-schema == 'true' && 'auto' || 'manual' }} steps: - name: Harden Runner uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 diff --git a/cmd/jaeger/config-cassandra.yaml b/cmd/jaeger/config-cassandra.yaml index 3ead38258c2..2e262ee883e 100644 --- a/cmd/jaeger/config-cassandra.yaml +++ b/cmd/jaeger/config-cassandra.yaml @@ -34,6 +34,7 @@ extensions: cassandra: schema: keyspace: "jaeger_v1_dc1" + create: "${env:SKIP_APPLY_SCHEMA:-false}" connection: auth: basic: @@ -45,6 +46,7 @@ extensions: cassandra: schema: keyspace: "jaeger_v1_dc1" + create: "${env:SKIP_APPLY_SCHEMA:-false}" connection: auth: basic: diff --git a/cmd/jaeger/internal/integration/cassandra_test.go b/cmd/jaeger/internal/integration/cassandra_test.go index c851ef839af..1492561eff8 100644 --- a/cmd/jaeger/internal/integration/cassandra_test.go +++ b/cmd/jaeger/internal/integration/cassandra_test.go @@ -4,85 +4,16 @@ package integration import ( - "os" - "path/filepath" "testing" - "github.com/stretchr/testify/require" - "gopkg.in/yaml.v3" - "github.com/jaegertracing/jaeger/plugin/storage/integration" ) -func addCreateSchemaConfig(t *testing.T, configFile string) string { - data, err := os.ReadFile(configFile) - require.NoError(t, err) - var config map[string]any - err = yaml.Unmarshal(data, &config) - require.NoError(t, err) - - extensionsAny, ok := config["extensions"] - require.True(t, ok) - - extensions, ok := extensionsAny.(map[string]any) - require.True(t, ok) - - jaegerStorageAny, ok := extensions["jaeger_storage"] - require.True(t, ok) - - jaegerStorage, ok := jaegerStorageAny.(map[string]any) - require.True(t, ok) - - backendsAny, ok := jaegerStorage["backends"] - require.True(t, ok) - - backends, ok := backendsAny.(map[string]any) - require.True(t, ok) - - for _, storageName := range []string{"some_storage", "another_storage"} { - storageAny, ok := backends[storageName] - require.True(t, ok) - - storage, ok := storageAny.(map[string]any) - require.True(t, ok) - - cassandraAny, ok := storage["cassandra"] - require.True(t, ok) - - cassandra, ok := cassandraAny.(map[string]any) - require.True(t, ok) - - schemaAny, ok := cassandra["schema"] - require.True(t, ok) - - schema, ok := schemaAny.(map[string]any) - require.True(t, ok) - - schema["create"] = true - } - - newData, err := yaml.Marshal(config) - require.NoError(t, err) - tempFile := filepath.Join(t.TempDir(), "config-cassandra.yaml") - err = os.WriteFile(tempFile, newData, 0o600) - require.NoError(t, err) - - t.Logf("Transformed configuration file %s to %s", configFile, tempFile) - return tempFile -} - func TestCassandraStorage(t *testing.T) { integration.SkipUnlessEnv(t, "cassandra") - configFile := "../../config-cassandra.yaml" - - if os.Getenv("SKIP_APPLY_SCHEMA") == "true" { - // update config file with create = true, to allow schema creation on fly - configFile = addCreateSchemaConfig(t, configFile) - } - s := &E2EStorageIntegration{ - ConfigFile: configFile, + ConfigFile: "../../config-cassandra.yaml", StorageIntegration: integration.StorageIntegration{ CleanUp: purge, GetDependenciesReturnsSource: true, From 72464946f1c6225572a04c1681be8f5a68c74261 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Thu, 28 Nov 2024 23:25:00 +0530 Subject: [PATCH 36/55] made template params private Signed-off-by: Alok Kumar Singh --- pkg/cassandra/config/schema.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/cassandra/config/schema.go b/pkg/cassandra/config/schema.go index 34dc7df305e..77776c9946d 100644 --- a/pkg/cassandra/config/schema.go +++ b/pkg/cassandra/config/schema.go @@ -17,7 +17,7 @@ import ( //go:embed v004-go-tmpl.cql.tmpl var schemaFile embed.FS -type TemplateParams struct { +type templateParams struct { // Keyspace in which tables and types will be created for storage Keyspace string // Replication is the replication strategy used. Ex: "{'class': 'NetworkTopologyStrategy', 'replication_factor': '1' }" @@ -35,8 +35,8 @@ type schemaCreator struct { schema Schema } -func (sc *schemaCreator) constructTemplateParams() TemplateParams { - return TemplateParams{ +func (sc *schemaCreator) constructTemplateParams() templateParams { + return templateParams{ Keyspace: sc.schema.Keyspace, Replication: fmt.Sprintf("{'class': 'NetworkTopologyStrategy', 'replication_factor': '%v' }", sc.schema.ReplicationFactor), CompactionWindowInMinutes: int64(sc.schema.CompactionWindow / time.Minute), @@ -45,7 +45,7 @@ func (sc *schemaCreator) constructTemplateParams() TemplateParams { } } -func (sc *schemaCreator) getQueryFileAsBytes(fileName string, params TemplateParams) ([]byte, error) { +func (sc *schemaCreator) getQueryFileAsBytes(fileName string, params templateParams) ([]byte, error) { tmpl, err := template.ParseFS(schemaFile, fileName) if err != nil { return nil, err From d8613f1ec5cb34affd830c155c14b6c28a30eecb Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Thu, 28 Nov 2024 23:37:22 +0530 Subject: [PATCH 37/55] workflow fix Signed-off-by: Alok Kumar Singh --- .github/workflows/ci-e2e-cassandra.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-e2e-cassandra.yml b/.github/workflows/ci-e2e-cassandra.yml index fd38e9603ac..64783732065 100644 --- a/.github/workflows/ci-e2e-cassandra.yml +++ b/.github/workflows/ci-e2e-cassandra.yml @@ -34,7 +34,7 @@ jobs: # Exclude v1 as create schema on fly is available for v2 only - jaeger-version: v1 skip-apply-schema: true - name: ${{ matrix.version.distribution }} ${{ matrix.version.major }} ${{ matrix.jaeger-version }} ${{ matrix.skip-apply-schema == 'true' && 'auto' || 'manual' }} + name: ${{ matrix.version.distribution }} ${{ matrix.version.major }} ${{ matrix.jaeger-version }} ${{ matrix.skip-apply-schema == true && 'auto' || 'manual' }} steps: - name: Harden Runner uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 From a7853ec2a49a97e1531d0a91f32a8bf9408ca589 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Fri, 29 Nov 2024 21:41:09 +0530 Subject: [PATCH 38/55] Changed env variable name Signed-off-by: Alok Kumar Singh --- .github/workflows/ci-e2e-cassandra.yml | 2 +- cmd/jaeger/config-cassandra.yaml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-e2e-cassandra.yml b/.github/workflows/ci-e2e-cassandra.yml index 64783732065..bc3392e3846 100644 --- a/.github/workflows/ci-e2e-cassandra.yml +++ b/.github/workflows/ci-e2e-cassandra.yml @@ -51,7 +51,7 @@ jobs: id: test-execution run: bash scripts/cassandra-integration-test.sh ${{ matrix.version.major }} ${{ matrix.version.schema }} ${{ matrix.jaeger-version }} env: - SKIP_APPLY_SCHEMA: ${{ matrix.skip-apply-schema }} + CASSANDRA_CREATE_SCHEMA: ${{ matrix.skip-apply-schema }} - name: Upload coverage to codecov uses: ./.github/actions/upload-codecov diff --git a/cmd/jaeger/config-cassandra.yaml b/cmd/jaeger/config-cassandra.yaml index 2e262ee883e..afa89163f6b 100644 --- a/cmd/jaeger/config-cassandra.yaml +++ b/cmd/jaeger/config-cassandra.yaml @@ -34,7 +34,7 @@ extensions: cassandra: schema: keyspace: "jaeger_v1_dc1" - create: "${env:SKIP_APPLY_SCHEMA:-false}" + create: "${env:CASSANDRA_CREATE_SCHEMA:-false}" connection: auth: basic: @@ -45,8 +45,8 @@ extensions: another_storage: cassandra: schema: - keyspace: "jaeger_v1_dc1" - create: "${env:SKIP_APPLY_SCHEMA:-false}" + keyspace: "jaeger_archive_v1_dc1" + create: "${env:CASSANDRA_CREATE_SCHEMA:-false}" connection: auth: basic: From 10bd9aa2ba980c6ae2739a2ed9846c823227f950 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Fri, 29 Nov 2024 21:42:54 +0530 Subject: [PATCH 39/55] lint fixes Signed-off-by: Alok Kumar Singh --- pkg/cassandra/config/schema.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/cassandra/config/schema.go b/pkg/cassandra/config/schema.go index 77776c9946d..fe7a28d5c55 100644 --- a/pkg/cassandra/config/schema.go +++ b/pkg/cassandra/config/schema.go @@ -45,7 +45,7 @@ func (sc *schemaCreator) constructTemplateParams() templateParams { } } -func (sc *schemaCreator) getQueryFileAsBytes(fileName string, params templateParams) ([]byte, error) { +func (_ *schemaCreator) getQueryFileAsBytes(fileName string, params templateParams) ([]byte, error) { tmpl, err := template.ParseFS(schemaFile, fileName) if err != nil { return nil, err @@ -60,7 +60,7 @@ func (sc *schemaCreator) getQueryFileAsBytes(fileName string, params templatePar return result.Bytes(), nil } -func (sc *schemaCreator) getQueriesFromBytes(queryFile []byte) ([]string, error) { +func (_ *schemaCreator) getQueriesFromBytes(queryFile []byte) ([]string, error) { lines := bytes.Split(queryFile, []byte("\n")) var extractedLines [][]byte From a682db2ef558368ce5136cb8e938c55e42a9e246 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Fri, 29 Nov 2024 21:52:53 +0530 Subject: [PATCH 40/55] lint fix Signed-off-by: Alok Kumar Singh --- pkg/cassandra/config/schema.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/cassandra/config/schema.go b/pkg/cassandra/config/schema.go index fe7a28d5c55..b0e69f35bc6 100644 --- a/pkg/cassandra/config/schema.go +++ b/pkg/cassandra/config/schema.go @@ -45,7 +45,7 @@ func (sc *schemaCreator) constructTemplateParams() templateParams { } } -func (_ *schemaCreator) getQueryFileAsBytes(fileName string, params templateParams) ([]byte, error) { +func (*schemaCreator) getQueryFileAsBytes(fileName string, params templateParams) ([]byte, error) { tmpl, err := template.ParseFS(schemaFile, fileName) if err != nil { return nil, err @@ -60,7 +60,7 @@ func (_ *schemaCreator) getQueryFileAsBytes(fileName string, params templatePara return result.Bytes(), nil } -func (_ *schemaCreator) getQueriesFromBytes(queryFile []byte) ([]string, error) { +func (*schemaCreator) getQueriesFromBytes(queryFile []byte) ([]string, error) { lines := bytes.Split(queryFile, []byte("\n")) var extractedLines [][]byte From 35c26b50464e31845441230b4ec04da55b10e51e Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Fri, 29 Nov 2024 22:11:29 +0530 Subject: [PATCH 41/55] test fix Signed-off-by: Alok Kumar Singh --- cmd/jaeger/config-cassandra.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/jaeger/config-cassandra.yaml b/cmd/jaeger/config-cassandra.yaml index afa89163f6b..519b9888c06 100644 --- a/cmd/jaeger/config-cassandra.yaml +++ b/cmd/jaeger/config-cassandra.yaml @@ -45,7 +45,7 @@ extensions: another_storage: cassandra: schema: - keyspace: "jaeger_archive_v1_dc1" + keyspace: "jaeger_v1_dc1_archive" create: "${env:CASSANDRA_CREATE_SCHEMA:-false}" connection: auth: From ddf4fc09f80c68077a7fa2b900794f3203eba460 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Sat, 30 Nov 2024 00:07:58 +0530 Subject: [PATCH 42/55] Workflow and test minor changes Signed-off-by: Alok Kumar Singh --- .github/workflows/ci-e2e-cassandra.yml | 7 ++++--- pkg/cassandra/config/config_test.go | 5 +++++ pkg/cassandra/config/schema.go | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-e2e-cassandra.yml b/.github/workflows/ci-e2e-cassandra.yml index bc3392e3846..ff35450fe83 100644 --- a/.github/workflows/ci-e2e-cassandra.yml +++ b/.github/workflows/ci-e2e-cassandra.yml @@ -22,7 +22,7 @@ jobs: fail-fast: false matrix: jaeger-version: [v1, v2] - skip-apply-schema: [true, false] + create-schema: [manual, auto] version: - distribution: cassandra major: 4.x @@ -34,7 +34,7 @@ jobs: # Exclude v1 as create schema on fly is available for v2 only - jaeger-version: v1 skip-apply-schema: true - name: ${{ matrix.version.distribution }} ${{ matrix.version.major }} ${{ matrix.jaeger-version }} ${{ matrix.skip-apply-schema == true && 'auto' || 'manual' }} + name: ${{ matrix.version.distribution }} ${{ matrix.version.major }} ${{ matrix.jaeger-version }} ${{ matrix.create-schema }} steps: - name: Harden Runner uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 @@ -51,7 +51,8 @@ jobs: id: test-execution run: bash scripts/cassandra-integration-test.sh ${{ matrix.version.major }} ${{ matrix.version.schema }} ${{ matrix.jaeger-version }} env: - CASSANDRA_CREATE_SCHEMA: ${{ matrix.skip-apply-schema }} + CASSANDRA_CREATE_SCHEMA: ${{ matrix.create-schema == 'auto' && true || false }} + SKIP_APPLY_SCHEMA: ${{ matrix.create-schema == 'auto' && true || false }} - name: Upload coverage to codecov uses: ./.github/actions/upload-codecov diff --git a/pkg/cassandra/config/config_test.go b/pkg/cassandra/config/config_test.go index 3f218592916..f1de4f6d55b 100644 --- a/pkg/cassandra/config/config_test.go +++ b/pkg/cassandra/config/config_test.go @@ -112,4 +112,9 @@ func TestConfigSchemaValidation(t *testing.T) { cfg.Schema.CompactionWindow = time.Minute - 1 err = cfg.Validate() require.Error(t, err) + + cfg.Schema.CompactionWindow = time.Minute + cfg.Schema.DependenciesTTL = time.Second - 1 + err = cfg.Validate() + require.Error(t, err) } diff --git a/pkg/cassandra/config/schema.go b/pkg/cassandra/config/schema.go index b0e69f35bc6..902667bcd36 100644 --- a/pkg/cassandra/config/schema.go +++ b/pkg/cassandra/config/schema.go @@ -95,7 +95,7 @@ func (*schemaCreator) getQueriesFromBytes(queryFile []byte) ([]string, error) { } if len(queryString) > 0 { - return nil, errors.New(`invalid template`) + return nil, errors.New(`query exists in template without ";"`) } return queries, nil From bbf3ac8876705a50b3c3ed167d84040349b9143a Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Sat, 30 Nov 2024 15:06:11 +0530 Subject: [PATCH 43/55] test fix Signed-off-by: Alok Kumar Singh --- pkg/cassandra/config/schema_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/cassandra/config/schema_test.go b/pkg/cassandra/config/schema_test.go index b5bebb06e5d..f43dda21724 100644 --- a/pkg/cassandra/config/schema_test.go +++ b/pkg/cassandra/config/schema_test.go @@ -55,5 +55,5 @@ func TestInvalidQueryTemplate(t *testing.T) { sc := schemaCreator{} queriesAsBytes := []byte(queriesAsString) _, err := sc.getQueriesFromBytes(queriesAsBytes) - require.ErrorContains(t, err, "invalid template") + require.Error(t, err) } From a8e3aaea1ee69d3b455aa1edebadecacf88c47e6 Mon Sep 17 00:00:00 2001 From: Alok Kumar Singh Date: Sat, 30 Nov 2024 15:09:35 +0530 Subject: [PATCH 44/55] workflow changes Signed-off-by: Alok Kumar Singh --- .github/workflows/ci-e2e-cassandra.yml | 1 - scripts/cassandra-integration-test.sh | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-e2e-cassandra.yml b/.github/workflows/ci-e2e-cassandra.yml index ff35450fe83..66026c93392 100644 --- a/.github/workflows/ci-e2e-cassandra.yml +++ b/.github/workflows/ci-e2e-cassandra.yml @@ -51,7 +51,6 @@ jobs: id: test-execution run: bash scripts/cassandra-integration-test.sh ${{ matrix.version.major }} ${{ matrix.version.schema }} ${{ matrix.jaeger-version }} env: - CASSANDRA_CREATE_SCHEMA: ${{ matrix.create-schema == 'auto' && true || false }} SKIP_APPLY_SCHEMA: ${{ matrix.create-schema == 'auto' && true || false }} - name: Upload coverage to codecov diff --git a/scripts/cassandra-integration-test.sh b/scripts/cassandra-integration-test.sh index 40fd4b3b00f..a612801d501 100755 --- a/scripts/cassandra-integration-test.sh +++ b/scripts/cassandra-integration-test.sh @@ -12,6 +12,7 @@ timeout=600 end_time=$((SECONDS + timeout)) SKIP_APPLY_SCHEMA=${SKIP_APPLY_SCHEMA:-"false"} +export CASSANDRA_CREATE_SCHEMA=SKIP_APPLY_SCHEMA usage() { echo $"Usage: $0 " From c2b89e01dac0a2bd14d1174e0780ac020154f5d8 Mon Sep 17 00:00:00 2001 From: Yuri Shkuro Date: Sat, 30 Nov 2024 12:52:19 -0400 Subject: [PATCH 45/55] Apply suggestions from code review change default for v2 to auto-create schema Signed-off-by: Yuri Shkuro --- cmd/jaeger/config-cassandra.yaml | 4 ++-- cmd/jaeger/internal/integration/cassandra_test.go | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/cmd/jaeger/config-cassandra.yaml b/cmd/jaeger/config-cassandra.yaml index 7387d1afc8f..4b55737f624 100644 --- a/cmd/jaeger/config-cassandra.yaml +++ b/cmd/jaeger/config-cassandra.yaml @@ -34,7 +34,7 @@ extensions: cassandra: schema: keyspace: "jaeger_v1_dc1" - create: "${env:CASSANDRA_CREATE_SCHEMA:-false}" + create: "${env:CASSANDRA_CREATE_SCHEMA:-true}" connection: auth: basic: @@ -46,7 +46,7 @@ extensions: cassandra: schema: keyspace: "jaeger_v1_dc1_archive" - create: "${env:CASSANDRA_CREATE_SCHEMA:-false}" + create: "${env:CASSANDRA_CREATE_SCHEMA:-true}" connection: auth: basic: diff --git a/cmd/jaeger/internal/integration/cassandra_test.go b/cmd/jaeger/internal/integration/cassandra_test.go index 1492561eff8..a78f66b3ec9 100644 --- a/cmd/jaeger/internal/integration/cassandra_test.go +++ b/cmd/jaeger/internal/integration/cassandra_test.go @@ -11,7 +11,6 @@ import ( func TestCassandraStorage(t *testing.T) { integration.SkipUnlessEnv(t, "cassandra") - s := &E2EStorageIntegration{ ConfigFile: "../../config-cassandra.yaml", StorageIntegration: integration.StorageIntegration{ From de2d2ef0cb06692182a6e6430a3fac1a3ad4fdac Mon Sep 17 00:00:00 2001 From: Yuri Shkuro Date: Sat, 30 Nov 2024 12:58:59 -0400 Subject: [PATCH 46/55] Update docs Signed-off-by: Yuri Shkuro --- pkg/cassandra/config/config.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/cassandra/config/config.go b/pkg/cassandra/config/config.go index fa6d6b3b274..d8d9706c2b3 100644 --- a/pkg/cassandra/config/config.go +++ b/pkg/cassandra/config/config.go @@ -69,7 +69,8 @@ type Schema struct { DependenciesTTL time.Duration `mapstructure:"dependencies_ttl" valid:"optional"` // Replication factor for the db ReplicationFactor int `mapstructure:"replication_factor" valid:"optional"` - // CompactionWindow of format tells the compaction window of the db. Should atleast be 1 minute + // CompactionWindow is the size of the window for TimeWindowCompactionStrategy. + // All SSTables within that window are grouped together into one SSTable. CompactionWindow time.Duration `mapstructure:"compaction_window" valid:"optional"` } From 100208c6abc958a206ec2b5d4d74df976042d4b9 Mon Sep 17 00:00:00 2001 From: Yuri Shkuro Date: Sat, 30 Nov 2024 13:04:39 -0500 Subject: [PATCH 47/55] refactor Signed-off-by: Yuri Shkuro --- pkg/cassandra/config/config.go | 54 -------- plugin/storage/cassandra/factory.go | 63 ++++++++-- plugin/storage/cassandra/factory_test.go | 116 ++++++++++++------ plugin/storage/cassandra/options.go | 4 +- .../storage/cassandra/schema}/schema.go | 27 ++-- .../storage/cassandra/schema}/schema_test.go | 6 +- .../cassandra/schema}/v004-go-tmpl.cql.tmpl | 0 7 files changed, 157 insertions(+), 113 deletions(-) rename {pkg/cassandra/config => plugin/storage/cassandra/schema}/schema.go (81%) rename {pkg/cassandra/config => plugin/storage/cassandra/schema}/schema_test.go (94%) rename {pkg/cassandra/config => plugin/storage/cassandra/schema}/v004-go-tmpl.cql.tmpl (100%) diff --git a/pkg/cassandra/config/config.go b/pkg/cassandra/config/config.go index d8d9706c2b3..ea4e839a519 100644 --- a/pkg/cassandra/config/config.go +++ b/pkg/cassandra/config/config.go @@ -13,9 +13,6 @@ import ( "github.com/asaskevich/govalidator" "github.com/gocql/gocql" "go.opentelemetry.io/collector/config/configtls" - - "github.com/jaegertracing/jaeger/pkg/cassandra" - gocqlw "github.com/jaegertracing/jaeger/pkg/cassandra/gocql" ) // Configuration describes the configuration properties needed to connect to a Cassandra cluster. @@ -170,57 +167,6 @@ func (c *Configuration) ApplyDefaults(source *Configuration) { } } -// SessionBuilder creates new cassandra.Session -type SessionBuilder interface { - NewSession() (cassandra.Session, error) -} - -// createSession creates session from a configuration -func createSession(c *Configuration) (cassandra.Session, error) { - cluster, err := c.NewCluster() - if err != nil { - return nil, err - } - - session, err := cluster.CreateSession() - if err != nil { - return nil, err - } - - return gocqlw.WrapCQLSession(session), nil -} - -// newSessionPrerequisites creates tables and types before creating a session -func (c *Configuration) newSessionPrerequisites() error { - if !c.Schema.CreateSchema { - return nil - } - - cfg := *c // clone because we need to connect without specifying a keyspace - cfg.Schema.Keyspace = "" - - session, err := createSession(&cfg) - if err != nil { - return err - } - - sc := schemaCreator{ - session: session, - schema: c.Schema, - } - - return sc.createSchemaIfNotPresent() -} - -// NewSession creates a new Cassandra session -func (c *Configuration) NewSession() (cassandra.Session, error) { - if err := c.newSessionPrerequisites(); err != nil { - return nil, err - } - - return createSession(c) -} - // NewCluster creates a new gocql cluster from the configuration func (c *Configuration) NewCluster() (*gocql.ClusterConfig, error) { cluster := gocql.NewCluster(c.Connection.Servers...) diff --git a/plugin/storage/cassandra/factory.go b/plugin/storage/cassandra/factory.go index 4654a2a2c82..0e75d9f3e20 100644 --- a/plugin/storage/cassandra/factory.go +++ b/plugin/storage/cassandra/factory.go @@ -17,6 +17,7 @@ import ( "github.com/jaegertracing/jaeger/pkg/cassandra" "github.com/jaegertracing/jaeger/pkg/cassandra/config" + gocqlw "github.com/jaegertracing/jaeger/pkg/cassandra/gocql" "github.com/jaegertracing/jaeger/pkg/distributedlock" "github.com/jaegertracing/jaeger/pkg/hostname" "github.com/jaegertracing/jaeger/pkg/metrics" @@ -24,6 +25,7 @@ import ( cLock "github.com/jaegertracing/jaeger/plugin/pkg/distributedlock/cassandra" cDepStore "github.com/jaegertracing/jaeger/plugin/storage/cassandra/dependencystore" cSamplingStore "github.com/jaegertracing/jaeger/plugin/storage/cassandra/samplingstore" + "github.com/jaegertracing/jaeger/plugin/storage/cassandra/schema" cSpanStore "github.com/jaegertracing/jaeger/plugin/storage/cassandra/spanstore" "github.com/jaegertracing/jaeger/plugin/storage/cassandra/spanstore/dbmodel" "github.com/jaegertracing/jaeger/storage" @@ -55,17 +57,22 @@ type Factory struct { logger *zap.Logger tracer trace.TracerProvider - primaryConfig config.SessionBuilder + primaryConfig config.Configuration + archiveConfig *config.Configuration + primarySession cassandra.Session - archiveConfig config.SessionBuilder archiveSession cassandra.Session + + // test can override this + sessionBuilderFn func(*config.Configuration) (cassandra.Session, error) } // NewFactory creates a new Factory. func NewFactory() *Factory { return &Factory{ - tracer: otel.GetTracerProvider(), - Options: NewOptions(primaryStorageConfig, archiveStorageConfig), + tracer: otel.GetTracerProvider(), + Options: NewOptions(primaryStorageConfig, archiveStorageConfig), + sessionBuilderFn: newSession, } } @@ -127,7 +134,7 @@ func (f *Factory) configureFromOptions(o *Options) { } f.primaryConfig = o.GetPrimary() if cfg := f.Options.Get(archiveStorageConfig); cfg != nil { - f.archiveConfig = cfg // this is so stupid - see https://golang.org/doc/faq#nil_error + f.archiveConfig = cfg } } @@ -137,14 +144,14 @@ func (f *Factory) Initialize(metricsFactory metrics.Factory, logger *zap.Logger) f.archiveMetricsFactory = metricsFactory.Namespace(metrics.NSOptions{Name: "cassandra-archive", Tags: nil}) f.logger = logger - primarySession, err := f.primaryConfig.NewSession() + primarySession, err := f.sessionBuilderFn(&f.primaryConfig) if err != nil { return err } f.primarySession = primarySession if f.archiveConfig != nil { - archiveSession, err := f.archiveConfig.NewSession() + archiveSession, err := f.sessionBuilderFn(f.archiveConfig) if err != nil { return err } @@ -155,6 +162,48 @@ func (f *Factory) Initialize(metricsFactory metrics.Factory, logger *zap.Logger) return nil } +// createSession creates session from a configuration +func createSession(c *config.Configuration) (cassandra.Session, error) { + cluster, err := c.NewCluster() + if err != nil { + return nil, err + } + + session, err := cluster.CreateSession() + if err != nil { + return nil, err + } + + return gocqlw.WrapCQLSession(session), nil +} + +// newSessionPrerequisites creates tables and types before creating a session +func newSessionPrerequisites(c *config.Configuration) error { + if !c.Schema.CreateSchema { + return nil + } + + cfg := *c // clone because we need to connect without specifying a keyspace + cfg.Schema.Keyspace = "" + + session, err := createSession(&cfg) + if err != nil { + return err + } + + sc := schema.NewSchemaCreator(session, c.Schema) + return sc.CreateSchemaIfNotPresent() +} + +// NewSession creates a new Cassandra session +func newSession(c *config.Configuration) (cassandra.Session, error) { + if err := newSessionPrerequisites(c); err != nil { + return nil, err + } + + return createSession(c) +} + // CreateSpanReader implements storage.Factory func (f *Factory) CreateSpanReader() (spanstore.Reader, error) { return cSpanStore.NewSpanReader(f.primarySession, f.primaryMetricsFactory, f.logger, f.tracer.Tracer("cSpanStore.SpanReader")) diff --git a/plugin/storage/cassandra/factory_test.go b/plugin/storage/cassandra/factory_test.go index aec6bdbd5d5..16ea1f3df93 100644 --- a/plugin/storage/cassandra/factory_test.go +++ b/plugin/storage/cassandra/factory_test.go @@ -12,43 +12,55 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "go.opentelemetry.io/collector/config/configtls" "go.uber.org/zap" "github.com/jaegertracing/jaeger/pkg/cassandra" + "github.com/jaegertracing/jaeger/pkg/cassandra/config" cassandraCfg "github.com/jaegertracing/jaeger/pkg/cassandra/config" "github.com/jaegertracing/jaeger/pkg/cassandra/mocks" - "github.com/jaegertracing/jaeger/pkg/config" + viperize "github.com/jaegertracing/jaeger/pkg/config" "github.com/jaegertracing/jaeger/pkg/metrics" "github.com/jaegertracing/jaeger/pkg/testutils" ) type mockSessionBuilder struct { - session *mocks.Session - err error + index int + sessions []*mocks.Session + errors []error } -func newMockSessionBuilder(session *mocks.Session, err error) *mockSessionBuilder { - return &mockSessionBuilder{ - session: session, - err: err, - } +func (m *mockSessionBuilder) add(session *mocks.Session, err error) *mockSessionBuilder { + m.sessions = append(m.sessions, session) + m.errors = append(m.errors, err) + return m } -func (m *mockSessionBuilder) NewSession() (cassandra.Session, error) { - return m.session, m.err +func (m *mockSessionBuilder) build(*config.Configuration) (cassandra.Session, error) { + if m.index >= len(m.sessions) { + return nil, errors.New("no more sessions") + } + session := m.sessions[m.index] + err := m.errors[m.index] + m.index++ + return session, err } +// func newMockSessionBuilder(session *mocks.Session, err error) func(*config.Configuration) (cassandra.Session, error) { +// return func(*config.Configuration) (cassandra.Session, error) { +// return session, err +// } +// } + func TestCassandraFactory(t *testing.T) { logger, logBuf := testutils.NewLogger() f := NewFactory() - v, command := config.Viperize(f.AddFlags) + v, command := viperize.Viperize(f.AddFlags) command.ParseFlags([]string{"--cassandra-archive.enabled=true"}) f.InitFromViper(v, zap.NewNop()) - // after InitFromViper, f.primaryConfig points to a real session builder that will fail in unit tests, - // so we override it with a mock. - f.primaryConfig = newMockSessionBuilder(nil, errors.New("made-up error")) - require.EqualError(t, f.Initialize(metrics.NullFactory, zap.NewNop()), "made-up error") + f.sessionBuilderFn = new(mockSessionBuilder).add(nil, errors.New("made-up primary error")).build + require.EqualError(t, f.Initialize(metrics.NullFactory, zap.NewNop()), "made-up primary error") var ( session = &mocks.Session{} @@ -57,11 +69,13 @@ func TestCassandraFactory(t *testing.T) { session.On("Query", mock.AnythingOfType("string"), mock.Anything).Return(query) session.On("Close").Return() query.On("Exec").Return(nil) - f.primaryConfig = newMockSessionBuilder(session, nil) - f.archiveConfig = newMockSessionBuilder(nil, errors.New("made-up error")) - require.EqualError(t, f.Initialize(metrics.NullFactory, zap.NewNop()), "made-up error") + f.sessionBuilderFn = new(mockSessionBuilder). + add(session, nil). + add(nil, errors.New("made-up archive error")).build + require.EqualError(t, f.Initialize(metrics.NullFactory, zap.NewNop()), "made-up archive error") f.archiveConfig = nil + f.sessionBuilderFn = new(mockSessionBuilder).add(session, nil).build require.NoError(t, f.Initialize(metrics.NullFactory, logger)) assert.Contains(t, logBuf.String(), "Cassandra archive storage configuration is empty, skipping") @@ -80,7 +94,8 @@ func TestCassandraFactory(t *testing.T) { _, err = f.CreateArchiveSpanWriter() require.EqualError(t, err, "archive storage not configured") - f.archiveConfig = newMockSessionBuilder(session, nil) + f.archiveConfig = &config.Configuration{} + f.sessionBuilderFn = new(mockSessionBuilder).add(session, nil).add(session, nil).build require.NoError(t, f.Initialize(metrics.NullFactory, zap.NewNop())) _, err = f.CreateArchiveSpanReader() @@ -99,9 +114,8 @@ func TestCassandraFactory(t *testing.T) { } func TestExclusiveWhitelistBlacklist(t *testing.T) { - logger, logBuf := testutils.NewLogger() f := NewFactory() - v, command := config.Viperize(f.AddFlags) + v, command := viperize.Viperize(f.AddFlags) command.ParseFlags([]string{ "--cassandra-archive.enabled=true", "--cassandra.index.tag-whitelist=a,b,c", @@ -109,29 +123,25 @@ func TestExclusiveWhitelistBlacklist(t *testing.T) { }) f.InitFromViper(v, zap.NewNop()) - // after InitFromViper, f.primaryConfig points to a real session builder that will fail in unit tests, - // so we override it with a mock. - f.primaryConfig = newMockSessionBuilder(nil, errors.New("made-up error")) - require.EqualError(t, f.Initialize(metrics.NullFactory, zap.NewNop()), "made-up error") - var ( session = &mocks.Session{} query = &mocks.Query{} ) session.On("Query", mock.AnythingOfType("string"), mock.Anything).Return(query) query.On("Exec").Return(nil) - f.primaryConfig = newMockSessionBuilder(session, nil) - f.archiveConfig = newMockSessionBuilder(nil, errors.New("made-up error")) - require.EqualError(t, f.Initialize(metrics.NullFactory, zap.NewNop()), "made-up error") + f.sessionBuilderFn = new(mockSessionBuilder).add(session, nil).build + // f.sessionBuilderFn = newMockSessionBuilder(session, nil) + // require.EqualError(t, f.Initialize(metrics.NullFactory, zap.NewNop()), "made-up error") - f.archiveConfig = nil - require.NoError(t, f.Initialize(metrics.NullFactory, logger)) - assert.Contains(t, logBuf.String(), "Cassandra archive storage configuration is empty, skipping") + // f.archiveConfig = nil + // require.NoError(t, f.Initialize(metrics.NullFactory, logger)) + // assert.Contains(t, logBuf.String(), "Cassandra archive storage configuration is empty, skipping") _, err := f.CreateSpanWriter() require.EqualError(t, err, "only one of TagIndexBlacklist and TagIndexWhitelist can be specified") - f.archiveConfig = &mockSessionBuilder{} + f.archiveConfig = &config.Configuration{} + f.sessionBuilderFn = new(mockSessionBuilder).add(session, nil).add(session, nil).build require.NoError(t, f.Initialize(metrics.NullFactory, zap.NewNop())) _, err = f.CreateArchiveSpanWriter() @@ -140,7 +150,7 @@ func TestExclusiveWhitelistBlacklist(t *testing.T) { func TestWriterOptions(t *testing.T) { opts := NewOptions("cassandra") - v, command := config.Viperize(opts.AddFlags) + v, command := viperize.Viperize(opts.AddFlags) command.ParseFlags([]string{"--cassandra.index.tag-whitelist=a,b,c"}) opts.InitFromViper(v) @@ -148,7 +158,7 @@ func TestWriterOptions(t *testing.T) { assert.Len(t, options, 1) opts = NewOptions("cassandra") - v, command = config.Viperize(opts.AddFlags) + v, command = viperize.Viperize(opts.AddFlags) command.ParseFlags([]string{"--cassandra.index.tag-blacklist=a,b,c"}) opts.InitFromViper(v) @@ -156,7 +166,7 @@ func TestWriterOptions(t *testing.T) { assert.Len(t, options, 1) opts = NewOptions("cassandra") - v, command = config.Viperize(opts.AddFlags) + v, command = viperize.Viperize(opts.AddFlags) command.ParseFlags([]string{"--cassandra.index.tags=false"}) opts.InitFromViper(v) @@ -164,7 +174,7 @@ func TestWriterOptions(t *testing.T) { assert.Len(t, options, 1) opts = NewOptions("cassandra") - v, command = config.Viperize(opts.AddFlags) + v, command = viperize.Viperize(opts.AddFlags) command.ParseFlags([]string{"--cassandra.index.tags=false", "--cassandra.index.tag-blacklist=a,b,c"}) opts.InitFromViper(v) @@ -172,7 +182,7 @@ func TestWriterOptions(t *testing.T) { assert.Len(t, options, 1) opts = NewOptions("cassandra") - v, command = config.Viperize(opts.AddFlags) + v, command = viperize.Viperize(opts.AddFlags) command.ParseFlags([]string{""}) opts.InitFromViper(v) @@ -249,3 +259,33 @@ func TestFactory_Purge(t *testing.T) { session.AssertCalled(t, "Query", mock.AnythingOfType("string"), mock.Anything) query.AssertCalled(t, "Exec") } + +func TestNewSessionErrors(t *testing.T) { + t.Run("NewCluster error", func(t *testing.T) { + cfg := &config.Configuration{ + Connection: config.Connection{ + TLS: configtls.ClientConfig{ + Config: configtls.Config{ + CAFile: "foobar", + }, + }, + }, + } + _, err := newSession(cfg) + require.ErrorContains(t, err, "failed to load TLS config") + }) + t.Run("CreateSession error", func(t *testing.T) { + cfg := &config.Configuration{} + _, err := newSession(cfg) + require.ErrorContains(t, err, "no hosts provided") + }) + t.Run("CreateSession error with schema", func(t *testing.T) { + cfg := &config.Configuration{ + Schema: config.Schema{ + CreateSchema: true, + }, + } + _, err := newSession(cfg) + require.ErrorContains(t, err, "no hosts provided") + }) +} diff --git a/plugin/storage/cassandra/options.go b/plugin/storage/cassandra/options.go index e266436ba29..505d99c1ef3 100644 --- a/plugin/storage/cassandra/options.go +++ b/plugin/storage/cassandra/options.go @@ -256,8 +256,8 @@ func (cfg *NamespaceConfig) initFromViper(v *viper.Viper) { } // GetPrimary returns primary configuration. -func (opt *Options) GetPrimary() *config.Configuration { - return &opt.Primary.Configuration +func (opt *Options) GetPrimary() config.Configuration { + return opt.Primary.Configuration } // Get returns auxiliary named configuration. diff --git a/pkg/cassandra/config/schema.go b/plugin/storage/cassandra/schema/schema.go similarity index 81% rename from pkg/cassandra/config/schema.go rename to plugin/storage/cassandra/schema/schema.go index 902667bcd36..bb1dfdfa03d 100644 --- a/pkg/cassandra/config/schema.go +++ b/plugin/storage/cassandra/schema/schema.go @@ -1,7 +1,7 @@ // Copyright (c) 2024 The Jaeger Authors. // SPDX-License-Identifier: Apache-2.0 -package config +package schema import ( "bytes" @@ -12,6 +12,7 @@ import ( "time" "github.com/jaegertracing/jaeger/pkg/cassandra" + "github.com/jaegertracing/jaeger/pkg/cassandra/config" ) //go:embed v004-go-tmpl.cql.tmpl @@ -30,12 +31,20 @@ type templateParams struct { DependenciesTTLInSeconds int64 } -type schemaCreator struct { +type SchemaCreator struct { session cassandra.Session - schema Schema + schema config.Schema } -func (sc *schemaCreator) constructTemplateParams() templateParams { +// NewSchemaCreator returns a new SchemaCreator +func NewSchemaCreator(session cassandra.Session, schema config.Schema) *SchemaCreator { + return &SchemaCreator{ + session: session, + schema: schema, + } +} + +func (sc *SchemaCreator) constructTemplateParams() templateParams { return templateParams{ Keyspace: sc.schema.Keyspace, Replication: fmt.Sprintf("{'class': 'NetworkTopologyStrategy', 'replication_factor': '%v' }", sc.schema.ReplicationFactor), @@ -45,7 +54,7 @@ func (sc *schemaCreator) constructTemplateParams() templateParams { } } -func (*schemaCreator) getQueryFileAsBytes(fileName string, params templateParams) ([]byte, error) { +func (*SchemaCreator) getQueryFileAsBytes(fileName string, params templateParams) ([]byte, error) { tmpl, err := template.ParseFS(schemaFile, fileName) if err != nil { return nil, err @@ -60,7 +69,7 @@ func (*schemaCreator) getQueryFileAsBytes(fileName string, params templateParams return result.Bytes(), nil } -func (*schemaCreator) getQueriesFromBytes(queryFile []byte) ([]string, error) { +func (*SchemaCreator) getQueriesFromBytes(queryFile []byte) ([]string, error) { lines := bytes.Split(queryFile, []byte("\n")) var extractedLines [][]byte @@ -101,7 +110,7 @@ func (*schemaCreator) getQueriesFromBytes(queryFile []byte) ([]string, error) { return queries, nil } -func (sc *schemaCreator) getCassandraQueriesFromQueryStrings(queries []string) []cassandra.Query { +func (sc *SchemaCreator) getCassandraQueriesFromQueryStrings(queries []string) []cassandra.Query { var casQueries []cassandra.Query for _, query := range queries { @@ -111,7 +120,7 @@ func (sc *schemaCreator) getCassandraQueriesFromQueryStrings(queries []string) [ return casQueries } -func (sc *schemaCreator) contructSchemaQueries() ([]cassandra.Query, error) { +func (sc *SchemaCreator) contructSchemaQueries() ([]cassandra.Query, error) { params := sc.constructTemplateParams() queryFile, err := sc.getQueryFileAsBytes(`v004-go-tmpl.cql.tmpl`, params) @@ -129,7 +138,7 @@ func (sc *schemaCreator) contructSchemaQueries() ([]cassandra.Query, error) { return casQueries, nil } -func (sc *schemaCreator) createSchemaIfNotPresent() error { +func (sc *SchemaCreator) CreateSchemaIfNotPresent() error { casQueries, err := sc.contructSchemaQueries() if err != nil { return err diff --git a/pkg/cassandra/config/schema_test.go b/plugin/storage/cassandra/schema/schema_test.go similarity index 94% rename from pkg/cassandra/config/schema_test.go rename to plugin/storage/cassandra/schema/schema_test.go index f43dda21724..d6efe20bdfa 100644 --- a/pkg/cassandra/config/schema_test.go +++ b/plugin/storage/cassandra/schema/schema_test.go @@ -1,7 +1,7 @@ // Copyright (c) 2024 The Jaeger Authors. // SPDX-License-Identifier: Apache-2.0 -package config +package schema import ( "testing" @@ -30,7 +30,7 @@ query1-finished; `, } - sc := schemaCreator{} + sc := SchemaCreator{} queriesAsBytes := []byte(queriesAsString) queries, err := sc.getQueriesFromBytes(queriesAsBytes) require.NoError(t, err) @@ -52,7 +52,7 @@ func TestInvalidQueryTemplate(t *testing.T) { query2; query-3 query-3-continue query-3-finished -- missing semicolon ` - sc := schemaCreator{} + sc := SchemaCreator{} queriesAsBytes := []byte(queriesAsString) _, err := sc.getQueriesFromBytes(queriesAsBytes) require.Error(t, err) diff --git a/pkg/cassandra/config/v004-go-tmpl.cql.tmpl b/plugin/storage/cassandra/schema/v004-go-tmpl.cql.tmpl similarity index 100% rename from pkg/cassandra/config/v004-go-tmpl.cql.tmpl rename to plugin/storage/cassandra/schema/v004-go-tmpl.cql.tmpl From 37d34dd6161071495c2c78acb5ab6d2b021c78b8 Mon Sep 17 00:00:00 2001 From: Yuri Shkuro Date: Sat, 30 Nov 2024 13:06:33 -0500 Subject: [PATCH 48/55] clean-up imports Signed-off-by: Yuri Shkuro --- plugin/storage/cassandra/factory_test.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/plugin/storage/cassandra/factory_test.go b/plugin/storage/cassandra/factory_test.go index 16ea1f3df93..0909ce684fc 100644 --- a/plugin/storage/cassandra/factory_test.go +++ b/plugin/storage/cassandra/factory_test.go @@ -17,7 +17,6 @@ import ( "github.com/jaegertracing/jaeger/pkg/cassandra" "github.com/jaegertracing/jaeger/pkg/cassandra/config" - cassandraCfg "github.com/jaegertracing/jaeger/pkg/cassandra/config" "github.com/jaegertracing/jaeger/pkg/cassandra/mocks" viperize "github.com/jaegertracing/jaeger/pkg/config" "github.com/jaegertracing/jaeger/pkg/metrics" @@ -204,7 +203,7 @@ func TestNewFactoryWithConfig(t *testing.T) { t.Run("valid configuration", func(t *testing.T) { opts := &Options{ Primary: NamespaceConfig{ - Configuration: cassandraCfg.DefaultConfiguration(), + Configuration: config.DefaultConfiguration(), }, } f := NewFactory() @@ -222,7 +221,7 @@ func TestNewFactoryWithConfig(t *testing.T) { expErr := errors.New("made-up error") opts := &Options{ Primary: NamespaceConfig{ - Configuration: cassandraCfg.DefaultConfiguration(), + Configuration: config.DefaultConfiguration(), }, } f := NewFactory() From 8d658945048568dbd1ecde5ae112e9ec8f5f5966 Mon Sep 17 00:00:00 2001 From: Yuri Shkuro Date: Sat, 30 Nov 2024 13:16:26 -0500 Subject: [PATCH 49/55] clean-up Signed-off-by: Yuri Shkuro --- plugin/storage/cassandra/factory.go | 3 ++- plugin/storage/cassandra/factory_test.go | 12 ------------ plugin/storage/cassandra/schema/package_test.go | 14 ++++++++++++++ 3 files changed, 16 insertions(+), 13 deletions(-) create mode 100644 plugin/storage/cassandra/schema/package_test.go diff --git a/plugin/storage/cassandra/factory.go b/plugin/storage/cassandra/factory.go index 0e75d9f3e20..679ac53a61b 100644 --- a/plugin/storage/cassandra/factory.go +++ b/plugin/storage/cassandra/factory.go @@ -63,7 +63,7 @@ type Factory struct { primarySession cassandra.Session archiveSession cassandra.Session - // test can override this + // tests can override this sessionBuilderFn func(*config.Configuration) (cassandra.Session, error) } @@ -134,6 +134,7 @@ func (f *Factory) configureFromOptions(o *Options) { } f.primaryConfig = o.GetPrimary() if cfg := f.Options.Get(archiveStorageConfig); cfg != nil { + // avoid typed nil, see https://golang.org/doc/faq#nil_error f.archiveConfig = cfg } } diff --git a/plugin/storage/cassandra/factory_test.go b/plugin/storage/cassandra/factory_test.go index 0909ce684fc..4bb0509fa4d 100644 --- a/plugin/storage/cassandra/factory_test.go +++ b/plugin/storage/cassandra/factory_test.go @@ -45,12 +45,6 @@ func (m *mockSessionBuilder) build(*config.Configuration) (cassandra.Session, er return session, err } -// func newMockSessionBuilder(session *mocks.Session, err error) func(*config.Configuration) (cassandra.Session, error) { -// return func(*config.Configuration) (cassandra.Session, error) { -// return session, err -// } -// } - func TestCassandraFactory(t *testing.T) { logger, logBuf := testutils.NewLogger() f := NewFactory() @@ -129,12 +123,6 @@ func TestExclusiveWhitelistBlacklist(t *testing.T) { session.On("Query", mock.AnythingOfType("string"), mock.Anything).Return(query) query.On("Exec").Return(nil) f.sessionBuilderFn = new(mockSessionBuilder).add(session, nil).build - // f.sessionBuilderFn = newMockSessionBuilder(session, nil) - // require.EqualError(t, f.Initialize(metrics.NullFactory, zap.NewNop()), "made-up error") - - // f.archiveConfig = nil - // require.NoError(t, f.Initialize(metrics.NullFactory, logger)) - // assert.Contains(t, logBuf.String(), "Cassandra archive storage configuration is empty, skipping") _, err := f.CreateSpanWriter() require.EqualError(t, err, "only one of TagIndexBlacklist and TagIndexWhitelist can be specified") diff --git a/plugin/storage/cassandra/schema/package_test.go b/plugin/storage/cassandra/schema/package_test.go new file mode 100644 index 00000000000..5c3adb21543 --- /dev/null +++ b/plugin/storage/cassandra/schema/package_test.go @@ -0,0 +1,14 @@ +// Copyright (c) 2024 The Jaeger Authors. +// SPDX-License-Identifier: Apache-2.0 + +package schema + +import ( + "testing" + + "github.com/jaegertracing/jaeger/pkg/testutils" +) + +func TestMain(m *testing.M) { + testutils.VerifyGoLeaks(m) +} From 23a9b624ca2e4759bae1612e9ea7bfa8ac4cca2f Mon Sep 17 00:00:00 2001 From: Yuri Shkuro Date: Sat, 30 Nov 2024 13:17:32 -0500 Subject: [PATCH 50/55] simplify Signed-off-by: Yuri Shkuro --- plugin/storage/cassandra/factory.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/plugin/storage/cassandra/factory.go b/plugin/storage/cassandra/factory.go index 679ac53a61b..8ee72905f3d 100644 --- a/plugin/storage/cassandra/factory.go +++ b/plugin/storage/cassandra/factory.go @@ -133,10 +133,7 @@ func (f *Factory) configureFromOptions(o *Options) { o.others = make(map[string]*NamespaceConfig) } f.primaryConfig = o.GetPrimary() - if cfg := f.Options.Get(archiveStorageConfig); cfg != nil { - // avoid typed nil, see https://golang.org/doc/faq#nil_error - f.archiveConfig = cfg - } + f.archiveConfig = f.Options.Get(archiveStorageConfig) } // Initialize implements storage.Factory From d9250744a043045136119afe0a3638d0cd1a0f67 Mon Sep 17 00:00:00 2001 From: Yuri Shkuro Date: Sat, 30 Nov 2024 13:33:25 -0500 Subject: [PATCH 51/55] fix Signed-off-by: Yuri Shkuro --- plugin/storage/cassandra/factory.go | 4 ++-- plugin/storage/cassandra/factory_test.go | 6 +++--- plugin/storage/cassandra/savetracetest/main.go | 3 ++- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/plugin/storage/cassandra/factory.go b/plugin/storage/cassandra/factory.go index 8ee72905f3d..49c7a2a9c55 100644 --- a/plugin/storage/cassandra/factory.go +++ b/plugin/storage/cassandra/factory.go @@ -72,7 +72,7 @@ func NewFactory() *Factory { return &Factory{ tracer: otel.GetTracerProvider(), Options: NewOptions(primaryStorageConfig, archiveStorageConfig), - sessionBuilderFn: newSession, + sessionBuilderFn: NewSession, } } @@ -194,7 +194,7 @@ func newSessionPrerequisites(c *config.Configuration) error { } // NewSession creates a new Cassandra session -func newSession(c *config.Configuration) (cassandra.Session, error) { +func NewSession(c *config.Configuration) (cassandra.Session, error) { if err := newSessionPrerequisites(c); err != nil { return nil, err } diff --git a/plugin/storage/cassandra/factory_test.go b/plugin/storage/cassandra/factory_test.go index 4bb0509fa4d..d8800089a75 100644 --- a/plugin/storage/cassandra/factory_test.go +++ b/plugin/storage/cassandra/factory_test.go @@ -258,12 +258,12 @@ func TestNewSessionErrors(t *testing.T) { }, }, } - _, err := newSession(cfg) + _, err := NewSession(cfg) require.ErrorContains(t, err, "failed to load TLS config") }) t.Run("CreateSession error", func(t *testing.T) { cfg := &config.Configuration{} - _, err := newSession(cfg) + _, err := NewSession(cfg) require.ErrorContains(t, err, "no hosts provided") }) t.Run("CreateSession error with schema", func(t *testing.T) { @@ -272,7 +272,7 @@ func TestNewSessionErrors(t *testing.T) { CreateSchema: true, }, } - _, err := newSession(cfg) + _, err := NewSession(cfg) require.ErrorContains(t, err, "no hosts provided") }) } diff --git a/plugin/storage/cassandra/savetracetest/main.go b/plugin/storage/cassandra/savetracetest/main.go index d2190f5511e..d6c2b1f3fa1 100644 --- a/plugin/storage/cassandra/savetracetest/main.go +++ b/plugin/storage/cassandra/savetracetest/main.go @@ -14,6 +14,7 @@ import ( cascfg "github.com/jaegertracing/jaeger/pkg/cassandra/config" "github.com/jaegertracing/jaeger/pkg/jtracer" "github.com/jaegertracing/jaeger/pkg/metrics" + "github.com/jaegertracing/jaeger/plugin/storage/cassandra" cSpanStore "github.com/jaegertracing/jaeger/plugin/storage/cassandra/spanstore" "github.com/jaegertracing/jaeger/storage/spanstore" ) @@ -36,7 +37,7 @@ func main() { Timeout: time.Millisecond * 750, }, } - cqlSession, err := cConfig.NewSession() + cqlSession, err := cassandra.NewSession(cConfig) if err != nil { logger.Fatal("Cannot create Cassandra session", zap.Error(err)) } From 154deb9e41801934143cda7125ec18b588532afd Mon Sep 17 00:00:00 2001 From: Yuri Shkuro Date: Sat, 30 Nov 2024 14:46:05 -0400 Subject: [PATCH 52/55] Fix workflow Signed-off-by: Yuri Shkuro --- .github/workflows/ci-e2e-cassandra.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-e2e-cassandra.yml b/.github/workflows/ci-e2e-cassandra.yml index 66026c93392..489603a2b8e 100644 --- a/.github/workflows/ci-e2e-cassandra.yml +++ b/.github/workflows/ci-e2e-cassandra.yml @@ -33,7 +33,7 @@ jobs: exclude: # Exclude v1 as create schema on fly is available for v2 only - jaeger-version: v1 - skip-apply-schema: true + create-schema: auto name: ${{ matrix.version.distribution }} ${{ matrix.version.major }} ${{ matrix.jaeger-version }} ${{ matrix.create-schema }} steps: - name: Harden Runner From cc9db9cd8d9658ebccb90001a25038036fa1abed Mon Sep 17 00:00:00 2001 From: Yuri Shkuro Date: Sat, 30 Nov 2024 13:47:28 -0500 Subject: [PATCH 53/55] rename Signed-off-by: Yuri Shkuro --- plugin/storage/cassandra/schema/schema.go | 18 +++++++++--------- plugin/storage/cassandra/schema/schema_test.go | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/plugin/storage/cassandra/schema/schema.go b/plugin/storage/cassandra/schema/schema.go index bb1dfdfa03d..25aa172355f 100644 --- a/plugin/storage/cassandra/schema/schema.go +++ b/plugin/storage/cassandra/schema/schema.go @@ -31,20 +31,20 @@ type templateParams struct { DependenciesTTLInSeconds int64 } -type SchemaCreator struct { +type Creator struct { session cassandra.Session schema config.Schema } // NewSchemaCreator returns a new SchemaCreator -func NewSchemaCreator(session cassandra.Session, schema config.Schema) *SchemaCreator { - return &SchemaCreator{ +func NewSchemaCreator(session cassandra.Session, schema config.Schema) *Creator { + return &Creator{ session: session, schema: schema, } } -func (sc *SchemaCreator) constructTemplateParams() templateParams { +func (sc *Creator) constructTemplateParams() templateParams { return templateParams{ Keyspace: sc.schema.Keyspace, Replication: fmt.Sprintf("{'class': 'NetworkTopologyStrategy', 'replication_factor': '%v' }", sc.schema.ReplicationFactor), @@ -54,7 +54,7 @@ func (sc *SchemaCreator) constructTemplateParams() templateParams { } } -func (*SchemaCreator) getQueryFileAsBytes(fileName string, params templateParams) ([]byte, error) { +func (*Creator) getQueryFileAsBytes(fileName string, params templateParams) ([]byte, error) { tmpl, err := template.ParseFS(schemaFile, fileName) if err != nil { return nil, err @@ -69,7 +69,7 @@ func (*SchemaCreator) getQueryFileAsBytes(fileName string, params templateParams return result.Bytes(), nil } -func (*SchemaCreator) getQueriesFromBytes(queryFile []byte) ([]string, error) { +func (*Creator) getQueriesFromBytes(queryFile []byte) ([]string, error) { lines := bytes.Split(queryFile, []byte("\n")) var extractedLines [][]byte @@ -110,7 +110,7 @@ func (*SchemaCreator) getQueriesFromBytes(queryFile []byte) ([]string, error) { return queries, nil } -func (sc *SchemaCreator) getCassandraQueriesFromQueryStrings(queries []string) []cassandra.Query { +func (sc *Creator) getCassandraQueriesFromQueryStrings(queries []string) []cassandra.Query { var casQueries []cassandra.Query for _, query := range queries { @@ -120,7 +120,7 @@ func (sc *SchemaCreator) getCassandraQueriesFromQueryStrings(queries []string) [ return casQueries } -func (sc *SchemaCreator) contructSchemaQueries() ([]cassandra.Query, error) { +func (sc *Creator) contructSchemaQueries() ([]cassandra.Query, error) { params := sc.constructTemplateParams() queryFile, err := sc.getQueryFileAsBytes(`v004-go-tmpl.cql.tmpl`, params) @@ -138,7 +138,7 @@ func (sc *SchemaCreator) contructSchemaQueries() ([]cassandra.Query, error) { return casQueries, nil } -func (sc *SchemaCreator) CreateSchemaIfNotPresent() error { +func (sc *Creator) CreateSchemaIfNotPresent() error { casQueries, err := sc.contructSchemaQueries() if err != nil { return err diff --git a/plugin/storage/cassandra/schema/schema_test.go b/plugin/storage/cassandra/schema/schema_test.go index d6efe20bdfa..39e69b89916 100644 --- a/plugin/storage/cassandra/schema/schema_test.go +++ b/plugin/storage/cassandra/schema/schema_test.go @@ -30,7 +30,7 @@ query1-finished; `, } - sc := SchemaCreator{} + sc := Creator{} queriesAsBytes := []byte(queriesAsString) queries, err := sc.getQueriesFromBytes(queriesAsBytes) require.NoError(t, err) @@ -52,7 +52,7 @@ func TestInvalidQueryTemplate(t *testing.T) { query2; query-3 query-3-continue query-3-finished -- missing semicolon ` - sc := SchemaCreator{} + sc := Creator{} queriesAsBytes := []byte(queriesAsString) _, err := sc.getQueriesFromBytes(queriesAsBytes) require.Error(t, err) From 9d8ba06d42395bc2807b83655c4c9cf34561da27 Mon Sep 17 00:00:00 2001 From: Yuri Shkuro Date: Sat, 30 Nov 2024 14:59:27 -0400 Subject: [PATCH 54/55] Fix script Signed-off-by: Yuri Shkuro --- scripts/cassandra-integration-test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/cassandra-integration-test.sh b/scripts/cassandra-integration-test.sh index a612801d501..3789017d419 100755 --- a/scripts/cassandra-integration-test.sh +++ b/scripts/cassandra-integration-test.sh @@ -12,7 +12,7 @@ timeout=600 end_time=$((SECONDS + timeout)) SKIP_APPLY_SCHEMA=${SKIP_APPLY_SCHEMA:-"false"} -export CASSANDRA_CREATE_SCHEMA=SKIP_APPLY_SCHEMA +export CASSANDRA_CREATE_SCHEMA=${SKIP_APPLY_SCHEMA} usage() { echo $"Usage: $0 " From b0ac38a2da272fbb8504c76c958d96c8ecc8f818 Mon Sep 17 00:00:00 2001 From: Yuri Shkuro Date: Sat, 30 Nov 2024 14:10:38 -0500 Subject: [PATCH 55/55] fix naming for code coverage Signed-off-by: Yuri Shkuro --- .github/workflows/ci-e2e-cassandra.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-e2e-cassandra.yml b/.github/workflows/ci-e2e-cassandra.yml index 489603a2b8e..3ca6709e012 100644 --- a/.github/workflows/ci-e2e-cassandra.yml +++ b/.github/workflows/ci-e2e-cassandra.yml @@ -34,7 +34,7 @@ jobs: # Exclude v1 as create schema on fly is available for v2 only - jaeger-version: v1 create-schema: auto - name: ${{ matrix.version.distribution }} ${{ matrix.version.major }} ${{ matrix.jaeger-version }} ${{ matrix.create-schema }} + name: ${{ matrix.version.distribution }}-${{ matrix.version.major }} ${{ matrix.jaeger-version }} schema=${{ matrix.create-schema }} steps: - name: Harden Runner uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1 @@ -57,4 +57,4 @@ jobs: uses: ./.github/actions/upload-codecov with: files: cover.out - flags: cassandra-${{ matrix.version.major }}-${{ matrix.jaeger-version }} + flags: cassandra-${{ matrix.version.major }}-${{ matrix.jaeger-version }}-${{ matrix.create-schema }}