Skip to content

Commit

Permalink
feat: stats ordering / kpi view
Browse files Browse the repository at this point in the history
  • Loading branch information
mle-moni committed Jun 5, 2024
1 parent cf42a3b commit 14162e4
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 10 deletions.
58 changes: 53 additions & 5 deletions app/adomin/create_stats_view_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,21 @@ export interface StatsViewConfig {
* https://tabler.io/icons
*/
icon?: string
/**
* How to display the stats
* Use the 'name' property of the stats to define where to put the component on the grid, and it's size
*
* Example:
*
```ts
const gridTemplateAreas = `
"stat-name-1 stat-name-2"
"stat-name-3 stat-name-3"
`
```
* if you need a different layout for small screens, you can use pass an object with "normal" and "sm" property
*/
gridTemplateAreas?: string | { normal: string; sm: string }
}

type ChartDataRow = [string, number]
Expand All @@ -39,7 +54,7 @@ type ChartMultipleSeriesDataRow = { name: string; data: ChartDataRow[]; color?:

type ChartRowData = ChartMultipleSeriesDataRow[] | ChartDataRow[]

interface ChartKickOptions {
interface ChartkickOptions {
/** Title of x axis */
xtitle?: string
/** Title of y axis */
Expand Down Expand Up @@ -96,11 +111,22 @@ interface ChartKickOptions {
empty?: string
}

interface AdominStat {
interface ChartkickStat extends AdominStatBase {
/**
* Type of the chart to display
*/
type: 'pie' | 'bar' | 'column' | 'line' | 'area'
/**
* Options for the chart
*/
options?: ChartkickOptions
/**
* function to fetch the data to displayed in the chart
*/
dataFetcher: () => Promise<ChartRowData>
}

interface AdominStatBase {
/**
* Label of the stat, displayed in the frontend
*/
Expand All @@ -111,20 +137,41 @@ interface AdominStat {
* (e.g. in the react key prop)
*/
name: string
}

export interface KpiStatOptions {
/**
* If true, the value should be a number between 0-100 and will be displayed as a percentage
* @default false
*/
isPercentage?: boolean
/**
* Color of the mui CircularProgress
*/
color?: string
}

export interface KpiStat extends AdominStatBase {
/**
* Type of the chart to display
*/
type: 'kpi'
/**
* function to fetch the data to displayed in the chart
*/
dataFetcher: () => Promise<ChartRowData>
dataFetcher: () => Promise<string | number>
/**
* Options for the chart
*/
options?: ChartKickOptions
options?: KpiStatOptions
}

export type AdominStat = ChartkickStat | KpiStat

export type StatsViewConfigStaticOptions = Omit<StatsViewConfig, 'type'>

export const createStatsViewConfig = (options: StatsViewConfigStaticOptions): StatsViewConfig => {
const { name, stats, label, visibilityCheck, isHidden, icon } = options
const { name, stats, label, visibilityCheck, isHidden, icon, gridTemplateAreas } = options

return {
type: 'stats',
Expand All @@ -134,5 +181,6 @@ export const createStatsViewConfig = (options: StatsViewConfigStaticOptions): St
visibilityCheck,
isHidden,
icon,
gridTemplateAreas,
}
}
5 changes: 4 additions & 1 deletion app/adomin/routes/stats/get_stat_config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export const getStatConfigRoute = async (ctx: HttpContext) => {
return response.notFound({ error: `View '${viewString}' not found` })
}

const { label, name, isHidden, visibilityCheck } = statConfig
const { label, name, isHidden, visibilityCheck, type, gridTemplateAreas, icon } = statConfig

const visibilityCheckResult = await computeRightsCheck(ctx, visibilityCheck)

Expand All @@ -59,5 +59,8 @@ export const getStatConfigRoute = async (ctx: HttpContext) => {
label,
isHidden: isHidden ?? false,
stats: frontendStatConfig,
type,
gridTemplateAreas,
icon,
}
}
File renamed without changes.
61 changes: 61 additions & 0 deletions app/adomin/routes/stats/helpers/instance_metrics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Duration } from 'luxon'
import os from 'node:os'

const LOAD_AVG_TYPES = ['1m', '5m', '15m'] as const

type LoadAvgType = (typeof LOAD_AVG_TYPES)[number]

const LOAD_AVG_BY_TYPE: Record<LoadAvgType, number> = {
'1m': 0,
'5m': 1,
'15m': 2,
}

export const getCpuUsageEstimate = (loadAvgType: LoadAvgType) => {
const index = LOAD_AVG_BY_TYPE[loadAvgType]
const loadAvg = os.loadavg()[index]
const numCpus = os.cpus().length
const cpuUsagePercentage = (loadAvg / numCpus) * 100

return roundWithNDigits(cpuUsagePercentage, 2)
}

export const getMemoryUsage = () => {
const freeMemory = os.freemem()
const totalMemory = os.totalmem()
const memoryUsed = totalMemory - freeMemory
const memoryUsagePercentage = (memoryUsed / totalMemory) * 100

return {
used: getGBFromBytes(memoryUsed),
total: getGBFromBytes(totalMemory),
percentage: roundWithNDigits(memoryUsagePercentage, 2),
}
}

export const getUptime = () => {
const sysUptimeInSeconds = os.uptime()
const uptimeDuration = Duration.fromObject({ seconds: sysUptimeInSeconds })

const days = Math.floor(uptimeDuration.as('days'))
const hours = Math.floor(uptimeDuration.shiftTo('hours').hours % 24)
const minutes = Math.floor(uptimeDuration.shiftTo('minutes').minutes % 60)

return {
days,
hours,
minutes,
}
}

function roundWithNDigits(num: number, n: number) {
const factor = Math.pow(10, n)
return Math.round(num * factor) / factor
}

function getGBFromBytes(bytes: number) {
const BYTES_TO_GB_RATIO = 1_000_000_000
const value = roundWithNDigits(bytes / BYTES_TO_GB_RATIO, 1)

return value
}
47 changes: 45 additions & 2 deletions app/test_adomin_config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
/* eslint-disable unicorn/no-await-expression-member */
import { AdominViewConfig } from '#adomin/adomin_config.types'
import { createFolderViewConfig } from '#adomin/create_folder_view_config'
import { createModelViewConfig } from '#adomin/create_model_view_config'
import { createStatsViewConfig } from '#adomin/create_stats_view_config'
import { groupByDate, groupByDayOfWeek, groupByHour } from '#adomin/routes/stats/group_by_helpers'
import {
groupByDate,
groupByDayOfWeek,
groupByHour,
} from '#adomin/routes/stats/helpers/group_by_helpers'
import Idea from '#models/idea'
import Profile from '#models/profile'
import Test from '#models/test'
Expand Down Expand Up @@ -268,6 +273,44 @@ const FAKE_STATS_CONFIG = createStatsViewConfig({
icon: 'chart-bar',
})

const KPI_STATS_CONFIG = createStatsViewConfig({
label: 'KPI stats',
name: 'kpiStats',
stats: [
{
type: 'kpi',
label: 's1',
name: 's1',
dataFetcher: async () => '54h',
},
{
type: 'kpi',
label: 's2',
name: 's2',
dataFetcher: async () => 88,
options: { isPercentage: true },
},
{
type: 'column',
label: 's3',
name: 's3',
dataFetcher: async () => [
['a', 15],
['b', 20],
['c', 44],
],
},
],
gridTemplateAreas: {
normal: `"s1 s2"
"s3 s3"`,
sm: `"s1"
"s2"
"s3"`,
},
icon: 'chart-bar',
})

const FOLDER_FOUR = createFolderViewConfig({
label: 'Dossier 4',
name: 'folder4',
Expand All @@ -279,7 +322,7 @@ const FOLDER_FOUR = createFolderViewConfig({
createFolderViewConfig({
label: 'Dossier 6',
name: 'folder6',
views: [FAKE_STATS_CONFIG],
views: [FAKE_STATS_CONFIG, KPI_STATS_CONFIG],
icon: 'folder',
}),
],
Expand Down
5 changes: 4 additions & 1 deletion docs/src/content/docs/reference/views/stats/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,10 @@ import { FileTree } from '@astrojs/starlight/components';
- create_stats_view_config.ts [Open on GitHub](https://github.com/galadrimteam/adomin/blob/main/app/adomin/create_stats_view_config.ts)
- routes
- stats
- group_by_helpers.ts [Open on GitHub](https://github.com/galadrimteam/adomin/blob/main/app/adomin/routes/stats/group_by_helpers.ts)
- helpers
- group_by_helpers.ts [Open on GitHub](https://github.com/galadrimteam/adomin/blob/main/app/adomin/routes/stats/helpers/group_by_helpers.ts)
- get_cumulative_table_data.ts [Open on GitHub](https://github.com/galadrimteam/adomin/blob/main/app/adomin/routes/stats/helpers/get_cumulative_table_data.ts)
- instance_metrics.ts [Open on GitHub](https://github.com/galadrimteam/adomin/blob/main/app/adomin/routes/stats/helpers/instance_metrics.ts)

</FileTree>

3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@
"#config/*": ["./config/*.js"],
"#adomin/*": ["./app/adomin/*.js"]
}
}
},
"exclude": ["docs"]
}

0 comments on commit 14162e4

Please sign in to comment.