-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support archive storage in the query-service #604
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,10 +25,16 @@ import ( | |
"github.com/jaegertracing/jaeger/pkg/cassandra/config" | ||
cDepStore "github.com/jaegertracing/jaeger/plugin/storage/cassandra/dependencystore" | ||
cSpanStore "github.com/jaegertracing/jaeger/plugin/storage/cassandra/spanstore" | ||
"github.com/jaegertracing/jaeger/storage" | ||
"github.com/jaegertracing/jaeger/storage/dependencystore" | ||
"github.com/jaegertracing/jaeger/storage/spanstore" | ||
) | ||
|
||
const ( | ||
primaryStorageConfig = "cassandra" | ||
archiveStorageConfig = "cassandra-archive" | ||
) | ||
|
||
// Factory implements storage.Factory for Cassandra backend. | ||
type Factory struct { | ||
Options *Options | ||
|
@@ -38,13 +44,14 @@ type Factory struct { | |
|
||
primaryConfig config.SessionBuilder | ||
primarySession cassandra.Session | ||
// archiveSession cassandra.Session TODO | ||
archiveConfig config.SessionBuilder | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel that the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it's fully configurable by user. Given how marginal this feature is overall, I don't think introducing custom defaults per storage class is worth the complexity in the code. |
||
archiveSession cassandra.Session | ||
} | ||
|
||
// NewFactory creates a new Factory. | ||
func NewFactory() *Factory { | ||
return &Factory{ | ||
Options: NewOptions("cassandra"), // TODO add "cassandra-archive" once supported | ||
Options: NewOptions(primaryStorageConfig, archiveStorageConfig), | ||
} | ||
} | ||
|
||
|
@@ -57,6 +64,9 @@ func (f *Factory) AddFlags(flagSet *flag.FlagSet) { | |
func (f *Factory) InitFromViper(v *viper.Viper) { | ||
f.Options.InitFromViper(v) | ||
f.primaryConfig = f.Options.GetPrimary() | ||
if cfg := f.Options.Get(archiveStorageConfig); cfg != nil { | ||
f.archiveConfig = cfg // this is so stupid - see https://golang.org/doc/faq#nil_error | ||
} | ||
} | ||
|
||
// Initialize implements storage.Factory | ||
|
@@ -68,7 +78,14 @@ func (f *Factory) Initialize(metricsFactory metrics.Factory, logger *zap.Logger) | |
return err | ||
} | ||
f.primarySession = primarySession | ||
// TODO init archive (cf. https://github.com/jaegertracing/jaeger/pull/604) | ||
|
||
if f.archiveConfig != nil { | ||
if archiveSession, err := f.archiveConfig.NewSession(); err == nil { | ||
f.archiveSession = archiveSession | ||
} else { | ||
return err | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
|
@@ -86,3 +103,19 @@ func (f *Factory) CreateSpanWriter() (spanstore.Writer, error) { | |
func (f *Factory) CreateDependencyReader() (dependencystore.Reader, error) { | ||
return cDepStore.NewDependencyStore(f.primarySession, f.Options.DepStoreDataFrequency, f.metricsFactory, f.logger), nil | ||
} | ||
|
||
// CreateArchiveSpanReader implements storage.ArchiveFactory | ||
func (f *Factory) CreateArchiveSpanReader() (spanstore.Reader, error) { | ||
if f.archiveSession == nil { | ||
return nil, storage.ErrArchiveStorageNotConfigured | ||
} | ||
return cSpanStore.NewSpanReader(f.archiveSession, f.metricsFactory, f.logger), nil | ||
} | ||
|
||
// CreateArchiveSpanWriter implements storage.ArchiveFactory | ||
func (f *Factory) CreateArchiveSpanWriter() (spanstore.Writer, error) { | ||
if f.archiveSession == nil { | ||
return nil, storage.ErrArchiveStorageNotConfigured | ||
} | ||
return cSpanStore.NewSpanWriter(f.archiveSession, f.Options.SpanStoreWriteCacheTTL, f.metricsFactory, f.logger), nil | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm a bit confused, is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. at the moment, yes. The retention period of archive storage is expected to be much longer that for primary, so the short cache TTL for the primary is fine for archive too. Strictly speaking we don't even need this cache for archive, but whatever. |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,10 +25,12 @@ import ( | |
"github.com/jaegertracing/jaeger/pkg/cassandra" | ||
"github.com/jaegertracing/jaeger/pkg/cassandra/mocks" | ||
"github.com/jaegertracing/jaeger/pkg/config" | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ppppphhhhh |
||
"github.com/jaegertracing/jaeger/storage" | ||
) | ||
|
||
var _ storage.Factory = new(Factory) | ||
var _ storage.ArchiveFactory = new(Factory) | ||
|
||
type mockSessionBuilder struct { | ||
err error | ||
|
@@ -44,7 +46,7 @@ func (m *mockSessionBuilder) NewSession() (cassandra.Session, error) { | |
func TestCassandraFactory(t *testing.T) { | ||
f := NewFactory() | ||
v, command := config.Viperize(f.AddFlags) | ||
command.ParseFlags([]string{}) | ||
command.ParseFlags([]string{"--cassandra-archive.enabled=true"}) | ||
f.InitFromViper(v) | ||
|
||
// after InitFromViper, f.primaryConfig points to a real session builder that will fail in unit tests, | ||
|
@@ -53,6 +55,10 @@ func TestCassandraFactory(t *testing.T) { | |
assert.EqualError(t, f.Initialize(metrics.NullFactory, zap.NewNop()), "made-up error") | ||
|
||
f.primaryConfig = &mockSessionBuilder{} | ||
f.archiveConfig = &mockSessionBuilder{err: errors.New("made-up error")} | ||
assert.EqualError(t, f.Initialize(metrics.NullFactory, zap.NewNop()), "made-up error") | ||
|
||
f.archiveConfig = nil | ||
assert.NoError(t, f.Initialize(metrics.NullFactory, zap.NewNop())) | ||
|
||
_, err := f.CreateSpanReader() | ||
|
@@ -63,4 +69,19 @@ func TestCassandraFactory(t *testing.T) { | |
|
||
_, err = f.CreateDependencyReader() | ||
assert.NoError(t, err) | ||
|
||
_, err = f.CreateArchiveSpanReader() | ||
assert.EqualError(t, err, "Archive storage not configured") | ||
|
||
_, err = f.CreateArchiveSpanWriter() | ||
assert.EqualError(t, err, "Archive storage not configured") | ||
|
||
f.archiveConfig = &mockSessionBuilder{} | ||
assert.NoError(t, f.Initialize(metrics.NullFactory, zap.NewNop())) | ||
|
||
_, err = f.CreateArchiveSpanReader() | ||
assert.NoError(t, err) | ||
|
||
_, err = f.CreateArchiveSpanWriter() | ||
assert.NoError(t, err) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -131,3 +131,29 @@ func (f *Factory) InitFromViper(v *viper.Viper) { | |
} | ||
} | ||
} | ||
|
||
// CreateArchiveSpanReader implements storage.ArchiveFactory | ||
func (f *Factory) CreateArchiveSpanReader() (spanstore.Reader, error) { | ||
factory, ok := f.factories[f.SpanStorageType] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this means that the span store and archive span store both have to be using the same storage type? I think that's a fair assumption There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it can be changed in the future by introducing another env var. |
||
if !ok { | ||
return nil, fmt.Errorf("No %s backend registered for span store", f.SpanStorageType) | ||
} | ||
archive, ok := factory.(storage.ArchiveFactory) | ||
if !ok { | ||
return nil, storage.ErrArchiveStorageNotSupported | ||
} | ||
return archive.CreateArchiveSpanReader() | ||
} | ||
|
||
// CreateArchiveSpanWriter implements storage.ArchiveFactory | ||
func (f *Factory) CreateArchiveSpanWriter() (spanstore.Writer, error) { | ||
factory, ok := f.factories[f.SpanStorageType] | ||
if !ok { | ||
return nil, fmt.Errorf("No %s backend registered for span store", f.SpanStorageType) | ||
} | ||
archive, ok := factory.(storage.ArchiveFactory) | ||
if !ok { | ||
return nil, storage.ErrArchiveStorageNotSupported | ||
} | ||
return archive.CreateArchiveSpanWriter() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't this fail silently when
ErrArchiveStorageNotConfigured
is false; meaning it's configured; and whenErrArchiveStorageNotSupported
is true?Shouldn't we return the
ErrArchiveStorageNotSupported
when someone mistakenly configures archive storage on a storage that doesn't support archiving?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's not possible to configure archiving on a storage that doesn't support it. For example, with Cassandra you need to pass
--cassandra-archive.enabled=true
.