Add dinosaur wet metrics

This commit is contained in:
2023-10-16 17:52:02 -06:00
parent deb257b2fe
commit 295b217539
6 changed files with 108 additions and 38 deletions

View File

@@ -27,12 +27,14 @@
"@nestjs/jwt": "^10.1.1", "@nestjs/jwt": "^10.1.1",
"@nestjs/platform-express": "^10.0.0", "@nestjs/platform-express": "^10.0.0",
"@nestjs/swagger": "^7.1.11", "@nestjs/swagger": "^7.1.11",
"@willsoto/nestjs-prometheus": "^6.0.0",
"axios": "^1.5.0", "axios": "^1.5.0",
"bcrypt": "^5.1.1", "bcrypt": "^5.1.1",
"cache-manager": "^5.2.3", "cache-manager": "^5.2.3",
"hbs": "^4.2.0", "hbs": "^4.2.0",
"minio": "^7.1.3", "minio": "^7.1.3",
"open-graph-scraper": "^6.3.0", "open-graph-scraper": "^6.3.0",
"prom-client": "^15.0.0",
"ramda": "^0.29.0", "ramda": "^0.29.0",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1", "rxjs": "^7.8.1",

View File

@@ -13,6 +13,7 @@ import { IrcbotModule } from './ircbot/ircbot.module';
import { IrcbotService } from './ircbot/ircbot.service'; import { IrcbotService } from './ircbot/ircbot.service';
import { DinosaurwetModule } from './dinosaurwet/dinosaurwet.module'; import { DinosaurwetModule } from './dinosaurwet/dinosaurwet.module';
import { OgScraperModule } from './ogscraper/ogscraper.module'; import { OgScraperModule } from './ogscraper/ogscraper.module';
import { PrometheusModule } from '@willsoto/nestjs-prometheus';
@Module({ @Module({
imports: [ imports: [
@@ -20,6 +21,11 @@ import { OgScraperModule } from './ogscraper/ogscraper.module';
isGlobal: true, isGlobal: true,
load: [configuration], load: [configuration],
}), }),
PrometheusModule.register({
defaultLabels: {
app: 'us.dev api',
},
}),
CacheModule.register({ isGlobal: true }), CacheModule.register({ isGlobal: true }),
ParkioModule, ParkioModule,
IswordModule, IswordModule,

View File

@@ -10,8 +10,9 @@ import {
} from '@nestjs/common'; } from '@nestjs/common';
import { AuthService } from './auth.service'; import { AuthService } from './auth.service';
import { AuthGuard } from './auth.guard'; import { AuthGuard } from './auth.guard';
import { ApiBearerAuth } from '@nestjs/swagger'; import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
@ApiTags('auth')
@Controller('auth') @Controller('auth')
export class AuthController { export class AuthController {
constructor(private authService: AuthService) {} constructor(private authService: AuthService) {}
@@ -24,8 +25,8 @@ export class AuthController {
@UseGuards(AuthGuard) @UseGuards(AuthGuard)
@Post('hash') @Post('hash')
hash(@Body() hashDto: {pass: string, rounds?: number}) { hash(@Body() hashDto: { pass: string; rounds?: number }) {
return this.authService.hash(hashDto.pass, hashDto.rounds) return this.authService.hash(hashDto.pass, hashDto.rounds);
} }
@UseGuards(AuthGuard) @UseGuards(AuthGuard)

View File

@@ -2,6 +2,9 @@ import { Controller, Get, Res } from '@nestjs/common';
import { Response } from 'express'; import { Response } from 'express';
import { identity, prop } from 'ramda'; import { identity, prop } from 'ramda';
import * as xml from 'xml'; import * as xml from 'xml';
import { InjectMetric } from '@willsoto/nestjs-prometheus';
import { Gauge } from 'prom-client';
import { ApiTags } from '@nestjs/swagger';
const episodeFiles: [number, string][] = [ const episodeFiles: [number, string][] = [
[27544345, '01-Into-the-Big-Wet.mp3'], [27544345, '01-Into-the-Big-Wet.mp3'],
@@ -60,6 +63,34 @@ const buildFeeds = (
episodes: Episode[], episodes: Episode[],
pubDateFn: (index: number) => Date = () => startDate, pubDateFn: (index: number) => Date = () => startDate,
) => { ) => {
const episodeItems = episodes
.filter((episode: Episode, index: number) => pubDateFn(index) <= new Date())
.map(({ title, url, length, fakeReleaseDate }, index) => ({
item: [
{ title },
{ guid: url },
{ pubDate: pubDateFn(index).toUTCString() },
{
'itunes:image': {
_attr: {
href: dinosaurImage,
},
},
},
{ 'itunes:episode': index + 1 },
{
enclosure: [
{
_attr: {
url,
type: 'audio/mpeg',
length,
},
},
],
},
],
}));
const feedObject = { const feedObject = {
rss: [ rss: [
{ {
@@ -100,48 +131,24 @@ const buildFeeds = (
'A recreation of Dinosaur Wet as an RSS feed for listeners-with-licenses enjoyment.', 'A recreation of Dinosaur Wet as an RSS feed for listeners-with-licenses enjoyment.',
}, },
{ language: 'en-US' }, { language: 'en-US' },
...episodes ...episodeItems,
.filter(
(episode: Episode, index: number) =>
pubDateFn(index) <= new Date(),
)
.map(({ title, url, length, fakeReleaseDate }, index) => ({
item: [
{ title },
{ guid: url },
{ pubDate: pubDateFn(index).toUTCString() },
{
'itunes:image': {
_attr: {
href: dinosaurImage,
},
},
},
{ 'itunes:episode': index + 1 },
{
enclosure: [
{
_attr: {
url,
type: 'audio/mpeg',
length,
},
},
],
},
],
})),
], ],
}, },
], ],
}; };
const feed = '<?xml version="1.0" encoding="UTF-8"?>' + xml(feedObject); const feed = '<?xml version="1.0" encoding="UTF-8"?>' + xml(feedObject);
return feed; return { feed, episodeItems };
}; };
@ApiTags('dinosaurwet')
@Controller('dinosaurwet') @Controller('dinosaurwet')
export class DinosaurwetController { export class DinosaurwetController {
constructor(
@InjectMetric('weekly_count') public weeklyCount: Gauge<string>,
@InjectMetric('daily_count') public dailyCount: Gauge<string>,
) {}
@Get('') @Get('')
getAllAtOnce(@Res() response: Response) { getAllAtOnce(@Res() response: Response) {
response.header('Content-Type', 'application/xml'); response.header('Content-Type', 'application/xml');
@@ -158,7 +165,8 @@ export class DinosaurwetController {
(index: number) => (index: number) =>
new Date(new Date(startDate).setDate(startDate.getDate() + index)), new Date(new Date(startDate).setDate(startDate.getDate() + index)),
); );
return response.send(feed); this.dailyCount.set(feed.episodeItems.length);
return response.send(feed.feed);
} }
@Get('weekly') @Get('weekly')
@@ -170,6 +178,7 @@ export class DinosaurwetController {
(index: number) => (index: number) =>
new Date(new Date(startDate).setDate(startDate.getDate() + index * 7)), new Date(new Date(startDate).setDate(startDate.getDate() + index * 7)),
); );
return response.send(feed); this.weeklyCount.set(feed.episodeItems.length);
return response.send(feed.feed);
} }
} }

