Compare commits

..

3 Commits

Author SHA1 Message Date
Abhi Kumar
5d2f7394f5 chore: removed weakref 2026-02-28 19:59:00 +05:30
Abhi Kumar
85edb60a8a fix: fixed memory leak because of canvas persistance over mount 2026-02-28 19:45:06 +05:30
Srikanth Chekuri
95fc905448 chore: move savedview and integration types into their own types package (#10454)
Some checks are pending
build-staging / staging (push) Blocked by required conditions
build-staging / prepare (push) Waiting to run
build-staging / js-build (push) Blocked by required conditions
build-staging / go-build (push) Blocked by required conditions
Release Drafter / update_release_draft (push) Waiting to run
2026-02-28 12:55:26 +00:00
35 changed files with 184 additions and 251 deletions

View File

@@ -451,9 +451,6 @@ function K8sClustersList({
const handleRowClick = (record: K8sClustersRowData): void => {
if (groupBy.length === 0) {
if (!record.clusterNameRaw) {
return;
}
setSelectedRowData(null);
setselectedClusterName(record.clusterUID);
setSearchParams({
@@ -518,13 +515,9 @@ function K8sClustersList({
showHeader={false}
onRow={(record): { onClick: () => void; className: string } => ({
onClick: (): void => {
if (record.clusterNameRaw) {
setselectedClusterName(record.clusterUID);
}
setselectedClusterName(record.clusterUID);
},
className: record.clusterNameRaw
? 'expanded-clickable-row'
: 'disabled-row',
className: 'expanded-clickable-row',
})}
/>
@@ -714,10 +707,7 @@ function K8sClustersList({
onChange={handleTableChange}
onRow={(record): { onClick: () => void; className: string } => ({
onClick: (): void => handleRowClick(record),
className:
groupBy.length > 0 || record.clusterNameRaw
? 'clickable-row'
: 'disabled-row',
className: 'clickable-row',
})}
expandable={{
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,

View File

@@ -47,7 +47,6 @@ export const defaultAddedColumns: IEntityColumn[] = [
export interface K8sClustersRowData {
key: string;
clusterUID: string;
clusterNameRaw: string;
clusterName: React.ReactNode;
cpu: React.ReactNode;
memory: React.ReactNode;
@@ -176,7 +175,6 @@ export const formatDataForTable = (
data.map((cluster, index) => ({
key: index.toString(),
clusterUID: cluster.meta.k8s_cluster_name,
clusterNameRaw: cluster.meta.k8s_cluster_name || '',
clusterName: (
<Tooltip title={cluster.meta.k8s_cluster_name}>
{cluster.meta.k8s_cluster_name}

View File

@@ -457,9 +457,6 @@ function K8sDaemonSetsList({
const handleRowClick = (record: K8sDaemonSetsRowData): void => {
if (groupBy.length === 0) {
if (!record.daemonsetNameRaw) {
return;
}
setSelectedRowData(null);
setSelectedDaemonSetUID(record.daemonsetUID);
setSearchParams({
@@ -524,13 +521,9 @@ function K8sDaemonSetsList({
showHeader={false}
onRow={(record): { onClick: () => void; className: string } => ({
onClick: (): void => {
if (record.daemonsetNameRaw) {
setSelectedDaemonSetUID(record.daemonsetUID);
}
setSelectedDaemonSetUID(record.daemonsetUID);
},
className: record.daemonsetNameRaw
? 'expanded-clickable-row'
: 'disabled-row',
className: 'expanded-clickable-row',
})}
/>
@@ -722,10 +715,7 @@ function K8sDaemonSetsList({
onChange={handleTableChange}
onRow={(record): { onClick: () => void; className: string } => ({
onClick: (): void => handleRowClick(record),
className:
groupBy.length > 0 || record.daemonsetNameRaw
? 'clickable-row'
: 'disabled-row',
className: 'clickable-row',
})}
expandable={{
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,

View File

@@ -82,7 +82,6 @@ export const defaultAddedColumns: IEntityColumn[] = [
export interface K8sDaemonSetsRowData {
key: string;
daemonsetUID: string;
daemonsetNameRaw: string;
daemonsetName: React.ReactNode;
cpu_request: React.ReactNode;
cpu_limit: React.ReactNode;
@@ -277,7 +276,6 @@ export const formatDataForTable = (
data.map((daemonSet, index) => ({
key: index.toString(),
daemonsetUID: daemonSet.daemonSetName,
daemonsetNameRaw: daemonSet.meta.k8s_daemonset_name || '',
daemonsetName: (
<Tooltip title={daemonSet.meta.k8s_daemonset_name}>
{daemonSet.meta.k8s_daemonset_name || ''}

View File

@@ -463,9 +463,6 @@ function K8sDeploymentsList({
const handleRowClick = (record: K8sDeploymentsRowData): void => {
if (groupBy.length === 0) {
if (!record.deploymentNameRaw) {
return;
}
setSelectedRowData(null);
setselectedDeploymentUID(record.deploymentUID);
setSearchParams({
@@ -530,13 +527,9 @@ function K8sDeploymentsList({
showHeader={false}
onRow={(record): { onClick: () => void; className: string } => ({
onClick: (): void => {
if (record.deploymentNameRaw) {
setselectedDeploymentUID(record.deploymentUID);
}
setselectedDeploymentUID(record.deploymentUID);
},
className: record.deploymentNameRaw
? 'expanded-clickable-row'
: 'disabled-row',
className: 'expanded-clickable-row',
})}
/>
@@ -729,10 +722,7 @@ function K8sDeploymentsList({
onChange={handleTableChange}
onRow={(record): { onClick: () => void; className: string } => ({
onClick: (): void => handleRowClick(record),
className:
groupBy.length > 0 || record.deploymentNameRaw
? 'clickable-row'
: 'disabled-row',
className: 'clickable-row',
})}
expandable={{
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,

View File

@@ -81,7 +81,6 @@ export const defaultAddedColumns: IEntityColumn[] = [
export interface K8sDeploymentsRowData {
key: string;
deploymentUID: string;
deploymentNameRaw: string;
deploymentName: React.ReactNode;
available_pods: React.ReactNode;
desired_pods: React.ReactNode;
@@ -268,7 +267,6 @@ export const formatDataForTable = (
data.map((deployment, index) => ({
key: index.toString(),
deploymentUID: deployment.meta.k8s_deployment_name,
deploymentNameRaw: deployment.meta.k8s_deployment_name || '',
deploymentName: (
<Tooltip title={deployment.meta.k8s_deployment_name}>
{deployment.meta.k8s_deployment_name}

View File

@@ -337,11 +337,6 @@
cursor: pointer;
}
.disabled-row {
cursor: default;
opacity: 0.6;
}
.k8s-list-table {
.ant-table {
.ant-table-thead > tr > th {

View File

@@ -428,9 +428,6 @@ function K8sJobsList({
const handleRowClick = (record: K8sJobsRowData): void => {
if (groupBy.length === 0) {
if (!record.jobNameRaw) {
return;
}
setSelectedRowData(null);
setselectedJobUID(record.jobUID);
setSearchParams({
@@ -495,11 +492,9 @@ function K8sJobsList({
showHeader={false}
onRow={(record): { onClick: () => void; className: string } => ({
onClick: (): void => {
if (record.jobNameRaw) {
setselectedJobUID(record.jobUID);
}
setselectedJobUID(record.jobUID);
},
className: record.jobNameRaw ? 'expanded-clickable-row' : 'disabled-row',
className: 'expanded-clickable-row',
})}
/>
@@ -689,10 +684,7 @@ function K8sJobsList({
onChange={handleTableChange}
onRow={(record): { onClick: () => void; className: string } => ({
onClick: (): void => handleRowClick(record),
className:
groupBy.length > 0 || record.jobNameRaw
? 'clickable-row'
: 'disabled-row',
className: 'clickable-row',
})}
expandable={{
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,

View File

@@ -94,7 +94,6 @@ export const defaultAddedColumns: IEntityColumn[] = [
export interface K8sJobsRowData {
key: string;
jobUID: string;
jobNameRaw: string;
jobName: React.ReactNode;
namespaceName: React.ReactNode;
successful_pods: React.ReactNode;
@@ -304,7 +303,6 @@ export const formatDataForTable = (
data.map((job, index) => ({
key: index.toString(),
jobUID: job.jobName,
jobNameRaw: job.meta.k8s_job_name || '',
jobName: (
<Tooltip title={job.meta.k8s_job_name}>
{job.meta.k8s_job_name || ''}

View File

@@ -459,9 +459,6 @@ function K8sNamespacesList({
const handleRowClick = (record: K8sNamespacesRowData): void => {
if (groupBy.length === 0) {
if (!record.namespaceNameRaw) {
return;
}
setSelectedRowData(null);
setselectedNamespaceUID(record.namespaceUID);
setSearchParams({
@@ -526,13 +523,9 @@ function K8sNamespacesList({
showHeader={false}
onRow={(record): { onClick: () => void; className: string } => ({
onClick: (): void => {
if (record.namespaceNameRaw) {
setselectedNamespaceUID(record.namespaceUID);
}
setselectedNamespaceUID(record.namespaceUID);
},
className: record.namespaceNameRaw
? 'expanded-clickable-row'
: 'disabled-row',
className: 'expanded-clickable-row',
})}
/>
@@ -723,10 +716,7 @@ function K8sNamespacesList({
onChange={handleTableChange}
onRow={(record): { onClick: () => void; className: string } => ({
onClick: (): void => handleRowClick(record),
className:
groupBy.length > 0 || record.namespaceNameRaw
? 'clickable-row'
: 'disabled-row',
className: 'clickable-row',
})}
expandable={{
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,

View File

@@ -41,7 +41,6 @@ export const defaultAddedColumns: IEntityColumn[] = [
export interface K8sNamespacesRowData {
key: string;
namespaceUID: string;
namespaceNameRaw: string;
namespaceName: string;
clusterName: string;
cpu: React.ReactNode;
@@ -162,7 +161,6 @@ export const formatDataForTable = (
data.map((namespace, index) => ({
key: index.toString(),
namespaceUID: namespace.namespaceName,
namespaceNameRaw: namespace.namespaceName || '',
namespaceName: namespace.namespaceName,
clusterName: namespace.meta.k8s_cluster_name,
cpu: (

View File

@@ -438,9 +438,6 @@ function K8sNodesList({
const handleRowClick = (record: K8sNodesRowData): void => {
if (groupBy.length === 0) {
if (!record.nodeNameRaw) {
return;
}
setSelectedRowData(null);
setSelectedNodeUID(record.nodeUID);
setSearchParams({
@@ -506,13 +503,9 @@ function K8sNodesList({
showHeader={false}
onRow={(record): { onClick: () => void; className: string } => ({
onClick: (): void => {
if (record.nodeNameRaw) {
setSelectedNodeUID(record.nodeUID);
}
setSelectedNodeUID(record.nodeUID);
},
className: record.nodeNameRaw
? 'expanded-clickable-row'
: 'disabled-row',
className: 'expanded-clickable-row',
})}
/>
@@ -702,10 +695,7 @@ function K8sNodesList({
onChange={handleTableChange}
onRow={(record): { onClick: () => void; className: string } => ({
onClick: (): void => handleRowClick(record),
className:
groupBy.length > 0 || record.nodeNameRaw
? 'clickable-row'
: 'disabled-row',
className: 'clickable-row',
})}
expandable={{
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,

View File

@@ -53,7 +53,6 @@ export const defaultAddedColumns: IEntityColumn[] = [
export interface K8sNodesRowData {
key: string;
nodeUID: string;
nodeNameRaw: string;
nodeName: React.ReactNode;
clusterName: string;
cpu: React.ReactNode;
@@ -194,7 +193,6 @@ export const formatDataForTable = (
data.map((node, index) => ({
key: `${node.nodeUID}-${index}`,
nodeUID: node.nodeUID || '',
nodeNameRaw: node.meta.k8s_node_name || '',
nodeName: (
<Tooltip title={node.meta.k8s_node_name}>
{node.meta.k8s_node_name || ''}

View File

@@ -496,9 +496,6 @@ function K8sPodsList({
const handleRowClick = (record: K8sPodsRowData): void => {
if (groupBy.length === 0) {
if (!record.podNameRaw) {
return;
}
setSelectedPodUID(record.podUID);
setSearchParams({
...Object.fromEntries(searchParams.entries()),
@@ -619,11 +616,9 @@ function K8sPodsList({
}}
onRow={(record): { onClick: () => void; className: string } => ({
onClick: (): void => {
if (record.podNameRaw) {
setSelectedPodUID(record.podUID);
}
setSelectedPodUID(record.podUID);
},
className: record.podNameRaw ? 'expanded-clickable-row' : 'disabled-row',
className: 'expanded-clickable-row',
})}
/>
@@ -758,10 +753,7 @@ function K8sPodsList({
onChange={handleTableChange}
onRow={(record): { onClick: () => void; className: string } => ({
onClick: (): void => handleRowClick(record),
className:
groupBy.length > 0 || record.podNameRaw
? 'clickable-row'
: 'disabled-row',
className: 'clickable-row',
})}
expandable={{
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,

View File

@@ -460,9 +460,6 @@ function K8sStatefulSetsList({
const handleRowClick = (record: K8sStatefulSetsRowData): void => {
if (groupBy.length === 0) {
if (!record.statefulsetNameRaw) {
return;
}
setSelectedRowData(null);
setselectedStatefulSetUID(record.statefulsetUID);
setSearchParams({
@@ -527,13 +524,9 @@ function K8sStatefulSetsList({
showHeader={false}
onRow={(record): { onClick: () => void; className: string } => ({
onClick: (): void => {
if (record.statefulsetNameRaw) {
setselectedStatefulSetUID(record.statefulsetUID);
}
setselectedStatefulSetUID(record.statefulsetUID);
},
className: record.statefulsetNameRaw
? 'expanded-clickable-row'
: 'disabled-row',
className: 'expanded-clickable-row',
})}
/>
@@ -725,10 +718,7 @@ function K8sStatefulSetsList({
onChange={handleTableChange}
onRow={(record): { onClick: () => void; className: string } => ({
onClick: (): void => handleRowClick(record),
className:
groupBy.length > 0 || record.statefulsetNameRaw
? 'clickable-row'
: 'disabled-row',
className: 'clickable-row',
})}
expandable={{
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,

View File

@@ -82,7 +82,6 @@ export const defaultAddedColumns: IEntityColumn[] = [
export interface K8sStatefulSetsRowData {
key: string;
statefulsetUID: string;
statefulsetNameRaw: string;
statefulsetName: React.ReactNode;
cpu_request: React.ReactNode;
cpu_limit: React.ReactNode;
@@ -277,7 +276,6 @@ export const formatDataForTable = (
data.map((statefulSet, index) => ({
key: index.toString(),
statefulsetUID: statefulSet.statefulSetName,
statefulsetNameRaw: statefulSet.meta.k8s_statefulset_name || '',
statefulsetName: (
<Tooltip title={statefulSet.meta.k8s_statefulset_name}>
{statefulSet.meta.k8s_statefulset_name || ''}

View File

@@ -390,9 +390,6 @@ function K8sVolumesList({
const handleRowClick = (record: K8sVolumesRowData): void => {
if (groupBy.length === 0) {
if (!record.volumeNameRaw) {
return;
}
setSelectedRowData(null);
setselectedVolumeUID(record.volumeUID);
setSearchParams({
@@ -457,13 +454,9 @@ function K8sVolumesList({
showHeader={false}
onRow={(record): { onClick: () => void; className: string } => ({
onClick: (): void => {
if (record.volumeNameRaw) {
setselectedVolumeUID(record.volumeUID);
}
setselectedVolumeUID(record.volumeUID);
},
className: record.volumeNameRaw
? 'expanded-clickable-row'
: 'disabled-row',
className: 'expanded-clickable-row',
})}
/>
@@ -648,10 +641,7 @@ function K8sVolumesList({
onChange={handleTableChange}
onRow={(record): { onClick: () => void; className: string } => ({
onClick: (): void => handleRowClick(record),
className:
groupBy.length > 0 || record.volumeNameRaw
? 'clickable-row'
: 'disabled-row',
className: 'clickable-row',
})}
expandable={{
expandedRowRender: isGroupedByAttribute ? expandedRowRender : undefined,

View File

@@ -47,7 +47,6 @@ export const defaultAddedColumns: IEntityColumn[] = [
export interface K8sVolumesRowData {
key: string;
volumeUID: string;
volumeNameRaw: string;
pvcName: React.ReactNode;
namespaceName: React.ReactNode;
capacity: React.ReactNode;
@@ -187,7 +186,6 @@ export const formatDataForTable = (
data.map((volume, index) => ({
key: index.toString(),
volumeUID: volume.persistentVolumeClaimName,
volumeNameRaw: volume.persistentVolumeClaimName || '',
pvcName: (
<Tooltip title={volume.persistentVolumeClaimName}>
{volume.persistentVolumeClaimName || ''}

View File

@@ -105,7 +105,6 @@ export const defaultAvailableColumns = [
export interface K8sPodsRowData {
key: string;
podName: React.ReactNode;
podNameRaw: string;
podUID: string;
cpu_request: React.ReactNode;
cpu_limit: React.ReactNode;
@@ -348,7 +347,6 @@ export const formatDataForTable = (
{pod.meta.k8s_pod_name || ''}
</Tooltip>
),
podNameRaw: pod.meta.k8s_pod_name || '',
podUID: pod.podUID || '',
cpu_request: (
<ValidateColumnValueWrapper

View File

@@ -8,6 +8,7 @@ import {
createSetCursorHandler,
createSetLegendHandler,
createSetSeriesHandler,
getPlot,
isScrollEventInPlot,
updatePlotVisibility,
updateWindowSize,
@@ -53,7 +54,7 @@ export default function TooltipPlugin({
const [viewState, setState] = useState<TooltipViewState>(
createInitialViewState,
);
const { plot, isHovering, isPinned, contents, style } = viewState;
const { hasPlot, isHovering, isPinned, contents, style } = viewState;
/**
* Merge a partial view update into the current React state.
@@ -72,12 +73,25 @@ export default function TooltipPlugin({
layoutRef.current?.observer.disconnect();
layoutRef.current = createLayoutObserver(layoutRef);
/**
* Plot lifecycle and GC: viewState uses hasPlot (boolean), not the plot
* reference; clearPlotReferences runs in cleanup so
* detached canvases can be garbage collected.
*/
// Controller holds the mutable interaction state for this tooltip
// instance. It is intentionally *not* React state so uPlot hooks
// and DOM listeners can update it freely without triggering a
// render on every mouse move.
const controller: TooltipControllerState = createInitialControllerState();
/**
* Clear plot references so detached canvases can be garbage collected.
*/
const clearPlotReferences = (): void => {
controller.plot = null;
updateState({ hasPlot: false });
};
const syncTooltipWithDashboard = syncMode === DashboardCursorSync.Tooltip;
// Enable uPlot's built-in cursor sync when requested so that
@@ -110,9 +124,10 @@ export default function TooltipPlugin({
// Lock uPlot's internal cursor when the tooltip is pinned so
// subsequent mouse moves do not move the crosshair.
function updateCursorLock(): void {
if (controller.plot) {
const plot = getPlot(controller);
if (plot) {
// @ts-ignore uPlot cursor lock is not working as expected
controller.plot.cursor._lock = controller.pinned;
plot.cursor._lock = controller.pinned;
}
}
@@ -142,8 +157,9 @@ export default function TooltipPlugin({
const isPinnedBeforeDismiss = controller.pinned;
controller.pinned = false;
controller.hoverActive = false;
if (controller.plot) {
controller.plot.setCursor({ left: -10, top: -10 });
const plot = getPlot(controller);
if (plot) {
plot.setCursor({ left: -10, top: -10 });
}
scheduleRender(isPinnedBeforeDismiss);
}
@@ -151,11 +167,12 @@ export default function TooltipPlugin({
// Build the React node to be rendered inside the tooltip by
// delegating to the caller-provided `render` function.
function createTooltipContents(): React.ReactNode {
if (!controller.hoverActive || !controller.plot) {
const plot = getPlot(controller);
if (!controller.hoverActive || !plot) {
return null;
}
return renderRef.current({
uPlotInstance: controller.plot,
uPlotInstance: plot,
dataIndexes: controller.seriesIndexes,
seriesIndex: controller.focusedSeriesIndex,
isPinned: controller.pinned,
@@ -240,9 +257,13 @@ export default function TooltipPlugin({
// When pinning is enabled, a click on the plot overlay while
// hovering converts the transient tooltip into a pinned one.
const handleUPlotOverClick = (u: uPlot, event: MouseEvent): void => {
// Uses getPlot(controller) to avoid closing over u (plot), which
// would retain the plot and detached canvases across unmounts.
const handleUPlotOverClick = (event: MouseEvent): void => {
const plot = getPlot(controller);
if (
event.target === u.over &&
plot &&
event.target === plot.over &&
controller.hoverActive &&
!controller.pinned &&
controller.focusedSeriesIndex != null
@@ -260,10 +281,9 @@ export default function TooltipPlugin({
// on the controller and optionally attach the pinning handler.
const handleInit = (u: uPlot): void => {
controller.plot = u;
updateState({ plot: u });
updateState({ hasPlot: true });
if (canPinTooltip) {
overClickHandler = (event: MouseEvent): void =>
handleUPlotOverClick(u, event);
overClickHandler = handleUPlotOverClick;
u.over.addEventListener('click', overClickHandler);
}
};
@@ -299,7 +319,6 @@ export default function TooltipPlugin({
const handleSetCursor = createSetCursorHandler(ctx);
handleWindowResize();
const removeReadyHook = config.addHook('ready', (): void =>
updatePlotVisibility(controller),
);
@@ -325,16 +344,20 @@ export default function TooltipPlugin({
removeSetSeriesHook();
removeSetLegendHook();
removeSetCursorHook();
if (controller.plot && overClickHandler) {
controller.plot.over.removeEventListener('click', overClickHandler);
if (overClickHandler) {
const plot = getPlot(controller);
if (plot) {
plot.over.removeEventListener('click', overClickHandler);
}
overClickHandler = null;
}
clearPlotReferences();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [config]);
useLayoutEffect((): void => {
if (!plot || !layoutRef.current) {
if (!hasPlot || !layoutRef.current) {
return;
}
const layout = layoutRef.current;
@@ -349,9 +372,9 @@ export default function TooltipPlugin({
layout.width = 0;
layout.height = 0;
}
}, [isHovering, plot]);
}, [isHovering, hasPlot]);
if (!plot) {
if (!hasPlot) {
return null;
}

View File

@@ -10,6 +10,11 @@ import {
const WINDOW_OFFSET = 16;
/** Get the plot instance from the controller; returns null if never set or cleared. */
export function getPlot(controller: TooltipControllerState): uPlot | null {
return controller.plot ?? null;
}
export function createInitialControllerState(): TooltipControllerState {
return {
plot: null,
@@ -46,12 +51,13 @@ export function updateWindowSize(controller: TooltipControllerState): void {
* This is used to decide if a synced tooltip should be shown at all.
*/
export function updatePlotVisibility(controller: TooltipControllerState): void {
if (!controller.plot) {
const plot = getPlot(controller);
if (!plot) {
controller.plotWithinViewport = false;
return;
}
controller.plotWithinViewport = isPlotInViewport(
controller.plot.rect,
plot.rect,
controller.windowWidth,
controller.windowHeight,
);
@@ -66,10 +72,11 @@ export function isScrollEventInPlot(
event: Event,
controller: TooltipControllerState,
): boolean {
const plot = getPlot(controller);
return (
event.target instanceof Node &&
controller.plot !== null &&
event.target.contains(controller.plot.root)
plot !== null &&
event.target.contains(plot.root)
);
}
@@ -165,11 +172,12 @@ export function createSetLegendHandler(
): (u: uPlot) => void {
return (u: uPlot): void => {
const { controller } = ctx;
if (!controller.plot?.cursor?.idxs) {
const plot = getPlot(controller);
if (!plot?.cursor?.idxs) {
return;
}
const newSeriesIndexes = controller.plot.cursor.idxs.slice();
const newSeriesIndexes = plot.cursor.idxs.slice();
const isAnySeriesActive = newSeriesIndexes.some((v, i) => i > 0 && v != null);
const previousCursorDrivenBySync = controller.cursorDrivenBySync;

View File

@@ -18,7 +18,8 @@ export enum DashboardCursorSync {
}
export interface TooltipViewState {
plot?: uPlot | null;
/** Whether a plot instance exists; plot reference is in controller, not state. */
hasPlot?: boolean;
style: Partial<CSSProperties>;
isHovering: boolean;
isPinned: boolean;

View File

@@ -123,7 +123,7 @@ export function createInitialViewState(): TooltipViewState {
isHovering: false,
isPinned: false,
contents: null,
plot: null,
hasPlot: false,
dismiss: (): void => {},
};
}

View File

@@ -12,6 +12,7 @@ import (
"github.com/SigNoz/signoz/pkg/sqlstore"
"github.com/SigNoz/signoz/pkg/types"
"github.com/SigNoz/signoz/pkg/types/authtypes"
"github.com/SigNoz/signoz/pkg/types/savedviewtypes"
"github.com/SigNoz/signoz/pkg/valuer"
)
@@ -24,7 +25,7 @@ func NewModule(sqlstore sqlstore.SQLStore) savedview.Module {
}
func (module *module) GetViewsForFilters(ctx context.Context, orgID string, sourcePage string, name string, category string) ([]*v3.SavedView, error) {
var views []types.SavedView
var views []savedviewtypes.SavedView
var err error
if len(category) == 0 {
err = module.sqlstore.BunDB().NewSelect().Model(&views).Where("org_id = ? AND source_page = ? AND name LIKE ?", orgID, sourcePage, "%"+name+"%").Scan(ctx)
@@ -76,7 +77,7 @@ func (module *module) CreateView(ctx context.Context, orgID string, view v3.Save
createBy := claims.Email
updatedBy := claims.Email
dbView := types.SavedView{
dbView := savedviewtypes.SavedView{
TimeAuditable: types.TimeAuditable{
CreatedAt: createdAt,
UpdatedAt: updatedAt,
@@ -105,7 +106,7 @@ func (module *module) CreateView(ctx context.Context, orgID string, view v3.Save
}
func (module *module) GetView(ctx context.Context, orgID string, uuid valuer.UUID) (*v3.SavedView, error) {
var view types.SavedView
var view savedviewtypes.SavedView
err := module.sqlstore.BunDB().NewSelect().Model(&view).Where("org_id = ? AND id = ?", orgID, uuid.StringValue()).Scan(ctx)
if err != nil {
return nil, errors.WrapInternalf(err, errors.CodeInternal, "error in getting saved view")
@@ -146,7 +147,7 @@ func (module *module) UpdateView(ctx context.Context, orgID string, uuid valuer.
updatedBy := claims.Email
_, err = module.sqlstore.BunDB().NewUpdate().
Model(&types.SavedView{}).
Model(&savedviewtypes.SavedView{}).
Set("updated_at = ?, updated_by = ?, name = ?, category = ?, source_page = ?, tags = ?, data = ?, extra_data = ?",
updatedAt, updatedBy, view.Name, view.Category, view.SourcePage, strings.Join(view.Tags, ","), data, view.ExtraData).
Where("id = ?", uuid.StringValue()).
@@ -160,7 +161,7 @@ func (module *module) UpdateView(ctx context.Context, orgID string, uuid valuer.
func (module *module) DeleteView(ctx context.Context, orgID string, uuid valuer.UUID) error {
_, err := module.sqlstore.BunDB().NewDelete().
Model(&types.SavedView{}).
Model(&savedviewtypes.SavedView{}).
Where("id = ?", uuid.StringValue()).
Where("org_id = ?", orgID).
Exec(ctx)
@@ -171,7 +172,7 @@ func (module *module) DeleteView(ctx context.Context, orgID string, uuid valuer.
}
func (module *module) Collect(ctx context.Context, orgID valuer.UUID) (map[string]any, error) {
savedViews := []*types.SavedView{}
savedViews := []*savedviewtypes.SavedView{}
err := module.
sqlstore.
@@ -184,5 +185,5 @@ func (module *module) Collect(ctx context.Context, orgID valuer.UUID) (map[strin
return nil, err
}
return types.NewStatsFromSavedViews(savedViews), nil
return savedviewtypes.NewStatsFromSavedViews(savedViews), nil
}

View File

@@ -13,6 +13,7 @@ import (
root "github.com/SigNoz/signoz/pkg/modules/user"
"github.com/SigNoz/signoz/pkg/types"
"github.com/SigNoz/signoz/pkg/types/authtypes"
"github.com/SigNoz/signoz/pkg/types/integrationtypes"
"github.com/SigNoz/signoz/pkg/valuer"
"github.com/gorilla/mux"
)
@@ -462,7 +463,7 @@ func (h *handler) UpdateAPIKey(w http.ResponseWriter, r *http.Request) {
return
}
if slices.Contains(types.AllIntegrationUserEmails, types.IntegrationUserEmail(createdByUser.Email.String())) {
if slices.Contains(integrationtypes.AllIntegrationUserEmails, integrationtypes.IntegrationUserEmail(createdByUser.Email.String())) {
render.Error(w, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "API Keys for integration users cannot be revoked"))
return
}
@@ -507,7 +508,7 @@ func (h *handler) RevokeAPIKey(w http.ResponseWriter, r *http.Request) {
return
}
if slices.Contains(types.AllIntegrationUserEmails, types.IntegrationUserEmail(createdByUser.Email.String())) {
if slices.Contains(integrationtypes.AllIntegrationUserEmails, integrationtypes.IntegrationUserEmail(createdByUser.Email.String())) {
render.Error(w, errors.Newf(errors.TypeInvalidInput, errors.CodeInvalidInput, "API Keys for integration users cannot be revoked"))
return
}

View File

@@ -19,6 +19,7 @@ import (
"github.com/SigNoz/signoz/pkg/types"
"github.com/SigNoz/signoz/pkg/types/authtypes"
"github.com/SigNoz/signoz/pkg/types/emailtypes"
"github.com/SigNoz/signoz/pkg/types/integrationtypes"
"github.com/SigNoz/signoz/pkg/types/roletypes"
"github.com/SigNoz/signoz/pkg/valuer"
"github.com/dustin/go-humanize"
@@ -279,7 +280,7 @@ func (module *Module) DeleteUser(ctx context.Context, orgID valuer.UUID, id stri
return errors.WithAdditionalf(err, "cannot delete root user")
}
if slices.Contains(types.AllIntegrationUserEmails, types.IntegrationUserEmail(user.Email.String())) {
if slices.Contains(integrationtypes.AllIntegrationUserEmails, integrationtypes.IntegrationUserEmail(user.Email.String())) {
return errors.New(errors.TypeForbidden, errors.CodeForbidden, "integration user cannot be deleted")
}

View File

@@ -10,15 +10,16 @@ import (
"github.com/SigNoz/signoz/pkg/query-service/model"
"github.com/SigNoz/signoz/pkg/sqlstore"
"github.com/SigNoz/signoz/pkg/types"
"github.com/SigNoz/signoz/pkg/types/integrationtypes"
"github.com/SigNoz/signoz/pkg/valuer"
)
type cloudProviderAccountsRepository interface {
listConnected(ctx context.Context, orgId string, provider string) ([]types.CloudIntegration, *model.ApiError)
listConnected(ctx context.Context, orgId string, provider string) ([]integrationtypes.CloudIntegration, *model.ApiError)
get(ctx context.Context, orgId string, provider string, id string) (*types.CloudIntegration, *model.ApiError)
get(ctx context.Context, orgId string, provider string, id string) (*integrationtypes.CloudIntegration, *model.ApiError)
getConnectedCloudAccount(ctx context.Context, orgId string, provider string, accountID string) (*types.CloudIntegration, *model.ApiError)
getConnectedCloudAccount(ctx context.Context, orgId string, provider string, accountID string) (*integrationtypes.CloudIntegration, *model.ApiError)
// Insert an account or update it by (cloudProvider, id)
// for specified non-empty fields
@@ -27,11 +28,11 @@ type cloudProviderAccountsRepository interface {
orgId string,
provider string,
id *string,
config *types.AccountConfig,
config *integrationtypes.AccountConfig,
accountId *string,
agentReport *types.AgentReport,
agentReport *integrationtypes.AgentReport,
removedAt *time.Time,
) (*types.CloudIntegration, *model.ApiError)
) (*integrationtypes.CloudIntegration, *model.ApiError)
}
func newCloudProviderAccountsRepository(store sqlstore.SQLStore) (
@@ -48,8 +49,8 @@ type cloudProviderAccountsSQLRepository struct {
func (r *cloudProviderAccountsSQLRepository) listConnected(
ctx context.Context, orgId string, cloudProvider string,
) ([]types.CloudIntegration, *model.ApiError) {
accounts := []types.CloudIntegration{}
) ([]integrationtypes.CloudIntegration, *model.ApiError) {
accounts := []integrationtypes.CloudIntegration{}
err := r.store.BunDB().NewSelect().
Model(&accounts).
@@ -72,8 +73,8 @@ func (r *cloudProviderAccountsSQLRepository) listConnected(
func (r *cloudProviderAccountsSQLRepository) get(
ctx context.Context, orgId string, provider string, id string,
) (*types.CloudIntegration, *model.ApiError) {
var result types.CloudIntegration
) (*integrationtypes.CloudIntegration, *model.ApiError) {
var result integrationtypes.CloudIntegration
err := r.store.BunDB().NewSelect().
Model(&result).
@@ -97,8 +98,8 @@ func (r *cloudProviderAccountsSQLRepository) get(
func (r *cloudProviderAccountsSQLRepository) getConnectedCloudAccount(
ctx context.Context, orgId string, provider string, accountId string,
) (*types.CloudIntegration, *model.ApiError) {
var result types.CloudIntegration
) (*integrationtypes.CloudIntegration, *model.ApiError) {
var result integrationtypes.CloudIntegration
err := r.store.BunDB().NewSelect().
Model(&result).
@@ -127,11 +128,11 @@ func (r *cloudProviderAccountsSQLRepository) upsert(
orgId string,
provider string,
id *string,
config *types.AccountConfig,
config *integrationtypes.AccountConfig,
accountId *string,
agentReport *types.AgentReport,
agentReport *integrationtypes.AgentReport,
removedAt *time.Time,
) (*types.CloudIntegration, *model.ApiError) {
) (*integrationtypes.CloudIntegration, *model.ApiError) {
// Insert
if id == nil {
temp := valuer.GenerateUUID().StringValue()
@@ -181,7 +182,7 @@ func (r *cloudProviderAccountsSQLRepository) upsert(
)
}
integration := types.CloudIntegration{
integration := integrationtypes.CloudIntegration{
OrgID: orgId,
Provider: provider,
Identifiable: types.Identifiable{ID: valuer.MustNewUUID(*id)},

View File

@@ -14,6 +14,7 @@ import (
"github.com/SigNoz/signoz/pkg/sqlstore"
"github.com/SigNoz/signoz/pkg/types"
"github.com/SigNoz/signoz/pkg/types/dashboardtypes"
"github.com/SigNoz/signoz/pkg/types/integrationtypes"
"github.com/SigNoz/signoz/pkg/valuer"
"golang.org/x/exp/maps"
)
@@ -52,7 +53,7 @@ func NewController(sqlStore sqlstore.SQLStore) (*Controller, error) {
}
type ConnectedAccountsListResponse struct {
Accounts []types.Account `json:"accounts"`
Accounts []integrationtypes.Account `json:"accounts"`
}
func (c *Controller) ListConnectedAccounts(ctx context.Context, orgId string, cloudProvider string) (
@@ -67,7 +68,7 @@ func (c *Controller) ListConnectedAccounts(ctx context.Context, orgId string, cl
return nil, model.WrapApiError(apiErr, "couldn't list cloud accounts")
}
connectedAccounts := []types.Account{}
connectedAccounts := []integrationtypes.Account{}
for _, a := range accountRecords {
connectedAccounts = append(connectedAccounts, a.Account())
}
@@ -81,7 +82,7 @@ type GenerateConnectionUrlRequest struct {
// Optional. To be specified for updates.
AccountId *string `json:"account_id,omitempty"`
AccountConfig types.AccountConfig `json:"account_config"`
AccountConfig integrationtypes.AccountConfig `json:"account_config"`
AgentConfig SigNozAgentConfig `json:"agent_config"`
}
@@ -149,9 +150,9 @@ func (c *Controller) GenerateConnectionUrl(ctx context.Context, orgId string, cl
}
type AccountStatusResponse struct {
Id string `json:"id"`
CloudAccountId *string `json:"cloud_account_id,omitempty"`
Status types.AccountStatus `json:"status"`
Id string `json:"id"`
CloudAccountId *string `json:"cloud_account_id,omitempty"`
Status integrationtypes.AccountStatus `json:"status"`
}
func (c *Controller) GetAccountStatus(ctx context.Context, orgId string, cloudProvider string, accountId string) (
@@ -217,7 +218,7 @@ func (c *Controller) CheckInAsAgent(ctx context.Context, orgId string, cloudProv
))
}
agentReport := types.AgentReport{
agentReport := integrationtypes.AgentReport{
TimestampMillis: time.Now().UnixMilli(),
Data: req.Data,
}
@@ -286,10 +287,10 @@ func (c *Controller) CheckInAsAgent(ctx context.Context, orgId string, cloudProv
}
type UpdateAccountConfigRequest struct {
Config types.AccountConfig `json:"config"`
Config integrationtypes.AccountConfig `json:"config"`
}
func (c *Controller) UpdateAccountConfig(ctx context.Context, orgId string, cloudProvider string, accountId string, req UpdateAccountConfigRequest) (*types.Account, *model.ApiError) {
func (c *Controller) UpdateAccountConfig(ctx context.Context, orgId string, cloudProvider string, accountId string, req UpdateAccountConfigRequest) (*integrationtypes.Account, *model.ApiError) {
if apiErr := validateCloudProviderName(cloudProvider); apiErr != nil {
return nil, apiErr
}
@@ -306,7 +307,7 @@ func (c *Controller) UpdateAccountConfig(ctx context.Context, orgId string, clou
return &account, nil
}
func (c *Controller) DisconnectAccount(ctx context.Context, orgId string, cloudProvider string, accountId string) (*types.CloudIntegration, *model.ApiError) {
func (c *Controller) DisconnectAccount(ctx context.Context, orgId string, cloudProvider string, accountId string) (*integrationtypes.CloudIntegration, *model.ApiError) {
if apiErr := validateCloudProviderName(cloudProvider); apiErr != nil {
return nil, apiErr
}
@@ -346,7 +347,7 @@ func (c *Controller) ListServices(
return nil, model.WrapApiError(apiErr, "couldn't list cloud services")
}
svcConfigs := map[string]*types.CloudServiceConfig{}
svcConfigs := map[string]*integrationtypes.CloudServiceConfig{}
if cloudAccountId != nil {
activeAccount, apiErr := c.accountsRepo.getConnectedCloudAccount(
ctx, orgID, cloudProvider, *cloudAccountId,
@@ -441,8 +442,8 @@ func (c *Controller) GetServiceDetails(
}
type UpdateServiceConfigRequest struct {
CloudAccountId string `json:"cloud_account_id"`
Config types.CloudServiceConfig `json:"config"`
CloudAccountId string `json:"cloud_account_id"`
Config integrationtypes.CloudServiceConfig `json:"config"`
}
func (u *UpdateServiceConfigRequest) Validate(def *services.Definition) error {
@@ -460,8 +461,8 @@ func (u *UpdateServiceConfigRequest) Validate(def *services.Definition) error {
}
type UpdateServiceConfigResponse struct {
Id string `json:"id"`
Config types.CloudServiceConfig `json:"config"`
Id string `json:"id"`
Config integrationtypes.CloudServiceConfig `json:"config"`
}
func (c *Controller) UpdateServiceConfig(

View File

@@ -3,20 +3,20 @@ package cloudintegrations
import (
"github.com/SigNoz/signoz/pkg/errors"
"github.com/SigNoz/signoz/pkg/query-service/app/cloudintegrations/services"
"github.com/SigNoz/signoz/pkg/types"
"github.com/SigNoz/signoz/pkg/types/integrationtypes"
)
type ServiceSummary struct {
services.Metadata
Config *types.CloudServiceConfig `json:"config"`
Config *integrationtypes.CloudServiceConfig `json:"config"`
}
type ServiceDetails struct {
services.Definition
Config *types.CloudServiceConfig `json:"config"`
ConnectionStatus *ServiceConnectionStatus `json:"status,omitempty"`
Config *integrationtypes.CloudServiceConfig `json:"config"`
ConnectionStatus *ServiceConnectionStatus `json:"status,omitempty"`
}
type AccountStatus struct {
@@ -61,7 +61,7 @@ func NewCompiledCollectionStrategy(provider string) (*CompiledCollectionStrategy
// Helper for accumulating strategies for enabled services.
func AddServiceStrategy(serviceType string, cs *CompiledCollectionStrategy,
definitionStrat *services.CollectionStrategy, config *types.CloudServiceConfig) error {
definitionStrat *services.CollectionStrategy, config *integrationtypes.CloudServiceConfig) error {
if definitionStrat.Provider != cs.Provider {
return errors.NewInternalf(CodeMismatchCloudProvider, "can't add %s service strategy to compiled strategy for %s",
definitionStrat.Provider, cs.Provider)

View File

@@ -9,6 +9,7 @@ import (
"github.com/SigNoz/signoz/pkg/query-service/model"
"github.com/SigNoz/signoz/pkg/sqlstore"
"github.com/SigNoz/signoz/pkg/types"
"github.com/SigNoz/signoz/pkg/types/integrationtypes"
"github.com/SigNoz/signoz/pkg/valuer"
)
@@ -18,7 +19,7 @@ type ServiceConfigDatabase interface {
orgID string,
cloudAccountId string,
serviceType string,
) (*types.CloudServiceConfig, *model.ApiError)
) (*integrationtypes.CloudServiceConfig, *model.ApiError)
upsert(
ctx context.Context,
@@ -26,15 +27,15 @@ type ServiceConfigDatabase interface {
cloudProvider string,
cloudAccountId string,
serviceId string,
config types.CloudServiceConfig,
) (*types.CloudServiceConfig, *model.ApiError)
config integrationtypes.CloudServiceConfig,
) (*integrationtypes.CloudServiceConfig, *model.ApiError)
getAllForAccount(
ctx context.Context,
orgID string,
cloudAccountId string,
) (
configsBySvcId map[string]*types.CloudServiceConfig,
configsBySvcId map[string]*integrationtypes.CloudServiceConfig,
apiErr *model.ApiError,
)
}
@@ -56,9 +57,9 @@ func (r *serviceConfigSQLRepository) get(
orgID string,
cloudAccountId string,
serviceType string,
) (*types.CloudServiceConfig, *model.ApiError) {
) (*integrationtypes.CloudServiceConfig, *model.ApiError) {
var result types.CloudIntegrationService
var result integrationtypes.CloudIntegrationService
err := r.store.BunDB().NewSelect().
Model(&result).
@@ -89,14 +90,14 @@ func (r *serviceConfigSQLRepository) upsert(
cloudProvider string,
cloudAccountId string,
serviceId string,
config types.CloudServiceConfig,
) (*types.CloudServiceConfig, *model.ApiError) {
config integrationtypes.CloudServiceConfig,
) (*integrationtypes.CloudServiceConfig, *model.ApiError) {
// get cloud integration id from account id
// if the account is not connected, we don't need to upsert the config
var cloudIntegrationId string
err := r.store.BunDB().NewSelect().
Model((*types.CloudIntegration)(nil)).
Model((*integrationtypes.CloudIntegration)(nil)).
Column("id").
Where("provider = ?", cloudProvider).
Where("account_id = ?", cloudAccountId).
@@ -111,7 +112,7 @@ func (r *serviceConfigSQLRepository) upsert(
))
}
serviceConfig := types.CloudIntegrationService{
serviceConfig := integrationtypes.CloudIntegrationService{
Identifiable: types.Identifiable{ID: valuer.GenerateUUID()},
TimeAuditable: types.TimeAuditable{
CreatedAt: time.Now(),
@@ -139,8 +140,8 @@ func (r *serviceConfigSQLRepository) getAllForAccount(
ctx context.Context,
orgID string,
cloudAccountId string,
) (map[string]*types.CloudServiceConfig, *model.ApiError) {
serviceConfigs := []types.CloudIntegrationService{}
) (map[string]*integrationtypes.CloudServiceConfig, *model.ApiError) {
serviceConfigs := []integrationtypes.CloudIntegrationService{}
err := r.store.BunDB().NewSelect().
Model(&serviceConfigs).
@@ -154,7 +155,7 @@ func (r *serviceConfigSQLRepository) getAllForAccount(
))
}
result := map[string]*types.CloudServiceConfig{}
result := map[string]*integrationtypes.CloudServiceConfig{}
for _, r := range serviceConfigs {
result[r.Type] = &r.Config

View File

@@ -11,6 +11,7 @@ import (
"github.com/SigNoz/signoz/pkg/sqlstore"
"github.com/SigNoz/signoz/pkg/types"
"github.com/SigNoz/signoz/pkg/types/dashboardtypes"
"github.com/SigNoz/signoz/pkg/types/integrationtypes"
"github.com/SigNoz/signoz/pkg/types/pipelinetypes"
ruletypes "github.com/SigNoz/signoz/pkg/types/ruletypes"
"github.com/SigNoz/signoz/pkg/valuer"
@@ -107,7 +108,7 @@ type IntegrationsListItem struct {
type Integration struct {
IntegrationDetails
Installation *types.InstalledIntegration `json:"installation"`
Installation *integrationtypes.InstalledIntegration `json:"installation"`
}
type Manager struct {
@@ -223,7 +224,7 @@ func (m *Manager) InstallIntegration(
ctx context.Context,
orgId string,
integrationId string,
config types.InstalledIntegrationConfig,
config integrationtypes.InstalledIntegrationConfig,
) (*IntegrationsListItem, *model.ApiError) {
integrationDetails, apiErr := m.getIntegrationDetails(ctx, integrationId)
if apiErr != nil {
@@ -429,7 +430,7 @@ func (m *Manager) getInstalledIntegration(
ctx context.Context,
orgId string,
integrationId string,
) (*types.InstalledIntegration, *model.ApiError) {
) (*integrationtypes.InstalledIntegration, *model.ApiError) {
iis, apiErr := m.installedIntegrationsRepo.get(
ctx, orgId, []string{integrationId},
)
@@ -457,7 +458,7 @@ func (m *Manager) getInstalledIntegrations(
return nil, apiErr
}
installedTypes := utils.MapSlice(installations, func(i types.InstalledIntegration) string {
installedTypes := utils.MapSlice(installations, func(i integrationtypes.InstalledIntegration) string {
return i.Type
})
integrationDetails, apiErr := m.availableIntegrationsRepo.get(ctx, installedTypes)

View File

@@ -4,22 +4,22 @@ import (
"context"
"github.com/SigNoz/signoz/pkg/query-service/model"
"github.com/SigNoz/signoz/pkg/types"
"github.com/SigNoz/signoz/pkg/types/integrationtypes"
)
type InstalledIntegrationsRepo interface {
list(ctx context.Context, orgId string) ([]types.InstalledIntegration, *model.ApiError)
list(ctx context.Context, orgId string) ([]integrationtypes.InstalledIntegration, *model.ApiError)
get(
ctx context.Context, orgId string, integrationTypes []string,
) (map[string]types.InstalledIntegration, *model.ApiError)
) (map[string]integrationtypes.InstalledIntegration, *model.ApiError)
upsert(
ctx context.Context,
orgId string,
integrationType string,
config types.InstalledIntegrationConfig,
) (*types.InstalledIntegration, *model.ApiError)
config integrationtypes.InstalledIntegrationConfig,
) (*integrationtypes.InstalledIntegration, *model.ApiError)
delete(ctx context.Context, orgId string, integrationType string) *model.ApiError
}

View File

@@ -7,6 +7,7 @@ import (
"github.com/SigNoz/signoz/pkg/query-service/model"
"github.com/SigNoz/signoz/pkg/sqlstore"
"github.com/SigNoz/signoz/pkg/types"
"github.com/SigNoz/signoz/pkg/types/integrationtypes"
"github.com/SigNoz/signoz/pkg/valuer"
"github.com/uptrace/bun"
)
@@ -26,8 +27,8 @@ func NewInstalledIntegrationsSqliteRepo(store sqlstore.SQLStore) (
func (r *InstalledIntegrationsSqliteRepo) list(
ctx context.Context,
orgId string,
) ([]types.InstalledIntegration, *model.ApiError) {
integrations := []types.InstalledIntegration{}
) ([]integrationtypes.InstalledIntegration, *model.ApiError) {
integrations := []integrationtypes.InstalledIntegration{}
err := r.store.BunDB().NewSelect().
Model(&integrations).
@@ -44,8 +45,8 @@ func (r *InstalledIntegrationsSqliteRepo) list(
func (r *InstalledIntegrationsSqliteRepo) get(
ctx context.Context, orgId string, integrationTypes []string,
) (map[string]types.InstalledIntegration, *model.ApiError) {
integrations := []types.InstalledIntegration{}
) (map[string]integrationtypes.InstalledIntegration, *model.ApiError) {
integrations := []integrationtypes.InstalledIntegration{}
typeValues := []interface{}{}
for _, integrationType := range integrationTypes {
@@ -62,7 +63,7 @@ func (r *InstalledIntegrationsSqliteRepo) get(
))
}
result := map[string]types.InstalledIntegration{}
result := map[string]integrationtypes.InstalledIntegration{}
for _, ii := range integrations {
result[ii.Type] = ii
}
@@ -74,10 +75,10 @@ func (r *InstalledIntegrationsSqliteRepo) upsert(
ctx context.Context,
orgId string,
integrationType string,
config types.InstalledIntegrationConfig,
) (*types.InstalledIntegration, *model.ApiError) {
config integrationtypes.InstalledIntegrationConfig,
) (*integrationtypes.InstalledIntegration, *model.ApiError) {
integration := types.InstalledIntegration{
integration := integrationtypes.InstalledIntegration{
Identifiable: types.Identifiable{
ID: valuer.GenerateUUID(),
},
@@ -114,7 +115,7 @@ func (r *InstalledIntegrationsSqliteRepo) delete(
ctx context.Context, orgId string, integrationType string,
) *model.ApiError {
_, dbErr := r.store.BunDB().NewDelete().
Model(&types.InstalledIntegration{}).
Model(&integrationtypes.InstalledIntegration{}).
Where("type = ?", integrationType).
Where("org_id = ?", orgId).
Exec(ctx)

View File

@@ -1,4 +1,4 @@
package types
package integrationtypes
import (
"database/sql/driver"
@@ -6,6 +6,7 @@ import (
"time"
"github.com/SigNoz/signoz/pkg/errors"
"github.com/SigNoz/signoz/pkg/types"
"github.com/uptrace/bun"
)
@@ -26,17 +27,17 @@ var AllIntegrationUserEmails = []IntegrationUserEmail{
type InstalledIntegration struct {
bun.BaseModel `bun:"table:installed_integration"`
Identifiable
types.Identifiable
Type string `json:"type" bun:"type,type:text,unique:org_id_type"`
Config InstalledIntegrationConfig `json:"config" bun:"config,type:text"`
InstalledAt time.Time `json:"installed_at" bun:"installed_at,default:current_timestamp"`
OrgID string `json:"org_id" bun:"org_id,type:text,unique:org_id_type,references:organizations(id),on_delete:cascade"`
}
type InstalledIntegrationConfig map[string]interface{}
type InstalledIntegrationConfig map[string]any
// For serializing from db
func (c *InstalledIntegrationConfig) Scan(src interface{}) error {
func (c *InstalledIntegrationConfig) Scan(src any) error {
var data []byte
switch v := src.(type) {
case []byte:
@@ -67,8 +68,8 @@ func (c *InstalledIntegrationConfig) Value() (driver.Value, error) {
type CloudIntegration struct {
bun.BaseModel `bun:"table:cloud_integration"`
Identifiable
TimeAuditable
types.Identifiable
types.TimeAuditable
Provider string `json:"provider" bun:"provider,type:text,unique:provider_id"`
Config *AccountConfig `json:"config" bun:"config,type:text"`
AccountID *string `json:"account_id" bun:"account_id,type:text"`
@@ -194,8 +195,8 @@ func (r *AgentReport) Value() (driver.Value, error) {
type CloudIntegrationService struct {
bun.BaseModel `bun:"table:cloud_integration_service,alias:cis"`
Identifiable
TimeAuditable
types.Identifiable
types.TimeAuditable
Type string `bun:"type,type:text,notnull,unique:cloud_integration_id_type"`
Config CloudServiceConfig `bun:"config,type:text"`
CloudIntegrationID string `bun:"cloud_integration_id,type:text,notnull,unique:cloud_integration_id_type,references:cloud_integrations(id),on_delete:cascade"`

View File

@@ -1,17 +1,18 @@
package types
package savedviewtypes
import (
"strings"
"github.com/SigNoz/signoz/pkg/types"
"github.com/uptrace/bun"
)
type SavedView struct {
bun.BaseModel `bun:"table:saved_views"`
Identifiable
TimeAuditable
UserAuditable
types.Identifiable
types.TimeAuditable
types.UserAuditable
OrgID string `json:"orgId" bun:"org_id,notnull"`
Name string `json:"name" bun:"name,type:text,notnull"`
Category string `json:"category" bun:"category,type:text,notnull"`