feat(core): implement winston support

This commit is contained in:
2018-01-27 19:16:05 +01:00
parent 9e85f22891
commit fd1d92edd6
17 changed files with 273 additions and 99 deletions

View File

@@ -1,46 +1,50 @@
export type Environment = 'local' | 'test' | 'staging' | 'production' ;
export type Environment = "local" | "test" | "staging" | "production";
// interfaces
import { Client as ElasticClient } from 'elasticsearch'
import { Client as ElasticClient } from "elasticsearch";
import { IWinstonStandardLogParams } from "./elasticlog.classes.winstontransport";
// other classes
import { LogScheduler } from "./elasticlog.classes.logscheduler";
export interface LogContext {
zone?: string,
containerName?: string
environment: Environment
zone?: string;
containerName?: string;
environment: Environment;
}
export type TLogSeverity = 'log' | 'info' | 'warn' | 'error' | 'fatal'
export type TLogSeverity = "log" | "info" | "warn" | "error" | "fatal";
export interface IStandardLogParams {
message: string
severity: string
message: string;
severity: string;
}
export interface IElasticLogConstructorOptions {
port: number
domain: string
ssl: boolean
user?: string
pass?: string
logContext: LogContext
port: number;
domain: string;
ssl: boolean;
user?: string;
pass?: string;
logContext: LogContext;
}
export class ElasticLog<T> {
client: ElasticClient
logContext: LogContext
logScheduler = new LogScheduler()
client: ElasticClient;
logContext: LogContext;
logScheduler = new LogScheduler(this);
/**
* sets up an instance of Elastic log
* @param optionsArg
*/
constructor (optionsArg: IElasticLogConstructorOptions) {
this.logContext = optionsArg.logContext
constructor(optionsArg: IElasticLogConstructorOptions) {
this.logContext = optionsArg.logContext;
this.client = new ElasticClient({
host: this.computeHostString(optionsArg),
log: 'trace'
log: "trace"
});
};
}
/**
* computes the host string from the constructor options
@@ -48,42 +52,46 @@ export class ElasticLog<T> {
*/
private computeHostString(optionsArg: IElasticLogConstructorOptions): string {
let hostString = `${optionsArg.domain}:${optionsArg.port}`;
if(optionsArg.user && optionsArg.pass) {
hostString = `${optionsArg.user}:${optionsArg.pass}@${hostString}`
if (optionsArg.user && optionsArg.pass) {
hostString = `${optionsArg.user}:${optionsArg.pass}@${hostString}`;
}
if(optionsArg.ssl) {
hostString = `https://${hostString}`
if (optionsArg.ssl) {
hostString = `https://${hostString}`;
} else {
hostString = `http://${hostString}`
hostString = `http://${hostString}`;
}
return hostString;
}
log(logObject: IStandardLogParams) {
const now = new Date()
this.client.index({
index: `logs-${now.getFullYear()}.${("0" + (now.getMonth() + 1)).slice(-2)}.${now.getDate()}`,
type: 'log',
body: {
'@timestamp': now.toISOString(),
container: this.logContext.containerName,
environment: this.logContext.environment,
severity: logObject.severity,
message: logObject.message
async log(logObject: IStandardLogParams, scheduleOverwrite = false) {
const now = new Date();
if (this.logScheduler.logsScheduled && !scheduleOverwrite) {
this.logScheduler.scheduleLog(logObject);
return;
}
this.client.index(
{
index: `logs-${now.getFullYear()}.${("0" + (now.getMonth() + 1)).slice(
-2
)}.${now.getDate()}`,
type: "log",
body: {
"@timestamp": now.toISOString(),
container: this.logContext.containerName,
environment: this.logContext.environment,
severity: logObject.severity,
message: logObject.message
}
},
(error, response) => {
if (error) {
console.log("ElasticLog encountered an error:");
console.log(error);
this.logScheduler.addFailedLog(logObject);
} else {
console.log(`ElasticLog: ${logObject.message}`);
}
}
}, (error, response) => {
if(error) {
console.log(error)
this.logScheduler.addFailedLog(logObject)
}
})
);
}
};
export class LogScheduler {
logStorage: any[]
addFailedLog(objectArg: any | IStandardLogParams) {
}
}
}

View File

@@ -0,0 +1,47 @@
import {
ElasticLog,
IStandardLogParams
} from "./elasticlog.classes.elasticlog";
export class LogScheduler {
elasticLogRef: ElasticLog<any>;
logsScheduled = false;
logStorage: any[] = [];
constructor(elasticLogRefArg: ElasticLog<any>) {
this.elasticLogRef = elasticLogRefArg;
}
addFailedLog(objectArg: any | IStandardLogParams) {
this.logStorage.push(objectArg);
this.setRetry();
}
scheduleLog(logObject: any) {
this.logStorage.push(logObject);
}
setRetry() {
setTimeout(() => {
const oldStorage = this.logStorage;
this.logStorage = [];
for (let logObject of oldStorage) {
this.elasticLogRef.log(logObject, true);
}
if (this.logStorage.length === 0) {
console.log("ElasticLog retry success!!!");
this.logsScheduled = false;
} else {
console.log("ElasticLog retry failed");
this.setRetry();
}
}, 5000);
}
deferSend() {
if (!this.logsScheduled) {
console.log("Retry ElasticLog in 5 seconds!");
this.logsScheduled = true;
this.setRetry();
}
}
}

View File

@@ -0,0 +1,27 @@
import { Transport } from "winston-transport";
import {
ElasticLog,
IElasticLogConstructorOptions
} from "./elasticlog.classes.elasticlog";
export interface IWinstonStandardLogParams {
message: string;
level: string;
}
export class ElasticWinstonTransport extends Transport {
client: ElasticLog<any>;
constructor(optsArg: IElasticLogConstructorOptions) {
super(optsArg);
this.client = new ElasticLog(optsArg);
}
log(info, callback) {
this.client.log({
severity: info.level,
message: info.message,
});
callback();
}
}

View File

@@ -1,6 +1,3 @@
import * as elasticsearch from 'elasticsearch';
import * as smartdelay from 'smartdelay';
export {
elasticsearch,
smartdelay
}
import * as elasticsearch from "elasticsearch";
import * as smartdelay from "smartdelay";
export { elasticsearch, smartdelay };

View File

@@ -1 +1 @@
export * from './elasticlog.classes.elasticlog'
export * from "./elasticlog.classes.elasticlog";