Repository: iamolegga/nestjs-pino (ts)

Issue:
[QUESTION] Why `PinoLogger` instance don't show the error object
When I use a `PinoLogger` instance to display some error object like `this.logger.error(Error('foo'))` I get this:
```json
{
  "level": 50,
  "time": 1590422389076,
  "pid": 27787,
  "hostname": "--",
  "name": "app",
  "req": {
    "id": 1,
    "method": "GET",
    "url": "--",
    "headers": {
      "host": "localhost:3000",
      "user-agent": "insomnia/7.1.1",
      "accept": "*/*"
    },
    "remoteAddress": "127.0.0.1",
    "remotePort": 52126
  },
  "context": "ExceptionsHandler"
}
```
seems like the arg isn't serialized by `pino.stdSerializers.err` because 
```js
this.logger.error( pino.stdSerializers.err(Error('foo')) )
```
works as expected (with `{ type, message, stack }`). This happen even when I explicity define the serializers. Is it the right behavior?

Great lib btw!

Pull request description:
add handling of direct error passing
fixes #304 

Patch:
diff --git a/src/PinoLogger.ts b/src/PinoLogger.ts
index d75911a..cea60f4 100644
--- a/src/PinoLogger.ts
+++ b/src/PinoLogger.ts
@@ -88,10 +88,17 @@ export class PinoLogger implements PinoMethods {
     if (context) {
       const firstArg = args[0];
       if (typeof firstArg === "object") {
-        args = [
-          Object.assign({ [this.contextName]: context }, firstArg),
-          ...args.slice(1)
-        ];
+        if (firstArg instanceof Error) {
+          args = [
+            Object.assign({ [this.contextName]: context }, { err: firstArg }),
+            ...args.slice(1)
+          ];
+        } else {
+          args = [
+            Object.assign({ [this.contextName]: context }, firstArg),
+            ...args.slice(1)
+          ];
+        }
       } else {
         args = [{ [this.contextName]: context }, ...args];
       }


Test patch:
diff --git a/__tests__/errors.spec.ts b/__tests__/errors.spec.ts
new file mode 100644
index 0000000..957f70a
--- /dev/null
+++ b/__tests__/errors.spec.ts
@@ -0,0 +1,69 @@
+import { NestFactory } from "@nestjs/core";
+import { Module, Controller, Get } from "@nestjs/common";
+import MemoryStream = require("memorystream");
+import * as request from "supertest";
+import { PinoLogger, InjectPinoLogger, LoggerModule } from "../src";
+import { platforms } from "./utils/platforms";
+import { fastifyExtraWait } from "./utils/fastifyExtraWait";
+import { parseLogs } from "./utils/logs";
+import { __resetOutOfContextForTests } from "../src/PinoLogger";
+
+describe("error logging", () => {
+  beforeEach(() => __resetOutOfContextForTests());
+
+  for (const PlatformAdapter of platforms) {
+    describe(PlatformAdapter.name, () => {
+      it("direct error passing", async () => {
+        const stream = new MemoryStream();
+        const context = Math.random().toString();
+        let logs = "";
+
+        stream.on("data", (chunk: string) => {
+          logs += chunk.toString();
+        });
+
+        @Controller("/")
+        class TestController {
+          constructor(
+            @InjectPinoLogger(context) private readonly logger: PinoLogger
+          ) {}
+          @Get()
+          get() {
+            this.logger.info(new Error('direct error passing'));
+            return {};
+          }
+        }
+
+        @Module({
+          imports: [LoggerModule.forRoot({ pinoHttp: stream })],
+          controllers: [TestController],
+        })
+        class TestModule {}
+
+        const app = await NestFactory.create(
+          TestModule,
+          new PlatformAdapter(),
+          { logger: false }
+        );
+        const server = app.getHttpServer();
+
+        await app.init();
+        await fastifyExtraWait(PlatformAdapter, app);
+
+        await request(server).get("/");
+
+        await app.close();
+
+        const parsedLogs = parseLogs(logs);
+
+        const errorLogObject = parsedLogs.find(
+          v =>
+            v.req &&
+            v.context === context &&
+            (v as any).err
+        );
+        expect(errorLogObject).toBeTruthy();
+      });
+    });
+  }
+});