Add GCP logging extender (#503)

* Add GCP logging extender

* Minor version bump for new API

* Update packages/logger/src/logger.ts

Co-Authored-By: kylecarbs <kyle@kwc.io>
This commit is contained in:
Kyle Carberry 2019-04-17 13:41:10 -05:00 committed by GitHub
parent e907dbe7e6
commit 8a4da542ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 104 additions and 3 deletions

View File

@ -5,9 +5,12 @@
"build": "tsc -p tsconfig.build.json && cp ./out/packages/logger/src/* ./out && rm -rf out/packages && ../../node_modules/.bin/webpack --config ./webpack.config.js", "build": "tsc -p tsconfig.build.json && cp ./out/packages/logger/src/* ./out && rm -rf out/packages && ../../node_modules/.bin/webpack --config ./webpack.config.js",
"postinstall": "if [ ! -d out ];then npm run build; fi" "postinstall": "if [ ! -d out ];then npm run build; fi"
}, },
"version": "1.0.3", "version": "1.1.0",
"main": "out/main.js", "main": "out/main.js",
"types": "out/index.d.ts", "types": "out/index.d.ts",
"author": "Coder", "author": "Coder",
"license": "MIT" "license": "MIT",
"dependencies": {
"@google-cloud/logging": "^4.5.2"
}
} }

View File

@ -0,0 +1,12 @@
import { field, logger } from "./logger";
import { createStackdriverExtender } from "./extender";
describe("Extender", () => {
it("should add stackdriver extender", () => {
logger.extend(createStackdriverExtender("coder-dev-1", "logging-package-tests"));
});
it("should log", async () => {
logger.debug("Bananas!", field("frog", { hi: "wow" }));
});
});

View File

@ -0,0 +1,63 @@
import * as gcl from "@google-cloud/logging";
import { Extender, logger, field } from "./logger";
export const createStackdriverExtender = (projectId: string, logId: string): Extender => {
enum GcpLogSeverity {
DEFAULT = 0,
DEBUG = 100,
INFO = 200,
NOTICE = 300,
WARNING = 400,
ERROR = 500,
CRITICAL = 600,
ALERT = 700,
EMERGENCY = 800,
}
const logging = new gcl.Logging({
autoRetry: true,
projectId,
});
const log = logging.log(logId);
const convertSeverity = (severity: "trace" | "info" | "warn" | "debug" | "error"): GcpLogSeverity => {
switch (severity) {
case "trace":
case "debug":
return GcpLogSeverity.DEBUG;
case "info":
return GcpLogSeverity.INFO;
case "error":
return GcpLogSeverity.ERROR;
case "warn":
return GcpLogSeverity.WARNING;
}
};
return (options): void => {
const severity = convertSeverity(options.type);
// tslint:disable-next-line:no-any
const metadata = {} as any;
if (options.fields) {
options.fields.forEach((f) => {
if (!f) {
return;
}
metadata[f.identifier] = f.value;
});
}
const entry = log.entry({
// tslint:disable-next-line:no-any
severity: severity as any,
}, {
...metadata,
message: options.message,
});
log.write(entry).catch((ex) => {
logger.named("GCP").error("Failed to log", field("error", ex));
});
};
};

View File

@ -59,6 +59,14 @@ export const field = <T>(name: string, value: T): Field<T> => {
return new Field(name, value); return new Field(name, value);
}; };
export type Extender = (msg: {
message: string,
level: Level,
type: "trace" | "info" | "warn" | "debug" | "error",
fields?: FieldArray,
section?: string,
}) => void;
/** /**
* This formats & builds text for logging. * This formats & builds text for logging.
* It should only be used to build one log item at a time since it stores the * It should only be used to build one log item at a time since it stores the
@ -221,6 +229,7 @@ export class Logger {
private _formatter: Formatter, private _formatter: Formatter,
private readonly name?: string, private readonly name?: string,
private readonly defaultFields?: FieldArray, private readonly defaultFields?: FieldArray,
private readonly extenders: Extender[] = [],
) { ) {
if (name) { if (name) {
this.nameColor = this.hashStringToColor(name); this.nameColor = this.hashStringToColor(name);
@ -248,6 +257,10 @@ export class Logger {
this.muted = true; this.muted = true;
} }
public extend(extender: Extender): void {
this.extenders.push(extender);
}
/** /**
* Outputs information. * Outputs information.
*/ */
@ -328,7 +341,7 @@ export class Logger {
* Each name is deterministically generated a color. * Each name is deterministically generated a color.
*/ */
public named(name: string, ...fields: FieldArray): Logger { public named(name: string, ...fields: FieldArray): Logger {
const l = new Logger(this._formatter, name, fields); const l = new Logger(this._formatter, name, fields, this.extenders);
if (this.muted) { if (this.muted) {
l.mute(); l.mute();
} }
@ -393,6 +406,16 @@ export class Logger {
console.log(...this._formatter.flush()); console.log(...this._formatter.flush());
} }
// tslint:enable no-console // tslint:enable no-console
this.extenders.forEach((extender) => {
extender({
section: this.name,
fields: options.fields,
level: options.level,
message: options.message as string,
type: options.type,
});
});
} }
/** /**