The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
grafana/public/app/features/plugins/datasource_srv.ts

326 lines
10 KiB

// Libraries
import coreModule from 'app/angular/core_module';
// Services & Utils
import { importDataSourcePlugin } from './plugin_loader';
import {
GetDataSourceListFilters,
DataSourceSrv as DataSourceService,
getDataSourceSrv as getDataSourceService,
TemplateSrv,
} from '@grafana/runtime';
// Types
import {
AppEvents,
DataSourceApi,
DataSourceInstanceSettings,
DataSourceRef,
DataSourceSelectItem,
ScopedVars,
} from '@grafana/data';
import { auto } from 'angular';
import { GrafanaRootScope } from 'app/routes/GrafanaCtrl';
// Pretend Datasource
import {
dataSource as expressionDatasource,
ExpressionDatasourceUID,
instanceSettings as expressionInstanceSettings,
} from 'app/features/expressions/ExpressionDatasource';
import { DataSourceVariableModel } from '../variables/types';
import { ExpressionDatasourceRef } from '@grafana/runtime/src/utils/DataSourceWithBackend';
export class DatasourceSrv implements DataSourceService {
private datasources: Record<string, DataSourceApi> = {}; // UID
private settingsMapByName: Record<string, DataSourceInstanceSettings> = {};
private settingsMapByUid: Record<string, DataSourceInstanceSettings> = {};
private settingsMapById: Record<string, DataSourceInstanceSettings> = {};
private defaultName = ''; // actually UID
/** @ngInject */
constructor(
private $injector: auto.IInjectorService,
private $rootScope: GrafanaRootScope,
private templateSrv: TemplateSrv
) {}
init(settingsMapByName: Record<string, DataSourceInstanceSettings>, defaultName: string) {
this.datasources = {};
this.settingsMapByUid = {};
this.settingsMapByName = settingsMapByName;
this.defaultName = defaultName;
for (const dsSettings of Object.values(settingsMapByName)) {
if (!dsSettings.uid) {
dsSettings.uid = dsSettings.name; // -- Grafana --, -- Mixed etc
}
this.settingsMapByUid[dsSettings.uid] = dsSettings;
this.settingsMapById[dsSettings.id] = dsSettings;
}
// Preload expressions
this.datasources[ExpressionDatasourceRef.type] = expressionDatasource as any;
this.datasources[ExpressionDatasourceUID] = expressionDatasource as any;
this.settingsMapByUid[ExpressionDatasourceRef.uid] = expressionInstanceSettings;
this.settingsMapByUid[ExpressionDatasourceUID] = expressionInstanceSettings;
}
getDataSourceSettingsByUid(uid: string): DataSourceInstanceSettings | undefined {
return this.settingsMapByUid[uid];
}
getInstanceSettings(ref: string | null | undefined | DataSourceRef): DataSourceInstanceSettings | undefined {
const isstring = typeof ref === 'string';
let nameOrUid = isstring ? (ref as string) : ((ref as any)?.uid as string | undefined);
if (nameOrUid === 'default' || nameOrUid === null || nameOrUid === undefined) {
if (!isstring && ref) {
const type = (ref as any)?.type as string;
if (type === ExpressionDatasourceRef.type) {
return expressionDatasource.instanceSettings;
} else if (type) {
console.log('FIND Default instance for datasource type?', ref);
}
}
return this.settingsMapByUid[this.defaultName] ?? this.settingsMapByName[this.defaultName];
}
// Complex logic to support template variable data source names
// For this we just pick the current or first data source in the variable
if (nameOrUid[0] === '$') {
const interpolatedName = this.templateSrv.replace(nameOrUid, {}, variableInterpolation);
let dsSettings;
if (interpolatedName === 'default') {
dsSettings = this.settingsMapByName[this.defaultName];
} else {
dsSettings = this.settingsMapByUid[interpolatedName] ?? this.settingsMapByName[interpolatedName];
}
if (!dsSettings) {
return undefined;
}
// Return an instance with un-interpolated values for name and uid
return {
...dsSettings,
isDefault: false,
name: nameOrUid,
uid: nameOrUid,
};
}
return this.settingsMapByUid[nameOrUid] ?? this.settingsMapByName[nameOrUid];
}
get(ref?: string | DataSourceRef | null, scopedVars?: ScopedVars): Promise<DataSourceApi> {
let nameOrUid = typeof ref === 'string' ? (ref as string) : ((ref as any)?.uid as string | undefined);
if (!nameOrUid) {
return this.get(this.defaultName);
}
// Check if nameOrUid matches a uid and then get the name
const byName = this.settingsMapByName[nameOrUid];
if (byName) {
nameOrUid = byName.uid;
}
// This check is duplicated below, this is here mainly as performance optimization to skip interpolation
if (this.datasources[nameOrUid]) {
return Promise.resolve(this.datasources[nameOrUid]);
}
// Interpolation here is to support template variable in data source selection
nameOrUid = this.templateSrv.replace(nameOrUid, scopedVars, variableInterpolation);
if (nameOrUid === 'default' && this.defaultName !== 'default') {
return this.get(this.defaultName);
}
if (this.datasources[nameOrUid]) {
return Promise.resolve(this.datasources[nameOrUid]);
}
return this.loadDatasource(nameOrUid);
}
async loadDatasource(key: string): Promise<DataSourceApi<any, any>> {
if (this.datasources[key]) {
return Promise.resolve(this.datasources[key]);
}
// find the metadata
const dsConfig = this.settingsMapByUid[key] ?? this.settingsMapByName[key] ?? this.settingsMapById[key];
if (!dsConfig) {
return Promise.reject({ message: `Datasource ${key} was not found` });
}
Chore: Remove angular dependency from backendSrv (#20999) * Chore: Remove angular dependency from backendSrv * Refactor: Naive soultion for logging out unauthorized users * Refactor: Restructures to different streams * Refactor: Restructures datasourceRequest * Refactor: Flipped back if statement * Refactor: Extracted getFromFetchStream * Refactor: Extracts toFailureStream operation * Refactor: Fixes issue when options.params contains arrays * Refactor: Fixes broken test (but we need a lot more) * Refactor: Adds explaining comments * Refactor: Adds latest RxJs version so cancellations work * Refactor: Cleans up the takeUntil code * Refactor: Adds tests for request function * Refactor: Separates into smaller functions * Refactor: Adds last error tests * Started to changed so we require getBackendSrv from the @grafana-runtime when applicable. * Using the getBackendSrv from @grafana/runtime. * Changed so we use the getBackendSrv from the @grafana-runtime when possible. * Fixed so Server Admin -> Orgs works again. * Removed unused dependency. * Fixed digest issues on the Server Admin -> Users page. * Fix: Fixes digest problems in Playlists * Fix: Fixes digest issues in VersionHistory * Tests: Fixes broken tests * Fix: Fixes digest issues in Alerting => Notification channels * Fixed digest issues on the Intive page. * Fixed so we run digest after password reset email sent. * Fixed digest issue when trying to sign up account. * Fixed so the Server Admin -> Edit Org works with backendSrv * Fixed so Server Admin -> Users works with backend srv. * Fixed digest issues in Server Admin -> Orgs * Fix: Fixes digest issues in DashList plugin * Fixed digest issues on Server Admin -> users. * Fix: Fixes digest issues with Snapshots * Fixed digest issue when deleting a user. * Fix: Fixes digest issues with dashLink * Chore: Changes RxJs version to 6.5.4 which includes the same cancellation fix * Fix: Fixes digest issue when toggling folder in manage dashboards * Fix: Fixes bug in executeInOrder * Fix: Fixes digest issue with CreateFolderCtrl and FolderDashboardsCtrl * Fix: Fixes tslint error in test * Refactor: Changes default behaviour for emitted messages as before migration * Fix: Fixes various digest issues when saving, starring or deleting dashboards * Fix: Fixes digest issues with FolderPickerCtrl * Fixed digest issue. * Fixed digest issues. * Fixed issues with angular digest. * Removed the this.digest pattern. Co-authored-by: Hugo Häggmark <hugo.haggmark@gmail.com> Co-authored-by: Marcus Andersson <systemvetaren@gmail.com>
6 years ago
try {
const dsPlugin = await importDataSourcePlugin(dsConfig.meta);
// check if its in cache now
if (this.datasources[key]) {
return this.datasources[key];
Chore: Remove angular dependency from backendSrv (#20999) * Chore: Remove angular dependency from backendSrv * Refactor: Naive soultion for logging out unauthorized users * Refactor: Restructures to different streams * Refactor: Restructures datasourceRequest * Refactor: Flipped back if statement * Refactor: Extracted getFromFetchStream * Refactor: Extracts toFailureStream operation * Refactor: Fixes issue when options.params contains arrays * Refactor: Fixes broken test (but we need a lot more) * Refactor: Adds explaining comments * Refactor: Adds latest RxJs version so cancellations work * Refactor: Cleans up the takeUntil code * Refactor: Adds tests for request function * Refactor: Separates into smaller functions * Refactor: Adds last error tests * Started to changed so we require getBackendSrv from the @grafana-runtime when applicable. * Using the getBackendSrv from @grafana/runtime. * Changed so we use the getBackendSrv from the @grafana-runtime when possible. * Fixed so Server Admin -> Orgs works again. * Removed unused dependency. * Fixed digest issues on the Server Admin -> Users page. * Fix: Fixes digest problems in Playlists * Fix: Fixes digest issues in VersionHistory * Tests: Fixes broken tests * Fix: Fixes digest issues in Alerting => Notification channels * Fixed digest issues on the Intive page. * Fixed so we run digest after password reset email sent. * Fixed digest issue when trying to sign up account. * Fixed so the Server Admin -> Edit Org works with backendSrv * Fixed so Server Admin -> Users works with backend srv. * Fixed digest issues in Server Admin -> Orgs * Fix: Fixes digest issues in DashList plugin * Fixed digest issues on Server Admin -> users. * Fix: Fixes digest issues with Snapshots * Fixed digest issue when deleting a user. * Fix: Fixes digest issues with dashLink * Chore: Changes RxJs version to 6.5.4 which includes the same cancellation fix * Fix: Fixes digest issue when toggling folder in manage dashboards * Fix: Fixes bug in executeInOrder * Fix: Fixes digest issue with CreateFolderCtrl and FolderDashboardsCtrl * Fix: Fixes tslint error in test * Refactor: Changes default behaviour for emitted messages as before migration * Fix: Fixes various digest issues when saving, starring or deleting dashboards * Fix: Fixes digest issues with FolderPickerCtrl * Fixed digest issue. * Fixed digest issues. * Fixed issues with angular digest. * Removed the this.digest pattern. Co-authored-by: Hugo Häggmark <hugo.haggmark@gmail.com> Co-authored-by: Marcus Andersson <systemvetaren@gmail.com>
6 years ago
}
Chore: Remove angular dependency from backendSrv (#20999) * Chore: Remove angular dependency from backendSrv * Refactor: Naive soultion for logging out unauthorized users * Refactor: Restructures to different streams * Refactor: Restructures datasourceRequest * Refactor: Flipped back if statement * Refactor: Extracted getFromFetchStream * Refactor: Extracts toFailureStream operation * Refactor: Fixes issue when options.params contains arrays * Refactor: Fixes broken test (but we need a lot more) * Refactor: Adds explaining comments * Refactor: Adds latest RxJs version so cancellations work * Refactor: Cleans up the takeUntil code * Refactor: Adds tests for request function * Refactor: Separates into smaller functions * Refactor: Adds last error tests * Started to changed so we require getBackendSrv from the @grafana-runtime when applicable. * Using the getBackendSrv from @grafana/runtime. * Changed so we use the getBackendSrv from the @grafana-runtime when possible. * Fixed so Server Admin -> Orgs works again. * Removed unused dependency. * Fixed digest issues on the Server Admin -> Users page. * Fix: Fixes digest problems in Playlists * Fix: Fixes digest issues in VersionHistory * Tests: Fixes broken tests * Fix: Fixes digest issues in Alerting => Notification channels * Fixed digest issues on the Intive page. * Fixed so we run digest after password reset email sent. * Fixed digest issue when trying to sign up account. * Fixed so the Server Admin -> Edit Org works with backendSrv * Fixed so Server Admin -> Users works with backend srv. * Fixed digest issues in Server Admin -> Orgs * Fix: Fixes digest issues in DashList plugin * Fixed digest issues on Server Admin -> users. * Fix: Fixes digest issues with Snapshots * Fixed digest issue when deleting a user. * Fix: Fixes digest issues with dashLink * Chore: Changes RxJs version to 6.5.4 which includes the same cancellation fix * Fix: Fixes digest issue when toggling folder in manage dashboards * Fix: Fixes bug in executeInOrder * Fix: Fixes digest issue with CreateFolderCtrl and FolderDashboardsCtrl * Fix: Fixes tslint error in test * Refactor: Changes default behaviour for emitted messages as before migration * Fix: Fixes various digest issues when saving, starring or deleting dashboards * Fix: Fixes digest issues with FolderPickerCtrl * Fixed digest issue. * Fixed digest issues. * Fixed issues with angular digest. * Removed the this.digest pattern. Co-authored-by: Hugo Häggmark <hugo.haggmark@gmail.com> Co-authored-by: Marcus Andersson <systemvetaren@gmail.com>
6 years ago
// If there is only one constructor argument it is instanceSettings
const useAngular = dsPlugin.DataSourceClass.length !== 1;
const instance: DataSourceApi = useAngular
? this.$injector.instantiate(dsPlugin.DataSourceClass, {
instanceSettings: dsConfig,
})
: new dsPlugin.DataSourceClass(dsConfig);
instance.components = dsPlugin.components;
instance.meta = dsConfig.meta;
// store in instance cache
this.datasources[key] = instance;
this.datasources[instance.uid] = instance;
Chore: Remove angular dependency from backendSrv (#20999) * Chore: Remove angular dependency from backendSrv * Refactor: Naive soultion for logging out unauthorized users * Refactor: Restructures to different streams * Refactor: Restructures datasourceRequest * Refactor: Flipped back if statement * Refactor: Extracted getFromFetchStream * Refactor: Extracts toFailureStream operation * Refactor: Fixes issue when options.params contains arrays * Refactor: Fixes broken test (but we need a lot more) * Refactor: Adds explaining comments * Refactor: Adds latest RxJs version so cancellations work * Refactor: Cleans up the takeUntil code * Refactor: Adds tests for request function * Refactor: Separates into smaller functions * Refactor: Adds last error tests * Started to changed so we require getBackendSrv from the @grafana-runtime when applicable. * Using the getBackendSrv from @grafana/runtime. * Changed so we use the getBackendSrv from the @grafana-runtime when possible. * Fixed so Server Admin -> Orgs works again. * Removed unused dependency. * Fixed digest issues on the Server Admin -> Users page. * Fix: Fixes digest problems in Playlists * Fix: Fixes digest issues in VersionHistory * Tests: Fixes broken tests * Fix: Fixes digest issues in Alerting => Notification channels * Fixed digest issues on the Intive page. * Fixed so we run digest after password reset email sent. * Fixed digest issue when trying to sign up account. * Fixed so the Server Admin -> Edit Org works with backendSrv * Fixed so Server Admin -> Users works with backend srv. * Fixed digest issues in Server Admin -> Orgs * Fix: Fixes digest issues in DashList plugin * Fixed digest issues on Server Admin -> users. * Fix: Fixes digest issues with Snapshots * Fixed digest issue when deleting a user. * Fix: Fixes digest issues with dashLink * Chore: Changes RxJs version to 6.5.4 which includes the same cancellation fix * Fix: Fixes digest issue when toggling folder in manage dashboards * Fix: Fixes bug in executeInOrder * Fix: Fixes digest issue with CreateFolderCtrl and FolderDashboardsCtrl * Fix: Fixes tslint error in test * Refactor: Changes default behaviour for emitted messages as before migration * Fix: Fixes various digest issues when saving, starring or deleting dashboards * Fix: Fixes digest issues with FolderPickerCtrl * Fixed digest issue. * Fixed digest issues. * Fixed issues with angular digest. * Removed the this.digest pattern. Co-authored-by: Hugo Häggmark <hugo.haggmark@gmail.com> Co-authored-by: Marcus Andersson <systemvetaren@gmail.com>
6 years ago
return instance;
} catch (err) {
if (this.$rootScope) {
this.$rootScope.appEvent(AppEvents.alertError, [dsConfig.name + ' plugin failed', err.toString()]);
}
return Promise.reject({ message: `Datasource: ${key} was not found` });
Chore: Remove angular dependency from backendSrv (#20999) * Chore: Remove angular dependency from backendSrv * Refactor: Naive soultion for logging out unauthorized users * Refactor: Restructures to different streams * Refactor: Restructures datasourceRequest * Refactor: Flipped back if statement * Refactor: Extracted getFromFetchStream * Refactor: Extracts toFailureStream operation * Refactor: Fixes issue when options.params contains arrays * Refactor: Fixes broken test (but we need a lot more) * Refactor: Adds explaining comments * Refactor: Adds latest RxJs version so cancellations work * Refactor: Cleans up the takeUntil code * Refactor: Adds tests for request function * Refactor: Separates into smaller functions * Refactor: Adds last error tests * Started to changed so we require getBackendSrv from the @grafana-runtime when applicable. * Using the getBackendSrv from @grafana/runtime. * Changed so we use the getBackendSrv from the @grafana-runtime when possible. * Fixed so Server Admin -> Orgs works again. * Removed unused dependency. * Fixed digest issues on the Server Admin -> Users page. * Fix: Fixes digest problems in Playlists * Fix: Fixes digest issues in VersionHistory * Tests: Fixes broken tests * Fix: Fixes digest issues in Alerting => Notification channels * Fixed digest issues on the Intive page. * Fixed so we run digest after password reset email sent. * Fixed digest issue when trying to sign up account. * Fixed so the Server Admin -> Edit Org works with backendSrv * Fixed so Server Admin -> Users works with backend srv. * Fixed digest issues in Server Admin -> Orgs * Fix: Fixes digest issues in DashList plugin * Fixed digest issues on Server Admin -> users. * Fix: Fixes digest issues with Snapshots * Fixed digest issue when deleting a user. * Fix: Fixes digest issues with dashLink * Chore: Changes RxJs version to 6.5.4 which includes the same cancellation fix * Fix: Fixes digest issue when toggling folder in manage dashboards * Fix: Fixes bug in executeInOrder * Fix: Fixes digest issue with CreateFolderCtrl and FolderDashboardsCtrl * Fix: Fixes tslint error in test * Refactor: Changes default behaviour for emitted messages as before migration * Fix: Fixes various digest issues when saving, starring or deleting dashboards * Fix: Fixes digest issues with FolderPickerCtrl * Fixed digest issue. * Fixed digest issues. * Fixed issues with angular digest. * Removed the this.digest pattern. Co-authored-by: Hugo Häggmark <hugo.haggmark@gmail.com> Co-authored-by: Marcus Andersson <systemvetaren@gmail.com>
6 years ago
}
}
getAll(): DataSourceInstanceSettings[] {
return Object.values(this.settingsMapByName);
}
getList(filters: GetDataSourceListFilters = {}): DataSourceInstanceSettings[] {
const base = Object.values(this.settingsMapByName).filter((x) => {
if (x.meta.id === 'grafana' || x.meta.id === 'mixed' || x.meta.id === 'dashboard') {
return false;
}
if (filters.metrics && !x.meta.metrics) {
return false;
}
if (filters.alerting && !x.meta.alerting) {
return false;
}
if (filters.tracing && !x.meta.tracing) {
return false;
}
if (filters.annotations && !x.meta.annotations) {
return false;
}
if (filters.alerting && !x.meta.alerting) {
return false;
}
if (filters.pluginId && x.meta.id !== filters.pluginId) {
return false;
}
if (filters.filter && !filters.filter(x)) {
return false;
}
if (filters.type && (Array.isArray(filters.type) ? !filters.type.includes(x.type) : filters.type !== x.type)) {
return false;
}
if (
!filters.all &&
x.meta.metrics !== true &&
x.meta.annotations !== true &&
x.meta.tracing !== true &&
x.meta.logs !== true &&
x.meta.alerting !== true
) {
return false;
}
return true;
});
if (filters.variables) {
for (const variable of this.templateSrv.getVariables().filter((variable) => variable.type === 'datasource')) {
const dsVar = variable as DataSourceVariableModel;
const first = dsVar.current.value === 'default' ? this.defaultName : dsVar.current.value;
const dsName = (first as unknown) as string;
const dsSettings = this.settingsMapByName[dsName];
if (dsSettings) {
const key = `$\{${variable.name}\}`;
base.push({
...dsSettings,
name: key,
uid: key,
});
}
}
}
const sorted = base.sort((a, b) => {
if (a.name.toLowerCase() > b.name.toLowerCase()) {
return 1;
}
if (a.name.toLowerCase() < b.name.toLowerCase()) {
return -1;
}
return 0;
});
if (!filters.pluginId && !filters.alerting) {
if (filters.mixed) {
base.push(this.getInstanceSettings('-- Mixed --')!);
}
if (filters.dashboard) {
base.push(this.getInstanceSettings('-- Dashboard --')!);
}
if (!filters.tracing) {
base.push(this.getInstanceSettings('-- Grafana --')!);
}
}
return sorted;
}
/**
* @deprecated use getList
* */
getExternal(): DataSourceInstanceSettings[] {
return this.getList();
}
/**
* @deprecated use getList
* */
getAnnotationSources() {
return this.getList({ annotations: true, variables: true }).map((x) => {
return {
name: x.name,
value: x.isDefault ? null : x.name,
meta: x.meta,
};
});
}
/**
* @deprecated use getList
* */
getMetricSources(options?: { skipVariables?: boolean }): DataSourceSelectItem[] {
return this.getList({ metrics: true, variables: !options?.skipVariables }).map((x) => {
return {
name: x.name,
value: x.isDefault ? null : x.name,
meta: x.meta,
};
});
}
}
export function variableInterpolation(value: any[]) {
if (Array.isArray(value)) {
return value[0];
}
return value;
}
export const getDatasourceSrv = (): DatasourceSrv => {
return getDataSourceService() as DatasourceSrv;
};
coreModule.service('datasourceSrv', DatasourceSrv);
export default DatasourceSrv;