feat: add basic webui

This commit is contained in:
2024-12-30 06:39:09 +08:00
parent 608a7fb9c6
commit a4c549e7c3
462 changed files with 35900 additions and 2491 deletions

View File

@@ -0,0 +1,24 @@
import { captureException } from '@sentry/nextjs';
import { log } from './log';
export const parseError = (error: unknown): string => {
let message = 'An error occurred';
if (error instanceof Error) {
message = error.message;
} else if (error && typeof error === 'object' && 'message' in error) {
message = error.message as string;
} else {
message = String(error);
}
try {
captureException(error);
log.error(`Parsing error: ${message}`);
} catch (newError) {
// biome-ignore lint/suspicious/noConsole: Need console here
console.error('Error parsing error:', newError);
}
return message;
};

View File

@@ -0,0 +1,3 @@
import { log as logtail } from '@logtail/next';
export const log = process.env.NODE_ENV === 'production' ? logtail : console;

View File

@@ -0,0 +1,22 @@
{
"name": "@konobangu/observability",
"version": "0.0.0",
"private": true,
"scripts": {
"clean": "git clean -xdf .cache .turbo dist node_modules",
"typecheck": "tsc --noEmit --emitDeclarationOnly false"
},
"dependencies": {
"@logtail/next": "^0.1.7",
"@konobangu/env": "workspace:*",
"@sentry/nextjs": "^8.43.0",
"react": "^19.0.0"
},
"devDependencies": {
"@konobangu/typescript-config": "workspace:*",
"@types/node": "22.10.1",
"@types/react": "19.0.1",
"@types/react-dom": "^19.0.2",
"typescript": "^5.7.2"
}
}

View File

@@ -0,0 +1,66 @@
import 'server-only';
import { env } from '@konobangu/env';
import type { BetterStackResponse } from './types';
export const Status = async () => {
if (!env.BETTERSTACK_API_KEY || !env.BETTERSTACK_URL) {
return null;
}
let statusColor = 'bg-muted-foreground';
let statusLabel = 'Unable to fetch status';
try {
const response = await fetch(
'https://uptime.betterstack.com/api/v2/monitors',
{
headers: {
Authorization: `Bearer ${env.BETTERSTACK_API_KEY}`,
},
}
);
if (!response.ok) {
throw new Error('Failed to fetch status');
}
const { data } = (await response.json()) as BetterStackResponse;
const status =
data.filter((monitor) => monitor.attributes.status === 'up').length /
data.length;
if (status === 0) {
statusColor = 'bg-destructive';
statusLabel = 'Degraded performance';
} else if (status < 1) {
statusColor = 'bg-warning';
statusLabel = 'Partial outage';
} else {
statusColor = 'bg-success';
statusLabel = 'All systems normal';
}
} catch {
statusColor = 'bg-muted-foreground';
statusLabel = 'Unable to fetch status';
}
return (
<a
className="flex items-center gap-3 font-medium text-sm"
target="_blank"
rel="noreferrer"
href={env.BETTERSTACK_URL}
>
<span className="relative flex h-2 w-2">
<span
className={`absolute inline-flex h-full w-full animate-ping rounded-full opacity-75 ${statusColor}`}
/>
<span
className={`relative inline-flex h-2 w-2 rounded-full ${statusColor}`}
/>
</span>
<span className="text-muted-foreground">{statusLabel}</span>
</a>
);
};

View File

@@ -0,0 +1,62 @@
export type BetterStackResponse = {
data: {
id: string;
type: string;
attributes: {
url: string;
pronounceable_name: string;
auth_username: string;
auth_password: string;
monitor_type: string;
monitor_group_id: unknown;
last_checked_at: string;
status:
| 'down'
| 'maintenance'
| 'paused'
| 'pending'
| 'up'
| 'validating';
policy_id: unknown;
required_keyword: unknown;
verify_ssl: boolean;
check_frequency: number;
call: boolean;
sms: boolean;
email: boolean;
push: boolean;
team_wait: unknown;
http_method: string;
request_timeout: number;
recovery_period: number;
request_headers: unknown[];
request_body: string;
follow_redirects: boolean;
remember_cookies: boolean;
created_at: string;
updated_at: string;
ssl_expiration: unknown;
domain_expiration: unknown;
regions: string[];
expected_status_codes: unknown[];
port: unknown;
confirmation_period: number;
paused_at: unknown;
paused: boolean;
maintenance_from: unknown;
maintenance_to: unknown;
maintenance_timezone: string;
};
relationships: {
policy: {
data: unknown;
};
};
}[];
pagination: {
first: string;
last: string;
prev: unknown;
next: unknown;
};
};

View File

@@ -0,0 +1,8 @@
{
"extends": "@konobangu/typescript-config/react-library.json",
"compilerOptions": {
"baseUrl": "."
},
"include": ["**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}