+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('Loading...') }}
+
+
+
+
+
+
+ {{ kpi.value }}
+
+
+ {{ kpi.label }}
+
+
+
+
+
+ {{ $t('Guardrails') }}
+
+
+
+
+
+ {{ $t('Guardrail outcomes') }}
+
+
+
+
+
+ {{ $t('No guardrail evaluations in this period.') }}
+
+
+
+
+
+ {{ $t('Block rate by FlowGenie') }}
+
+
+
+
+
+ {{ $t('No blocked sessions in this period.') }}
+
+
+
+
+
+
+
+ {{ $t('Violations by kind') }}
+
+
+
+
+
+ {{ $t('No violations in this period.') }}
+
+
+
+
+
+ {{ $t('Where it fired') }}
+
+
+
+
+
+ {{ $t('No guardrail evaluations in this period.') }}
+
+
+
+
+
+
+ {{ $t('Blocked vs redacted sessions') }}
+
+
+
+
+
+
+
+ {{ $t('Usage') }}
+
+
+
+
+
+ {{ $t('Tokens in vs out') }}
+
+
+
+
+
+ {{ $t('No token usage in this period.') }}
+
+
+
+
+
+ {{ $t('Tokens by FlowGenie') }}
+
+
+
+
+
+ {{ $t('No token usage in this period.') }}
+
+
+
+
+
+
+
+ {{ $t('Sessions per day') }}
+
+
+
+
+
+
+
+
+ {{ $t('Session status') }}
+
+
+
+
+
+ {{ $t('No sessions in this period.') }}
+
+
+
+
+
+
+ {{ $t('Top users by blocks') }}
+
+
+
+
+
+ | {{ $t('User') }} |
+ {{ $t('FlowGenie') }} |
+ {{ $t('Sessions') }} |
+ {{ $t('Blocks') }} |
+ {{ $t('Block rate') }} |
+
+
+
+
+ | {{ row.user }} |
+ {{ row.genie }} |
+ {{ row.sessions }} |
+ {{ row.blocks }} |
+ {{ formatRate(row.block_rate) }} |
+
+
+
+
+ {{ $t('No blocked sessions in this period.') }}
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/js/admin/logs/components/Logs/Monitoring/index.js b/resources/js/admin/logs/components/Logs/Monitoring/index.js
new file mode 100644
index 0000000000..baa481f302
--- /dev/null
+++ b/resources/js/admin/logs/components/Logs/Monitoring/index.js
@@ -0,0 +1,2 @@
+// eslint-disable-next-line import/prefer-default-export
+export { default as MonitoringDashboard } from './MonitoringDashboard.vue';
diff --git a/resources/js/admin/logs/components/Logs/Sidebar/Sidebar.vue b/resources/js/admin/logs/components/Logs/Sidebar/Sidebar.vue
index a2276bbff7..6d947d71ca 100644
--- a/resources/js/admin/logs/components/Logs/Sidebar/Sidebar.vue
+++ b/resources/js/admin/logs/components/Logs/Sidebar/Sidebar.vue
@@ -104,7 +104,7 @@
:visible="isAgentsActive"
>
- FlowGenie Agents logs
+ {{ $t('Monitoring') }}
+
+
+ {{ $t('FlowGenie Agents logs') }}
@@ -153,13 +170,25 @@ export default {
isAgentsActive() {
return this.$route.path.startsWith("/agents");
},
+ isAgentsLogsActive() {
+ return this.$route.path === '/agents/design' || this.$route.path === '/agents/execution';
+ },
+ isMonitoringActive() {
+ return this.$route.path.startsWith('/agents/monitoring');
+ },
emailLinkClasses() {
- return this.isEmailActive
- ? "tw-bg-blue-50 tw-font-semibold tw-text-blue-500"
- : "tw-font-medium tw-text-zinc-700 hover:tw-bg-zinc-50";
+ return this.linkClasses(this.isEmailActive);
+ },
+ agentsLogsLinkClasses() {
+ return this.linkClasses(this.isAgentsLogsActive);
},
- agentsLinkClasses() {
- return this.isAgentsActive
+ monitoringLinkClasses() {
+ return this.linkClasses(this.isMonitoringActive);
+ },
+ },
+ methods: {
+ linkClasses(isActive) {
+ return isActive
? "tw-bg-blue-50 tw-font-semibold tw-text-blue-500"
: "tw-font-medium tw-text-zinc-700 hover:tw-bg-zinc-50";
},
diff --git a/resources/js/admin/logs/components/Logs/charts/BarChart.vue b/resources/js/admin/logs/components/Logs/charts/BarChart.vue
new file mode 100644
index 0000000000..fd46f8cb06
--- /dev/null
+++ b/resources/js/admin/logs/components/Logs/charts/BarChart.vue
@@ -0,0 +1,38 @@
+
diff --git a/resources/js/admin/logs/components/Logs/charts/ChartFrame.vue b/resources/js/admin/logs/components/Logs/charts/ChartFrame.vue
new file mode 100644
index 0000000000..e010c4054f
--- /dev/null
+++ b/resources/js/admin/logs/components/Logs/charts/ChartFrame.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/resources/js/admin/logs/components/Logs/charts/DoughnutChart.vue b/resources/js/admin/logs/components/Logs/charts/DoughnutChart.vue
new file mode 100644
index 0000000000..5691a36bbd
--- /dev/null
+++ b/resources/js/admin/logs/components/Logs/charts/DoughnutChart.vue
@@ -0,0 +1,38 @@
+
diff --git a/resources/js/admin/logs/components/Logs/charts/HorizontalBarChart.vue b/resources/js/admin/logs/components/Logs/charts/HorizontalBarChart.vue
new file mode 100644
index 0000000000..5ddcfa75b7
--- /dev/null
+++ b/resources/js/admin/logs/components/Logs/charts/HorizontalBarChart.vue
@@ -0,0 +1,38 @@
+
diff --git a/resources/js/admin/logs/components/Logs/charts/LineChart.vue b/resources/js/admin/logs/components/Logs/charts/LineChart.vue
new file mode 100644
index 0000000000..fa8a6674e9
--- /dev/null
+++ b/resources/js/admin/logs/components/Logs/charts/LineChart.vue
@@ -0,0 +1,38 @@
+
diff --git a/resources/js/admin/logs/components/Logs/charts/chartTheme.js b/resources/js/admin/logs/components/Logs/charts/chartTheme.js
new file mode 100644
index 0000000000..8ad3a3fa92
--- /dev/null
+++ b/resources/js/admin/logs/components/Logs/charts/chartTheme.js
@@ -0,0 +1,93 @@
+export const CHART_COLORS = {
+ pass: '#0CA442',
+ redact: '#EC8E00',
+ block: '#EC5962',
+ info: '#2773F3',
+ muted: '#728092',
+ completed: '#0CA442',
+ error: '#EC5962',
+};
+
+export const doughnutOptions = {
+ legend: {
+ display: true,
+ position: 'bottom',
+ },
+ maintainAspectRatio: false,
+ responsive: true,
+ cutoutPercentage: 60,
+ layout: {
+ padding: 4,
+ },
+};
+
+export const horizontalBarOptions = (valueSuffix = '') => ({
+ legend: {
+ display: false,
+ },
+ maintainAspectRatio: false,
+ responsive: true,
+ layout: {
+ padding: {
+ right: 12,
+ },
+ },
+ scales: {
+ xAxes: [{
+ ticks: {
+ beginAtZero: true,
+ callback: (value) => `${value}${valueSuffix}`,
+ },
+ }],
+ yAxes: [{
+ gridLines: {
+ display: false,
+ },
+ afterFit: (scale) => {
+ scale.width = Math.min(scale.width, 140);
+ },
+ }],
+ },
+});
+
+export const stackedBarOptions = {
+ legend: {
+ display: true,
+ position: 'bottom',
+ },
+ maintainAspectRatio: false,
+ responsive: true,
+ layout: {
+ padding: 4,
+ },
+ scales: {
+ xAxes: [{ stacked: true }],
+ yAxes: [{
+ stacked: true,
+ ticks: { beginAtZero: true },
+ }],
+ },
+};
+
+export const lineOptions = {
+ legend: {
+ display: true,
+ position: 'bottom',
+ },
+ maintainAspectRatio: false,
+ responsive: true,
+ layout: {
+ padding: 4,
+ },
+ scales: {
+ yAxes: [{
+ ticks: { beginAtZero: true },
+ }],
+ },
+};
+
+export const chartBoxStyles = {
+ width: '100%',
+ height: '220px',
+ position: 'relative',
+};
diff --git a/resources/js/admin/logs/components/Logs/routes.js b/resources/js/admin/logs/components/Logs/routes.js
index 398d462193..85443ea7d3 100644
--- a/resources/js/admin/logs/components/Logs/routes.js
+++ b/resources/js/admin/logs/components/Logs/routes.js
@@ -1,4 +1,5 @@
import { LogTable } from "./LogTable";
+import { MonitoringDashboard } from "./Monitoring";
export default {};
@@ -70,6 +71,18 @@ export const routes = [
path: "/agents",
redirect: "/agents/design",
},
+ {
+ name: "logs.agents.monitoring",
+ path: "/agents/monitoring",
+ component: MonitoringDashboard,
+ beforeEnter: (to, from, next) => {
+ if (!hasAiPackage()) {
+ next(hasEmailPackage() ? "/email/errors" : "/");
+ } else {
+ next();
+ }
+ },
+ },
{
name: "logs.agents",
path: "/agents/:logType",
diff --git a/resources/lang/en.json b/resources/lang/en.json
index 257686e0f1..e6a75a84e0 100644
--- a/resources/lang/en.json
+++ b/resources/lang/en.json
@@ -2695,5 +2695,96 @@
"Your PMQL search could not be completed.": "Your PMQL search could not be completed.",
"Your profile was saved.": "Your profile was saved.",
"Zoom In": "Zoom In",
- "Zoom Out": "Zoom Out"
+ "Zoom Out": "Zoom Out",
+ "After tool": "After tool",
+ "Agent": "Agent",
+ "Arguments": "Arguments",
+ "Avg duration": "Avg duration",
+ "Before response": "Before response",
+ "Before tool": "Before tool",
+ "Block": "Block",
+ "Block rate": "Block rate",
+ "Block rate by FlowGenie": "Block rate by FlowGenie",
+ "Blocked sessions": "Blocked sessions",
+ "Blocked vs redacted sessions": "Blocked vs redacted sessions",
+ "Blocks": "Blocks",
+ "Connected": "Connected",
+ "Connection": "Connection",
+ "Date Email": "Date Email",
+ "Email From": "Email From",
+ "Error Code": "Error Code",
+ "Error rate": "Error rate",
+ "Execution Time": "Execution Time",
+ "Export to CSV": "Export to CSV",
+ "Files Attached": "Files Attached",
+ "FlowGenie": "FlowGenie",
+ "FlowGenie Agents logs": "FlowGenie Agents logs",
+ "FlowGenie Monitoring": "FlowGenie Monitoring",
+ "FlowGenie Name": "FlowGenie Name",
+ "Guardrail": "Guardrail",
+ "Guardrail outcomes": "Guardrail outcomes",
+ "Guardrails": "Guardrails",
+ "Input": "Input",
+ "Instructions": "Instructions",
+ "LLM": "LLM",
+ "LLM Calls": "LLM Calls",
+ "Last 30 days": "Last 30 days",
+ "Last 7 days": "Last 7 days",
+ "Last 90 days": "Last 90 days",
+ "Loading session details...": "Loading session details...",
+ "MCP Servers": "MCP Servers",
+ "Max Turns": "Max Turns",
+ "Model": "Model",
+ "Model Request": "Model Request",
+ "Model Settings": "Model Settings",
+ "Monitoring": "Monitoring",
+ "No": "No",
+ "No blocked sessions in this period.": "No blocked sessions in this period.",
+ "No events recorded for this session": "No events recorded for this session",
+ "No guardrail evaluations in this period.": "No guardrail evaluations in this period.",
+ "No sessions in this period.": "No sessions in this period.",
+ "No token usage in this period.": "No token usage in this period.",
+ "No violations in this period.": "No violations in this period.",
+ "Node": "Node",
+ "On input": "On input",
+ "On output": "On output",
+ "Pass": "Pass",
+ "Passed": "Passed",
+ "Phase": "Phase",
+ "Policy": "Policy",
+ "Processing": "Processing",
+ "Processing Started": "Processing Started",
+ "Properties": "Properties",
+ "Reasoning": "Reasoning",
+ "Redact": "Redact",
+ "Redact rate": "Redact rate",
+ "Redacted": "Redacted",
+ "Redacted sessions": "Redacted sessions",
+ "Request Config": "Request Config",
+ "Request ID": "Request ID",
+ "Response": "Response",
+ "Runtime": "Runtime",
+ "Session Details": "Session Details",
+ "Session ID": "Session ID",
+ "Session status": "Session status",
+ "Sessions": "Sessions",
+ "Sessions per day": "Sessions per day",
+ "Studio": "Studio",
+ "Thinking": "Thinking",
+ "Tokens Used": "Tokens Used",
+ "Tokens by FlowGenie": "Tokens by FlowGenie",
+ "Tokens in vs out": "Tokens in vs out",
+ "Tool": "Tool",
+ "Tool Call": "Tool Call",
+ "Tool Calls": "Tool Calls",
+ "Tools": "Tools",
+ "Top users by blocks": "Top users by blocks",
+ "Total Emails": "Total Emails",
+ "Total Matches": "Total Matches",
+ "Total Tokens": "Total Tokens",
+ "Usage": "Usage",
+ "User Email": "User Email",
+ "Violations": "Violations",
+ "Violations by kind": "Violations by kind",
+ "Where it fired": "Where it fired"
}