-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Phase out the distinction between primary and archive storage #6065
Comments
@yurishkuro dug into this a little bit while redoing the configurations and here's what I found
So I believe that this is working as expected. Let me know if there's anything I'm missing here. One other thing to note is that in v1, the additional namespaces need to be explictly enabled (https://github.com/jaegertracing/jaeger/blob/main/plugin/storage/es/options.go#L110) but the archive namespace is enabled by default in v2 (https://github.com/jaegertracing/jaeger/blob/main/plugin/storage/es/options.go#L437). |
@mahadzaryab1 In v1 the workflow is:
The key observation here is that the distinction between primary and archive is handled inside the Factory because the caller clearly indicates the intent by calling In contrast, in v2 the workflow is supposed to be different
So v2 is serendipitously working right now, but not as expected. We can see it in how Memory storage is handled - when I configured all-in-one with primary and archive storage, originally it did not work for me because Memory storage factory never implemented the Archive sub-API, so I had to add it (and the side effect of it is that archive for memory cannot be turned off now). But that was exactly the opposite of what I wanted to happen - I wanted the config to be able to configure two storages and designate each as primary / archive, so that the v2 extension would only interact with the factories via |
@yurishkuro Thanks so much for the helpful context. Do you have any thoughts on how we should proceed here? Do we want to make changes to the query extension to not use |
Yes that would be ideal. It may need refactoring of query service, eg perhaps it should be taking a separate archive factory instead of using a different interface on the main factory. |
@yurishkuro just looking for a bit of clarification so today, we're doing the following: f, err := jaegerstorage.GetStorageFactory(s.config.Storage.TracesArchive, host)
if err != nil {
return fmt.Errorf("cannot find archive storage factory: %w", err)
}
if !opts.InitArchiveStorage(f, s.telset.Logger) {
s.telset.Logger.Info("Archive storage not initialized")
} Is the goal to be able to just do the following? Why do we need to introduce a new archive factory? f, err := jaegerstorage.GetStorageFactory(s.config.Storage.TracesArchive, host)
if err != nil {
return fmt.Errorf("cannot find archive storage factory: %w", err)
}
spanReader, err := f.CreateSpanReader()
if err != nil {
return fmt.Errorf("cannot create span reader: %w", err)
}
opts.ArchiveSpanReader = f.spanReader |
yes |
@yurishkuro do we still need a separate interface to do the above? One other question I had was, will simply calling |
That is a good question, but if you look at all implementations of GetArchiveSomething they are no different from regular method. I think the only difference is in ES implementation which needs the isArchive flag. We can expose that flag as part of the ES config - not ideal because the user has to remember to set it, otherwise they might get limited look back. But I think in ES the archive storage requires separate settings anyway, eg you may not want to rollover index every day. |
@yurishkuro How would it work if we add the
|
Do we want to refactor the ES factory to only only hold one config/client and then propagate the isArchive flag to it? |
In v2 we have two independent factories. I'd say yes, we want to refactor the factories to represent just one kind of storage. It will require changes to query service. I think only Cassandra and ES factories are storing two different namespaces. |
@yurishkuro Got it! I'll get started on that. Thanks! |
This is not blocking for v2 GA, I confirmed that a proper code path is being invoked, e.g. by introducing a panic in CreateArchiveSpanReader:
|
@yurishkuro just wanted to walk through the plan for this refactoring with a couple of questions
type Factory interface {
// Initialize performs internal initialization of the factory, such as opening connections to the backend store.
// It is called after all configuration of the factory itself has been done.
Initialize(metricsFactory metrics.Factory, logger *zap.Logger) error
// CreateSpanReader creates a spanstore.Reader.
CreateSpanReader() (spanstore.Reader, error)
// CreateSpanWriter creates a spanstore.Writer.
CreateSpanWriter() (spanstore.Writer, error)
// CreateDependencyReader creates a dependencystore.Reader.
CreateDependencyReader() (dependencystore.Reader, error)
}
|
(1) Yes on the first point. I'd say this is more of a question to the binaries using the factory to create readers/writers, right now those binaries cast the Factory to ArchiveFactory, and it will need to change. (2) It's not from the same config, primary/archive have their own configs (but the latter is derived from the former for defaults, so that people don't need to duplicate CLI flags - we don't plan to support such reuse in v2 config). The |
@yurishkuro Following up on (2) - do primary/archive have their own configs in v2 as well? Or is this just in v1? Another question I had was the jaegerquery extension initializes the ES storage as follows: case cfg.Elasticsearch != nil:
factory, err = es.NewFactoryWithConfig(*cfg.Elasticsearch, mf, s.telset.Logger) How would it work if we changed the factory to only initialize one config (primary or archive) instead of having both in the same configuration? |
They do. In v2 config we already make no distinction - you declare a storage with some name X of some backend type (e.g. Elastic). Then the query extension has two foreign key fields, PrimaryStore and ArchiveStore. In theory they could point to the same name X (but then the data will be written to the same db), but if they point to different names then you have different configs.
The caller is supposed to use different factories for different purposes. |
I see. But from the user's perspective in v2 - wouldn't they just define one config and they would get the archive storage out of the box with same configurations?
Got it. But what would the factory get set to in this case? Would the |
factory is not supposed to know if it's used for primary or archive storage, that's the point. |
@yurishkuro Sorry my question was actually about the extension (https://github.com/jaegertracing/jaeger/blob/main/cmd/jaeger/internal/extension/jaegerstorage/extension.go#L133). Currently, this part here will initialize both the primary and archive config. If we refactor |
|
@yurishkuro Got it. So when creating the factory using |
We discussed elsewhere if we even need this flag, or if the same effect can be achieved by tweaking the existing parameters. |
@yurishkuro I think I'm a bit confused about how the config is laid out. For ES, we have a config like the following: some_storage:
elasticsearch:
indices:
index_prefix: "jaeger-main"
spans:
date_layout: "2006-01-02"
rollover_frequency: "day"
shards: 5
replicas: 1
services:
date_layout: "2006-01-02"
rollover_frequency: "day"
shards: 5
replicas: 1
dependencies:
date_layout: "2006-01-02"
rollover_frequency: "day"
shards: 5
replicas: 1
sampling:
date_layout: "2006-01-02"
rollover_frequency: "day"
shards: 5
replicas: 1
another_storage:
elasticsearch:
indices:
index_prefix: "jaeger-archive" How does each config get "chosen" as the primary or the archive configuration? Is it because of this delegation here? jaeger_query:
storage:
traces: some_storage
traces_archive: another_storage |
Yep - that discussion was in #6065 (comment). How would we use maxspanage to decide if we should set isArchive or not? |
@yurishkuro Another question I had was related to the setup of the config. Currently, the |
The namespace configs should go away, they were a mechanism for a single factory to represent multiple storages, which is what we're trying to move away from. One factory, one storage namespace, one role (primary/archive). |
it's used for both reading and writing, by affecting which index names are utilized. We need to inspect that logic to see if the same selections can be made based on existing parameters. |
@yurishkuro If we don't want to change the behaviour of the archive storage for v1, then can we still upgrade the v2 storages in place? If we update the storages to the v2 interface in place and get rid of the v1 implementation, we'll lose the |
…factories (#6526) ## Which problem is this PR solving? - Towards #6065 ## Description of the changes - Some of the storage factories were currently adding the `role` tag to the metrics factory that it was getting to differentiate between `primary` and `archive`. Given that goal in v2 is not have that distinction, the adding of the `primary` tag was moved to the v1 meta-factory. This tag can then be overriden by the archive specific methods in the storage factories (mainly `CreateArchiveSpanReader` and `CreateArchiveSpanWriter`) with `role=archive`. ## How was this change tested? - CI ## Checklist - [x] I have read https://github.com/jaegertracing/jaeger/blob/master/CONTRIBUTING_GUIDELINES.md - [x] I have signed all commits - [x] I have added unit tests for the new functionality - [x] I have run lint and test steps successfully - for `jaeger`: `make lint test` - for `jaeger-ui`: `npm run lint` and `npm run test` --------- Signed-off-by: Mahad Zaryab <[email protected]>
…factories (jaegertracing#6526) ## Which problem is this PR solving? - Towards jaegertracing#6065 ## Description of the changes - Some of the storage factories were currently adding the `role` tag to the metrics factory that it was getting to differentiate between `primary` and `archive`. Given that goal in v2 is not have that distinction, the adding of the `primary` tag was moved to the v1 meta-factory. This tag can then be overriden by the archive specific methods in the storage factories (mainly `CreateArchiveSpanReader` and `CreateArchiveSpanWriter`) with `role=archive`. ## How was this change tested? - CI ## Checklist - [x] I have read https://github.com/jaegertracing/jaeger/blob/master/CONTRIBUTING_GUIDELINES.md - [x] I have signed all commits - [x] I have added unit tests for the new functionality - [x] I have run lint and test steps successfully - for `jaeger`: `make lint test` - for `jaeger-ui`: `npm run lint` and `npm run test` --------- Signed-off-by: Mahad Zaryab <[email protected]>
Update Jan 7 2025: the intention of this issue is to do away with awareness in the code of the differences between primary and archive storage. The two implementations are generally identical, have identical reader/writer API, with only minor changes in behavior that can be managed with more explicit parameters instead if a hardcoded
isArchive
flag. For example, in the "legacy" mode the ES primary storage uses manual rotation of indices, e.g. by creating a new index name every rollover period, whereas archive storage always uses a fixed index name. The latter behavior can be reproduced by settinguse_aliases
flag instead of having an explicit understanding ofisArchive
mode.This unification becomes especially important in Jaeger-v2 where storage backends are already declared uniformly in the
jaeger_storage
extension without any knowledge of primary/archive distinction. The distinction only appears oncejaegerquery
extension retrieves a specific backend by name and uses it as either primary or archive backend, by which point the backend itself is already initialized. The intent is to expose required configuration options to the user such that they can customize the behavior of the backend used for archive as they see fit, e.g. if they still want to rotate the ES indices, they can do so.This thread #6060 (comment)
The text was updated successfully, but these errors were encountered: