Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Metrics: Add service to track service metrics #14

Closed
wants to merge 31 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
b6a64a6
create atlas-metrics
MaximilianAnzinger Nov 21, 2024
65fadd4
add endpoint activity chart
MaximilianAnzinger Nov 21, 2024
a501ef2
prettier
MaximilianAnzinger Nov 22, 2024
eee4f5d
influx setup
MaximilianAnzinger Nov 22, 2024
9c69965
add admin page and some misc
MaximilianAnzinger Nov 24, 2024
f654358
mostly working github auth
MaximilianAnzinger Nov 24, 2024
b554fd5
fix auth api
MaximilianAnzinger Nov 25, 2024
0e34bd4
create endpoints for endpoint-activity
MaximilianAnzinger Nov 26, 2024
325e8de
let admin view load actual data
MaximilianAnzinger Nov 27, 2024
426bb42
improve time picker
MaximilianAnzinger Nov 27, 2024
b2d1e12
lint and upgrade
MaximilianAnzinger Nov 28, 2024
8b96547
fix next config
MaximilianAnzinger Nov 28, 2024
c463c4d
clean up
MaximilianAnzinger Nov 28, 2024
f47055d
make imports prettier
MaximilianAnzinger Nov 28, 2024
fee3081
run prettier
MaximilianAnzinger Nov 28, 2024
b84a3ee
fix eslint import resolver
MaximilianAnzinger Nov 28, 2024
1aed65e
create service select
MaximilianAnzinger Nov 28, 2024
e20c35c
prettier
MaximilianAnzinger Nov 28, 2024
859e1cf
cleanup
MaximilianAnzinger Nov 28, 2024
7b58fe6
fetch real data
MaximilianAnzinger Nov 29, 2024
26fa319
cleanup
MaximilianAnzinger Nov 29, 2024
816f74b
update
MaximilianAnzinger Nov 29, 2024
b079321
update
MaximilianAnzinger Nov 29, 2024
8ea4548
prettier
MaximilianAnzinger Nov 29, 2024
41f357b
add admin authorization
MaximilianAnzinger Nov 29, 2024
aff1a6f
authorization pretty
MaximilianAnzinger Nov 29, 2024
72cdc1a
Merge branch 'main' into feature/metrics
MaximilianAnzinger Dec 3, 2024
47b0a1f
add navigation
MaximilianAnzinger Dec 7, 2024
6a1ce0f
add endpoint to retrieve services
MaximilianAnzinger Dec 9, 2024
0e72d35
Update metrics.service.ts
MaximilianAnzinger Dec 9, 2024
9917a7f
use select in dashboard to filter
MaximilianAnzinger Dec 11, 2024
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
2 changes: 2 additions & 0 deletions atlas-metrics/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
.env
17 changes: 17 additions & 0 deletions atlas-metrics/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Influx db setup
INFLUXDB_TOKEN=atlas-influxdb-token
INFLUXDB_ORG=atlas
INFLUXDB_BUCKET=atlas-metrics
DOCKER_INFLUXDB_INIT_USERNAME=admin
DOCKER_INFLUXDB_INIT_PASSWORD=password

# Auth Config
NEXTAUTH_SECRET=myjwtsecretkey # `npx auth secret` or `openssl rand -hex 32`
NEXTAUTH_URL=http://localhost:3000

# Auth Provider
GITHUB_ID=provider-id
GITHUB_SECRET=provider-secret

# Github Repository
[email protected]
114 changes: 114 additions & 0 deletions atlas-metrics/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/** @type {import('eslint').Linter.Config} */
module.exports = {
root: true,
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
ecmaFeatures: {
jsx: true,
},
},
env: {
browser: true,
commonjs: true,
es6: true,
},

// Base config
extends: ["eslint:recommended", "prettier", "plugin:@next/next/recommended"],

rules: {
"no-console": "warn",
"react/jsx-curly-brace-presence": [2, { props: "never", children: "never" }],
"react/no-unknown-property": [
2,
{
ignore: ["jsx"],
},
],
"@typescript-eslint/explicit-function-return-type": "off",
"no-restricted-syntax": [
"error",
// Ensure import from 'react' is not `useLayoutEffect`
{
selector:
'ImportDeclaration[source.value="react"] > ImportSpecifier[imported.name="useLayoutEffect"]',
message: "Please use ``useLayoutEffect` from custom hook `useIsomorphicLayoutEffect",
},
// Ensure import from '*useIsomorphicLayoutEffect' is `useLayoutEffect` to leverage `eslint-plugin-react-hooks`
{
selector:
'ImportDeclaration[source.value=/useIsomorphicLayoutEffect/] > ImportDefaultSpecifier[local.name!="useLayoutEffect"]',
message:
"Must use `useLayoutEffect` as the name of the import from `*useIsomorphicLayoutEffect` to leverage `eslint-plugin-react-hooks`",
},
],
},

overrides: [
// React
{
files: ["**/*.{js,jsx,ts,tsx}"],
plugins: ["react", "jsx-a11y"],
extends: [
"plugin:react/recommended",
"plugin:react/jsx-runtime",
"plugin:react-hooks/recommended",
"plugin:jsx-a11y/recommended",
],
settings: {
react: {
version: "detect",
},
formComponents: ["Form", "ValidatedForm"],
linkComponents: [
{ name: "Link", linkAttribute: "to" },
{ name: "NavLink", linkAttribute: "to" },
],
"import/resolver": {
typescript: {},
},
},
},
// shadcn
{
files: ["**/components/ui/*.tsx"],
rules: {
"react/prop-types": "off",
"react-refresh/only-export-components": "off",
},
},

// Typescript
{
files: ["**/*.{ts,tsx}"],
plugins: ["@typescript-eslint", "import"],
parser: "@typescript-eslint/parser",
settings: {
"import/internal-regex": "^~/",
"import/resolver": {
node: {
extensions: [".ts", ".tsx"],
},
typescript: {
alwaysTryTypes: true,
project: ["./tsconfig.json"],
},
},
},
extends: [
"plugin:@typescript-eslint/recommended",
"plugin:import/recommended",
"plugin:import/typescript",
],
},

// Node
{
files: [".eslintrc.js"],
env: {
node: true,
},
},
],
};
41 changes: 41 additions & 0 deletions atlas-metrics/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts

.idea

.env
.next
3 changes: 3 additions & 0 deletions atlas-metrics/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Required for Recharts
# See https://ui.shadcn.com/docs/react-19
legacy-peer-deps=true
5 changes: 5 additions & 0 deletions atlas-metrics/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules

/.next
/build
.env
21 changes: 21 additions & 0 deletions atlas-metrics/.prettierrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/** @type {import("prettier").Config} */
const config = {
arrowParens: "always",
bracketSameLine: true,
bracketSpacing: true,
endOfLine: "lf",
htmlWhitespaceSensitivity: "ignore",
jsxSingleQuote: false,
printWidth: 100,
proseWrap: "never",
quoteProps: "as-needed",
semi: true,
singleQuote: false,
tabWidth: 2,
useTabs: false,
trailingComma: "all",
plugins: ["prettier-plugin-tailwindcss"],
tailwindFunctions: ["cn"],
};

module.exports = config;
37 changes: 37 additions & 0 deletions atlas-metrics/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
FROM node:20-alpine AS atlas-metrics-dev

WORKDIR /app
EXPOSE 3000

# Skip npm install if node_modules exists.
CMD \[ -d "node_modules" \] && npm run dev || npm install && npm run dev

FROM node:20-alpine AS atlas-metrics-build

WORKDIR /app

COPY package.json /app/package.json
COPY package-lock.json /app/package-lock.json
# See .npmrc for more information.
RUN npm install --legacy-peer-deps

COPY . /app
RUN npm run build

FROM node:20-alpine AS atlas-metrics

# install node
RUN apk add --no-cache nodejs=~20 npm=~10

WORKDIR /app

COPY --from=atlas-metrics-build /app/.next /app/.next
COPY --from=atlas-metrics-build /app/package.json /app/package.json
COPY --from=atlas-metrics-build /app/package-lock.json /app/package-lock.json
# See .npmrc for more information.
RUN npm install --omit=dev --legacy-peer-deps

ENV NODE_ENV=production

EXPOSE 3000
CMD npm run start
36 changes: 36 additions & 0 deletions atlas-metrics/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.

This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
51 changes: 51 additions & 0 deletions atlas-metrics/app/admin/columns.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"use client";

import { ColumnDef } from "@tanstack/table-core";
import { EndpointActivityDAO } from "@server/domain/dao/endpointActivity";
import { DataTableColumnHeader } from "@components/custom/DataTableColumnHeader";
import { useEffect, useState } from "react";

export const endpointActivityColumns: ColumnDef<EndpointActivityDAO>[] = [
{
accessorKey: "date",
header: ({ column }) => <DataTableColumnHeader column={column} title="Timestamp" />,
cell: ({ row }) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const [date, setDate] = useState("");
// eslint-disable-next-line react-hooks/rules-of-hooks
useEffect(() => {
const d = row.getValue("date") as Date;
setDate(d.toLocaleString());
}, [row]);
return <div className="text-left">{date}</div>;
},
},
{
accessorKey: "service",
header: ({ column }) => <DataTableColumnHeader column={column} title="Service" />,
cell: ({ row }) => {
return <div className="text-center">{row.getValue("service")}</div>;
},
},
{
accessorKey: "version",
header: ({ column }) => <DataTableColumnHeader column={column} title="Version" />,
cell: ({ row }) => {
return <div className="text-center">{row.getValue("version")}</div>;
},
},
{
accessorKey: "endpoint",
header: ({ column }) => <DataTableColumnHeader column={column} title="Endpoint" />,
cell: ({ row }) => {
return <div className="text-left">{row.getValue("endpoint")}</div>;
},
},
{
accessorKey: "type",
header: ({ column }) => <DataTableColumnHeader column={column} title="RequestType" />,
cell: ({ row }) => {
return <div className="text-center">{row.getValue("type")}</div>;
},
},
];
24 changes: 24 additions & 0 deletions atlas-metrics/app/admin/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Menu } from "@components/custom/Menu";
import { DataTable } from "@components/custom/DataTable";
import applicationContainer from "@server/applicationContainer";
import { endpointActivityColumns } from "./columns";

export default async function Admin() {
const metricsService = applicationContainer.getMetricsService();
const data = await metricsService.getEndpointActivity();
return (
<div className="m-5 text-center">
<div className="pb-5">
<Menu />
</div>
<div className="pb-5">
<DataTable
title="Endpoint Activity"
description="Time series of all endpoint activities"
columns={endpointActivityColumns}
data={data}
/>
</div>
</div>
);
}
Loading
Loading