Skip to content

Commit

Permalink
Make ArchiveTrace button auto-configurable
Browse files Browse the repository at this point in the history
- Resolves jaegertracing#4874

The button to archive a trace is now configured based on the state of
the QueryService in addition to the UI configuration. It is now
possible to request features from the QueryService to inject them
into the UI.

All corresponding tests have been updated.

- [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

---------

Signed-off-by: Barthelemy Antonin <[email protected]>
  • Loading branch information
thecoons committed Oct 31, 2023
1 parent f99eae5 commit 0c9cd06
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 18 deletions.
19 changes: 19 additions & 0 deletions cmd/query/app/querysvc/query_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ type QueryServiceOptions struct {
Adjuster adjuster.Adjuster
}

// QueryServiceFeature is a feature flag for query service
type QueryServiceFeature struct {
SupportArchive bool
// SupportRegex bool
// SupportTagFilter bool
}

// QueryService contains span utils required by the query-service.
type QueryService struct {
spanReader spanstore.Reader
Expand Down Expand Up @@ -122,6 +129,13 @@ func (qs QueryService) GetDependencies(ctx context.Context, endTs time.Time, loo
return qs.dependencyReader.GetDependencies(ctx, endTs, lookback)
}

// GetFeatures returns the features supported by the query service.
func (qs QueryService) GetFeatures() QueryServiceFeature {
return QueryServiceFeature{
SupportArchive: qs.options.isSupportsArchive(),
}
}

// InitArchiveStorage tries to initialize archive storage reader/writer if storage factory supports them.
func (opts *QueryServiceOptions) InitArchiveStorage(storageFactory storage.Factory, logger *zap.Logger) bool {
archiveFactory, ok := storageFactory.(storage.ArchiveFactory)
Expand Down Expand Up @@ -151,3 +165,8 @@ func (opts *QueryServiceOptions) InitArchiveStorage(storageFactory storage.Facto
opts.ArchiveSpanWriter = writer
return true
}

// isSupportsArchive returns true if archive storage reader/writer are initialized.
func (opts *QueryServiceOptions) isSupportsArchive() bool {
return opts.ArchiveSpanReader != nil && opts.ArchiveSpanWriter != nil
}
18 changes: 18 additions & 0 deletions cmd/query/app/querysvc/query_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,24 @@ func TestGetDependencies(t *testing.T) {
assert.Equal(t, expectedDependencies, actualDependencies)
}

// Test QueryService.GetFeatures()
func TestGetFeatures(t *testing.T) {
tqs := initializeTestService()
expectedQueryServiceFeature := QueryServiceFeature{
SupportArchive: false,
}
assert.Equal(t, expectedQueryServiceFeature, tqs.queryService.GetFeatures())
}

func TestGetFeaturesWithSupportsArchive(t *testing.T) {
tqs := initializeTestService(withArchiveSpanReader(), withArchiveSpanWriter())

expectedQueryServiceFeature := QueryServiceFeature{
SupportArchive: true,
}
assert.Equal(t, expectedQueryServiceFeature, tqs.queryService.GetFeatures())
}

type fakeStorageFactory1 struct{}

type fakeStorageFactory2 struct {
Expand Down
2 changes: 1 addition & 1 deletion cmd/query/app/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ func createHTTPServer(querySvc *querysvc.QueryService, metricsQuerySvc querysvc.
}

apiHandler.RegisterRoutes(r)
RegisterStaticHandler(r, logger, queryOpts)
RegisterStaticHandler(r, logger, queryOpts, querySvc.GetFeatures())
var handler http.Handler = r
handler = additionalHeadersHandler(handler, queryOpts.AdditionalHeaders)
if queryOpts.BearerTokenPropagation {
Expand Down
24 changes: 15 additions & 9 deletions cmd/query/app/static_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/gorilla/mux"
"go.uber.org/zap"

"github.com/jaegertracing/jaeger/cmd/query/app/querysvc"
"github.com/jaegertracing/jaeger/cmd/query/app/ui"
"github.com/jaegertracing/jaeger/pkg/fswatcher"
"github.com/jaegertracing/jaeger/pkg/version"
Expand All @@ -44,10 +45,11 @@ var (
)

// RegisterStaticHandler adds handler for static assets to the router.
func RegisterStaticHandler(r *mux.Router, logger *zap.Logger, qOpts *QueryOptions) {
func RegisterStaticHandler(r *mux.Router, logger *zap.Logger, qOpts *QueryOptions, qFeatures querysvc.QueryServiceFeature) {
staticHandler, err := NewStaticAssetsHandler(qOpts.StaticAssets.Path, StaticAssetsHandlerOptions{
BasePath: qOpts.BasePath,
UIConfigPath: qOpts.UIConfig,
Features: qFeatures,
Logger: logger,
LogAccess: qOpts.StaticAssets.LogAccess,
})
Expand All @@ -71,12 +73,14 @@ type StaticAssetsHandlerOptions struct {
BasePath string
UIConfigPath string
LogAccess bool
Features querysvc.QueryServiceFeature
Logger *zap.Logger
}

type loadedConfig struct {
regexp *regexp.Regexp
config []byte
regexp *regexp.Regexp
backendSupportsArchive bool
config []byte
}

// NewStaticAssetsHandler returns a StaticAssetsHandler
Expand Down Expand Up @@ -118,7 +122,7 @@ func loadAndEnrichIndexHTML(open func(string) (http.File, error), options Static
return nil, fmt.Errorf("cannot load index.html: %w", err)
}
// replace UI config
if configObject, err := loadUIConfig(options.UIConfigPath); err != nil {
if configObject, err := loadUIConfig(options.UIConfigPath, options.Features); err != nil {
return nil, err
} else if configObject != nil {
indexBytes = configObject.regexp.ReplaceAll(indexBytes, configObject.config)
Expand Down Expand Up @@ -164,7 +168,7 @@ func loadIndexHTML(open func(string) (http.File, error)) ([]byte, error) {
return indexBytes, nil
}

func loadUIConfig(uiConfig string) (*loadedConfig, error) {
func loadUIConfig(uiConfig string, features querysvc.QueryServiceFeature) (*loadedConfig, error) {
if uiConfig == "" {
return nil, nil
}
Expand All @@ -185,8 +189,9 @@ func loadUIConfig(uiConfig string) (*loadedConfig, error) {
r, _ = json.Marshal(c)

return &loadedConfig{
regexp: configPattern,
config: append([]byte("JAEGER_CONFIG = "), append(r, byte(';'))...),
regexp: configPattern,
config: append([]byte("JAEGER_CONFIG = "), append(r, byte(';'))...),
backendSupportsArchive: features.SupportArchive,
}, nil
case ".js":
r = bytes.TrimSpace(bytesConfig)
Expand All @@ -196,8 +201,9 @@ func loadUIConfig(uiConfig string) (*loadedConfig, error) {
}

return &loadedConfig{
regexp: configJsPattern,
config: r,
regexp: configJsPattern,
config: r,
backendSupportsArchive: features.SupportArchive,
}, nil
default:
return nil, fmt.Errorf("unrecognized UI config file format, expecting .js or .json file: %v", uiConfig)
Expand Down
26 changes: 18 additions & 8 deletions cmd/query/app/static_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"go.uber.org/zap/zapcore"
"go.uber.org/zap/zaptest/observer"

"github.com/jaegertracing/jaeger/cmd/query/app/querysvc"
"github.com/jaegertracing/jaeger/pkg/testutils"
)

Expand All @@ -58,6 +59,7 @@ func TestRegisterStaticHandlerPanic(t *testing.T) {
},
},
},
querysvc.QueryServiceFeature{SupportArchive: false},
)
})
assert.Contains(t, buf.String(), "Could not create static assets handler")
Expand Down Expand Up @@ -117,7 +119,9 @@ func TestRegisterStaticHandler(t *testing.T) {
BasePath: testCase.basePath,
UIConfig: testCase.UIConfigPath,
},
})
},
querysvc.QueryServiceFeature{SupportArchive: false},
)

server := httptest.NewServer(r)
defer server.Close()
Expand Down Expand Up @@ -206,13 +210,14 @@ func TestHotReloadUIConfig(t *testing.T) {
func TestLoadUIConfig(t *testing.T) {
type testCase struct {
configFile string
features querysvc.QueryServiceFeature
expected *loadedConfig
expectedError string
}

run := func(description string, testCase testCase) {
t.Run(description, func(t *testing.T) {
config, err := loadUIConfig(testCase.configFile)
config, err := loadUIConfig(testCase.configFile, testCase.features)
if testCase.expectedError != "" {
assert.EqualError(t, err, testCase.expectedError)
} else {
Expand All @@ -237,9 +242,11 @@ func TestLoadUIConfig(t *testing.T) {
})
run("json", testCase{
configFile: "fixture/ui-config.json",
features: querysvc.QueryServiceFeature{SupportArchive: true},
expected: &loadedConfig{
config: []byte(`JAEGER_CONFIG = {"x":"y"};`),
regexp: configPattern,
config: []byte(`JAEGER_CONFIG = {"x":"y"};`),
backendSupportsArchive: true,
regexp: configPattern,
},
})
c, _ := json.Marshal(map[string]interface{}{
Expand All @@ -253,8 +260,9 @@ func TestLoadUIConfig(t *testing.T) {
run("json-menu", testCase{
configFile: "fixture/ui-config-menu.json",
expected: &loadedConfig{
config: append([]byte("JAEGER_CONFIG = "), append(c, byte(';'))...),
regexp: configPattern,
config: append([]byte("JAEGER_CONFIG = "), append(c, byte(';'))...),
backendSupportsArchive: false,
regexp: configPattern,
},
})
run("malformed js config", testCase{
Expand All @@ -264,7 +272,8 @@ func TestLoadUIConfig(t *testing.T) {
run("js", testCase{
configFile: "fixture/ui-config.js",
expected: &loadedConfig{
regexp: configJsPattern,
regexp: configJsPattern,
backendSupportsArchive: false,
config: []byte(`function UIConfig(){
return {
x: "y"
Expand All @@ -275,7 +284,8 @@ func TestLoadUIConfig(t *testing.T) {
run("js-menu", testCase{
configFile: "fixture/ui-config-menu.js",
expected: &loadedConfig{
regexp: configJsPattern,
regexp: configJsPattern,
backendSupportsArchive: false,
config: []byte(`function UIConfig(){
return {
menu: [
Expand Down

0 comments on commit 0c9cd06

Please sign in to comment.