Logging improvements

* Insert activity identifier into logging labels after subreddit using dynamic labels
* Simplify logger creation (don't need shuffle using improvements from above)
* Add logging to Actions
* Make check logging clearer and more succinct
* Log more information on startup
This commit is contained in:
FoxxMD
2021-06-09 13:36:32 -04:00
parent 318a1d3326
commit 64a97ee048
15 changed files with 157 additions and 146 deletions

View File

@@ -4,20 +4,25 @@ import {RemoveAction} from "./RemoveAction";
import {ReportAction, ReportActionJson} from "./ReportAction";
import {FlairAction, FlairActionJson} from "./SubmissionAction/FlairAction";
import Action, {ActionJson} from "./index";
import {Logger} from "winston";
export function actionFactory
(config: ActionJson): Action {
(config: ActionJson, logger: Logger): Action {
let cfg;
switch (config.kind) {
case 'comment':
return new CommentAction(config as CommentActionJson);
cfg = config as CommentActionJson;
return new CommentAction({...cfg, logger});
case 'lock':
return new LockAction();
return new LockAction({logger});
case 'remove':
return new RemoveAction();
return new RemoveAction({logger});
case 'report':
return new ReportAction(config as ReportActionJson);
cfg = config as ReportActionJson;
return new ReportAction({...cfg, logger});
case 'flair':
return new FlairAction(config as FlairActionJson);
cfg = config as FlairActionJson;
return new FlairAction({...cfg, logger});
default:
throw new Error('rule "kind" was not recognized.');
}

View File

@@ -1,10 +1,11 @@
import Action, {ActionJson, ActionConfig, ActionOptions} from "./index";
import Snoowrap, {Comment} from "snoowrap";
import Action, {ActionJson, ActionOptions} from "./index";
import {Comment} from "snoowrap";
import Submission from "snoowrap/dist/objects/Submission";
import dayjs, {Dayjs} from "dayjs";
import {renderContent} from "../Utils/SnoowrapUtils";
import {RichContent} from "../Common/interfaces";
import {RuleResult} from "../Rule";
import LoggedError from "../Utils/LoggedError";
export const WIKI_DESCRIM = 'wiki:';
@@ -16,7 +17,6 @@ export class CommentAction extends Action {
lock: boolean = false;
sticky: boolean = false;
distinguish: boolean = false;
name?: string = 'Comment';
constructor(options: CommentActionOptions) {
super(options);
@@ -36,22 +36,30 @@ export class CommentAction extends Action {
this.distinguish = distinguish;
}
async handle(item: Comment | Submission, ruleResults: RuleResult[]): Promise<void> {
getKind() {
return 'Comment';
}
async process(item: Comment | Submission, ruleResults: RuleResult[]): Promise<void> {
if (this.hasWiki && (this.wikiFetched === undefined || Math.abs(dayjs().diff(this.wikiFetched, 'minute')) > 5)) {
try {
const wiki = item.subreddit.getWikiPage(this.wiki as string);
this.content = await wiki.content_md;
this.wikiFetched = dayjs();
} catch (err) {
this.logger.error(err);
throw new Error(`Could not read wiki page. Please ensure the page '${this.wiki}' exists and is readable`);
this.logger.error(`Could not read wiki page. Please ensure the page '${this.wiki}' exists and is readable`, err);
throw new LoggedError(`Could not read wiki page. Please ensure the page '${this.wiki}' exists and is readable`);
}
}
// @ts-ignore
const reply: Comment = await item.reply(renderContent(this.content, item, ruleResults));
if (this.lock && item instanceof Submission) {
// @ts-ignore
await item.lock();
if (this.lock) {
if(item instanceof Submission) {
// @ts-ignore
await item.lock();
} else {
this.logger.warn('Snoowrap does not support locking Comments');
}
}
if (this.distinguish) {
// @ts-ignore

View File

@@ -4,11 +4,16 @@ import Snoowrap, {Comment, Submission} from "snoowrap";
import {RuleResult} from "../Rule";
export class LockAction extends Action {
name?: string = 'Lock';
async handle(item: Comment|Submission, ruleResults: RuleResult[]): Promise<void> {
getKind() {
return 'Lock';
}
async process(item: Comment|Submission, ruleResults: RuleResult[]): Promise<void> {
if (item instanceof Submission) {
// @ts-ignore
await item.lock();
} else {
this.logger.warn('Snoowrap does not support locking Comments');
}
}
}

View File

@@ -4,8 +4,11 @@ import Snoowrap, {Comment, Submission} from "snoowrap";
import {RuleResult} from "../Rule";
export class RemoveAction extends Action {
name?: string = 'Remove';
async handle(item: Comment|Submission, ruleResults: RuleResult[]): Promise<void> {
getKind() {
return 'Remove';
}
async process(item: Comment|Submission, ruleResults: RuleResult[]): Promise<void> {
// @ts-ignore
await item.remove();
}

View File

@@ -12,14 +12,17 @@ import {RuleResult} from "../Rule";
export class ReportAction extends Action {
content: string;
name?: string = 'Report';
constructor(options: ReportActionOptions) {
super(options);
this.content = options.content || '';
}
async handle(item: Comment | Submission, ruleResults: RuleResult[]): Promise<void> {
getKind() {
return 'Report';
}
async process(item: Comment | Submission, ruleResults: RuleResult[]): Promise<void> {
const renderedContent = await renderContent(this.content, item, ruleResults);
//const truncatedContent = reportTrunc(renderedContent);
// @ts-ignore

View File

@@ -1,12 +1,11 @@
import {SubmissionActionConfig} from "./index";
import Action, {ActionJson} from "../index";
import Action, {ActionJson, ActionOptions} from "../index";
import Snoowrap, {Comment, Submission} from "snoowrap";
import {RuleResult} from "../../Rule";
export class FlairAction extends Action {
text: string;
css: string;
name?: string = 'Flair';
constructor(options: FlairActionOptions) {
super(options);
@@ -17,10 +16,16 @@ export class FlairAction extends Action {
this.css = options.css || '';
}
async handle(item: Comment | Submission, ruleResults: RuleResult[]): Promise<void> {
getKind() {
return 'Flair';
}
async process(item: Comment | Submission, ruleResults: RuleResult[]): Promise<void> {
if (item instanceof Submission) {
// @ts-ignore
await item.assignFlair({text: this.text, cssClass: this.css})
} else {
this.logger.warn('Cannot flair Comment');
}
}
}
@@ -29,7 +34,7 @@ export class FlairAction extends Action {
* @minProperties 1
* @additionalProperties false
* */
export interface FlairActionOptions extends SubmissionActionConfig {
export interface FlairActionConfig extends SubmissionActionConfig {
/**
* The text of the flair to apply
* */
@@ -40,9 +45,13 @@ export interface FlairActionOptions extends SubmissionActionConfig {
css?: string,
}
export interface FlairActionOptions extends FlairActionConfig,ActionOptions {
}
/**
* Flair the Submission
* */
export interface FlairActionJson extends FlairActionOptions, ActionJson {
export interface FlairActionJson extends FlairActionConfig, ActionJson {
}

View File

@@ -1,36 +1,35 @@
import Snoowrap, {Comment, Submission} from "snoowrap";
import {Comment, Submission} from "snoowrap";
import {Logger} from "winston";
import {createLabelledLogger, loggerMetaShuffle} from "../util";
import {RuleResult} from "../Rule";
export abstract class Action {
name?: string;
logger: Logger;
constructor(options: ActionOptions = {}) {
constructor(options: ActionOptions) {
const {
name,
loggerPrefix = '',
name = this.getKind(),
logger,
} = options;
if (name !== undefined) {
this.name = name;
}
if (logger === undefined) {
const prefix = `${loggerPrefix}|${this.name}`;
this.logger = createLabelledLogger(prefix, prefix);
} else {
this.logger = logger.child(loggerMetaShuffle(logger, name || 'Action', undefined, {truncateLength: 100}));
}
this.name = name;
const uniqueName = this.name === this.getKind() ? this.getKind() : `${this.getKind()} - ${this.name}`;
this.logger = logger.child({labels: ['Action', uniqueName]});
}
abstract handle(item: Comment | Submission, ruleResults: RuleResult[]): Promise<void>;
abstract getKind(): string;
async handle(item: Comment | Submission, ruleResults: RuleResult[]): Promise<void> {
await this.process(item, ruleResults);
this.logger.debug('Done');
}
abstract process(item: Comment | Submission, ruleResults: RuleResult[]): Promise<void>;
}
export interface ActionOptions {
name?: string;
logger?: Logger,
loggerPrefix?: string,
logger: Logger,
}
export interface ActionConfig {

View File

@@ -1,7 +1,7 @@
import Snoowrap from "snoowrap";
import {Manager} from "./Subreddit/Manager";
import winston, {Logger} from "winston";
import {labelledFormat, loggerMetaShuffle} from "./util";
import {labelledFormat} from "./util";
import snoowrap from "snoowrap";
import pEvent from "p-event";
import EventEmitter from "events";
@@ -100,31 +100,36 @@ export class App {
maxRetryAttempts: 5,
debug: shouldDebug,
// @ts-ignore
logger: this.logger.child(loggerMetaShuffle(this.logger, undefined, ['Snoowrap'])),
logger: this.logger.child({labels: ['Snoowrap']}),
continueAfterRatelimitError: true,
});
}
async buildManagers(subreddits: string[] = []) {
let availSubs = [];
const name = await this.client.getMe().name;
this.logger.info(`Authenticated Account: /u/${name}`);
for (const sub of await this.client.getModeratedSubreddits()) {
// TODO don't know a way to check permissions yet
availSubs.push(sub);
}
this.logger.info(`/u/${name} is a moderator of these subreddits: ${availSubs.map(x => x.display_name).join(', ')}`);
let subsToRun = [];
const subsToUse = subreddits.length > 0 ? subreddits : this.subreddits;
if (subsToUse.length > 0) {
this.logger.info(`User-defined subreddit constraints detected (CLI argument or environmental variable), will try to run on: ${subsToUse.join(', ')}`);
for (const sub of subsToUse) {
const asub = availSubs.find(x => x.display_name.toLowerCase() === sub.trim().toLowerCase())
if (asub === undefined) {
this.logger.error(`Will not run on ${sub} because is not modded by, or does not have appropriate permissions to mod with, for this client.`);
this.logger.warn(`Will not run on ${sub} because is not modded by, or does not have appropriate permissions to mod with, for this client.`);
} else {
subsToRun.push(asub);
}
}
} else {
// otherwise assume all moddable subs from client should be run on
this.logger.info('No user-defined subreddit constraints detected, will try to run on all');
subsToRun = availSubs;
}
@@ -137,21 +142,20 @@ export class App {
const wiki = sub.getWikiPage(this.wikiLocation);
content = await wiki.content_md;
} catch (err) {
this.logger.error(`Could not read wiki configuration for ${sub.display_name}. Please ensure the page 'contextbot' exists and is readable -- error: ${err.message}`);
this.logger.error(`[${sub.display_name}] Could not read wiki configuration. Please ensure the page 'contextbot' exists and is readable -- error: ${err.message}`);
continue;
}
try {
json = JSON.parse(content);
} catch (err) {
this.logger.error(`Wiki page contents for ${sub.display_name} was not valid -- error: ${err.message}`);
this.logger.error(`[${sub.display_name}] Wiki page contents was not valid -- error: ${err.message}`);
continue;
}
try {
subSchedule.push(new Manager(sub, this.client, this.logger, json));
} catch (err) {
debugger;
this.logger.error(`Config for ${sub.display_name} was not valid, will not run for this subreddit`, undefined, err);
this.logger.error(`[${sub.display_name}] Config was not valid`, undefined, err);
}
}
this.subManagers = subSchedule;

View File

@@ -5,7 +5,7 @@ import {Logger} from "winston";
import {Comment, Submission} from "snoowrap";
import {actionFactory} from "../Action/ActionFactory";
import {ruleFactory} from "../Rule/RuleFactory";
import {createLabelledLogger, loggerMetaShuffle, mergeArr} from "../util";;
import {mergeArr, ruleNamesFromResults} from "../util";
import {JoinCondition, JoinOperands} from "../Common/interfaces";
import * as RuleSchema from '../Schema/Rule.json';
import * as RuleSetSchema from '../Schema/RuleSet.json';
@@ -32,12 +32,7 @@ export class Check implements ICheck {
actions = [],
} = options;
if (options.logger !== undefined) {
// @ts-ignore
this.logger = options.logger.child(loggerMetaShuffle(options.logger, undefined, [`CHK ${name}`]), mergeArr);
} else {
this.logger = createLabelledLogger('Check');
}
this.logger = options.logger.child({labels: [`Check ${name}`]}, mergeArr);
this.name = name;
this.description = description;
@@ -50,16 +45,13 @@ export class Check implements ICheck {
let setErrors: any = [];
let ruleErrors: any = [];
if (valid) {
// @ts-ignore
r.logger = this.logger;
this.rules.push(new RuleSet(r as RuleSetObjectJson));
const ruleConfig = r as RuleSetObjectJson;
this.rules.push(new RuleSet({...ruleConfig, logger: this.logger}));
} else {
setErrors = ajv.errors;
valid = ajv.validate(RuleSchema, r);
if (valid) {
// @ts-ignore
r.logger = this.logger;
this.rules.push(ruleFactory(r as RuleJSONConfig));
this.rules.push(ruleFactory(r as RuleJSONConfig, this.logger));
} else {
ruleErrors = ajv.errors;
const leastErrorType = setErrors.length < ruleErrors ? 'RuleSet' : 'Rule';
@@ -79,7 +71,8 @@ export class Check implements ICheck {
} else {
let valid = ajv.validate(ActionSchema, a);
if (valid) {
this.actions.push(actionFactory(a as ActionJson));
const aj = a as ActionJson;
this.actions.push(actionFactory(aj, this.logger));
// @ts-ignore
a.logger = this.logger;
} else {
@@ -92,13 +85,11 @@ export class Check implements ICheck {
}
async run(item: Submission | Comment, existingResults: RuleResult[] = []): Promise<[boolean, RuleResult[]]> {
//this.logger.debug('Starting check');
let allResults: RuleResult[] = [];
let runOne = false;
for (const r of this.rules) {
const combinedResults = [...existingResults, ...allResults];
const [passed, results] = await r.run(item, combinedResults);
//allResults = allResults.concat(determineNewResults(combinedResults, results));
allResults = allResults.concat(results);
if (passed === null) {
continue;
@@ -106,22 +97,28 @@ export class Check implements ICheck {
runOne = true;
if (passed) {
if (this.condition === 'OR') {
this.logger.info(`✔️ => Rules (OR): ${ruleNamesFromResults(allResults)}`);
return [true, allResults];
}
} else if (this.condition === 'AND') {
this.logger.info(`❌ => Rules (AND): ${ruleNamesFromResults(allResults)}`);
return [false, allResults];
}
}
if (!runOne) {
this.logger.info('❌ => All Rules skipped because of Author checks');
return [false, allResults];
}
this.logger.info(`✔️ => Rules (AND) : ${ruleNamesFromResults(allResults)}`);
return [true, allResults];
}
async runActions(item: Submission | Comment, ruleResults: RuleResult[]): Promise<void> {
this.logger.debug('Running Actions');
for (const a of this.actions) {
await a.handle(item, ruleResults);
}
this.logger.info('Ran Actions');
}
}
@@ -140,7 +137,7 @@ export interface ICheck extends JoinCondition {
export interface CheckOptions extends ICheck {
rules: Array<IRuleSet | IRule>
actions: ActionConfig[]
logger?: Logger
logger: Logger
}
export interface CheckJson extends ICheck {

View File

@@ -1,5 +1,5 @@
import {Logger} from "winston";
import {createLabelledLogger, loggerMetaShuffle, mergeArr} from "./util";
import {mergeArr} from "./util";
import {CommentCheck} from "./Check/CommentCheck";
import {SubmissionCheck} from "./Check/SubmissionCheck";
@@ -17,19 +17,17 @@ import {isActionJson} from "./Action";
const ajv = new Ajv();
export interface ConfigBuilderOptions {
logger?: Logger,
logger: Logger,
}
export class ConfigBuilder {
configLogger: Logger;
logger: Logger;
constructor(options: ConfigBuilderOptions) {
if (options.logger !== undefined) {
this.logger = options.logger.child(loggerMetaShuffle(options.logger, 'Config'), mergeArr);
} else {
this.logger = createLabelledLogger(`Config`, `Config`);
}
this.configLogger = options.logger.child({leaf: 'Config'}, mergeArr);
this.logger = options.logger;
}
buildFromJson(config: object): [Array<SubmissionCheck>,Array<CommentCheck>,ManagerOptions] {
@@ -66,7 +64,7 @@ export class ConfigBuilder {
}
}
} else {
this.logger.error('Json config was not valid. Please use schema to check validity.');
this.configLogger.error('Json config was not valid. Please use schema to check validity.');
if(Array.isArray(ajv.errors)) {
for(const err of ajv.errors) {
let suffix = '';
@@ -76,7 +74,7 @@ export class ConfigBuilder {
suffix = err.params.allowedValues.join(', ');
suffix = ` [${suffix}]`;
}
this.logger.error(`${err.keyword}: ${err.schemaPath} => ${err.message}${suffix}`);
this.configLogger.error(`${err.keyword}: ${err.schemaPath} => ${err.message}${suffix}`);
}
}
throw new LoggedError();

View File

@@ -3,18 +3,24 @@ import RepeatActivityRule, {RepeatActivityJSONConfig} from "./SubmissionRule/Rep
import {Rule, RuleJSONConfig} from "./index";
import AuthorRule, {AuthorRuleJSONConfig} from "./AuthorRule";
import {AttributionJSONConfig, AttributionRule} from "./SubmissionRule/AttributionRule";
import {Logger} from "winston";
export function ruleFactory
(config: RuleJSONConfig): Rule {
(config: RuleJSONConfig, logger: Logger): Rule {
let cfg;
switch (config.kind) {
case 'recentActivity':
return new RecentActivityRule(config as RecentActivityRuleJSONConfig);
cfg = config as RecentActivityRuleJSONConfig;
return new RecentActivityRule({...cfg, logger});
case 'repeatActivity':
return new RepeatActivityRule(config as RepeatActivityJSONConfig);
cfg = config as RepeatActivityJSONConfig;
return new RepeatActivityRule({...cfg, logger});
case 'author':
return new AuthorRule(config as AuthorRuleJSONConfig);
cfg = config as AuthorRuleJSONConfig;
return new AuthorRule({...cfg, logger});
case 'attribution':
return new AttributionRule(config as AttributionJSONConfig);
cfg = config as AttributionJSONConfig;
return new AttributionRule({...cfg, logger});
default:
throw new Error('rule "kind" was not recognized.');
}

View File

@@ -1,7 +1,7 @@
import {IRule, Triggerable, Rule, RuleJSONConfig, RuleResult} from "./index";
import {Comment, Submission} from "snoowrap";
import {ruleFactory} from "./RuleFactory";
import {createLabelledLogger, loggerMetaShuffle} from "../util";
import {mergeArr} from "../util";
import {Logger} from "winston";
import {JoinCondition, JoinOperands} from "../Common/interfaces";
import * as RuleSchema from '../Schema/Rule.json';
@@ -17,11 +17,7 @@ export class RuleSet implements IRuleSet, Triggerable {
constructor(options: RuleSetOptions) {
const {logger, condition = 'AND', rules = []} = options;
if (logger !== undefined) {
this.logger = logger.child(loggerMetaShuffle(logger, 'Rule Set'));
} else {
this.logger = createLabelledLogger('Rule Set');
}
this.logger = logger.child({leaf: 'Rule Set'}, mergeArr);
this.condition = condition;
for (const r of rules) {
if (r instanceof Rule) {
@@ -29,9 +25,7 @@ export class RuleSet implements IRuleSet, Triggerable {
} else {
const valid = ajv.validate(RuleSchema, r);
if (valid) {
// @ts-ignore
r.logger = this.logger;
this.rules.push(ruleFactory(r as RuleJSONConfig));
this.rules.push(ruleFactory(r as RuleJSONConfig, logger));
} else {
this.logger.warn('Could not build rule because of JSON errors', {}, {errors: ajv.errors, obj: r});
}
@@ -77,7 +71,7 @@ export interface IRuleSet extends JoinCondition {
export interface RuleSetOptions extends IRuleSet {
rules: Array<IRule | RuleJSONConfig>,
logger?: Logger
logger: Logger
}
/**

View File

@@ -1,14 +1,13 @@
import {Comment, RedditUser} from "snoowrap";
import {Comment} from "snoowrap";
import Submission from "snoowrap/dist/objects/Submission";
import {Logger} from "winston";
import {createLabelledLogger, findResultByPremise, loggerMetaShuffle, mergeArr} from "../util";
import {findResultByPremise, mergeArr} from "../util";
import {testAuthorCriteria} from "../Utils/SnoowrapUtils";
export interface RuleOptions {
name?: string;
authors?: AuthorOptions;
logger?: Logger
loggerPrefix?: string
logger: Logger
}
export interface RulePremise {
@@ -39,7 +38,6 @@ export abstract class Rule implements IRule, Triggerable {
constructor(options: RuleOptions) {
const {
name = this.getKind(),
loggerPrefix = '',
logger,
authors: {
include = [],
@@ -54,20 +52,13 @@ export abstract class Rule implements IRule, Triggerable {
}
const ruleUniqueName = this.name === undefined ? this.getKind() : `${this.getKind()} - ${this.name}`;
if (logger === undefined) {
const prefix = `${loggerPrefix}|${ruleUniqueName}`;
this.logger = createLabelledLogger(prefix, prefix);
} else {
this.logger = logger.child(loggerMetaShuffle(logger, undefined, [ruleUniqueName], {truncateLength: 100}));
}
this.logger = logger.child({labels: ['Rule',`${ruleUniqueName}`]}, mergeArr);
}
async run(item: Comment | Submission, existingResults: RuleResult[] = []): Promise<[(boolean | null), RuleResult[]]> {
this.logger = this.logger.child(loggerMetaShuffle(this.logger, `${item instanceof Submission ? 'SUB' : 'COMM'} ${item.id}`), mergeArr);
this.logger.debug('Starting');
const existingResult = findResultByPremise(this.getPremise(), existingResults);
if (existingResult) {
this.logger.debug('Returning existing result');
this.logger.debug(`Returning existing result of ${existingResult.triggered ? '✔️' : '❌'}`);
return Promise.resolve([existingResult.triggered, [{...existingResult, name: this.name}]]);
}
if (this.authors.include !== undefined && this.authors.include.length > 0) {

View File

@@ -4,7 +4,6 @@ import {SubmissionCheck} from "../Check/SubmissionCheck";
import {CommentCheck} from "../Check/CommentCheck";
import {
determineNewResults,
loggerMetaShuffle,
mergeArr,
} from "../util";
import {CommentStream, SubmissionStream} from "snoostorm";
@@ -32,8 +31,23 @@ export class Manager {
lastHeartbeat = dayjs();
apiLimitWarning: number;
displayLabel: string;
currentLabels?: string[];
getCurrentLabels = () => {
return this.currentLabels;
}
constructor(sub: Subreddit, client: Snoowrap, logger: Logger, sourceData: object, opts: ManagerOptions = {}) {
this.logger = logger.child(loggerMetaShuffle(logger, undefined, [`r/${sub.display_name}`], {truncateLength: 40}), mergeArr);
const displayLabel = `r/${sub.display_name}`;
this.displayLabel = displayLabel;
this.currentLabels = [displayLabel];
const getLabels = this.getCurrentLabels;
// dynamic default meta for winston feasible using function getters
// https://github.com/winstonjs/winston/issues/1626#issuecomment-531142958
this.logger = logger.child({
get labels () { return getLabels() }
}, mergeArr);
const configBuilder = new ConfigBuilder({logger: this.logger});
const [subChecks, commentChecks, configManagerOptions] = configBuilder.buildFromJson(sourceData);
@@ -64,15 +78,15 @@ export class Manager {
const itemId = await item.id;
let allRuleResults: RuleResult[] = [];
const itemIdentifier = `${checkType} ${itemId}`;
this.currentLabels = [this.displayLabel, itemIdentifier];
const [peek, _] = await itemContentPeek(item);
this.logger.info(`New Event: ${itemIdentifier} => ${peek}`);
this.logger.info(`<EVENT> ${peek}`);
for (const check of checks) {
if(checkNames.length > 0 && !checkNames.map(x => x.toLowerCase()).some(x => x === check.name.toLowerCase())) {
this.logger.debug(`Check ${check} not in array of requested checks to run, skipping`);
continue;
}
this.logger.debug(`[${itemIdentifier}] Running Check ${check.name}`);
let triggered = false;
let currentResults: RuleResult[] = [];
try {
@@ -80,22 +94,12 @@ export class Manager {
currentResults = checkResults;
allRuleResults = allRuleResults.concat(determineNewResults(allRuleResults, checkResults));
triggered = checkTriggered;
const invokedRules = checkResults.map(x => x.name || x.premise.kind).join(' | ');
if (checkTriggered) {
this.logger.info(`[${itemIdentifier}] [CHK ${check.name}] Triggered with invoked Rules: ${invokedRules}`);
} else {
this.logger.debug(`[${itemIdentifier}] [CHK ${check.name}] WAS NOT triggered with invoked Rule(s): ${invokedRules}`);
}
} catch (e) {
this.logger.warn(`[${itemIdentifier}] [CHK ${check.name}] Failed with error: ${e.message}`, e);
this.logger.warn(`[Check ${check.name}] Failed with error: ${e.message}`, e);
}
if (triggered) {
this.logger.debug(`[${itemIdentifier}] [CHK ${check.name}] Running actions`);
// TODO give actions a name
await check.runActions(item, currentResults);
this.logger.info(`[${itemIdentifier}] [CHK ${check.name}] Ran actions`);
break;
}
}
@@ -129,8 +133,6 @@ export class Manager {
this.streamSub.once('listing', async (listing) => {
this.subListedOnce = true;
// for debugging
// await this.runChecks('Submission', listing[0]);
});
this.streamSub.on('item', async (item) => {
if (!this.subListedOnce) {
@@ -164,11 +166,16 @@ export class Manager {
}
if (this.streamSub !== undefined) {
this.logger.info('Bot Running');
await pEvent(this.streamSub, 'end');
} else if (this.streamComments !== undefined) {
this.logger.info('Bot Running');
await pEvent(this.streamComments, 'end');
} else {
this.logger.warn('No submission or comment checks to run!');
this.logger.warn('No submission or comment checks to run! Bot will not run.');
return;
}
this.logger.info('Bot Stopped');
}
}

View File

@@ -19,15 +19,6 @@ const CWD = process.cwd();
export const truncateStringToLength = (length: number, truncStr = '...') => (str: string) => str.length > length ? `${str.slice(0, length - truncStr.length - 1)}${truncStr}` : str;
export const loggerMetaShuffle = (logger: Logger, newLeaf: (string | undefined | null) = null, extraLabels: string[] = [], {truncateLength = 50} = {}) => {
const labelTrunc = truncateStringToLength(truncateLength);
const {labels = [], leaf} = logger.defaultMeta || {};
return {
labels: labels.concat(extraLabels.map(x => labelTrunc(x))),
leaf: newLeaf
};
}
let longestLabel = 3;
// @ts-ignore
export const defaultFormat = printf(({
@@ -62,7 +53,7 @@ export const defaultFormat = printf(({
let labelContent = `[${label.padEnd(longestLabel)}]`;
if (labels.length > 0 || (leaf !== null && leaf !== undefined)) {
let nodes = labels;
if (leaf !== null) {
if (leaf !== null && leaf !== undefined) {
nodes.push(leaf);
}
//labelContent = `${labels.slice(0, labels.length).map((x: string) => `[${x}]`).join(' ')}`
@@ -89,19 +80,6 @@ export const labelledFormat = (labelName = 'App') => {
);
}
export const createLabelledLogger = (name = 'default', label = 'App') => {
if (winston.loggers.has(name)) {
return winston.loggers.get(name);
}
const def = winston.loggers.get('default');
winston.loggers.add(name, {
transports: def.transports,
level: def.level,
format: labelledFormat(label)
});
return winston.loggers.get(name);
}
export interface groupByOptions {
lowercase?: boolean
}
@@ -212,6 +190,10 @@ export const mergeArr = (objValue: [], srcValue: []): (any[] | undefined) => {
}
}
export const ruleNamesFromResults = (results: RuleResult[]) => {
return results.map(x => x.name || x.premise.kind).join(' | ')
}