Skip to content

Commit

Permalink
Merge pull request #104 from zhiyan114/master
Browse files Browse the repository at this point in the history
TEST IN PRODUCTION
  • Loading branch information
zhiyan114 authored May 16, 2024
2 parents 976d971 + 383d259 commit a62e93b
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 119 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"lint:check": "eslint . --ext .ts",
"build:check": "tsc -p tsconfig.json",
"build": "rimraf dist && node build.js",
"start": "node ./dist/index.js"
"start": "node ./dist/loader.js"
},
"devDependencies": {
"@sentry/cli": "^2.31.2",
Expand Down
107 changes: 3 additions & 104 deletions src/core/DiscordClient.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,18 @@
import { ActivityType, Client, GatewayIntentBits, Partials, DiscordAPIError, DefaultWebSocketManagerOptions } from "discord.js";
import { APIErrors } from "../utils/discordErrorCode";
import { ActivityType, Client, GatewayIntentBits, Partials, DefaultWebSocketManagerOptions } from "discord.js";
import config from '../config.json';
import { PrismaClient } from "@prisma/client";
import Redis from "ioredis";
import { connect, Connection } from "amqplib";
import { eventLogger } from "./helper/eventLogger";
import { DiscordEvents, RedisEvents, AMQPEvents } from "../events";

import { init as sentryInit, flush, extraErrorDataIntegration, rewriteFramesIntegration, expressIntegration, prismaIntegration } from "@sentry/node";
import { Prisma } from "@prisma/client";
import path from "path";
import { ReactRoleLoader } from "../services/ReactRoleHandler";
import { baseClient } from "./baseClient";
import { DiscordCommandHandler } from "../events/helper/DiscordCommandHandler";
import { TwitchClient } from "./TwitchClient";
import { YoutubeClient } from "./YoutubeClient";

import { SEMRESATTRS_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { registerInstrumentations } from '@opentelemetry/instrumentation';
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
import { PrismaInstrumentation } from '@prisma/instrumentation';
import { Resource } from '@opentelemetry/resources';



/**
Expand Down Expand Up @@ -87,12 +77,6 @@ export class DiscordClient extends Client implements baseClient {
new RedisEvents(this)
.registerEvents();

// Enable Telemetry Systems
if(process.env["SENTRY_DSN"]) {
this.configureOpenTelemetry();
this.initSentry();
}

// Initialize Twitch Client
if(!process.env["TWITCH_TOKEN"] || !process.env["TWITCH_USERNAME"])
throw new Error("No twitch username/token provided");
Expand Down Expand Up @@ -137,13 +121,12 @@ export class DiscordClient extends Client implements baseClient {
public async dispose() {
// Close all connections
await this.prisma.$disconnect();
await this.redis.disconnect();
await this.redis.quit();
if(this.amqp) {
this.events.amqp.noAutoReconnect = true;
await this.amqp.close();
}
await this.destroy();
await flush();
}

public updateStatus() {
Expand All @@ -164,89 +147,5 @@ export class DiscordClient extends Client implements baseClient {
private async loadServices() {
await ReactRoleLoader(this);
}


/* Telemetry Systems Below */

private initSentry() {
sentryInit({
dsn: process.env["SENTRY_DSN"],
maxValueLength: 1000,
tracesSampleRate: 0.1,

integrations: [
extraErrorDataIntegration({
depth: 5
}),
rewriteFramesIntegration({
iteratee: (frame) => {
const absPath = frame.filename;
if(!absPath) return frame;
// Set the base path as the dist output to match the naming artifact on sentry
frame.filename = `/${path.relative(__dirname, absPath).replace(/\\/g, "/")}`;
return frame;
}
}),
prismaIntegration(),
expressIntegration(),
],

beforeBreadcrumb: (breadcrumb) => {
// List of urls to ignore
const ignoreUrl = [
"https://api.twitch.tv",
"https://discord.com",
"https://cdn.discordapp.com"
];

// Ignore Http Breadcrumbs from the blacklisted url
if(breadcrumb.category === "http" &&
ignoreUrl.filter(url=>breadcrumb.data?.url.startsWith(url)).length > 0) return null;
return breadcrumb;
},

ignoreErrors: [
"ETIMEDOUT",
"EADDRINUSE",
"ENOTFOUND",
"TimeoutError",
"AbortError",
"NetworkError",
"ECONNREFUSED",
"ECONNRESET",
],

beforeSend : (evnt, hint) => {
const ex = hint.originalException;
if(ex instanceof DiscordAPIError && ex.code === APIErrors.UNKNOWN_INTERACTION) return null;
// Somehow prisma bugged and threw this error :/
if(ex instanceof Prisma.PrismaClientKnownRequestError && ex.code === "P1017") return null;
return evnt;
},

release: process.env['COMMITHASH'],
environment: process.env["ENVIRONMENT"]
});
}

private configureOpenTelemetry() {
// Default Prisma Configuration

const provider = new NodeTracerProvider({
resource: new Resource({
[SEMRESATTRS_SERVICE_NAME]: 'example application',
}),
});

provider.addSpanProcessor(new SimpleSpanProcessor(new OTLPTraceExporter()));

registerInstrumentations({
tracerProvider: provider,
instrumentations: [new PrismaInstrumentation()],
});

// Register the provider globally
provider.register();
}

}
19 changes: 5 additions & 14 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { DiscordClient } from "./core/DiscordClient";
import { existsSync, readFileSync, writeFileSync } from "fs";
import {config as dotenv} from "dotenv";
import { writeFileSync } from "fs";
import { flush } from "@sentry/node";


/**
* .env persistance setup for docker
*/

export function saveEnv() {
function saveEnv() {
const envToWrite = process.env["WRITE_ENV"];
if(envToWrite) {
const envs = envToWrite.replaceAll(' ', '').split(",");
Expand All @@ -18,7 +18,6 @@ export function saveEnv() {
}
}

dotenv();
if(process.env['ISDOCKER'])
saveEnv();

Expand All @@ -29,14 +28,6 @@ if(process.env['ISDOCKER'])
if(!process.env["BOTTOKEN"])
throw new Error("No token provided");

if(!process.env["COMMITHASH"]) {
// Try to load the commit hash via file
if(existsSync("commitHash"))
process.env["COMMITHASH"] = readFileSync("commitHash").toString();
else
console.warn("No commit hash found!");
}

/**
* Setup our beloved client stuff and start it
*/
Expand All @@ -52,10 +43,10 @@ async function quitSignalHandler() {
await CoreClient.dispose();
await CoreClient.twitch.dispose();
await CoreClient.youtube.dispose();
await flush(15000);
process.exit(0);
}

process.on("SIGINT", quitSignalHandler);
process.on("SIGTERM", quitSignalHandler);
process.on("SIGQUIT", quitSignalHandler);

process.on("SIGQUIT", quitSignalHandler);
110 changes: 110 additions & 0 deletions src/loader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/* Software Loader */


// Load Env Variable
import {config as dotenv} from "dotenv";
dotenv();


// Load Commit Hash
import {existsSync, readFileSync} from "fs";
if(!process.env["COMMITHASH"]) {
// Try to load the commit hash via file
if(existsSync("commitHash"))
process.env["COMMITHASH"] = readFileSync("commitHash").toString();
else
console.warn("No commit hash found!");
}


// Run Sentry first as required by the docs
import { expressIntegration, extraErrorDataIntegration, prismaIntegration, rewriteFramesIntegration, init as sentryInit } from "@sentry/node";
import { DiscordAPIError } from "discord.js";
import { relative } from "path";
import { APIErrors } from "./utils/discordErrorCode";
import { Prisma } from "@prisma/client";

sentryInit({
dsn: process.env["SENTRY_DSN"],
maxValueLength: 1000,
tracesSampleRate: 0.1,

integrations: [
extraErrorDataIntegration({
depth: 5
}),
rewriteFramesIntegration({
iteratee: (frame) => {
const absPath = frame.filename;
if(!absPath) return frame;
// Set the base path as the dist output to match the naming artifact on sentry
frame.filename = `/${relative(__dirname, absPath).replace(/\\/g, "/")}`;
return frame;
}
}),
prismaIntegration(),
expressIntegration(),
],

beforeBreadcrumb: (breadcrumb) => {
// List of urls to ignore
const ignoreUrl = [
"https://api.twitch.tv",
"https://discord.com",
"https://cdn.discordapp.com"
];

// Ignore Http Breadcrumbs from the blacklisted url
if(breadcrumb.category === "http" &&
ignoreUrl.filter(url=>breadcrumb.data?.url.startsWith(url)).length > 0) return null;
return breadcrumb;
},

ignoreErrors: [
"ETIMEDOUT",
"EADDRINUSE",
"ENOTFOUND",
"TimeoutError",
"AbortError",
"NetworkError",
"ECONNREFUSED",
"ECONNRESET",
],

beforeSend : (evnt, hint) => {
const ex = hint.originalException;
if(ex instanceof DiscordAPIError && ex.code === APIErrors.UNKNOWN_INTERACTION) return null;
// Somehow prisma bugged and threw this error :/
if(ex instanceof Prisma.PrismaClientKnownRequestError && ex.code === "P1017") return null;
return evnt;
},

release: process.env['COMMITHASH'],
environment: process.env["ENVIRONMENT"]
});


// Load OpenTelemetry Config
import { SEMRESATTRS_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { registerInstrumentations } from '@opentelemetry/instrumentation';
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
import { PrismaInstrumentation } from '@prisma/instrumentation';
import { Resource } from '@opentelemetry/resources';

const provider = new NodeTracerProvider({
resource: new Resource({
[SEMRESATTRS_SERVICE_NAME]: 'example application',
}),
});
provider.addSpanProcessor(new SimpleSpanProcessor(new OTLPTraceExporter()));

registerInstrumentations({
tracerProvider: provider,
instrumentations: [new PrismaInstrumentation()],
});
provider.register();

// Start the main software
import('./index');

0 comments on commit a62e93b

Please sign in to comment.