View File

@@ -1,7 +1,29 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { DinosaurwetController } from './dinosaurwet.controller'; import { DinosaurwetController } from './dinosaurwet.controller';
import {
PrometheusModule,
makeGaugeProvider,
} from '@willsoto/nestjs-prometheus';
@Module({ @Module({
controllers: [DinosaurwetController] imports: [
PrometheusModule.register({
customMetricPrefix: 'dinosaurwet',
defaultMetrics: {
enabled: false,
},
}),
],
controllers: [DinosaurwetController],
providers: [
makeGaugeProvider({
name: 'daily_count',
help: 'The current daily Dinosaur Wet episode count',
}),
makeGaugeProvider({
name: 'weekly_count',
help: 'The current weekly Dinosaur Wet episode count',
}),
],
}) })
export class DinosaurwetModule {} export class DinosaurwetModule {}

View File

@@ -849,6 +849,11 @@
consola "^2.15.0" consola "^2.15.0"
node-fetch "^2.6.1" node-fetch "^2.6.1"
"@opentelemetry/api@^1.4.0":
version "1.6.0"
resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.6.0.tgz#de2c6823203d6f319511898bb5de7e70f5267e19"
integrity sha512-OWlrQAnWn9577PhVgqjUvMr1pg57Bc4jv0iL4w0PRuOSRvq67rvHW9Ie/dZVMvCzhSCB+UxhcY/PmCmFj33Q+g==
"@pkgr/utils@^2.3.1": "@pkgr/utils@^2.3.1":
version "2.4.2" version "2.4.2"
resolved "https://registry.yarnpkg.com/@pkgr/utils/-/utils-2.4.2.tgz#9e638bbe9a6a6f165580dc943f138fd3309a2cbc" resolved "https://registry.yarnpkg.com/@pkgr/utils/-/utils-2.4.2.tgz#9e638bbe9a6a6f165580dc943f138fd3309a2cbc"
@@ -1370,6 +1375,11 @@
"@webassemblyjs/ast" "1.11.6" "@webassemblyjs/ast" "1.11.6"
"@xtuc/long" "4.2.2" "@xtuc/long" "4.2.2"
"@willsoto/nestjs-prometheus@^6.0.0":
version "6.0.0"
resolved "https://registry.yarnpkg.com/@willsoto/nestjs-prometheus/-/nestjs-prometheus-6.0.0.tgz#6ef4d5d5dfb04ebe982aab6f3a7893974e89a669"
integrity sha512-Krmda5CT9xDPjab8Eqdqiwi7xkZSX60A5rEGVLEDjUG6J6Rw5SCZ/BPaRk+MxNGWzUrRkM7K5FtTg38vWIOt1Q==
"@xtuc/ieee754@^1.2.0": "@xtuc/ieee754@^1.2.0":
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
@@ -1668,6 +1678,11 @@ binary-extensions@^2.0.0:
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
bintrees@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/bintrees/-/bintrees-1.0.2.tgz#49f896d6e858a4a499df85c38fb399b9aff840f8"
integrity sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==
bl@^4.1.0: bl@^4.1.0:
version "4.1.0" version "4.1.0"
resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
@@ -4621,6 +4636,14 @@ process-nextick-args@~2.0.0:
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
prom-client@^15.0.0:
version "15.0.0"
resolved "https://registry.yarnpkg.com/prom-client/-/prom-client-15.0.0.tgz#067da874a2aa5d2e21bd5cdba9f24a8178bdab6a"
integrity sha512-UocpgIrKyA2TKLVZDSfm8rGkL13C19YrQBAiG3xo3aDFWcHedxRxI3z+cIcucoxpSO0h5lff5iv/SXoxyeopeA==
dependencies:
"@opentelemetry/api" "^1.4.0"
tdigest "^0.1.1"
prompts@^2.0.1: prompts@^2.0.1:
version "2.4.2" version "2.4.2"
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069"
@@ -5230,6 +5253,13 @@ tar@^6.1.11:
mkdirp "^1.0.3" mkdirp "^1.0.3"
yallist "^4.0.0" yallist "^4.0.0"
tdigest@^0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/tdigest/-/tdigest-0.1.2.tgz#96c64bac4ff10746b910b0e23b515794e12faced"
integrity sha512-+G0LLgjjo9BZX2MfdvPfH+MKLCrxlXSYec5DaPYP1fe6Iyhf0/fSmJ0bFiZ1F8BT6cGXl2LpltQptzjXKWEkKA==
dependencies:
bintrees "1.0.2"
terser-webpack-plugin@^5.3.7: terser-webpack-plugin@^5.3.7:
version "5.3.9" version "5.3.9"
resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz#832536999c51b46d468067f9e37662a3b96adfe1" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz#832536999c51b46d468067f9e37662a3b96adfe1"