1import { Observable } from 'rxjs'; 2import { ComponentType } from 'react'; 3import { GrafanaPlugin, PluginMeta } from './plugin'; 4import { PanelData } from './panel'; 5import { LogRowModel } from './logs'; 6import { AnnotationEvent, AnnotationQuery, AnnotationSupport } from './annotations'; 7import { KeyValue, LoadingState, TableData, TimeSeries } from './data'; 8import { DataFrame, DataFrameDTO } from './dataFrame'; 9import { RawTimeRange, TimeRange } from './time'; 10import { ScopedVars } from './ScopedVars'; 11import { CoreApp } from './app'; 12import { CustomVariableSupport, DataSourceVariableSupport, StandardVariableSupport } from './variables'; 13import { makeClassES5Compatible } from '../utils/makeClassES5Compatible'; 14import { DataQuery } from './query'; 15import { DataSourceRef } from '.'; 16 17export interface DataSourcePluginOptionsEditorProps<JSONData = DataSourceJsonData, SecureJSONData = {}> { 18 options: DataSourceSettings<JSONData, SecureJSONData>; 19 onOptionsChange: (options: DataSourceSettings<JSONData, SecureJSONData>) => void; 20} 21 22// Utility type to extract the query type TQuery from a class extending DataSourceApi<TQuery, TOptions> 23export type DataSourceQueryType<DSType> = DSType extends DataSourceApi<infer TQuery, any> ? TQuery : never; 24 25// Utility type to extract the options type TOptions from a class extending DataSourceApi<TQuery, TOptions> 26export type DataSourceOptionsType<DSType> = DSType extends DataSourceApi<any, infer TOptions> ? TOptions : never; 27 28export class DataSourcePlugin< 29 DSType extends DataSourceApi<TQuery, TOptions>, 30 TQuery extends DataQuery = DataSourceQueryType<DSType>, 31 TOptions extends DataSourceJsonData = DataSourceOptionsType<DSType>, 32 TSecureOptions = {} 33> extends GrafanaPlugin<DataSourcePluginMeta<TOptions>> { 34 components: DataSourcePluginComponents<DSType, TQuery, TOptions, TSecureOptions> = {}; 35 36 constructor(public DataSourceClass: DataSourceConstructor<DSType, TQuery, TOptions>) { 37 super(); 38 } 39 40 setConfigEditor(editor: ComponentType<DataSourcePluginOptionsEditorProps<TOptions, TSecureOptions>>) { 41 this.components.ConfigEditor = editor; 42 return this; 43 } 44 45 setConfigCtrl(ConfigCtrl: any) { 46 this.angularConfigCtrl = ConfigCtrl; 47 return this; 48 } 49 50 setQueryCtrl(QueryCtrl: any) { 51 this.components.QueryCtrl = QueryCtrl; 52 return this; 53 } 54 55 setAnnotationQueryCtrl(AnnotationsQueryCtrl: any) { 56 this.components.AnnotationsQueryCtrl = AnnotationsQueryCtrl; 57 return this; 58 } 59 60 setQueryEditor(QueryEditor: ComponentType<QueryEditorProps<DSType, TQuery, TOptions>>) { 61 this.components.QueryEditor = QueryEditor; 62 return this; 63 } 64 65 setExploreQueryField(ExploreQueryField: ComponentType<QueryEditorProps<DSType, TQuery, TOptions>>) { 66 this.components.ExploreQueryField = ExploreQueryField; 67 return this; 68 } 69 70 setExploreMetricsQueryField(ExploreQueryField: ComponentType<QueryEditorProps<DSType, TQuery, TOptions>>) { 71 this.components.ExploreMetricsQueryField = ExploreQueryField; 72 return this; 73 } 74 75 setExploreLogsQueryField(ExploreQueryField: ComponentType<QueryEditorProps<DSType, TQuery, TOptions>>) { 76 this.components.ExploreLogsQueryField = ExploreQueryField; 77 return this; 78 } 79 80 setQueryEditorHelp(QueryEditorHelp: ComponentType<QueryEditorHelpProps<TQuery>>) { 81 this.components.QueryEditorHelp = QueryEditorHelp; 82 return this; 83 } 84 85 /** 86 * @deprecated prefer using `setQueryEditorHelp` 87 */ 88 setExploreStartPage(ExploreStartPage: ComponentType<QueryEditorHelpProps<TQuery>>) { 89 return this.setQueryEditorHelp(ExploreStartPage); 90 } 91 92 /* 93 * @deprecated -- prefer using {@link StandardVariableSupport} or {@link CustomVariableSupport} or {@link DataSourceVariableSupport} in data source instead 94 * */ 95 setVariableQueryEditor(VariableQueryEditor: any) { 96 this.components.VariableQueryEditor = VariableQueryEditor; 97 return this; 98 } 99 100 setMetadataInspector(MetadataInspector: ComponentType<MetadataInspectorProps<DSType, TQuery, TOptions>>) { 101 this.components.MetadataInspector = MetadataInspector; 102 return this; 103 } 104 105 setComponentsFromLegacyExports(pluginExports: any) { 106 this.angularConfigCtrl = pluginExports.ConfigCtrl; 107 108 this.components.QueryCtrl = pluginExports.QueryCtrl; 109 this.components.AnnotationsQueryCtrl = pluginExports.AnnotationsQueryCtrl; 110 this.components.ExploreQueryField = pluginExports.ExploreQueryField; 111 this.components.QueryEditor = pluginExports.QueryEditor; 112 this.components.QueryEditorHelp = pluginExports.QueryEditorHelp; 113 this.components.VariableQueryEditor = pluginExports.VariableQueryEditor; 114 } 115} 116 117export interface DataSourcePluginMeta<T extends KeyValue = {}> extends PluginMeta<T> { 118 builtIn?: boolean; // Is this for all 119 metrics?: boolean; 120 logs?: boolean; 121 annotations?: boolean; 122 alerting?: boolean; 123 tracing?: boolean; 124 mixed?: boolean; 125 hasQueryHelp?: boolean; 126 category?: string; 127 queryOptions?: PluginMetaQueryOptions; 128 sort?: number; 129 streaming?: boolean; 130 unlicensed?: boolean; 131 backend?: boolean; 132 isBackend?: boolean; 133} 134 135interface PluginMetaQueryOptions { 136 cacheTimeout?: boolean; 137 maxDataPoints?: boolean; 138 minInterval?: boolean; 139} 140 141export interface DataSourcePluginComponents< 142 DSType extends DataSourceApi<TQuery, TOptions>, 143 TQuery extends DataQuery = DataQuery, 144 TOptions extends DataSourceJsonData = DataSourceJsonData, 145 TSecureOptions = {} 146> { 147 QueryCtrl?: any; 148 AnnotationsQueryCtrl?: any; 149 VariableQueryEditor?: any; 150 QueryEditor?: ComponentType<QueryEditorProps<DSType, TQuery, TOptions>>; 151 ExploreQueryField?: ComponentType<QueryEditorProps<DSType, TQuery, TOptions>>; 152 ExploreMetricsQueryField?: ComponentType<QueryEditorProps<DSType, TQuery, TOptions>>; 153 ExploreLogsQueryField?: ComponentType<QueryEditorProps<DSType, TQuery, TOptions>>; 154 QueryEditorHelp?: ComponentType<QueryEditorHelpProps<TQuery>>; 155 ConfigEditor?: ComponentType<DataSourcePluginOptionsEditorProps<TOptions, TSecureOptions>>; 156 MetadataInspector?: ComponentType<MetadataInspectorProps<DSType, TQuery, TOptions>>; 157} 158 159// Only exported for tests 160export interface DataSourceConstructor< 161 DSType extends DataSourceApi<TQuery, TOptions>, 162 TQuery extends DataQuery = DataQuery, 163 TOptions extends DataSourceJsonData = DataSourceJsonData 164> { 165 new (instanceSettings: DataSourceInstanceSettings<TOptions>, ...args: any[]): DSType; 166} 167 168/** 169 * The main data source abstraction interface, represents an instance of a data source 170 * 171 * Although this is a class, datasource implementations do not *yet* need to extend it. 172 * As such, we can not yet add functions with default implementations. 173 */ 174abstract class DataSourceApi< 175 TQuery extends DataQuery = DataQuery, 176 TOptions extends DataSourceJsonData = DataSourceJsonData, 177 TQueryImportConfiguration extends Record<string, object> = {} 178> { 179 /** 180 * Set in constructor 181 */ 182 readonly name: string; 183 184 /** 185 * Set in constructor 186 */ 187 readonly id: number; 188 189 /** 190 * Set in constructor 191 */ 192 readonly type: string; 193 194 /** 195 * Set in constructor 196 */ 197 readonly uid: string; 198 199 /** 200 * min interval range 201 */ 202 interval?: string; 203 204 constructor(instanceSettings: DataSourceInstanceSettings<TOptions>) { 205 this.name = instanceSettings.name; 206 this.id = instanceSettings.id; 207 this.type = instanceSettings.type; 208 this.meta = instanceSettings.meta; 209 this.uid = instanceSettings.uid; 210 } 211 212 /** 213 * Imports queries from a different datasource 214 */ 215 async importQueries?(queries: DataQuery[], originDataSource: DataSourceApi<DataQuery>): Promise<TQuery[]>; 216 217 /** 218 * Returns configuration for importing queries from other data sources 219 */ 220 getImportQueryConfiguration?(): TQueryImportConfiguration; 221 222 /** 223 * Initializes a datasource after instantiation 224 */ 225 init?: () => void; 226 227 /** 228 * Query for data, and optionally stream results 229 */ 230 abstract query(request: DataQueryRequest<TQuery>): Promise<DataQueryResponse> | Observable<DataQueryResponse>; 231 232 /** 233 * Test & verify datasource settings & connection details (returning TestingStatus) 234 * 235 * When verification fails - errors specific to the data source should be handled here and converted to 236 * a TestingStatus object. Unknown errors and HTTP errors can be re-thrown and will be handled here: 237 * public/app/features/datasources/state/actions.ts 238 */ 239 abstract testDatasource(): Promise<any>; 240 241 /** 242 * Override to skip executing a query 243 * 244 * @returns false if the query should be skipped 245 * 246 * @virtual 247 */ 248 filterQuery?(query: TQuery): boolean; 249 250 /** 251 * Get hints for query improvements 252 */ 253 getQueryHints?(query: TQuery, results: any[], ...rest: any): QueryHint[]; 254 255 /** 256 * Convert a query to a simple text string 257 */ 258 getQueryDisplayText?(query: TQuery): string; 259 260 /** 261 * @deprecated getLogRowContext and showContextToggle in `DataSourceApi` is deprecated. 262 * 263 * DataSourceWithLogsContextSupport should be implemented instead (these methods have exactly 264 * the same signature in DataSourceWithLogsContextSupport). 265 * This method will be removed from DataSourceApi in the future. Some editors may still show 266 * a deprecation warning which can be ignored for time being. 267 */ 268 getLogRowContext?: <TContextQueryOptions extends {}>( 269 row: LogRowModel, 270 options?: TContextQueryOptions 271 ) => Promise<DataQueryResponse>; 272 273 /** 274 * @deprecated getLogRowContext and showContextToggle in `DataSourceApi` is deprecated. 275 * 276 * DataSourceWithLogsContextSupport should be implemented instead (these methods have exactly 277 * the same signature in DataSourceWithLogsContextSupport). 278 * This method will be removed from DataSourceApi in the future. Some editors may still show 279 * a deprecation warning which can be ignored for time being. 280 */ 281 showContextToggle?(row?: LogRowModel): boolean; 282 283 /** 284 * Variable query action. 285 */ 286 metricFindQuery?(query: any, options?: any): Promise<MetricFindValue[]>; 287 288 /** 289 * Get tag keys for adhoc filters 290 */ 291 getTagKeys?(options?: any): Promise<MetricFindValue[]>; 292 293 /** 294 * Get tag values for adhoc filters 295 */ 296 getTagValues?(options: any): Promise<MetricFindValue[]>; 297 298 /** 299 * Set after constructor call, as the data source instance is the most common thing to pass around 300 * we attach the components to this instance for easy access 301 */ 302 components?: DataSourcePluginComponents<DataSourceApi<TQuery, TOptions>, TQuery, TOptions>; 303 304 /** 305 * static information about the datasource 306 */ 307 meta: DataSourcePluginMeta; 308 309 /** 310 * Used by alerting to check if query contains template variables 311 */ 312 targetContainsTemplate?(query: TQuery): boolean; 313 314 /** 315 * Used in explore 316 */ 317 modifyQuery?(query: TQuery, action: QueryFixAction): TQuery; 318 319 /** 320 * @deprecated since version 8.2.0 321 * Not used anymore. 322 */ 323 getHighlighterExpression?(query: TQuery): string[]; 324 325 /** Get an identifier object for this datasource instance */ 326 getRef(): DataSourceRef { 327 return { type: this.type, uid: this.uid }; 328 } 329 330 /** 331 * Used in explore 332 */ 333 languageProvider?: any; 334 335 getVersion?(optionalOptions?: any): Promise<string>; 336 337 interpolateVariablesInQueries?(queries: TQuery[], scopedVars: ScopedVars | {}): TQuery[]; 338 339 /** 340 * An annotation processor allows explicit control for how annotations are managed. 341 * 342 * It is only necessary to configure an annotation processor if the default behavior is not desirable 343 */ 344 annotations?: AnnotationSupport<TQuery>; 345 346 /** 347 * Can be optionally implemented to allow datasource to be a source of annotations for dashboard. 348 * This function will only be called if an angular {@link AnnotationsQueryCtrl} is configured and 349 * the {@link annotations} is undefined 350 * 351 * @deprecated -- prefer using {@link AnnotationSupport} 352 */ 353 annotationQuery?(options: AnnotationQueryRequest<TQuery>): Promise<AnnotationEvent[]>; 354 355 /** 356 * Defines new variable support 357 * @alpha -- experimental 358 */ 359 variables?: 360 | StandardVariableSupport<DataSourceApi<TQuery, TOptions>> 361 | CustomVariableSupport<DataSourceApi<TQuery, TOptions>> 362 | DataSourceVariableSupport<DataSourceApi<TQuery, TOptions>>; 363} 364 365export interface MetadataInspectorProps< 366 DSType extends DataSourceApi<TQuery, TOptions>, 367 TQuery extends DataQuery = DataQuery, 368 TOptions extends DataSourceJsonData = DataSourceJsonData 369> { 370 datasource: DSType; 371 372 // All Data from this DataSource 373 data: DataFrame[]; 374} 375 376export interface QueryEditorProps< 377 DSType extends DataSourceApi<TQuery, TOptions>, 378 TQuery extends DataQuery = DataQuery, 379 TOptions extends DataSourceJsonData = DataSourceJsonData, 380 TVQuery extends DataQuery = TQuery 381> { 382 datasource: DSType; 383 query: TVQuery; 384 onRunQuery: () => void; 385 onChange: (value: TVQuery) => void; 386 onBlur?: () => void; 387 /** 388 * Contains query response filtered by refId of QueryResultBase and possible query error 389 */ 390 data?: PanelData; 391 range?: TimeRange; 392 exploreId?: any; 393 history?: Array<HistoryItem<TQuery>>; 394 queries?: DataQuery[]; 395 app?: CoreApp; 396} 397 398// TODO: not really needed but used as type in some data sources and in DataQueryRequest 399export enum ExploreMode { 400 Logs = 'Logs', 401 Metrics = 'Metrics', 402 Tracing = 'Tracing', 403} 404 405/** 406 * @deprecated use QueryEditorProps instead 407 */ 408export type ExploreQueryFieldProps< 409 DSType extends DataSourceApi<TQuery, TOptions>, 410 TQuery extends DataQuery = DataQuery, 411 TOptions extends DataSourceJsonData = DataSourceJsonData 412> = QueryEditorProps<DSType, TQuery, TOptions>; 413 414export interface QueryEditorHelpProps<TQuery extends DataQuery = DataQuery> { 415 datasource: DataSourceApi<TQuery>; 416 onClickExample: (query: TQuery) => void; 417 exploreId?: any; 418} 419 420/** 421 * Starting in v6.2 DataFrame can represent both TimeSeries and TableData 422 */ 423export type LegacyResponseData = TimeSeries | TableData | any; 424 425export type DataQueryResponseData = DataFrame | DataFrameDTO | LegacyResponseData; 426 427export interface DataQueryResponse { 428 /** 429 * The response data. When streaming, this may be empty 430 * or a partial result set 431 */ 432 data: DataQueryResponseData[]; 433 434 /** 435 * When returning multiple partial responses or streams 436 * Use this key to inform Grafana how to combine the partial responses 437 * Multiple responses with same key are replaced (latest used) 438 */ 439 key?: string; 440 441 /** 442 * Optionally include error info along with the response data 443 */ 444 error?: DataQueryError; 445 446 /** 447 * Use this to control which state the response should have 448 * Defaults to LoadingState.Done if state is not defined 449 */ 450 state?: LoadingState; 451} 452 453export enum DataQueryErrorType { 454 Cancelled = 'cancelled', 455 Timeout = 'timeout', 456 Unknown = 'unknown', 457} 458 459export interface DataQueryError { 460 data?: { 461 /** 462 * Short information about the error 463 */ 464 message?: string; 465 /** 466 * Detailed information about the error. Only returned when app_mode is development. 467 */ 468 error?: string; 469 }; 470 message?: string; 471 status?: string; 472 statusText?: string; 473 refId?: string; 474 type?: DataQueryErrorType; 475} 476 477export interface DataQueryRequest<TQuery extends DataQuery = DataQuery> { 478 requestId: string; // Used to identify results and optionally cancel the request in backendSrv 479 480 interval: string; 481 intervalMs: number; 482 maxDataPoints?: number; 483 range: TimeRange; 484 reverse?: boolean; 485 scopedVars: ScopedVars; 486 targets: TQuery[]; 487 timezone: string; 488 app: CoreApp | string; 489 490 cacheTimeout?: string | null; 491 rangeRaw?: RawTimeRange; 492 timeInfo?: string; // The query time description (blue text in the upper right) 493 panelId?: number; 494 dashboardId?: number; 495 496 // Request Timing 497 startTime: number; 498 endTime?: number; 499 500 // Explore state used by various datasources 501 liveStreaming?: boolean; 502} 503 504export interface DataQueryTimings { 505 dataProcessingTime: number; 506} 507 508export interface QueryFix { 509 label: string; 510 action?: QueryFixAction; 511} 512 513export interface QueryFixAction { 514 type: string; 515 query?: string; 516 preventSubmit?: boolean; 517} 518 519export interface QueryHint { 520 type: string; 521 label: string; 522 fix?: QueryFix; 523} 524 525export interface MetricFindValue { 526 text: string; 527 value?: string | number; 528 expandable?: boolean; 529} 530 531export interface DataSourceJsonData { 532 authType?: string; 533 defaultRegion?: string; 534 profile?: string; 535 manageAlerts?: boolean; 536 alertmanagerUid?: string; 537} 538 539/** 540 * Data Source instance edit model. This is returned from: 541 * /api/datasources 542 */ 543export interface DataSourceSettings<T extends DataSourceJsonData = DataSourceJsonData, S = {}> { 544 id: number; 545 uid: string; 546 orgId: number; 547 name: string; 548 typeLogoUrl: string; 549 type: string; 550 typeName: string; 551 access: string; 552 url: string; 553 password: string; 554 user: string; 555 database: string; 556 basicAuth: boolean; 557 basicAuthPassword: string; 558 basicAuthUser: string; 559 isDefault: boolean; 560 jsonData: T; 561 secureJsonData?: S; 562 secureJsonFields: KeyValue<boolean>; 563 readOnly: boolean; 564 withCredentials: boolean; 565 version?: number; 566} 567 568/** 569 * Frontend settings model that is passed to Datasource constructor. This differs a bit from the model above 570 * as this data model is available to every user who has access to a data source (Viewers+). This is loaded 571 * in bootData (on page load), or from: /api/frontend/settings 572 */ 573export interface DataSourceInstanceSettings<T extends DataSourceJsonData = DataSourceJsonData> { 574 id: number; 575 uid: string; 576 type: string; 577 name: string; 578 meta: DataSourcePluginMeta; 579 url?: string; 580 jsonData: T; 581 username?: string; 582 password?: string; // when access is direct, for some legacy datasources 583 database?: string; 584 isDefault?: boolean; 585 access: 'direct' | 'proxy'; // Currently we support 2 options - direct (browser) and proxy (server) 586 587 /** 588 * This is the full Authorization header if basic auth is enabled. 589 * Only available here when access is Browser (direct), when access is Server (proxy) 590 * The basic auth header, username & password is never exposed to browser/Frontend 591 * so this will be empty then. 592 */ 593 basicAuth?: string; 594 withCredentials?: boolean; 595 596 /** When the name+uid are based on template variables, maintain access to the real values */ 597 rawRef?: DataSourceRef; 598} 599 600/** 601 * @deprecated -- use {@link DataSourceInstanceSettings} instead 602 */ 603export interface DataSourceSelectItem { 604 name: string; 605 value: string | null; 606 meta: DataSourcePluginMeta; 607} 608 609/** 610 * Options passed to the datasource.annotationQuery method. See docs/plugins/developing/datasource.md 611 * 612 * @deprecated -- use {@link AnnotationSupport} 613 */ 614export interface AnnotationQueryRequest<MoreOptions = {}> { 615 range: TimeRange; 616 rangeRaw: RawTimeRange; 617 // Should be DataModel but cannot import that here from the main app. Needs to be moved to package first. 618 dashboard: any; 619 annotation: AnnotationQuery; 620} 621 622export interface HistoryItem<TQuery extends DataQuery = DataQuery> { 623 ts: number; 624 query: TQuery; 625} 626 627abstract class LanguageProvider { 628 abstract datasource: DataSourceApi<any, any>; 629 abstract request: (url: string, params?: any) => Promise<any>; 630 631 /** 632 * Returns startTask that resolves with a task list when main syntax is loaded. 633 * Task list consists of secondary promises that load more detailed language features. 634 */ 635 abstract start: () => Promise<Array<Promise<any>>>; 636 startTask?: Promise<any[]>; 637} 638 639//@ts-ignore 640LanguageProvider = makeClassES5Compatible(LanguageProvider); 641export { LanguageProvider }; 642 643//@ts-ignore 644DataSourceApi = makeClassES5Compatible(DataSourceApi); 645 646export { DataSourceApi }; 647