mirror of
https://github.com/KeyZox71/knl_meowscendence.git
synced 2025-08-14 04:22:54 +02:00
「🏗️」 wip: ELK workingggggggggggggggggggggggggggggggggggg
This commit is contained in:
2
Justfile
2
Justfile
@ -13,7 +13,7 @@ set dotenv-load
|
|||||||
|
|
||||||
# To launch all apis
|
# To launch all apis
|
||||||
@apis:
|
@apis:
|
||||||
node src/dev.js
|
node src/start.js
|
||||||
|
|
||||||
# To launch the front end
|
# To launch the front end
|
||||||
@front:
|
@front:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
include:
|
include:
|
||||||
- ./logstash/compose.yml
|
- ./logstash/compose.yml
|
||||||
# - ./kibana/compose.yml
|
- ./kibana/compose.yml
|
||||||
# - ./elasticsearch/compose.yml
|
- ./elasticsearch/compose.yml
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
FROM docker.elastic.co/elasticsearch/elasticsearch-wolfi:9.0.3
|
FROM docker.elastic.co/elasticsearch/elasticsearch-wolfi:9.0.4
|
||||||
|
|
||||||
COPY --chown=elasticsearch:elasticsearch elasticsearch.yml /usr/share/elasticsearch/config/
|
COPY --chown=elasticsearch:elasticsearch elasticsearch.yml /usr/share/elasticsearch/config/
|
||||||
|
COPY --chown=elasticsearch:elasticsearch jvm.options /usr/share/elasticsearch/config/jvm.options.d/custom.options
|
||||||
|
@ -6,5 +6,5 @@ services:
|
|||||||
context: .
|
context: .
|
||||||
environment:
|
environment:
|
||||||
- LOG_LEVEL=info
|
- LOG_LEVEL=info
|
||||||
- ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
|
networks:
|
||||||
mem_limit: 1gb
|
- elk
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
cluster.name: docker-cluster
|
||||||
|
|
||||||
|
node.name: transcendence-elasticsearch
|
||||||
|
|
||||||
|
discovery.type: single-node
|
||||||
|
|
||||||
|
xpack.security.enabled: false
|
||||||
|
|
||||||
|
network.host: 0.0.0.0
|
||||||
|
2
docker/ELK/elasticsearch/jvm.options
Normal file
2
docker/ELK/elasticsearch/jvm.options
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
-Xms1g
|
||||||
|
-Xmx1g
|
@ -1 +1,3 @@
|
|||||||
FROM kibana:9.0.3
|
FROM docker.elastic.co/kibana/kibana-wolfi:9.0.4
|
||||||
|
|
||||||
|
COPY --chmod=777 kibana.yml /etc/kibana/kibana.yml
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
services:
|
||||||
|
kibana:
|
||||||
|
container_name: transcendence-kibana
|
||||||
|
build:
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
context: .
|
||||||
|
ports:
|
||||||
|
- ${ELK_PORT}:5601
|
||||||
|
environment:
|
||||||
|
- LOG_LEVEL=info
|
||||||
|
networks:
|
||||||
|
- elk
|
||||||
|
6
docker/ELK/kibana/kibana.yml
Normal file
6
docker/ELK/kibana/kibana.yml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
server.name: kibana
|
||||||
|
server.host: "0.0.0.0"
|
||||||
|
|
||||||
|
elasticsearch.hosts: ["https://transcendence-elasticsearch:9200"]
|
||||||
|
|
||||||
|
telemetry.enabled: false
|
@ -1,4 +1,4 @@
|
|||||||
FROM docker.elastic.co/logstash/logstash-wolfi:9.0.3
|
FROM docker.elastic.co/logstash/logstash-wolfi:9.0.4
|
||||||
|
|
||||||
RUN rm -f /usr/share/logstash/pipeline/logstash.conf
|
RUN rm -f /usr/share/logstash/pipeline/logstash.conf
|
||||||
|
|
||||||
|
@ -12,3 +12,4 @@ services:
|
|||||||
- LOG_LEVEL=info
|
- LOG_LEVEL=info
|
||||||
networks:
|
networks:
|
||||||
- elk
|
- elk
|
||||||
|
- logstash
|
||||||
|
@ -14,6 +14,7 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- TZ=Europe/Paris
|
- TZ=Europe/Paris
|
||||||
- API_TARGET=user
|
- API_TARGET=user
|
||||||
|
- LOG_FILE_PATH=/var/log/log.log
|
||||||
- JWT_SECRET=${JWT_SECRET}
|
- JWT_SECRET=${JWT_SECRET}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
auth-api:
|
auth-api:
|
||||||
@ -31,5 +32,6 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- TZ=Europe/Paris
|
- TZ=Europe/Paris
|
||||||
- API_TARGET=auth
|
- API_TARGET=auth
|
||||||
|
- LOG_FILE_PATH=/var/log/log.log
|
||||||
- JWT_SECRET=${JWT_SECRET}
|
- JWT_SECRET=${JWT_SECRET}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
@ -3,7 +3,7 @@ name: ft_transcendence
|
|||||||
include:
|
include:
|
||||||
- ./volumes.yml
|
- ./volumes.yml
|
||||||
- ./networks.yml
|
- ./networks.yml
|
||||||
- ./monitoring/compose.yml
|
# - ./monitoring/compose.yml
|
||||||
- ./api-base/compose.yml
|
- ./api-base/compose.yml
|
||||||
- ./front/compose.yml
|
- ./front/compose.yml
|
||||||
- ./ELK/compose.yml
|
- ./ELK/compose.yml
|
||||||
|
@ -31,7 +31,5 @@ RUN touch /var/log/front/err.log /var/log/front/log.log
|
|||||||
RUN chmod -R 777 /var/log/front
|
RUN chmod -R 777 /var/log/front
|
||||||
USER nginx
|
USER nginx
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
EXPOSE 80 443
|
EXPOSE 80 443
|
||||||
STOPSIGNAL SIGINT
|
STOPSIGNAL SIGINT
|
||||||
|
@ -9,7 +9,6 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- log-nginx:/var/log/front
|
- log-nginx:/var/log/front
|
||||||
environment:
|
environment:
|
||||||
- SERVER_NAME=localhost
|
|
||||||
- TZ=Europe/Paris
|
- TZ=Europe/Paris
|
||||||
depends_on:
|
depends_on:
|
||||||
user-api:
|
user-api:
|
||||||
|
@ -24,7 +24,7 @@ scrape_configs:
|
|||||||
static_configs:
|
static_configs:
|
||||||
- targets: ['node-exporter:9100']
|
- targets: ['node-exporter:9100']
|
||||||
|
|
||||||
- job_name: 'nodejs'
|
# - job_name: 'nodejs'
|
||||||
static_configs:
|
# static_configs:
|
||||||
- targets: ['transcendence-api-auth:3000']
|
# - targets: ['transcendence-api-auth:3000']
|
||||||
- targets: ['transcendence-api-user:3000']
|
# - targets: ['transcendence-api-user:3000']
|
||||||
|
@ -9,3 +9,5 @@ networks:
|
|||||||
name: transcendence-prom-exporter
|
name: transcendence-prom-exporter
|
||||||
elk:
|
elk:
|
||||||
name: transcendence-elk
|
name: transcendence-elk
|
||||||
|
logstash:
|
||||||
|
name: transcendence-logstash
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
"fastify": "^5.4.0",
|
"fastify": "^5.4.0",
|
||||||
"fastify-cli": "^7.4.0",
|
"fastify-cli": "^7.4.0",
|
||||||
"google-auth-library": "^10.1.0",
|
"google-auth-library": "^10.1.0",
|
||||||
|
"pino": "^9.7.0",
|
||||||
|
"pino-logstash": "^1.0.0",
|
||||||
"prom-client": "^15.1.3",
|
"prom-client": "^15.1.3",
|
||||||
"solhint": "^6.0.0"
|
"solhint": "^6.0.0"
|
||||||
},
|
},
|
||||||
|
11
pnpm-lock.yaml
generated
11
pnpm-lock.yaml
generated
@ -38,6 +38,12 @@ importers:
|
|||||||
google-auth-library:
|
google-auth-library:
|
||||||
specifier: ^10.1.0
|
specifier: ^10.1.0
|
||||||
version: 10.1.0
|
version: 10.1.0
|
||||||
|
pino:
|
||||||
|
specifier: ^9.7.0
|
||||||
|
version: 9.7.0
|
||||||
|
pino-logstash:
|
||||||
|
specifier: ^1.0.0
|
||||||
|
version: 1.0.0
|
||||||
prom-client:
|
prom-client:
|
||||||
specifier: ^15.1.3
|
specifier: ^15.1.3
|
||||||
version: 15.1.3
|
version: 15.1.3
|
||||||
@ -1328,6 +1334,9 @@ packages:
|
|||||||
pino-abstract-transport@2.0.0:
|
pino-abstract-transport@2.0.0:
|
||||||
resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==}
|
resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==}
|
||||||
|
|
||||||
|
pino-logstash@1.0.0:
|
||||||
|
resolution: {integrity: sha512-v8UCUxGROClKZW6mB0GumsfCi3gnmupMNDzh86TX9Oab9ijDjIW3vJdMjlcNaAyJK9GiJxUdLtI6amzLhpuARg==}
|
||||||
|
|
||||||
pino-pretty@13.0.0:
|
pino-pretty@13.0.0:
|
||||||
resolution: {integrity: sha512-cQBBIVG3YajgoUjo1FdKVRX6t9XPxwB9lcNJVD5GCnNM4Y6T12YYx8c6zEejxQsU0wrg9TwmDulcE9LR7qcJqA==}
|
resolution: {integrity: sha512-cQBBIVG3YajgoUjo1FdKVRX6t9XPxwB9lcNJVD5GCnNM4Y6T12YYx8c6zEejxQsU0wrg9TwmDulcE9LR7qcJqA==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@ -2785,6 +2794,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
split2: 4.2.0
|
split2: 4.2.0
|
||||||
|
|
||||||
|
pino-logstash@1.0.0: {}
|
||||||
|
|
||||||
pino-pretty@13.0.0:
|
pino-pretty@13.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
colorette: 2.0.20
|
colorette: 2.0.20
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import fastifyJWT from '@fastify/jwt';
|
import fastifyJWT from '@fastify/jwt';
|
||||||
import fastifyCookie from '@fastify/cookie';
|
import fastifyCookie from '@fastify/cookie';
|
||||||
import client from 'prom-client';
|
|
||||||
|
|
||||||
import { register } from './register.js';
|
import { register } from './register.js';
|
||||||
import { login } from './login.js';
|
import { login } from './login.js';
|
||||||
@ -14,7 +13,6 @@ import { totpVerify } from './totpVerify.js';
|
|||||||
|
|
||||||
const saltRounds = 10;
|
const saltRounds = 10;
|
||||||
export const appName = process.env.APP_NAME || 'knl_meowscendence';
|
export const appName = process.env.APP_NAME || 'knl_meowscendence';
|
||||||
const collectDefaultMetrics = client.collectDefaultMetrics
|
|
||||||
|
|
||||||
authDB.prepareDB();
|
authDB.prepareDB();
|
||||||
|
|
||||||
@ -24,29 +22,6 @@ authDB.prepareDB();
|
|||||||
*/
|
*/
|
||||||
export default async function(fastify, options) {
|
export default async function(fastify, options) {
|
||||||
|
|
||||||
collectDefaultMetrics({ labels: { service: "auth-api" } })
|
|
||||||
client.register.setDefaultLabels({ service: "auth-api" })
|
|
||||||
|
|
||||||
const httpRequestCounter = new client.Counter({
|
|
||||||
name: 'http_requests_total',
|
|
||||||
help: 'Total number of HTTP requests',
|
|
||||||
labelNames: ['method', 'route', 'status_code'],
|
|
||||||
})
|
|
||||||
|
|
||||||
fastify.addHook('onResponse', (req, res, done) => {
|
|
||||||
httpRequestCounter.inc({
|
|
||||||
method: req.method,
|
|
||||||
route: req.routerPath || req.url,
|
|
||||||
status_code: res.statusCode,
|
|
||||||
})
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
fastify.get('/metrics', async (req, reply) => {
|
|
||||||
reply
|
|
||||||
.header('Content-Type', client.register.contentType)
|
|
||||||
.send(await client.register.metrics())
|
|
||||||
})
|
|
||||||
|
|
||||||
fastify.register(fastifyJWT, {
|
fastify.register(fastifyJWT, {
|
||||||
secret: process.env.JWT_SECRET || '123456789101112131415161718192021',
|
secret: process.env.JWT_SECRET || '123456789101112131415161718192021',
|
||||||
cookie: {
|
cookie: {
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import fastifyJWT from '@fastify/jwt';
|
import fastifyJWT from '@fastify/jwt';
|
||||||
import fastifyCookie from '@fastify/cookie';
|
import fastifyCookie from '@fastify/cookie';
|
||||||
import Database from 'better-sqlite3';
|
import Database from 'better-sqlite3';
|
||||||
import client from 'prom-client';
|
|
||||||
|
|
||||||
var env = process.env.NODE_ENV || 'development';
|
var env = process.env.NODE_ENV || 'development';
|
||||||
const collectDefaultMetrics = client.collectDefaultMetrics
|
|
||||||
|
|
||||||
let database;
|
let database;
|
||||||
|
|
||||||
@ -58,31 +56,6 @@ const deleteFriends = database.prepare('DELETE FROM friends WHERE username = ?;'
|
|||||||
* @param {import('fastify').FastifyPluginOptions} options
|
* @param {import('fastify').FastifyPluginOptions} options
|
||||||
*/
|
*/
|
||||||
export default async function(fastify, options) {
|
export default async function(fastify, options) {
|
||||||
|
|
||||||
collectDefaultMetrics({ labels: { service: "auth-api" } })
|
|
||||||
client.register.setDefaultLabels({ service: "auth-api" })
|
|
||||||
|
|
||||||
const httpRequestCounter = new client.Counter({
|
|
||||||
name: 'http_requests_total',
|
|
||||||
help: 'Total number of HTTP requests',
|
|
||||||
labelNames: ['method', 'route', 'status_code'],
|
|
||||||
})
|
|
||||||
|
|
||||||
fastify.addHook('onResponse', (req, res, done) => {
|
|
||||||
httpRequestCounter.inc({
|
|
||||||
method: req.method,
|
|
||||||
route: req.routerPath || req.url,
|
|
||||||
status_code: res.statusCode,
|
|
||||||
})
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
fastify.get('/metrics', async (req, reply) => {
|
|
||||||
reply
|
|
||||||
.header('Content-Type', client.register.contentType)
|
|
||||||
.send(await client.register.metrics())
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
fastify.register(fastifyJWT, {
|
fastify.register(fastifyJWT, {
|
||||||
secret: process.env.JWT_SECRET || '123456789101112131415161718192021',
|
secret: process.env.JWT_SECRET || '123456789101112131415161718192021',
|
||||||
cookie: {
|
cookie: {
|
||||||
|
88
src/start.js
88
src/start.js
@ -1,53 +1,71 @@
|
|||||||
import Fastify from 'fastify';
|
import Fastify from 'fastify';
|
||||||
import authApi from './api/auth/default.js';
|
import authApi from './api/auth/default.js';
|
||||||
import userApi from './api/user/default.js';
|
import userApi from './api/user/default.js';
|
||||||
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
const loggerOption = {
|
const isProduction = process.env.NODE_ENV === 'production';
|
||||||
transport: {
|
const logFilePath = process.env.LOG_FILE_PATH || './logs/api.log';
|
||||||
target: 'pino-pretty',
|
|
||||||
options: {
|
const loggerOption = () => {
|
||||||
colorize: true,
|
if (!isProduction) {
|
||||||
translateTime: 'HH:MM:ss',
|
return {
|
||||||
ignore: 'pid,hostname'
|
transport: {
|
||||||
}
|
target: 'pino-pretty',
|
||||||
},
|
options: {
|
||||||
file: process.env.LOG_TARGET || ""
|
colorize: true,
|
||||||
|
translateTime: 'HH:MM:ss',
|
||||||
|
ignore: 'pid,hostname',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// Make sure the directory exists
|
||||||
|
const logDir = path.dirname(logFilePath);
|
||||||
|
fs.mkdirSync(logDir, { recursive: true });
|
||||||
|
|
||||||
|
const logStream = fs.createWriteStream(logFilePath, { flags: 'a' }); // append mode
|
||||||
|
return {
|
||||||
|
level: 'info',
|
||||||
|
stream: logStream,
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function sigHandle(signal) {
|
|
||||||
process.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
process.on('SIGINT', sigHandle);
|
|
||||||
|
|
||||||
async function start() {
|
async function start() {
|
||||||
const target = process.env.API_TARGET || 'all';
|
const target = process.env.API_TARGET || 'all';
|
||||||
|
|
||||||
|
const servers = [];
|
||||||
|
|
||||||
if (target === 'auth' || target === 'all') {
|
if (target === 'auth' || target === 'all') {
|
||||||
const auth = Fastify({ logger: loggerOption });
|
const auth = Fastify({ logger: loggerOption('auth') });
|
||||||
auth.register(authApi);
|
auth.register(authApi);
|
||||||
if (target !== 'all') {
|
const port = target === 'all' ? 3001 : 3000;
|
||||||
await auth.listen({ port: 3000, host: '0.0.0.0' });
|
const host = target === 'all' ? '127.0.0.1' : '0.0.0.0';
|
||||||
console.log('Auth API listening on http://0.0.0.0:3000');
|
await auth.listen({ port, host });
|
||||||
}
|
console.log(`Auth API listening on http://${host}:${port}`);
|
||||||
else {
|
servers.push(auth);
|
||||||
await auth.listen({ port: 3001, host: '127.0.0.1'});
|
|
||||||
console.log('Auth API listening on http://localhost:3001');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target === 'user' || target === 'all') {
|
if (target === 'user' || target === 'all') {
|
||||||
const user = Fastify({ logger: loggerOption });
|
const user = Fastify({ logger: loggerOption('user') });
|
||||||
user.register(userApi);
|
user.register(userApi);
|
||||||
if (target !== 'all') {
|
const port = target === 'all' ? 3002 : 3000;
|
||||||
await user.listen({ port: 3000, host: '0.0.0.0' });
|
const host = target === 'all' ? '127.0.0.1' : '0.0.0.0';
|
||||||
console.log('User API listening on http://0.0.0.0:3000');
|
await user.listen({ port, host });
|
||||||
}
|
console.log(`User API listening on http://${host}:${port}`);
|
||||||
else {
|
servers.push(user);
|
||||||
await user.listen({ port: 3002, host: '127.0.0.1'});
|
|
||||||
console.log('User API listening on http://localhost:3002');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Graceful shutdown on SIGINT
|
||||||
|
process.on('SIGINT', async () => {
|
||||||
|
console.log('SIGINT received, closing servers...');
|
||||||
|
await Promise.all(servers.map((srv) => srv.close()));
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
start().catch(console.error);
|
start().catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
Reference in New Issue
Block a user