Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions docs/overview/servicetopology.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ The Service Topology feature in Keep provides a visual representation of your se
}
></Card>
<Card
title="Pagerduty"
title="PagerDuty"
href="/providers/documentation/pagerduty-provider"
icon={
<img src="https://img.logo.dev/pagerduty.com?token=pk_dfXfZBoKQMGDTIgqu7LvYg" />
Expand All @@ -44,6 +44,13 @@ The Service Topology feature in Keep provides a visual representation of your se
<img src="https://img.logo.dev/cilium.io?token=pk_dfXfZBoKQMGDTIgqu7LvYg" />
}
></Card>
<Card
title="Grafana"
href="/providers/documentation/grafana-provider"
icon={
<img src="https://img.logo.dev/grafana.com?token=pk_dfXfZBoKQMGDTIgqu7LvYg" />
}
></Card>
<Card
title="Service Now"
href="/providers/documentation/service-now-provider"
Expand Down Expand Up @@ -80,7 +87,7 @@ Use filters to focus on specific parts of the topology, such as:

### Incident Integration

Service topology integrates seamlessly with Keeps incident management features. When an incident is triggered, you can:
Service topology integrates seamlessly with Keep's incident management features. When an incident is triggered, you can:

- View the affected nodes and their dependencies directly on the topology graph.
- Analyze how alerts related to the incident are propagating through the system.
Expand Down
13 changes: 9 additions & 4 deletions docs/providers/documentation/grafana-provider.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ You can check that the Grafana Provider works by testing Keep's contact point (w
height="200">
<img height="10" src="/images/grafana_sa_5.png" />
</Frame>
5. Go to Keep you should see an alert from Grafana!
5. Go to Keep - you should see an alert from Grafana!

**Alternative Validation Methods (When Keep is Not Accessible Externally):**

Expand All @@ -92,7 +92,7 @@ If Keep is not accessible externally and the webhook cannot be created, you can
- Trigger the alert and check Grafana's logs for errors or confirmation that the alert was sent.

2. **Check Logs in Grafana:**
- Access Grafanas log files or use the **Explore** feature to query logs related to the alerting mechanism.
- Access Grafana's log files or use the **Explore** feature to query logs related to the alerting mechanism.
- Ensure there are no errors related to the webhook integration and that alerts are processed correctly.

3. **Verify Integration Status:**
Expand All @@ -103,11 +103,16 @@ If Keep is not accessible externally and the webhook cannot be created, you can
4. **Network and Connectivity Check:**
- Use network monitoring tools to ensure Grafana can reach Keep or any alternative endpoint configured for alerts.

## Service Topology

Grafana can contribute data to Keep's Service Topology map when the provider is configured with a topology datasource UID. Keep queries Grafana service graph metrics from that datasource and uses the `client` and `server` labels to build services and dependencies.

<Note>
**Topology Map** is generated from the traces collect by Tempo.
The Topology Map is generated from traces collected by Tempo and exposed through a Prometheus-compatible datasource.

To get the Datasource UID, go to:
1. Connections > Data Sources.
2. Click the Prometheus instance which is scraping data from Tempo > Your URL is in the format `https://host/connections/datasources/edit/<DATASOURCE_UID>`
2. Click the Prometheus instance that is scraping data from Tempo. The URL is in the format `https://host/connections/datasources/edit/<DATASOURCE_UID>`.
3. Copy that DATASOURCE_UID and use it while installing the provider.
</Note>

Expand Down
14 changes: 7 additions & 7 deletions docs/providers/documentation/pagerduty-provider.mdx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
---
title: "Pagerduty Provider"
description: "Pagerduty Provider allows integration with PagerDuty to create, manage, and synchronize incidents and alerts within Keep."
title: "PagerDuty Provider"
description: "PagerDuty Provider allows integration with PagerDuty to create, manage, and synchronize incidents and alerts within Keep."
---
import AutoGeneratedSnippet from '/snippets/providers/pagerduty-snippet-autogenerated.mdx';

## Description

The Pagerduty Provider enables integration with PagerDuty to create, manage, and synchronize incidents and alerts within Keep. It supports both direct API key authentication and OAuth2, allowing greater flexibility for secure integration.
The PagerDuty Provider enables integration with PagerDuty to create, manage, and synchronize incidents and alerts within Keep. It supports both direct API key authentication and OAuth2, allowing greater flexibility for secure integration.

