mirror of
https://github.com/grafana/grafana.git
synced 2025-09-20 10:39:21 +08:00

* Alerting: Receivers integrations error feedback: WIP - Add notifications error at the top right on contact points view (#52390) * Add interfaces for contact point errors * [WIP] Create fake response for the new service to get contact point errors * [WIP] Create action an reducer for the new service to get contact point errors * Fetch fetchContactPointStates in Contact Points tab every 20s and when AM changes * [WIP] Use store to get error count * Show number of integrations errors at the contact points main view * Add warning icon and refactor styles using getStyles * Change lastNotify type to string instead of DateTime * Use Stack component from experimental library when it is possible * Alerting: Add receivers error feedback in contact point list (#52524) * Refactor types for contact points state * Add health column in ReceiversTable in case error state is available for this AM * Create method for converting contact points state DTO to the FE type used in Redux store * Update types * Fix indexOf criteria getting integration type * Change type name to integrationType name * Change new components to be named functions to follow the FE style-guide * Fix typos Co-authored-by: Konrad Lalik <konrad.lalik@grafana.com> * Decouple ReceiversTable from Redux state * Create private useContactPointsState hook to simplify code in ReceiversTable component * Add tests for getIntegrationType and refactor the method to validate the name * Add tests for contactPointsStateDtoToModel method * Remove unnecessary check * Use Badge compoment for health status in contact point list * Create new method parseIntegrationName to simplify getting types and index from integration name Co-authored-by: Konrad Lalik <konrad.lalik@grafana.com> * Alerting: Show integrations error feedback when expanding contact point in list (#52920) * Use DynamicTable for rendering list of contact points and make them expandable if error status is available * Render expanded content for contact points integrations * Style and format last notify column * Add send resolve column to the integration details * Fix receiver id for DynamicTable row * Update clock icon in integration state * Fix tests * Add PR review sugestions * Alerting/integrations error feedback handle null dates in response 3 (#55659) * Update fake response with lastNotify ISO8601 formatted, to be aligned with latest BE changes * Update LastNotify in ReceiversTable component to handle null date * Alerting/integrations error feedback handle 404 state not available (#55803) * Create fetchContactPointsState using the future contact point url and handle 404 error * Add contact points state tests * Alerting/update receivers dto naming 2 (#56201) * Update NotifierStatus naming and fix sendResolved not being updated in UI * Return always empty ContactPointsState array when catching an error in the request response * Fix test * Show notification status only in notifications main view * Calculate total error count from the final contactPointsState object, to avoid errors when duplicated entries are returned wronly in the response * Add PR review suggestions Co-authored-by: Konrad Lalik <konrad.lalik@grafana.com>
79 lines
2.8 KiB
TypeScript
79 lines
2.8 KiB
TypeScript
import { lastValueFrom } from 'rxjs';
|
|
|
|
import { getBackendSrv } from '@grafana/runtime';
|
|
import { ContactPointsState, NotifierDTO, ReceiversStateDTO, ReceiverState } from 'app/types';
|
|
|
|
import { getDatasourceAPIUid } from '../utils/datasource';
|
|
|
|
export function fetchNotifiers(): Promise<NotifierDTO[]> {
|
|
return getBackendSrv().get(`/api/alert-notifiers`);
|
|
}
|
|
|
|
interface IntegrationNameObject {
|
|
type: string;
|
|
index?: string;
|
|
}
|
|
export const parseIntegrationName = (integrationName: string): IntegrationNameObject => {
|
|
const matches = integrationName.match(/^(\w+)(\[\d+\])?$/);
|
|
if (!matches) {
|
|
return { type: integrationName, index: undefined };
|
|
}
|
|
|
|
return {
|
|
type: matches[1],
|
|
index: matches[2],
|
|
};
|
|
};
|
|
|
|
export const contactPointsStateDtoToModel = (receiversStateDto: ReceiversStateDTO[]): ContactPointsState => {
|
|
// init object to return
|
|
const contactPointsState: ContactPointsState = { receivers: {}, errorCount: 0 };
|
|
// for each receiver from response
|
|
receiversStateDto.forEach((cpState) => {
|
|
//init receiver state
|
|
contactPointsState.receivers[cpState.name] = { active: cpState.active, notifiers: {}, errorCount: 0 };
|
|
const receiverState = contactPointsState.receivers[cpState.name];
|
|
//update integrations in response
|
|
cpState.integrations.forEach((integrationStatusDTO) => {
|
|
//update errorcount
|
|
const hasError = Boolean(integrationStatusDTO?.lastNotifyAttemptError);
|
|
if (hasError) {
|
|
receiverState.errorCount += 1;
|
|
}
|
|
//add integration for this type
|
|
const integrationType = getIntegrationType(integrationStatusDTO.name);
|
|
if (integrationType) {
|
|
//if type still does not exist in IntegrationsTypeState we initialize it with an empty array
|
|
if (!receiverState.notifiers[integrationType]) {
|
|
receiverState.notifiers[integrationType] = [];
|
|
}
|
|
// add error status for this type
|
|
receiverState.notifiers[integrationType].push(integrationStatusDTO);
|
|
}
|
|
});
|
|
});
|
|
const errorsCount = Object.values(contactPointsState.receivers).reduce(
|
|
(prevCount: number, receiverState: ReceiverState) => prevCount + receiverState.errorCount,
|
|
0
|
|
);
|
|
return { ...contactPointsState, errorCount: errorsCount };
|
|
};
|
|
|
|
export const getIntegrationType = (integrationName: string): string | undefined =>
|
|
parseIntegrationName(integrationName)?.type;
|
|
|
|
export async function fetchContactPointsState(alertManagerSourceName: string): Promise<ContactPointsState> {
|
|
try {
|
|
const response = await lastValueFrom(
|
|
getBackendSrv().fetch<ReceiversStateDTO[]>({
|
|
url: `/api/alertmanager/${getDatasourceAPIUid(alertManagerSourceName)}/config/api/v1/receivers`,
|
|
showErrorAlert: false,
|
|
showSuccessAlert: false,
|
|
})
|
|
);
|
|
return contactPointsStateDtoToModel(response.data);
|
|
} catch (error) {
|
|
return contactPointsStateDtoToModel([]);
|
|
}
|
|
}
|