Skip to content

Commit 031d66e

Browse files
warwickschroederjasontaylordev
authored andcommitted
Finish initial audit and monitoring promo work
1 parent a31b243 commit 031d66e

File tree

7 files changed

+64
-118
lines changed

7 files changed

+64
-118
lines changed

src/Frontend/src/components/audit/AuditList.vue

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,27 @@ import { useRoute, useRouter } from "vue-router";
55
import ResultsCount from "@/components/ResultsCount.vue";
66
import FiltersPanel from "@/components/audit/FiltersPanel.vue";
77
import AuditListItem from "@/components/audit/AuditListItem.vue";
8-
import { onBeforeMount, ref, watch } from "vue";
8+
import { computed, onBeforeMount, ref, watch } from "vue";
99
import RefreshConfig from "../RefreshConfig.vue";
1010
import LoadingSpinner from "@/components/LoadingSpinner.vue";
1111
import useFetchWithAutoRefresh from "@/composables/autoRefresh";
1212
import FAIcon from "@/components/FAIcon.vue";
1313
import { faInfoCircle } from "@fortawesome/free-solid-svg-icons";
1414
import WizardDialog from "@/components/platformcapabilities/WizardDialog.vue";
1515
import { getAuditingWizardPages } from "@/components/platformcapabilities/wizards/AuditingWizardPages";
16+
import { useAuditingCapability } from "@/components/platformcapabilities/capabilities/AuditingCapability";
1617
import { CapabilityStatus } from "@/components/platformcapabilities/types";
1718
1819
const store = useAuditStore();
19-
const { hasSuccessfulMessages } = storeToRefs(store);
2020
const { messages, totalCount, sortBy, messageFilterString, selectedEndpointName, itemsPerPage, dateRange } = storeToRefs(store);
2121
const route = useRoute();
2222
const router = useRouter();
2323
const autoRefreshValue = ref<number | null>(null);
2424
const { refreshNow, isRefreshing, updateInterval, isActive, start, stop } = useFetchWithAutoRefresh("audit-list", store.refresh, 0);
2525
const firstLoad = ref(true);
2626
const showWizard = ref(false);
27-
const wizardPages = getAuditingWizardPages(CapabilityStatus.EndpointsNotConfigured);
27+
const { status: auditStatus } = useAuditingCapability();
28+
const wizardPages = computed(() => getAuditingWizardPages(auditStatus.value));
2829
2930
onBeforeMount(() => {
3031
setQuery();
@@ -108,14 +109,30 @@ watch(autoRefreshValue, (newValue) => {
108109
<div class="row">
109110
<ResultsCount :displayed="messages.length" :total="totalCount" />
110111
</div>
111-
<div v-if="!hasSuccessfulMessages" class="no-audit-banner">
112+
<div v-if="auditStatus !== CapabilityStatus.Available" class="no-audit-banner">
112113
<div class="banner-content">
113114
<FAIcon :icon="faInfoCircle" class="banner-icon" />
114115
<div class="banner-text">
115-
<strong>No successful audit messages found.</strong>
116-
<p>Auditing may not be enabled on your endpoints. Click 'Get Started' to find out how to enable auditing.</p>
116+
<template v-if="auditStatus === CapabilityStatus.InstanceNotConfigured">
117+
<strong>No ServiceControl Audit instance configured.</strong>
118+
<p>A ServiceControl Audit instance is required to view processed messages. Click 'Get Started' to learn how to set one up.</p>
119+
</template>
120+
<template v-else-if="auditStatus === CapabilityStatus.EndpointsNotConfigured">
121+
<strong>No successful audit messages found.</strong>
122+
<p>Auditing may not be enabled on your endpoints. Click 'Get Started' to find out how to enable auditing.</p>
123+
</template>
124+
<template v-else-if="auditStatus === CapabilityStatus.Unavailable">
125+
<strong>All ServiceControl Audit instances are not responding.</strong>
126+
<p>The configured audit instances appears to be offline or unreachable. Check that the service is running and accessible.</p>
127+
</template>
128+
<template v-else-if="auditStatus === CapabilityStatus.PartiallyUnavailable">
129+
<strong>Some ServiceControl Audit instances are not responding.</strong>
130+
<p>One or more audit instances appear to be offline. Some audit data may be unavailable until all instances are restored.</p>
131+
</template>
117132
</div>
118-
<button class="banner-link" @click="showWizard = true">Get Started</button>
133+
<template v-if="auditStatus !== CapabilityStatus.Unavailable && auditStatus !== CapabilityStatus.PartiallyUnavailable">
134+
<button class="banner-link" @click="showWizard = true">Get Started</button>
135+
</template>
119136
</div>
120137
</div>
121138
</div>

src/Frontend/src/components/platformcapabilities/CapabilityCard.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ const props = defineProps<{
2121
const showWizard = ref(false);
2222
2323
const shouldShowWizard = computed(() => {
24-
return props.wizardPages && props.wizardPages.length > 0 && (props.status === CapabilityStatus.EndpointsNotConfigured || props.status === CapabilityStatus.InstanceNotConfigured || props.status === CapabilityStatus.Unavailable);
24+
return props.wizardPages && props.wizardPages.length > 0 && (props.status === CapabilityStatus.EndpointsNotConfigured || props.status === CapabilityStatus.InstanceNotConfigured);
2525
});
2626
2727
function handleButtonClick() {
2828
if (shouldShowWizard.value) {
2929
showWizard.value = true;
30-
} else if (props.status === CapabilityStatus.Available) {
31-
window.location.href = props.helpButtonUrl;
30+
} else {
31+
window.open(props.helpButtonUrl, "_blank");
3232
}
3333
}
3434
</script>

src/Frontend/src/components/platformcapabilities/WizardDialog.vue

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup lang="ts">
2-
import { ref, computed, onMounted, onUnmounted } from "vue";
2+
import { ref, computed, onMounted, onUnmounted, nextTick } from "vue";
33
import { Modal } from "bootstrap";
44
import FAIcon from "@/components/FAIcon.vue";
55
import { faChevronLeft, faChevronRight, faExternalLinkAlt } from "@fortawesome/free-solid-svg-icons";
@@ -32,6 +32,8 @@ let modalInstance: Modal | null = null;
3232
const currentPageIndex = ref(0);
3333
const isImageExpanded = ref(false);
3434
const currentImageIndex = ref(0);
35+
const lightboxCloseRef = ref<HTMLButtonElement | null>(null);
36+
const lastFocusedElement = ref<HTMLElement | null>(null);
3537
3638
const currentPage = computed(() => props.pages[currentPageIndex.value]);
3739
function normalizeImage(img: string | WizardImage): WizardImage {
@@ -95,13 +97,32 @@ function handleHidden() {
9597
}
9698
9799
function handleKeydown(event: KeyboardEvent) {
100+
if (isImageExpanded.value && event.key === "Escape") {
101+
closeLightbox();
102+
return;
103+
}
98104
if (event.key === "ArrowRight" && !isLastPage.value) {
99105
nextPage();
100106
} else if (event.key === "ArrowLeft" && !isFirstPage.value) {
101107
previousPage();
102108
}
103109
}
104110
111+
function openLightbox() {
112+
lastFocusedElement.value = document.activeElement as HTMLElement;
113+
isImageExpanded.value = true;
114+
nextTick(() => {
115+
lightboxCloseRef.value?.focus();
116+
});
117+
}
118+
119+
function closeLightbox() {
120+
isImageExpanded.value = false;
121+
nextTick(() => {
122+
lastFocusedElement.value?.focus();
123+
});
124+
}
125+
105126
onMounted(() => {
106127
if (modalRef.value) {
107128
modalInstance = new Modal(modalRef.value, {
@@ -146,7 +167,7 @@ onUnmounted(() => {
146167
:alt="currentImageData?.caption || currentPage.title"
147168
class="img-fluid rounded clickable-image"
148169
:style="currentImageData?.maxHeight ? { maxHeight: currentImageData.maxHeight } : {}"
149-
@click="isImageExpanded = true"
170+
@click="openLightbox"
150171
/>
151172
<figcaption v-if="currentImageData?.caption" class="image-caption">{{ currentImageData.caption }}</figcaption>
152173
</figure>
@@ -190,9 +211,9 @@ onUnmounted(() => {
190211
</div>
191212

192213
<Teleport to="body">
193-
<div v-if="isImageExpanded && currentImageData" class="image-lightbox" @click="isImageExpanded = false">
214+
<div v-if="isImageExpanded && currentImageData" class="image-lightbox" role="dialog" aria-modal="true" aria-label="Expanded image" @click="closeLightbox">
194215
<div class="lightbox-content" @click.stop>
195-
<button type="button" class="lightbox-close" @click="isImageExpanded = false" aria-label="Close">&times;</button>
216+
<button ref="lightboxCloseRef" type="button" class="lightbox-close" @click="closeLightbox" aria-label="Close expanded image">&times;</button>
196217
<img :src="currentImageData.src" :alt="currentImageData.caption || currentPage.title" />
197218
</div>
198219
</div>

src/Frontend/src/components/platformcapabilities/capabilities/AuditingCapability.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ const AuditingHelpButtonText: CapabilityStatusToStringMap = {
2525
const AuditingHelpButtonUrl: CapabilityStatusToStringMap = {
2626
[CapabilityStatus.EndpointsNotConfigured]: "https://docs.particular.net/nservicebus/operations/auditing",
2727
[CapabilityStatus.InstanceNotConfigured]: "https://docs.particular.net/servicecontrol/audit-instances/",
28+
[CapabilityStatus.Unavailable]: "https://docs.particular.net/servicecontrol/troubleshooting",
29+
[CapabilityStatus.PartiallyUnavailable]: "https://docs.particular.net/servicecontrol/troubleshooting",
2830
[CapabilityStatus.Available]: "#/messages",
2931
};
3032

src/Frontend/src/components/platformcapabilities/capabilities/MonitoringCapability.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const MonitoringHelpButtonText: CapabilityStatusToStringMap = {
2323
const MonitoringHelpButtonUrl: CapabilityStatusToStringMap = {
2424
[CapabilityStatus.EndpointsNotConfigured]: "https://docs.particular.net/monitoring/metrics/install-plugin",
2525
[CapabilityStatus.InstanceNotConfigured]: "https://docs.particular.net/servicecontrol/monitoring-instances/",
26-
[CapabilityStatus.Unavailable]: "https://docs.particular.net/servicecontrol/monitoring-instances/",
26+
[CapabilityStatus.Unavailable]: "https://docs.particular.net/servicecontrol/troubleshooting",
2727
[CapabilityStatus.Available]: "#/monitoring",
2828
};
2929

src/Frontend/src/components/platformcapabilities/wizards/AuditingWizardPages.ts

Lines changed: 2 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -125,51 +125,6 @@ const AuditingInstanceNotConfiguredPages: WizardPage[] = [
125125
},
126126
];
127127

128-
const AuditingUnavailablePages: WizardPage[] = [
129-
{
130-
title: "Audit Instance Unavailable",
131-
content: `
132-
<p>ServicePulse cannot connect to your ServiceControl Audit instance. This could be due to:</p>
133-
<ul>
134-
<li><strong>Service not running</strong> - The ServiceControl Audit service may have stopped</li>
135-
<li><strong>Network issues</strong> - There may be connectivity problems between ServicePulse and ServiceControl</li>
136-
<li><strong>Configuration mismatch</strong> - The URL configured in ServicePulse may be incorrect</li>
137-
</ul>
138-
`,
139-
learnMoreUrl: "https://docs.particular.net/servicecontrol/troubleshooting",
140-
learnMoreText: "View troubleshooting guide",
141-
},
142-
{
143-
title: "Check the Service Status",
144-
content: `
145-
<p>To resolve this issue, try the following steps:</p>
146-
<ul>
147-
<li><strong>Step 1:</strong> Open Windows Services and check if the ServiceControl Audit service is running</li>
148-
<li><strong>Step 2:</strong> If stopped, try starting the service</li>
149-
<li><strong>Step 3:</strong> Check the ServiceControl Audit logs for any errors</li>
150-
<li><strong>Step 4:</strong> Verify the audit instance URL in your ServicePulse configuration</li>
151-
</ul>
152-
<p>Logs are typically located in the ServiceControl installation directory under the Logs folder.</p>
153-
`,
154-
learnMoreUrl: "https://docs.particular.net/servicecontrol/logging",
155-
learnMoreText: "Learn about ServiceControl logging",
156-
},
157-
{
158-
title: "Verify Your Configuration",
159-
content: `
160-
<p>Ensure ServicePulse is configured with the correct audit instance URL:</p>
161-
<ul>
162-
<li><strong>Check the URL</strong> - Verify the ServiceControl Audit API URL is correct</li>
163-
<li><strong>Test connectivity</strong> - Try accessing the API URL directly in a browser</li>
164-
<li><strong>Check firewall rules</strong> - Ensure the port is accessible</li>
165-
</ul>
166-
<p>Once the service is running and accessible, this page will automatically update.</p>
167-
`,
168-
learnMoreUrl: "https://docs.particular.net/servicecontrol/audit-instances/",
169-
learnMoreText: "View configuration guide",
170-
},
171-
];
172-
173128
const AuditingEndpointsNotConfiguredPages: WizardPage[] = [
174129
{
175130
title: "Enable Auditing for Your Endpoints",
@@ -190,8 +145,6 @@ const AuditingEndpointsNotConfiguredPages: WizardPage[] = [
190145
content: `
191146
<p>Add auditing configuration to your endpoint setup code:</p>
192147
<p><code>endpointConfiguration.AuditProcessedMessagesTo("audit");</code></p>
193-
<p>Or configure via app settings:</p>
194-
<p><code>&lt;add key="ServiceControl/Queue" value="audit" /&gt;</code></p>
195148
<p>Make sure the audit queue name matches what your ServiceControl Audit instance is monitoring.</p>
196149
`,
197150
learnMoreUrl: "https://docs.particular.net/nservicebus/operations/auditing#configuring-auditing",
@@ -203,8 +156,8 @@ const AuditingEndpointsNotConfiguredPages: WizardPage[] = [
203156
<p>Once configured:</p>
204157
<ul>
205158
<li><strong>Send a test message</strong> through one of your endpoints</li>
206-
<li><strong>Check this page</strong> - it will automatically update when messages are detected</li>
207-
<li><strong>View the Messages tab</strong> to see your processed messages</li>
159+
<li><strong>Check this capability card</strong> - it will automatically update when messages are detected</li>
160+
<li><strong>View the All Messages tab</strong> to see your processed messages</li>
208161
</ul>
209162
<p>If messages still don't appear after a few minutes, check your endpoint logs and ServiceControl logs for any errors.</p>
210163
`,
@@ -219,8 +172,6 @@ export function getAuditingWizardPages(status: CapabilityStatus): WizardPage[] {
219172
return AuditingInstanceNotConfiguredPages;
220173
case CapabilityStatus.EndpointsNotConfigured:
221174
return AuditingEndpointsNotConfiguredPages;
222-
case CapabilityStatus.Unavailable:
223-
return AuditingUnavailablePages;
224175
default:
225176
return [];
226177
}

src/Frontend/src/components/platformcapabilities/wizards/MonitoringWizardPages.ts

Lines changed: 7 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -78,51 +78,6 @@ const MonitoringInstanceNotConfiguredPages: WizardPage[] = [
7878
},
7979
];
8080

81-
const MonitoringUnavailablePages: WizardPage[] = [
82-
{
83-
title: "Monitoring Instance Unavailable",
84-
content: `
85-
<p>ServicePulse cannot connect to your ServiceControl Monitoring instance. This could be due to:</p>
86-
<ul>
87-
<li><strong>Service not running</strong> - The ServiceControl Monitoring service may have stopped</li>
88-
<li><strong>Network issues</strong> - There may be connectivity problems between ServicePulse and ServiceControl</li>
89-
<li><strong>Configuration mismatch</strong> - The URL configured in ServicePulse may be incorrect</li>
90-
</ul>
91-
`,
92-
learnMoreUrl: "https://docs.particular.net/servicecontrol/troubleshooting",
93-
learnMoreText: "View troubleshooting guide",
94-
},
95-
{
96-
title: "Check the Service Status",
97-
content: `
98-
<p>To resolve this issue, try the following steps:</p>
99-
<ul>
100-
<li><strong>Step 1:</strong> Open Windows Services and check if the ServiceControl Monitoring service is running</li>
101-
<li><strong>Step 2:</strong> If stopped, try starting the service</li>
102-
<li><strong>Step 3:</strong> Check the ServiceControl Monitoring logs for any errors</li>
103-
<li><strong>Step 4:</strong> Verify the monitoring instance URL in your ServicePulse configuration</li>
104-
</ul>
105-
<p>Logs are typically located in the ServiceControl installation directory under the Logs folder.</p>
106-
`,
107-
learnMoreUrl: "https://docs.particular.net/servicecontrol/logging",
108-
learnMoreText: "Learn about ServiceControl logging",
109-
},
110-
{
111-
title: "Verify Your Configuration",
112-
content: `
113-
<p>Ensure ServicePulse is configured with the correct monitoring instance URL:</p>
114-
<ul>
115-
<li><strong>Check the URL</strong> - Verify the ServiceControl Monitoring API URL is correct</li>
116-
<li><strong>Test connectivity</strong> - Try accessing the API URL directly in a browser</li>
117-
<li><strong>Check firewall rules</strong> - Ensure the port is accessible</li>
118-
</ul>
119-
<p>Once the service is running and accessible, this page will automatically update.</p>
120-
`,
121-
learnMoreUrl: "https://docs.particular.net/servicecontrol/monitoring-instances/",
122-
learnMoreText: "View configuration guide",
123-
},
124-
];
125-
12681
const MonitoringEndpointsNotConfiguredPages: WizardPage[] = [
12782
{
12883
title: "Install the Monitoring Plugin",
@@ -142,10 +97,12 @@ const MonitoringEndpointsNotConfiguredPages: WizardPage[] = [
14297
title: "Configure Your Endpoints",
14398
content: `
14499
<p>Add the metrics plugin to your endpoint configuration:</p>
145-
<p><code>var metrics = endpointConfiguration.EnableMetrics();</code></p>
146-
<p><code>metrics.SendMetricDataToServiceControl(</code></p>
147-
<p><code> "Particular.Monitoring",</code></p>
148-
<p><code> TimeSpan.FromSeconds(10));</code></p>
100+
<pre>
101+
<code>var metrics = endpointConfiguration.EnableMetrics();
102+
metrics.SendMetricDataToServiceControl(
103+
serviceControlMetricsAddress: SERVICE_CONTROL_METRICS_ADDRESS,
104+
interval: TimeSpan.FromMinutes(1),
105+
instanceId: "INSTANCE_ID_OPTIONAL");</code></pre>
149106
<p>Make sure the queue name matches your ServiceControl Monitoring instance queue.</p>
150107
`,
151108
learnMoreUrl: "https://docs.particular.net/monitoring/metrics/install-plugin#configuration",
@@ -157,7 +114,7 @@ const MonitoringEndpointsNotConfiguredPages: WizardPage[] = [
157114
<p>Once configured:</p>
158115
<ul>
159116
<li><strong>Start your endpoints</strong> - Metrics will begin flowing immediately</li>
160-
<li><strong>Check this page</strong> - it will automatically update when metrics are detected</li>
117+
<li><strong>Check this capability card</strong> - it will automatically update when metrics are detected</li>
161118
<li><strong>View the Monitoring tab</strong> to see real-time performance data</li>
162119
</ul>
163120
<p>Metrics are sent at regular intervals (default: every 10 seconds), so you should see data appear within a minute.</p>
@@ -173,8 +130,6 @@ export function getMonitoringWizardPages(status: CapabilityStatus): WizardPage[]
173130
return MonitoringInstanceNotConfiguredPages;
174131
case CapabilityStatus.EndpointsNotConfigured:
175132
return MonitoringEndpointsNotConfiguredPages;
176-
case CapabilityStatus.Unavailable:
177-
return MonitoringUnavailablePages;
178133
default:
179134
return [];
180135
}

0 commit comments

Comments
 (0)