<AutoGeneratedSnippet />

Expand Down Expand Up @@ -85,13 +85,13 @@ An expired trial while using the free version of PagerDuty may result in the "pa

## Webhook Integration Modifications

The webhook integration adds Keep as a destination within the "Integrations" API within Pagerduty.
This grants Keep access to the following scopes within Pagerduty:
The webhook integration adds Keep as a destination within the "Integrations" API within PagerDuty.
This grants Keep access to the following scopes within PagerDuty:

- `webhook_subscriptions_read`
- `webhook_subscriptions_write`

## Useful Links

- Pagerduty Events API documentation: https://v2.developer.pagerduty.com/docs/send-an-event-events-api-v2
- Pagerduty Incidents API documentation: https://v2.developer.pagerduty.com/docs/create-an-incident-incidents-api-v2
- PagerDuty Events API documentation: https://v2.developer.pagerduty.com/docs/send-an-event-events-api-v2
- PagerDuty Incidents API documentation: https://v2.developer.pagerduty.com/docs/create-an-incident-incidents-api-v2
2 changes: 1 addition & 1 deletion docs/providers/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ By leveraging Keep Providers, users are able to deeply integrate Keep with the t
- [OpenSearch Serverless](/providers/documentation/opensearchserverless-provider)
- [Openshift](/providers/documentation/openshift-provider)
- [Opsgenie](/providers/documentation/opsgenie-provider)
- [Pagerduty](/providers/documentation/pagerduty-provider)
- [PagerDuty](/providers/documentation/pagerduty-provider)
- [Pagertree](/providers/documentation/pagertree-provider)
- [Parseable](/providers/documentation/parseable-provider)
- [Pingdom](/providers/documentation/pingdom-provider)
Expand Down
2 changes: 1 addition & 1 deletion docs/providers/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ By leveraging Keep Providers, users are able to deeply integrate Keep with the t
></Card>

<Card
title="Pagerduty"
title="PagerDuty"
href="/providers/documentation/pagerduty-provider"
icon={
<img src="https://img.logo.dev/pagerduty.com?token=pk_dfXfZBoKQMGDTIgqu7LvYg" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import Alerts from "../alerts";
jest.mock("next/navigation", () => ({
useRouter: jest.fn(),
useSearchParams: jest.fn(),
usePathname: jest.fn().mockReturnValue("/alerts/feed"),
}));

// ─── Mock data hooks ─────────────────────────────────────────────────────────
Expand Down
15 changes: 7 additions & 8 deletions keep-ui/app/(keep)/alerts/[id]/ui/alerts.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { type AlertDto, type AlertsQuery } from "@/entities/alerts/model";
import { usePresets, type Preset } from "@/entities/presets/model";
import { AlertHistoryModal } from "@/features/alerts/alert-history";
Expand Down Expand Up @@ -61,6 +61,7 @@ export default function Alerts({ presetName, initialFacets }: AlertsProps) {
[providersData.installed_providers]
);

const pathname = usePathname();
const searchParams = useSearchParams();
// hooks for the note and ticket modals
const [noteModalAlert, setNoteModalAlert] = useState<AlertDto | null>();
Expand Down Expand Up @@ -165,18 +166,16 @@ export default function Alerts({ presetName, initialFacets }: AlertsProps) {
);

const resetUrlAfterModal = useCallback(() => {
const currentParams = new URLSearchParams(window.location.search);
const currentParams = new URLSearchParams(searchParams?.toString() ?? "");
Array.from(currentParams.keys())
.filter((paramKey) => paramKey !== "cel")
.forEach((paramKey) => currentParams.delete(paramKey));
let url = `${window.location.pathname}`;

if (currentParams.toString()) {
url += `?${currentParams.toString()}`;
}
const url = currentParams.toString()
? `${pathname}?${currentParams.toString()}`
: pathname;

router.replace(url);
}, [router]);
}, [router, pathname, searchParams]);

