Skip to content

Commit d4e312f

Browse files
authored
fix(default datasource): update default data source resolution (#1771)
* fix(default datasource): update default data source resolution * chore: before each * chore: fix types * chore: change default data source * chore: rename constant
1 parent cd9e1b3 commit d4e312f

File tree

4 files changed

+117
-5
lines changed

4 files changed

+117
-5
lines changed

provisioning/datasources/default.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ apiVersion: 1
22

33
datasources:
44
- name: gdev-testdata
5-
isDefault: true
65
type: testdata
76
- name: gdev-loki
87
type: loki
98
uid: gdev-loki
9+
isDefault: true
1010
access: proxy
1111
url: http://host.docker.internal:3100
1212
jsonData:

src/Components/IndexScene/IndexScene.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ import {
133133
} from 'services/variables';
134134
export const showLogsButtonSceneKey = 'showLogsButtonScene';
135135

136-
const DEFAULT_LOGS_DATASOURCE_UID = 'grafanacloud-logs';
136+
const FALLBACK_DATASOURCE_UID = 'grafanacloud-logs';
137137

138138
interface EmbeddedIndexSceneConstructor {
139139
datasourceUid?: string;
@@ -151,7 +151,7 @@ export class IndexScene extends SceneObjectBase<IndexSceneState> {
151151
jsonData?.dataSource ??
152152
getLastUsedDataSourceFromStorage() ??
153153
getDefaultDatasourceFromDatasourceSrv() ??
154-
DEFAULT_LOGS_DATASOURCE_UID;
154+
FALLBACK_DATASOURCE_UID;
155155

156156
const { unsub, variablesScene } = getVariableSet(
157157
datasourceUid,

src/services/store.test.ts

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import { DataSourceInstanceSettings } from '@grafana/data';
2+
import { getDataSourceSrv } from '@grafana/runtime';
3+
4+
import { getDefaultDatasourceFromDatasourceSrv } from './store';
5+
6+
jest.mock('@grafana/runtime', () => ({
7+
...jest.requireActual('@grafana/runtime'),
8+
getDataSourceSrv: jest.fn(),
9+
}));
10+
11+
function makeDs(overrides: Partial<DataSourceInstanceSettings>): DataSourceInstanceSettings {
12+
return {
13+
uid: 'uid',
14+
id: 1,
15+
name: 'ds',
16+
type: 'loki',
17+
isDefault: false,
18+
readOnly: false,
19+
jsonData: {},
20+
access: 'proxy',
21+
...overrides,
22+
} as DataSourceInstanceSettings;
23+
}
24+
25+
describe('getDefaultDatasourceFromDatasourceSrv', () => {
26+
beforeEach(() => jest.clearAllMocks());
27+
28+
it('returns the data source marked as default when present', () => {
29+
const defaultDs = makeDs({ uid: 'default-uid', name: 'Default Loki', isDefault: true });
30+
const otherDs = makeDs({ uid: 'other-uid', name: 'grafanacloud-mystack-logs', isDefault: false });
31+
jest.mocked(getDataSourceSrv).mockReturnValue({
32+
getList: () => [otherDs, defaultDs],
33+
} as any);
34+
35+
expect(getDefaultDatasourceFromDatasourceSrv()).toBe('default-uid');
36+
});
37+
38+
it('prefers grafanacloud-*-logs by name when no default is set', () => {
39+
const firstInList = makeDs({ uid: 'first-uid', name: 'Some Other Loki' });
40+
const grafanacloudDs = makeDs({
41+
uid: 'grafanacloud-dev-logs',
42+
name: 'grafanacloud-dev-logs',
43+
isDefault: false,
44+
});
45+
jest.mocked(getDataSourceSrv).mockReturnValue({
46+
getList: () => [firstInList, grafanacloudDs],
47+
} as any);
48+
49+
expect(getDefaultDatasourceFromDatasourceSrv()).toBe('grafanacloud-dev-logs');
50+
});
51+
52+
it('prefers grafanacloud-*-logs by uid when name is different', () => {
53+
const firstInList = makeDs({ uid: 'first-uid', name: 'First' });
54+
const grafanacloudDs = makeDs({
55+
uid: 'grafanacloud-prod-logs',
56+
name: 'Grafana Cloud Logs (prod)',
57+
isDefault: false,
58+
});
59+
jest.mocked(getDataSourceSrv).mockReturnValue({
60+
getList: () => [firstInList, grafanacloudDs],
61+
} as any);
62+
63+
expect(getDefaultDatasourceFromDatasourceSrv()).toBe('grafanacloud-prod-logs');
64+
});
65+
66+
it('returns first in list when no default and no grafanacloud-*-logs match', () => {
67+
const firstDs = makeDs({ uid: 'first-uid', name: 'First Loki' });
68+
const secondDs = makeDs({ uid: 'second-uid', name: 'Second Loki' });
69+
jest.mocked(getDataSourceSrv).mockReturnValue({
70+
getList: () => [firstDs, secondDs],
71+
} as any);
72+
73+
expect(getDefaultDatasourceFromDatasourceSrv()).toBe('first-uid');
74+
});
75+
76+
it('returns undefined when Loki list is empty', () => {
77+
jest.mocked(getDataSourceSrv).mockReturnValue({
78+
getList: () => [],
79+
} as any);
80+
81+
expect(getDefaultDatasourceFromDatasourceSrv()).toBeUndefined();
82+
});
83+
84+
it('does not match grafanacloud-logs without stack name (single dash)', () => {
85+
const exactName = makeDs({ uid: 'grafanacloud-logs', name: 'grafanacloud-logs', isDefault: false });
86+
const withStack = makeDs({
87+
uid: 'grafanacloud-mystack-logs',
88+
name: 'grafanacloud-mystack-logs',
89+
isDefault: false,
90+
});
91+
jest.mocked(getDataSourceSrv).mockReturnValue({
92+
getList: () => [exactName, withStack],
93+
} as any);
94+
95+
expect(getDefaultDatasourceFromDatasourceSrv()).toBe('grafanacloud-mystack-logs');
96+
});
97+
});

src/services/store.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,12 +165,27 @@ export function getLastUsedDataSourceFromStorage(): string | undefined {
165165
return localStorage.getItem(DS_LOCALSTORAGE_KEY) ?? undefined;
166166
}
167167

168+
/**
169+
* Matches Grafana Cloud Logs data source names/UIDs: grafanacloud-{stack}-logs
170+
*/
171+
const GRAFANACLOUD_LOGS_DS_PATTERN = /^grafanacloud-.+-logs$/;
172+
168173
export function getDefaultDatasourceFromDatasourceSrv(): string | undefined {
169174
const dsList = getDataSourceSrv().getList({
170175
type: 'loki',
171176
});
172-
const ds = dsList.find((ds) => ds.isDefault);
173-
return ds?.uid ?? dsList?.[0]?.uid;
177+
const defaultDs = dsList.find((ds) => ds.isDefault);
178+
if (defaultDs?.uid) {
179+
return defaultDs.uid;
180+
}
181+
const grafanacloudLogsDs = dsList.find(
182+
(ds) =>
183+
(ds.name && GRAFANACLOUD_LOGS_DS_PATTERN.test(ds.name)) || (ds.uid && GRAFANACLOUD_LOGS_DS_PATTERN.test(ds.uid))
184+
);
185+
if (grafanacloudLogsDs?.uid) {
186+
return grafanacloudLogsDs.uid;
187+
}
188+
return dsList?.[0]?.uid;
174189
}
175190

176191
export function addLastUsedDataSourceToStorage(dsKey: string) {

0 commit comments

Comments
 (0)