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
32 changes: 32 additions & 0 deletions src/Frontend/src/components/audit/auditClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import Message, { MessageStatus } from "@/resources/Message";
import type { SortInfo } from "@/components/SortInfo";
import type { DateRange } from "@/types/date";
import serviceControlClient from "@/components/serviceControlClient";

export interface AuditQuery {
endpointName?: string;
dateRange?: DateRange;
messageFilterString?: string;
itemsPerPage?: number;
sort?: SortInfo;
}

class AuditClient {
public async getMessages(query: AuditQuery): Promise<[Response, Message[]]> {
const [fromDate, toDate] = query.dateRange ?? [];
const from = fromDate?.toISOString() ?? "";
const to = toDate?.toISOString() ?? "";
return await serviceControlClient.fetchTypedFromServiceControl<Message[]>(
`messages2/?endpoint_name=${query.endpointName ?? ""}&from=${from}&to=${to}&q=${query.messageFilterString ?? ""}&page_size=${query.itemsPerPage ?? 100}&sort=${query.sort?.property ?? "time_sent"}&direction=${query.sort?.isAscending ? "asc" : "desc"}`
);
}

public async hasSuccessfulMessages(): Promise<boolean> {
// Fetch the latest 10 messages and check if any are successful
// ideally we would want to filter successful messages server-side, but the API doesn't currently support that
const [, data] = await serviceControlClient.fetchTypedFromServiceControl<Message[]>(`messages2/?page_size=10&sort=time_sent&direction=desc`);
return data?.some((msg) => msg.status === MessageStatus.Successful) ?? false;
}
}

export default new AuditClient();
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import useIsAllMessagesSupported, { minimumSCVersionForAllMessages } from "@/com
import { storeToRefs } from "pinia";
import { type CapabilityComposable, type CapabilityStatusToStringMap, useCapabilityBase } from "./BaseCapability";
import useRemoteInstancesAutoRefresh from "@/composables/useRemoteInstancesAutoRefresh";
import useAuditStoreAutoRefresh from "@/composables/useAuditStoreAutoRefresh";
import usePlatformCapabilitiesRefresh from "@/composables/usePlatformCapabilitiesRefresh";
import { RemoteInstanceStatus, RemoteInstanceType, type RemoteInstance } from "@/resources/RemoteInstance";
import routeLinks from "@/router/routeLinks";

