Tempo: Check for liveEnabled before trying to stream (#85173)

* Check for liveEnabled before attempting to stream

* Add tests

* Range const

* Update test text
This commit is contained in:
Joey 2024-03-28 09:19:21 +00:00 committed by GitHub
parent 5dd98a0fd5
commit df39fc54a6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 81 additions and 8 deletions

View File

@ -18,6 +18,7 @@ import {
} from '@grafana/data'; } from '@grafana/data';
import { import {
BackendDataSourceResponse, BackendDataSourceResponse,
config,
FetchResponse, FetchResponse,
setBackendSrv, setBackendSrv,
setDataSourceSrv, setDataSourceSrv,
@ -64,6 +65,74 @@ describe('Tempo data source', () => {
afterEach(() => (console.error = origError)); afterEach(() => (console.error = origError));
beforeEach(() => (console.error = consoleErrorMock)); beforeEach(() => (console.error = consoleErrorMock));
describe('runs correctly', () => {
config.featureToggles.traceQLStreaming = true;
jest.spyOn(TempoDatasource.prototype, 'isFeatureAvailable').mockImplementation(() => true);
const handleStreamingSearch = jest.spyOn(TempoDatasource.prototype, 'handleStreamingSearch');
const request = jest.spyOn(TempoDatasource.prototype, '_request');
const templateSrv: TemplateSrv = { replace: (s: string) => s } as unknown as TemplateSrv;
const range = {
from: dateTime(new Date(2022, 8, 13, 16, 0, 0, 0)),
to: dateTime(new Date(2022, 8, 13, 16, 15, 0, 0)),
raw: { from: '15m', to: 'now' },
};
const traceqlQuery = {
targets: [{ refId: 'refid1', queryType: 'traceql', query: '{}' }],
range,
};
const traceqlSearchQuery = {
targets: [
{
refId: 'refid1',
queryType: 'traceqlSearch',
filters: [
{
id: 'service-name',
operator: '=',
scope: TraceqlSearchScope.Resource,
tag: 'service.name',
valueType: 'string',
},
],
},
],
range,
};
it('for traceql queries when live is enabled', async () => {
config.liveEnabled = true;
const ds = new TempoDatasource(defaultSettings, templateSrv);
await lastValueFrom(ds.query(traceqlQuery as DataQueryRequest<TempoQuery>));
expect(handleStreamingSearch).toHaveBeenCalledTimes(1);
expect(request).toHaveBeenCalledTimes(0);
});
it('for traceqlSearch queries when live is enabled', async () => {
config.liveEnabled = true;
const ds = new TempoDatasource(defaultSettings, templateSrv);
await lastValueFrom(ds.query(traceqlSearchQuery as DataQueryRequest<TempoQuery>));
expect(handleStreamingSearch).toHaveBeenCalledTimes(2);
expect(request).toHaveBeenCalledTimes(0);
});
it('for traceql queries when live is not enabled', async () => {
config.liveEnabled = false;
const ds = new TempoDatasource(defaultSettings, templateSrv);
await lastValueFrom(ds.query(traceqlQuery as DataQueryRequest<TempoQuery>));
expect(handleStreamingSearch).toHaveBeenCalledTimes(2);
expect(request).toHaveBeenCalledTimes(1);
});
it('for traceqlSearch queries when live is not enabled', async () => {
config.liveEnabled = false;
const ds = new TempoDatasource(defaultSettings, templateSrv);
await lastValueFrom(ds.query(traceqlSearchQuery as DataQueryRequest<TempoQuery>));
expect(handleStreamingSearch).toHaveBeenCalledTimes(2);
expect(request).toHaveBeenCalledTimes(2);
});
});
it('returns empty response when traceId is empty', async () => { it('returns empty response when traceId is empty', async () => {
const templateSrv: TemplateSrv = { replace: jest.fn() } as unknown as TemplateSrv; const templateSrv: TemplateSrv = { replace: jest.fn() } as unknown as TemplateSrv;
const ds = new TempoDatasource(defaultSettings, templateSrv); const ds = new TempoDatasource(defaultSettings, templateSrv);

View File

@ -242,7 +242,7 @@ export class TempoDatasource extends DataSourceWithBackend<TempoQuery, TempoJson
* @param featureName - the name of the feature to consider * @param featureName - the name of the feature to consider
* @return true if the feature is available, false otherwise * @return true if the feature is available, false otherwise
*/ */
private isFeatureAvailable(featureName: FeatureName) { isFeatureAvailable(featureName: FeatureName) {
// We know for old Tempo instances we don't know their version, so resort to default // We know for old Tempo instances we don't know their version, so resort to default
const actualVersion = this.tempoVersion ?? defaultTempoVersion; const actualVersion = this.tempoVersion ?? defaultTempoVersion;
@ -349,7 +349,11 @@ export class TempoDatasource extends DataSourceWithBackend<TempoQuery, TempoJson
streaming: config.featureToggles.traceQLStreaming, streaming: config.featureToggles.traceQLStreaming,
}); });
if (config.featureToggles.traceQLStreaming && this.isFeatureAvailable(FeatureName.streaming)) { if (
config.featureToggles.traceQLStreaming &&
this.isFeatureAvailable(FeatureName.streaming) &&
config.liveEnabled
) {
subQueries.push(this.handleStreamingSearch(options, traceqlSearchTargets, queryValueFromFilters)); subQueries.push(this.handleStreamingSearch(options, traceqlSearchTargets, queryValueFromFilters));
} else { } else {
subQueries.push( subQueries.push(
@ -599,7 +603,11 @@ export class TempoDatasource extends DataSourceWithBackend<TempoQuery, TempoJson
}, },
queryValue: string queryValue: string
): Observable<DataQueryResponse> => { ): Observable<DataQueryResponse> => {
if (config.featureToggles.traceQLStreaming && this.isFeatureAvailable(FeatureName.streaming)) { if (
config.featureToggles.traceQLStreaming &&
this.isFeatureAvailable(FeatureName.streaming) &&
config.liveEnabled
) {
return this.handleStreamingSearch(options, targets.traceql, queryValue); return this.handleStreamingSearch(options, targets.traceql, queryValue);
} else { } else {
return this._request('/api/search', { return this._request('/api/search', {
@ -690,11 +698,7 @@ export class TempoDatasource extends DataSourceWithBackend<TempoQuery, TempoJson
return await lastValueFrom(this._request(url, params, { method: 'GET', hideFromInspector: true })); return await lastValueFrom(this._request(url, params, { method: 'GET', hideFromInspector: true }));
} }
private _request( _request(apiUrl: string, data?: unknown, options?: Partial<BackendSrvRequest>): Observable<Record<string, any>> {
apiUrl: string,
data?: unknown,
options?: Partial<BackendSrvRequest>
): Observable<Record<string, any>> {
const params = data ? urlUtil.serializeParams(data) : ''; const params = data ? urlUtil.serializeParams(data) : '';
const url = `${this.instanceSettings.url}${apiUrl}${params.length ? `?${params}` : ''}`; const url = `${this.instanceSettings.url}${apiUrl}${params.length ? `?${params}` : ''}`;
const req = { ...options, url }; const req = { ...options, url };