// if we don't have presets data yet, just show loading
if (!selectedPreset && isPresetsLoading) {
Expand Down
18 changes: 18 additions & 0 deletions keep-ui/app/(keep)/alerts/fingerprint/[fp]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { AlertFingerprintPage } from "./ui/alert-fingerprint-page";

type PageProps = {
params: Promise<{ fp: string }>;
};

export default async function Page({ params }: PageProps) {
const { fp } = await params;
return <AlertFingerprintPage fingerprint={fp} />;
}

export async function generateMetadata({ params }: PageProps) {
const { fp } = await params;
return {
title: `Keep - Alert ${fp}`,
description: "View alert details",
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
"use client";

import { useRouter } from "next/navigation";
import { useAlerts } from "@/entities/alerts/model";
import { ViewAlertModal } from "@/features/alerts/view-raw-alert";
import { KeepLoader } from "@/shared/ui";
import NotFound from "@/app/(keep)/not-found";

interface AlertFingerprintPageProps {
fingerprint: string;
}

export function AlertFingerprintPage({ fingerprint }: AlertFingerprintPageProps) {
const router = useRouter();
const { useAlertByFingerprint } = useAlerts();
const { data: alert, error, isLoading, mutate } = useAlertByFingerprint(fingerprint);

if (isLoading) {
return <KeepLoader loadingText="Loading alert..." />;
}

if (error || !alert) {
return <NotFound />;
}

return (
<ViewAlertModal
alert={alert}
handleClose={() => router.replace("/alerts/feed")}
mutate={mutate}
/>
);
}
12 changes: 12 additions & 0 deletions keep-ui/entities/alerts/model/useAlerts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,17 @@ export const useAlerts = () => {
);
};

const useAlertByFingerprint = (
fingerprint: string | null | undefined,
options: SWRConfiguration = { revalidateOnFocus: false }
) => {
return useSWR<AlertDto>(
() => (api.isReady() && fingerprint ? `/alerts/${fingerprint}` : null),
(url) => api.get(url),
options
);
};

const useErrorAlerts = (
options: SWRConfiguration = { revalidateOnFocus: false }
) => {
Expand Down Expand Up @@ -220,6 +231,7 @@ export const useAlerts = () => {
useAllAlerts,
usePresetAlerts,
useAlertAudit,
useAlertByFingerprint,
useMultipleFingerprintsAlertAudit,
useErrorAlerts,
useLastAlerts,
Expand Down
15 changes: 8 additions & 7 deletions keep-ui/shared/ui/MonacoCELEditor/MonacoCel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,12 @@

import { Editor, EditorProps, loader } from "@monaco-editor/react";
import { useEffect, useRef, useState } from "react";
import * as monaco from "monaco-editor";

interface MonacoCelProps extends EditorProps {
onMonacoLoaded?: (monacoInstance: typeof import("monaco-editor")) => void;
onMonacoLoadFailure?: (error: Error) => void;
}

// Monaco Editor - imported as an npm package instead of loading from the CDN to support air-gapped environments
// https://github.com/suren-atoyan/monaco-react?tab=readme-ov-file#use-monaco-editor-as-an-npm-package
loader.config({ monaco });

export function MonacoCelBase(props: MonacoCelProps) {
const [isLoaded, setIsLoaded] = useState(false);
const onMonacoLoadedRef = useRef<MonacoCelProps["onMonacoLoaded"] | null>(
Expand All @@ -25,8 +20,14 @@ export function MonacoCelBase(props: MonacoCelProps) {
onMonacoLoadFailureRef.current = props.onMonacoLoadFailure;

useEffect(() => {
loader
.init()
// Monaco Editor - imported as an npm package instead of loading from the
// CDN to support air-gapped environments.
// https://github.com/suren-atoyan/monaco-react?tab=readme-ov-file#use-monaco-editor-as-an-npm-package
import("monaco-editor")
.then((monaco) => {
loader.config({ monaco });
return loader.init();
})
.then((monacoInstance) => {
onMonacoLoadedRef.current?.(monacoInstance);
setIsLoaded(true);
Expand Down
2 changes: 1 addition & 1 deletion keep-ui/shared/ui/MonacoCELEditor/monaco-cel-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useEffect, useRef, useState } from "react";
import { ErrorComponent } from "../ErrorComponent/ErrorComponent";
import { setupCustomCellanguage } from "./cel-support";
import { MonacoCelBase } from "./MonacoCel";
import { editor, Token } from "monaco-editor";
import type { editor, Token } from "monaco-editor";
import "./editor.scss";
import { useCelValidation } from "./validation-hook";

Expand Down
Loading