Skip to content

Commit

Permalink
feat(extension-logging): add http access and method invocation logging
Browse files Browse the repository at this point in the history
- add architecture diagram and examples to README
- improve naming and exporting
- configure the http access logger for REST routes only
  • Loading branch information
raymondfeng committed Feb 5, 2020
1 parent 7a42d02 commit a1e97ee
Show file tree
Hide file tree
Showing 21 changed files with 736 additions and 671 deletions.
2 changes: 2 additions & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ packages/testlab/* @bajtos
packages/tsdocs/* @raymondfeng

extensions/health/* @raymondfeng
extensions/logging/* @raymondfeng
extensions/metrics/* @raymondfeng

examples/todo/* @bajtos @hacksparrow
examples/context/* @raymondfeng
Expand Down
56 changes: 27 additions & 29 deletions acceptance/extension-logging-fluentd/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ describe('LoggingComponent', () => {
async function givenAppWithCustomConfig() {
app = givenApplication();
app.configure(LoggingBindings.FLUENT_SENDER).to({
host: process.env.FLUENTD_SERVICE_HOST || '127.0.0.1',
port: +(process.env.FLUENTD_SERVICE_PORT_TCP || 0) || 24224,
host: process.env.FLUENTD_SERVICE_HOST ?? '127.0.0.1',
port: +(process.env.FLUENTD_SERVICE_PORT_TCP ?? 24224),
timeout: 3.0,
reconnectInterval: 600000, // 10 minutes
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {GenericContainer, StartedTestContainer} from 'testcontainers';
export const ROOT_DIR = path.join(__dirname, '../../../fixtures');
export const ETC_DIR = path.join(ROOT_DIR, 'etc');

/* eslint-disable require-atomic-updates */
async function startFluentd() {
if (process.env.FLUENTD_SERVICE_HOST != null) return;
const container = await new GenericContainer(
Expand Down
4 changes: 3 additions & 1 deletion docs/site/MONOREPO.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ The [loopback-next](https://github.com/strongloop/loopback-next) repository uses
| [example-soap-calculator](https://github.com/strongloop/loopback-next/tree/master/examples/soap-calculator) | @loopback/example-soap-calculator | A tutorial demonstrating integration with a SOAP webservice |
| [example-todo-list](https://github.com/strongloop/loopback-next/tree/master/examples/todo-list) | @loopback/example-todo-list | Continuation of the todo example using relations in LoopBack 4 |
| [example-todo](https://github.com/strongloop/loopback-next/tree/master/examples/todo) | @loopback/example-todo | A basic tutorial for getting started with Loopback 4 |
| [extension-health](https://github.com/strongloop/loopback-next/tree/master/extensions/health) | @loopback/extension-health | Expose health check related endpoints |
| [extension-logging](https://github.com/strongloop/loopback-next/tree/master/extensions/logging) | @loopback/extension-logging | Add Winston Logger and Fluentd integration |
| [extension-metrics](https://github.com/strongloop/loopback-next/tree/master/extensions/metrics) | @loopback/extension-metrics | Report metrics to Prometheus |
| [http-caching-proxy](https://github.com/strongloop/loopback-next/tree/master/packages/http-caching-proxy) | @loopback/http-caching-proxy | A caching HTTP proxy for integration tests. NOT SUITABLE FOR PRODUCTION USE! |
| [http-server](https://github.com/strongloop/loopback-next/tree/master/packages/http-server) | @loopback/http-server | A wrapper for creating HTTP/HTTPS servers |
| [metadata](https://github.com/strongloop/loopback-next/tree/master/packages/metadata) | @loopback/metadata | Utilities to help developers implement TypeScript decorators, define/merge metadata, and inspect metadata |
Expand All @@ -44,7 +47,6 @@ The [loopback-next](https://github.com/strongloop/loopback-next) repository uses
| [service-proxy](https://github.com/strongloop/loopback-next/tree/master/packages/service-proxy) | @loopback/service-proxy | A common set of interfaces for interacting with service oriented backends such as REST APIs, SOAP Web Services, and gRPC microservices |
| [testlab](https://github.com/strongloop/loopback-next/tree/master/packages/testlab) | @loopback/testlab | A collection of test utilities we use to write LoopBack tests |
| [tsdocs](https://github.com/strongloop/loopback-next/tree/master/packages/tsdocs) | @loopback/tsdocs | An internal package to generate api docs using Microsoft api-extractor and api-documenter |
| [extensions/health](https://github.com/strongloop/loopback-next/tree/master/extensions/health) | @loopback/extension-health | Expose health check related endpoints |

We use npm scripts declared in
[package.json](https://github.com/strongloop/loopback-next/blob/master/package.json)
Expand Down
105 changes: 95 additions & 10 deletions extensions/logging/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ This module contains a component provides logging facilities based on
> using `0.x.y` versions. Their APIs and functionality may be subject to
> breaking changes in future releases.
## Architecture overview

![logging-component](logging-component.png)

## Installation

```sh
Expand All @@ -34,21 +38,71 @@ In the constructor, add the component to your application:
this.component(LoggingComponent);
```

The component contributes bindings with keys listed below:
Now your application can add a controller as follows to leverage the logging
facilities:

```ts
import {inject} from '@loopback/context';
import {Logger, logInvocation} from '@loopback/extension-logging';
import {get, param} from '@loopback/rest';

class MyController {
// Inject a winston logger
@inject(LoggingBindings.WINSTON_LOGGER)
private logger: Logger;

// http access is logged by a global interceptor
@get('/greet/{name}')
// log the `greet` method invocations
@logInvocation()
greet(@param.path.string('name') name: string) {
return `Hello, ${name}`;
}

@get('/hello/{name}')
hello(@param.path.string('name') name: string) {
// Use the winston logger explicitly
this.logger.log('info', `greeting ${name}`);
return `Hello, ${name}`;
}
}
```

## Configure the logging component

The logging component can be configured as follows:

```ts
app.configure(LoggingBindings.COMPONENT).to({
enableFluent: false, // default to true
enableHttpAccessLog: true, // default to true
});
```

- `enableFluent`: Enable logs to be sent to Fluentd
- `enableHttpAccessLog`: Enable all http requests to be logged via a global
interceptor

The component contributes bindings with keys declared under `LoggingBindings`
namespace as follows:

- LoggingBindings.FLUENT_SENDER - A fluent sender
- LoggingBindings.WINSTON_LOGGER - A winston logger
- LoggingBindings.WINSTON_TRANSPORT_FLUENT - A fluent transport for winston
- FLUENT_SENDER - A fluent sender
- WINSTON_LOGGER - A winston logger
- WINSTON_TRANSPORT_FLUENT - A fluent transport for winston
- WINSTON_INTERCEPTOR - A local interceptor set by `@logInvocation` to log
method invocations
- WINSTON_HTTP_ACCESS_LOGGER - A global interceptor that logs http access with
[Morgan](https://github.com/expressjs/morgan) format

The fluent sender and transport for winston can be configured against
`LoggingBindings.FLUENT_SENDER`:
`FLUENT_SENDER`:

```ts
import {LoggingBindings} from '@loopback/extension-logging';

app.configure(LoggingBindings.FLUENT_SENDER).to({
host: process.env.FLUENTD_SERVICE_HOST || 'localhost',
port: +(process.env.FLUENTD_SERVICE_PORT_TCP || 0) || 24224,
host: process.env.FLUENTD_SERVICE_HOST ?? 'localhost',
port: +(process.env.FLUENTD_SERVICE_PORT_TCP ?? 24224),
timeout: 3.0,
reconnectInterval: 600000, // 10 minutes
});
Expand All @@ -75,9 +129,17 @@ points:
```ts
import {extensionFor} from '@loopback/core';
import {format} from 'winston';
import {WINSTON_FORMAT, WINSTON_TRANSPORT} from '@loopback/extension-logging';

const myFormat: Format = ...;
import {
WINSTON_FORMAT,
WINSTON_TRANSPORT,
WinstonFormat,
WinstonTransports,
} from '@loopback/extension-logging';

const myFormat: WinstonFormat = format((info, opts) => {
console.log(info);
return false;
})();

ctx
.bind('logging.winston.formats.myFormat')
Expand All @@ -87,6 +149,29 @@ ctx
.bind('logging.winston.formats.colorize')
.to(format.colorize())
.apply(extensionFor(WINSTON_FORMAT));

const consoleTransport = new WinstonTransports.Console({
level: 'info',
format: format.combine(format.colorize(), format.simple()),
});
ctx
.bind('logging.winston.transports.console')
.to(consoleTransport)
.apply(extensionFor(WINSTON_TRANSPORT));
```

If no transport is contributed, the winston logger uses the
[console transport](https://github.com/winstonjs/winston/blob/master/docs/transports.md#console-transport).

No default format is configured for the winston logger.

The access log interceptor can also be configured to customize
[Morgan format and options](https://github.com/expressjs/morgan#morganformat-options):

```ts
ctx
.configure(LoggingBindings.WINSTON_HTTP_ACCESS_LOGGER)
.to({format: 'combined'});
```

## Contributions
Expand Down
Binary file added extensions/logging/logging-component.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit a1e97ee

Please sign in to comment.