2021-08-19 12:38:31 +08:00
import { lastValueFrom , Observable , of } from 'rxjs' ;
2022-04-22 21:33:13 +08:00
2021-04-07 13:42:43 +08:00
import { DataQuery , DataQueryResponse , DataSourceApi , DataSourceInstanceSettings } from '@grafana/data' ;
2022-08-16 22:01:57 +08:00
import { BackendSrvRequest , getBackendSrv , isFetchError } from '@grafana/runtime' ;
import { discoverAlertmanagerFeaturesByUrl } from '../../../features/alerting/unified/api/buildInfo' ;
import { messageFromError } from '../../../features/alerting/unified/utils/redux' ;
import { AlertmanagerApiFeatures } from '../../../types/unified-alerting-dto' ;
2022-04-22 21:33:13 +08:00
2021-10-01 21:24:56 +08:00
import { AlertManagerDataSourceJsonData , AlertManagerImplementation } from './types' ;
2021-04-07 13:42:43 +08:00
export type AlertManagerQuery = {
query : string ;
} & DataQuery ;
2021-10-01 21:24:56 +08:00
export class AlertManagerDatasource extends DataSourceApi < AlertManagerQuery , AlertManagerDataSourceJsonData > {
constructor ( public instanceSettings : DataSourceInstanceSettings < AlertManagerDataSourceJsonData > ) {
2021-04-07 13:42:43 +08:00
super ( instanceSettings ) ;
}
// `query()` has to be implemented but we actually don't use it, just need this
// data source to proxy requests.
// @ts-ignore
query ( ) : Observable < DataQueryResponse > {
return of ( {
data : [ ] ,
} ) ;
}
_request ( url : string ) {
const options : BackendSrvRequest = {
headers : { } ,
method : 'GET' ,
url : this.instanceSettings.url + url ,
} ;
if ( this . instanceSettings . basicAuth || this . instanceSettings . withCredentials ) {
this . instanceSettings . withCredentials = true ;
}
if ( this . instanceSettings . basicAuth ) {
options . headers ! . Authorization = this . instanceSettings . basicAuth ;
}
2025-04-07 18:29:30 +08:00
return lastValueFrom ( getBackendSrv ( ) . fetch ( options ) ) ;
2021-04-07 13:42:43 +08:00
}
async testDatasource() {
let alertmanagerResponse ;
2022-08-16 22:01:57 +08:00
const amUrl = this . instanceSettings . url ;
const amFeatures : AlertmanagerApiFeatures = amUrl
? await discoverAlertmanagerFeaturesByUrl ( amUrl )
: { lazyConfigInit : false } ;
2021-04-07 13:42:43 +08:00
2021-10-01 21:24:56 +08:00
if ( this . instanceSettings . jsonData . implementation === AlertManagerImplementation . prometheus ) {
try {
alertmanagerResponse = await this . _request ( '/alertmanager/api/v2/status' ) ;
if ( alertmanagerResponse && alertmanagerResponse ? . status === 200 ) {
return {
status : 'error' ,
message :
2022-06-20 18:56:38 +08:00
'It looks like you have chosen Prometheus implementation, but detected a Mimir or Cortex endpoint. Please update implementation selection and try again.' ,
2021-10-01 21:24:56 +08:00
} ;
}
} catch ( e ) { }
try {
alertmanagerResponse = await this . _request ( '/api/v2/status' ) ;
} catch ( e ) { }
} else {
try {
alertmanagerResponse = await this . _request ( '/api/v2/status' ) ;
if ( alertmanagerResponse && alertmanagerResponse ? . status === 200 ) {
return {
status : 'error' ,
message :
2022-06-20 18:56:38 +08:00
'It looks like you have chosen a Mimir or Cortex implementation, but detected a Prometheus endpoint. Please update implementation selection and try again.' ,
2021-10-01 21:24:56 +08:00
} ;
}
} catch ( e ) { }
try {
alertmanagerResponse = await this . _request ( '/alertmanager/api/v2/status' ) ;
2022-08-16 22:01:57 +08:00
} catch ( e ) {
if (
isFetchError ( e ) &&
amFeatures . lazyConfigInit &&
messageFromError ( e ) ? . includes ( 'the Alertmanager is not configured' )
) {
return {
status : 'success' ,
message : 'Health check passed.' ,
details : { message : 'Mimir Alertmanager without the fallback configuration has been discovered.' } ,
} ;
}
}
2021-10-01 21:24:56 +08:00
}
2021-04-07 13:42:43 +08:00
2021-10-01 21:24:56 +08:00
return alertmanagerResponse ? . status === 200
2021-04-07 13:42:43 +08:00
? {
status : 'success' ,
message : 'Health check passed.' ,
}
: {
status : 'error' ,
message : 'Health check failed.' ,
} ;
}
}