Skip to content

Commit

Permalink
feat(logger): add Kibana log transporter
Browse files Browse the repository at this point in the history
Also adds some docs for the Prometheus metrics.
  • Loading branch information
mKeRix committed Jan 17, 2021
1 parent fef1a2c commit 076df21
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 15 deletions.
1 change: 1 addition & 0 deletions docs/.vuepress/config.js
Expand Up @@ -58,6 +58,7 @@ module.exports = {
'/guide/configuration',
'/guide/cluster',
'/guide/entities',
'/guide/monitoring',
'/guide/cli',
'/guide/api'
]
Expand Down
49 changes: 49 additions & 0 deletions docs/guide/monitoring.md
@@ -0,0 +1,49 @@
# Monitoring

Since room-assistant is a distributed system it quickly gets difficult to keep track of everything. To help we provide some tools for power users that wish to keep track of all their instance states without having to go to each one manually.

## Metrics

room-assistant provides metrics in the Prometheus format on port `6415`, path `/metrics`. This includes some default metrics about the general state of the application, as well as integration-specific metrics that you can explore. You can setup your Prometheus instance to scrape these endpoints like this:

```yaml
scrape_configs:
- job_name: 'room-assistant'
metrics_path: '/metrics'
scrape_interval: 30s
static_configs:
- targets:
- '<room-assistant-ip1>:6415'
- '<room-assistant-ip2>:6415'
```

## Logging

**Config Key:** `logger`

If you want to capture the logs of all your instances in a single place you can configure additional log outputs, which will be used alongside the console output you are used to.

### Elasticsearch/Kibana

**Config Key:** `elasticsearch`

room-assistant is capable of piping log output into an Elasticsearch cluster with the logstash format, which makes it searchable from Kibana.

| Name | Type | Default | Description |
| ------------- | ------- | --------------------- | ------------------------------------------------------------ |
| `enabled` | Boolean | `false` | Whether room-assistant should send logs to Elasticsearch or not. |
| `node` | String | http://localhost:9200 | The endpoint under which your Elasticsearch cluster is accessible. |
| `auth` | Object | | Object containing either `username` + `password` or `apiKey` that should be used for authenticating against your Elasticsearch cluster (matches `auth` in the [official client docs](https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/client-configuration.html)). |
| `indexPrefix` | String | `room-assistant` | The prefix of the indices that will be created. The indices follow the naming format `<indexPrefix>-<date>`. |

::: details Example Config

```yaml
logger:
elasticsearch:
enabled: true
node: http://192.168.0.20:9200
```

:::

2 changes: 2 additions & 0 deletions src/config/definitions/default.ts
Expand Up @@ -9,9 +9,11 @@ import { GpioConfig } from '../../integrations/gpio/gpio.config';
import { ShellConfig } from '../../integrations/shell/shell.config';
import { XiaomiMiConfig } from '../../integrations/xiaomi-mi/xiaomi-mi.config';
import { EntitiesConfig } from '../../entities/entities.config';
import { LoggerConfig } from '../logger.config';

export class AppConfig {
global: GlobalConfig = new GlobalConfig();
logger: LoggerConfig = new LoggerConfig();
cluster: ClusterConfig = new ClusterConfig();
entities: EntitiesConfig = new EntitiesConfig();
bluetoothLowEnergy: BluetoothLowEnergyConfig = new BluetoothLowEnergyConfig();
Expand Down
12 changes: 12 additions & 0 deletions src/config/logger.config.ts
@@ -0,0 +1,12 @@
import { ApiKeyAuth, BasicAuth } from '@elastic/elasticsearch/lib/pool';

export class LoggerConfig {
elasticsearch = new ElasticsearchConfig();
}

class ElasticsearchConfig {
enabled = false;
node = 'http://localhost:9200';
auth?: BasicAuth | ApiKeyAuth;
indexPrefix = 'room-assistant';
}
54 changes: 39 additions & 15 deletions src/logger.ts
@@ -1,22 +1,46 @@
import { WinstonModule } from 'nest-winston';
import winston from 'winston';
import { TransformableInfo } from 'logform';
import c from 'config';
import { LoggerConfig } from './config/logger.config';
import { ElasticsearchTransport } from 'winston-elasticsearch';
import * as TransportStream from 'winston-transport';

const config = c.get<LoggerConfig>('logger');
const instanceName = c.get<string>('global.instanceName');

const transports: TransportStream[] = [
new winston.transports.Console({
format: winston.format.combine(
winston.format.timestamp(),
process.stdout.isTTY
? winston.format.colorize()
: winston.format.uncolorize(),
winston.format.printf((info: TransformableInfo) => {
return `${new Date(info.timestamp).toLocaleString()} - ${
info.level
} - ${info.context}: ${info.message}`;
})
),
}),
];

if (config.elasticsearch.enabled) {
transports.push(
new ElasticsearchTransport({
indexPrefix: config.elasticsearch.indexPrefix,
clientOpts: {
node: config.elasticsearch.node,
auth: config.elasticsearch.auth,
},
})
);
}

export const WINSTON_LOGGER = WinstonModule.createLogger({
level: process.env.NODE_LOG_LEVEL || 'info',
transports: [
new winston.transports.Console({
format: winston.format.combine(
winston.format.timestamp(),
process.stdout.isTTY
? winston.format.colorize()
: winston.format.uncolorize(),
winston.format.printf((info: TransformableInfo) => {
return `${new Date(info.timestamp).toLocaleString()} - ${
info.level
} - ${info.context}: ${info.message}`;
})
),
}),
],
defaultMeta: {
instanceName,
},
transports,
});

0 comments on commit 076df21

Please sign in to comment.