|
1 | 1 | <script lang="ts" setup>
|
| 2 | +import { ref } from 'vue' |
| 3 | +import { useHead } from '@vueuse/head' |
| 4 | +import { Line, Bar } from 'vue-chartjs' |
| 5 | +import { |
| 6 | + Chart as ChartJS, |
| 7 | + CategoryScale, |
| 8 | + LinearScale, |
| 9 | + PointElement, |
| 10 | + LineElement, |
| 11 | + BarElement, |
| 12 | + Title, |
| 13 | + Tooltip, |
| 14 | + Legend, |
| 15 | + Filler, |
| 16 | +} from 'chart.js' |
| 17 | +
|
| 18 | +ChartJS.register( |
| 19 | + CategoryScale, |
| 20 | + LinearScale, |
| 21 | + PointElement, |
| 22 | + LineElement, |
| 23 | + BarElement, |
| 24 | + Title, |
| 25 | + Tooltip, |
| 26 | + Legend, |
| 27 | + Filler, |
| 28 | +) |
| 29 | +
|
2 | 30 | useHead({
|
3 | 31 | title: 'Dashboard - Requests',
|
4 | 32 | })
|
| 33 | +
|
| 34 | +// Chart options |
| 35 | +const chartOptions = { |
| 36 | + responsive: true, |
| 37 | + maintainAspectRatio: false, |
| 38 | + scales: { |
| 39 | + y: { |
| 40 | + beginAtZero: true, |
| 41 | + grid: { |
| 42 | + color: 'rgba(200, 200, 200, 0.1)', |
| 43 | + }, |
| 44 | + ticks: { |
| 45 | + color: 'rgb(156, 163, 175)', |
| 46 | + font: { |
| 47 | + family: "'JetBrains Mono', monospace", |
| 48 | + }, |
| 49 | + }, |
| 50 | + }, |
| 51 | + x: { |
| 52 | + grid: { |
| 53 | + display: false, |
| 54 | + }, |
| 55 | + ticks: { |
| 56 | + color: 'rgb(156, 163, 175)', |
| 57 | + font: { |
| 58 | + family: "'JetBrains Mono', monospace", |
| 59 | + }, |
| 60 | + }, |
| 61 | + }, |
| 62 | + }, |
| 63 | + plugins: { |
| 64 | + legend: { |
| 65 | + display: true, |
| 66 | + labels: { |
| 67 | + color: 'rgb(156, 163, 175)', |
| 68 | + font: { |
| 69 | + family: "'JetBrains Mono', monospace", |
| 70 | + }, |
| 71 | + }, |
| 72 | + }, |
| 73 | + }, |
| 74 | + elements: { |
| 75 | + line: { |
| 76 | + tension: 0.4, |
| 77 | + }, |
| 78 | + }, |
| 79 | +} |
| 80 | +
|
| 81 | +// Mock data for charts |
| 82 | +const requestVolumeData = { |
| 83 | + labels: ['12am', '3am', '6am', '9am', '12pm', '3pm', '6pm', '9pm'], |
| 84 | + datasets: [ |
| 85 | + { |
| 86 | + label: 'Requests', |
| 87 | + data: [1200, 1900, 800, 1600, 2400, 2100, 1800, 2200], |
| 88 | + backgroundColor: 'rgba(59, 130, 246, 0.1)', |
| 89 | + borderColor: 'rgb(59, 130, 246)', |
| 90 | + fill: true, |
| 91 | + } |
| 92 | + ] |
| 93 | +} |
| 94 | +
|
| 95 | +const responseTimeData = { |
| 96 | + labels: ['12am', '3am', '6am', '9am', '12pm', '3pm', '6pm', '9pm'], |
| 97 | + datasets: [ |
| 98 | + { |
| 99 | + label: 'Average', |
| 100 | + data: [320, 280, 300, 390, 420, 350, 360, 380], |
| 101 | + borderColor: 'rgb(59, 130, 246)', |
| 102 | + backgroundColor: 'rgba(59, 130, 246, 0.1)', |
| 103 | + fill: false, |
| 104 | + }, |
| 105 | + { |
| 106 | + label: 'p95', |
| 107 | + data: [480, 420, 450, 580, 630, 525, 540, 570], |
| 108 | + borderColor: 'rgb(147, 197, 253)', |
| 109 | + backgroundColor: 'rgba(147, 197, 253, 0.1)', |
| 110 | + fill: false, |
| 111 | + } |
| 112 | + ] |
| 113 | +} |
| 114 | +
|
| 115 | +const successRateData = { |
| 116 | + labels: ['12am', '3am', '6am', '9am', '12pm', '3pm', '6pm', '9pm'], |
| 117 | + datasets: [ |
| 118 | + { |
| 119 | + label: 'Success Rate', |
| 120 | + data: [98, 97, 99, 96, 95, 97, 98, 96], |
| 121 | + borderColor: 'rgb(34, 197, 94)', |
| 122 | + backgroundColor: 'rgba(34, 197, 94, 0.1)', |
| 123 | + fill: true, |
| 124 | + }, |
| 125 | + { |
| 126 | + label: 'Error Rate', |
| 127 | + data: [2, 3, 1, 4, 5, 3, 2, 4], |
| 128 | + borderColor: 'rgb(239, 68, 68)', |
| 129 | + backgroundColor: 'rgba(239, 68, 68, 0.1)', |
| 130 | + fill: true, |
| 131 | + } |
| 132 | + ] |
| 133 | +} |
| 134 | +
|
| 135 | +const statusCodesData = { |
| 136 | + labels: ['12am', '3am', '6am', '9am', '12pm', '3pm', '6pm', '9pm'], |
| 137 | + datasets: [ |
| 138 | + { |
| 139 | + label: '2xx', |
| 140 | + data: [980, 970, 990, 960, 950, 970, 980, 960], |
| 141 | + backgroundColor: 'rgba(34, 197, 94, 0.7)', |
| 142 | + }, |
| 143 | + { |
| 144 | + label: '3xx', |
| 145 | + data: [15, 20, 8, 25, 30, 20, 15, 25], |
| 146 | + backgroundColor: 'rgba(234, 179, 8, 0.7)', |
| 147 | + }, |
| 148 | + { |
| 149 | + label: '4xx/5xx', |
| 150 | + data: [5, 10, 2, 15, 20, 10, 5, 15], |
| 151 | + backgroundColor: 'rgba(239, 68, 68, 0.7)', |
| 152 | + } |
| 153 | + ] |
| 154 | +} |
| 155 | +
|
| 156 | +const barChartOptions = { |
| 157 | + ...chartOptions, |
| 158 | + scales: { |
| 159 | + ...chartOptions.scales, |
| 160 | + x: { |
| 161 | + ...chartOptions.scales.x, |
| 162 | + stacked: true, |
| 163 | + }, |
| 164 | + y: { |
| 165 | + ...chartOptions.scales.y, |
| 166 | + stacked: true, |
| 167 | + }, |
| 168 | + }, |
| 169 | +} |
5 | 170 | </script>
|
6 | 171 |
|
7 | 172 | <template>
|
@@ -99,6 +264,92 @@ useHead({
|
99 | 264 | </div>
|
100 | 265 | </div>
|
101 | 266 |
|
| 267 | + <!-- Graphs Section --> |
| 268 | + <div class="px-4 lg:px-8 sm:px-6"> |
| 269 | + <div class="grid grid-cols-1 lg:grid-cols-2 gap-6"> |
| 270 | + <!-- Request Volume Graph --> |
| 271 | + <div class="bg-white rounded-lg shadow p-6"> |
| 272 | + <div class="flex items-center justify-between mb-4"> |
| 273 | + <h3 class="text-base font-medium text-gray-900">Request Volume</h3> |
| 274 | + <div class="flex items-center space-x-4"> |
| 275 | + <select class="text-sm border-0 rounded-md bg-gray-50 py-1.5 pl-3 pr-8 text-gray-900 ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-blue-600"> |
| 276 | + <option>Last 24 hours</option> |
| 277 | + <option>Last 7 days</option> |
| 278 | + <option>Last 30 days</option> |
| 279 | + </select> |
| 280 | + </div> |
| 281 | + </div> |
| 282 | + <div class="relative h-[300px]"> |
| 283 | + <Line :data="requestVolumeData" :options="chartOptions" /> |
| 284 | + </div> |
| 285 | + </div> |
| 286 | + |
| 287 | + <!-- Response Time Graph --> |
| 288 | + <div class="bg-white rounded-lg shadow p-6"> |
| 289 | + <div class="flex items-center justify-between mb-4"> |
| 290 | + <h3 class="text-base font-medium text-gray-900">Response Time</h3> |
| 291 | + <div class="flex items-center space-x-4"> |
| 292 | + <div class="flex items-center space-x-2"> |
| 293 | + <div class="h-3 w-3 rounded-full bg-blue-400"></div> |
| 294 | + <span class="text-sm text-gray-600">Average</span> |
| 295 | + </div> |
| 296 | + <div class="flex items-center space-x-2"> |
| 297 | + <div class="h-3 w-3 rounded-full bg-blue-200"></div> |
| 298 | + <span class="text-sm text-gray-600">p95</span> |
| 299 | + </div> |
| 300 | + </div> |
| 301 | + </div> |
| 302 | + <div class="relative h-[300px]"> |
| 303 | + <Line :data="responseTimeData" :options="chartOptions" /> |
| 304 | + </div> |
| 305 | + </div> |
| 306 | + |
| 307 | + <!-- Success Rate Graph --> |
| 308 | + <div class="bg-white rounded-lg shadow p-6"> |
| 309 | + <div class="flex items-center justify-between mb-4"> |
| 310 | + <h3 class="text-base font-medium text-gray-900">Success Rate</h3> |
| 311 | + <div class="flex items-center space-x-4"> |
| 312 | + <div class="flex items-center space-x-2"> |
| 313 | + <div class="h-3 w-3 rounded-full bg-green-400"></div> |
| 314 | + <span class="text-sm text-gray-600">Success</span> |
| 315 | + </div> |
| 316 | + <div class="flex items-center space-x-2"> |
| 317 | + <div class="h-3 w-3 rounded-full bg-red-400"></div> |
| 318 | + <span class="text-sm text-gray-600">Error</span> |
| 319 | + </div> |
| 320 | + </div> |
| 321 | + </div> |
| 322 | + <div class="relative h-[300px]"> |
| 323 | + <Line :data="successRateData" :options="chartOptions" /> |
| 324 | + </div> |
| 325 | + </div> |
| 326 | + |
| 327 | + <!-- Status Code Distribution --> |
| 328 | + <div class="bg-white rounded-lg shadow p-6"> |
| 329 | + <div class="flex items-center justify-between mb-4"> |
| 330 | + <h3 class="text-base font-medium text-gray-900">Status Codes</h3> |
| 331 | + <div class="flex items-center space-x-4"> |
| 332 | + <div class="flex items-center space-x-2"> |
| 333 | + <div class="h-3 w-3 rounded-full bg-green-400"></div> |
| 334 | + <span class="text-sm text-gray-600">2xx</span> |
| 335 | + </div> |
| 336 | + <div class="flex items-center space-x-2"> |
| 337 | + <div class="h-3 w-3 rounded-full bg-yellow-400"></div> |
| 338 | + <span class="text-sm text-gray-600">3xx</span> |
| 339 | + </div> |
| 340 | + <div class="flex items-center space-x-2"> |
| 341 | + <div class="h-3 w-3 rounded-full bg-red-400"></div> |
| 342 | + <span class="text-sm text-gray-600">4xx/5xx</span> |
| 343 | + </div> |
| 344 | + </div> |
| 345 | + </div> |
| 346 | + <div class="relative h-[300px]"> |
| 347 | + <Bar :data="statusCodesData" :options="barChartOptions" /> |
| 348 | + </div> |
| 349 | + </div> |
| 350 | + </div> |
| 351 | + </div> |
| 352 | + |
102 | 353 | <div class="px-4 pt-12 lg:px-8 sm:px-6">
|
103 | 354 | <div class="sm:flex sm:items-center">
|
104 | 355 | <div class="sm:flex-auto">
|
|
0 commit comments