Expand Down Expand Up @@ -110,8 +110,8 @@ export function useAuditingCapability(): CapabilityComposable {

// This gives us the hasSuccessfulMessages flag which indicates if any successful messages exist.
// Uses auto-refresh (minimal) to periodically check for at least 1 successful message (every 5 seconds)
const { store: auditStore } = useAuditStoreAutoRefresh();
const { hasSuccessfulMessages } = storeToRefs(auditStore);
const { store: platformCapabilitiesStore } = usePlatformCapabilitiesRefresh();
const { hasSuccessfulMessages } = storeToRefs(platformCapabilitiesStore);

// This tells us if the "All Messages" feature is supported by checking the SC version
const isAllMessagesSupported = useIsAllMessagesSupported();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { StatusIndicator } from "@/components/platformcapabilities/types";
import { CapabilityStatus } from "@/components/platformcapabilities/constants";
import { storeToRefs } from "pinia";
import { useConnectionsAndStatsStore } from "@/stores/ConnectionsAndStatsStore";
import useMonitoringStoreAutoRefresh from "@/composables/useMonitoringStoreAutoRefresh";
import { type CapabilityComposable, type CapabilityStatusToStringMap, useCapabilityBase } from "./BaseCapability";
import monitoringClient from "@/components/monitoring/monitoringClient";
import { useEnvironmentAndVersionsStore } from "@/stores/EnvironmentAndVersionsStore";
import usePlatformCapabilitiesRefresh from "@/composables/usePlatformCapabilitiesRefresh";
import routeLinks from "@/router/routeLinks";

const MonitoringDescriptions: CapabilityStatusToStringMap = {
Expand Down Expand Up @@ -46,8 +46,8 @@ export function useMonitoringCapability(): CapabilityComposable {

// this tells us if there are any endpoints sending data
// Uses auto-refresh to periodically check for monitored endpoints (every 5 seconds)
const { store: monitoringStore } = useMonitoringStoreAutoRefresh();
const { hasMonitoredEndpoints } = storeToRefs(monitoringStore);
const { store: platformCapabilitiesStore } = usePlatformCapabilitiesRefresh();
const { hasMonitoredEndpoints } = storeToRefs(platformCapabilitiesStore);

// this tells us the connection state to the monitoring instance
// this is auto refreshed in the ConnectionsAndStatsStore (every 5 seconds)
Expand Down
10 changes: 0 additions & 10 deletions src/Frontend/src/composables/useAuditStoreAutoRefresh.ts

This file was deleted.

10 changes: 0 additions & 10 deletions src/Frontend/src/composables/useMonitoringStoreAutoRefresh.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { usePlatformCapabilitiesStore } from "@/stores/PlatformCapabilitiesStore";
import { useStoreAutoRefresh } from "./useAutoRefresh";

export default useStoreAutoRefresh("platformCapabilities", usePlatformCapabilitiesStore, 5000).autoRefresh;
31 changes: 9 additions & 22 deletions src/Frontend/src/stores/AuditStore.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { acceptHMRUpdate, defineStore } from "pinia";
import { ref } from "vue";
import type { SortInfo } from "@/components/SortInfo";
import Message, { MessageStatus } from "@/resources/Message";
import Message from "@/resources/Message";
import { EndpointsView } from "@/resources/EndpointView";
import type { DateRange } from "@/types/date";
import serviceControlClient from "@/components/serviceControlClient";
import auditClient from "@/components/audit/auditClient";

export enum FieldNames {
TimeSent = "time_sent",
Expand All @@ -27,19 +28,6 @@ export const useAuditStore = defineStore("AuditStore", () => {
const selectedEndpointName = ref<string>("");
const endpoints = ref<EndpointsView[]>([]);

const hasSuccessfulMessages = ref(false);

async function checkForSuccessfulMessages() {
try {
// Fetch the latest 10 messages and check if any are successful
// ideally we would want to filter successful messages server-side, but the API doesn't currently support that
const [, data] = await serviceControlClient.fetchTypedFromServiceControl<Message[]>(`messages2/?page_size=10&sort=time_sent&direction=desc`);
hasSuccessfulMessages.value = data?.some((msg) => msg.status === MessageStatus.Successful) ?? false;
} catch {
hasSuccessfulMessages.value = false;
}
}

async function loadEndpoints() {
try {
const [, data] = await serviceControlClient.fetchTypedFromServiceControl<EndpointsView[]>(`endpoints`);
Expand All @@ -52,12 +40,13 @@ export const useAuditStore = defineStore("AuditStore", () => {

async function refresh() {
try {
const [fromDate, toDate] = dateRange.value;
const from = fromDate?.toISOString() ?? "";
const to = toDate?.toISOString() ?? "";
const [response, data] = await serviceControlClient.fetchTypedFromServiceControl<Message[]>(
`messages2/?endpoint_name=${selectedEndpointName.value}&from=${from}&to=${to}&q=${messageFilterString.value}&page_size=${itemsPerPage.value}&sort=${sortByInstances.value.property}&direction=${sortByInstances.value.isAscending ? "asc" : "desc"}`
);
const [response, data] = await auditClient.getMessages({
endpointName: selectedEndpointName.value,
dateRange: dateRange.value,
messageFilterString: messageFilterString.value,
itemsPerPage: itemsPerPage.value,
sort: sortByInstances.value,
});
totalCount.value = parseInt(response.headers.get("total-count") ?? "0");
messages.value = data;
} catch (e) {
Expand All @@ -69,10 +58,8 @@ export const useAuditStore = defineStore("AuditStore", () => {
return {
refresh,
loadEndpoints,
checkForSuccessfulMessages,
sortBy: sortByInstances,
messages,
hasSuccessfulMessages,
messageFilterString,
selectedEndpointName,
itemsPerPage,
Expand Down
17 changes: 0 additions & 17 deletions src/Frontend/src/stores/MonitoringStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ export const useMonitoringStore = defineStore("MonitoringStore", () => {

const endpointList = ref<Endpoint[]>([]);
const filterString = ref("");
const hasMonitoredEndpoints = ref(false);
const endpointListCount = computed<number>(() => endpointList.value.length);
const endpointListIsEmpty = computed<boolean>(() => endpointListCount.value === 0);
const endpointListIsGrouped = computed<boolean>(() => grouping.value.selectedGrouping !== 0);
Expand Down Expand Up @@ -70,20 +69,6 @@ export const useMonitoringStore = defineStore("MonitoringStore", () => {
}
}

async function checkForMonitoredEndpoints() {
try {
if (!monitoringClient.isMonitoringEnabled || connectionStore.monitoringConnectionState.unableToConnect) {
hasMonitoredEndpoints.value = false;
return;
}
// Minimal query: just need to check if any endpoints exist
const data = await monitoringClient.getMonitoredEndpoints(1);
hasMonitoredEndpoints.value = (data?.length ?? 0) > 0;
} catch {
hasMonitoredEndpoints.value = false;
}
}

async function getAllMonitoredEndpoints() {
let endpoints: Endpoint[] = [];
if (monitoringClient.isMonitoringEnabled) {
Expand Down Expand Up @@ -217,7 +202,6 @@ export const useMonitoringStore = defineStore("MonitoringStore", () => {
grouping,
filterString,
sortBy,
hasMonitoredEndpoints,

//getters
endpointListIsEmpty,
Expand All @@ -228,7 +212,6 @@ export const useMonitoringStore = defineStore("MonitoringStore", () => {
updateSelectedGrouping,
updateEndpointList,
updateFilterString,
checkForMonitoredEndpoints,
};
});

Expand Down
37 changes: 36 additions & 1 deletion src/Frontend/src/stores/PlatformCapabilitiesStore.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { acceptHMRUpdate, defineStore } from "pinia";
import { ref, watch } from "vue";
import serviceControlClient from "@/components/serviceControlClient";
import auditClient from "@/components/audit/auditClient";
import monitoringClient from "@/components/monitoring/monitoringClient";
import useConnectionsAndStatsAutoRefresh from "@/composables/useConnectionsAndStatsAutoRefresh";

const STORAGE_KEY_PREFIX = "servicepulse-capabilities-vis";

Expand All @@ -16,7 +19,7 @@ function getStorageKey(): string {
return STORAGE_KEY_PREFIX;
}

interface PlatformCapabilitiesVisibility {
export interface PlatformCapabilitiesVisibility {
showSection: boolean;
showAuditingCard: boolean;
showMonitoringCard: boolean;
Expand Down Expand Up @@ -52,7 +55,36 @@ function saveVisibility(visibility: PlatformCapabilitiesVisibility): void {
}

export const usePlatformCapabilitiesStore = defineStore("PlatformCapabilitiesStore", () => {
const { store: connectionStore } = useConnectionsAndStatsAutoRefresh();
const visibility = ref<PlatformCapabilitiesVisibility>(loadVisibility());
const hasSuccessfulMessages = ref(false);
const hasMonitoredEndpoints = ref(false);

async function checkForSuccessfulMessages() {
try {
hasSuccessfulMessages.value = await auditClient.hasSuccessfulMessages();
} catch {
hasSuccessfulMessages.value = false;
}
}

async function checkForMonitoredEndpoints() {
try {
if (!monitoringClient.isMonitoringEnabled || connectionStore.monitoringConnectionState.unableToConnect) {
hasMonitoredEndpoints.value = false;
return;
}
// Minimal query: just need to check if any endpoints exist
const data = await monitoringClient.getMonitoredEndpoints(1);
hasMonitoredEndpoints.value = (data?.length ?? 0) > 0;
} catch {
hasMonitoredEndpoints.value = false;
}
}

async function refresh() {
await Promise.all([checkForSuccessfulMessages(), checkForMonitoredEndpoints()]);
}

// Watch for changes and persist to localStorage
watch(
Expand Down Expand Up @@ -93,6 +125,9 @@ export const usePlatformCapabilitiesStore = defineStore("PlatformCapabilitiesSto
toggleMonitoringCard,
toggleErrorCard,
showAll,
hasSuccessfulMessages,
hasMonitoredEndpoints,
refresh,
};
});

Expand Down
Loading