Unify Kibana & Elasticsearch logging config keys (#90764)
* align logging config with ES. rename kind to type. * rename file "path" to "fileName" * rename logger "context" to "name" * update audit log docs and tests * update docs * fix integration tests * update deprecations for audit appender * add tests for audit logging deprecations * fix eslint problem Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
db6cd8665c
commit
312351c52c
|
@ -34,7 +34,7 @@ Customize the configuration for the plugins.data.search context.
|
||||||
core.logging.configure(
|
core.logging.configure(
|
||||||
of({
|
of({
|
||||||
appenders: new Map(),
|
appenders: new Map(),
|
||||||
loggers: [{ context: 'search', appenders: ['default'] }]
|
loggers: [{ name: 'search', appenders: ['default'] }]
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -356,26 +356,26 @@ To enable the <<xpack-security-ecs-audit-logging, ECS audit logger>>, specify wh
|
||||||
[source,yaml]
|
[source,yaml]
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
xpack.security.audit.appender:
|
xpack.security.audit.appender:
|
||||||
kind: rolling-file
|
type: rolling-file
|
||||||
path: ./audit.log
|
fileName: ./audit.log
|
||||||
policy:
|
policy:
|
||||||
kind: time-interval
|
type: time-interval
|
||||||
interval: 24h <1>
|
interval: 24h <1>
|
||||||
strategy:
|
strategy:
|
||||||
kind: numeric
|
type: numeric
|
||||||
max: 10 <2>
|
max: 10 <2>
|
||||||
layout:
|
layout:
|
||||||
kind: json
|
type: json
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
<1> Rotates log files every 24 hours.
|
<1> Rotates log files every 24 hours.
|
||||||
<2> Keeps maximum of 10 log files before deleting older ones.
|
<2> Keeps maximum of 10 log files before deleting older ones.
|
||||||
|
|
||||||
| `xpack.security.audit.appender.kind`
|
| `xpack.security.audit.appender.type`
|
||||||
| Required. Specifies where audit logs should be written to. Allowed values are `console`, `file`, or `rolling-file`.
|
| Required. Specifies where audit logs should be written to. Allowed values are `console`, `file`, or `rolling-file`.
|
||||||
|
|
||||||
Refer to <<audit-logging-file-appender>> and <<audit-logging-rolling-file-appender>> for appender specific settings.
|
Refer to <<audit-logging-file-appender>> and <<audit-logging-rolling-file-appender>> for appender specific settings.
|
||||||
|
|
||||||
| `xpack.security.audit.appender.layout.kind`
|
| `xpack.security.audit.appender.layout.type`
|
||||||
| Required. Specifies how audit logs should be formatted. Allowed values are `json` or `pattern`.
|
| Required. Specifies how audit logs should be formatted. Allowed values are `json` or `pattern`.
|
||||||
|
|
||||||
Refer to <<audit-logging-pattern-layout>> for layout specific settings.
|
Refer to <<audit-logging-pattern-layout>> for layout specific settings.
|
||||||
|
@ -396,7 +396,7 @@ The `file` appender writes to a file and can be configured using the following s
|
||||||
|
|
||||||
[cols="2*<"]
|
[cols="2*<"]
|
||||||
|======
|
|======
|
||||||
| `xpack.security.audit.appender.path`
|
| `xpack.security.audit.appender.fileName`
|
||||||
| Required. Full file path the log file should be written to.
|
| Required. Full file path the log file should be written to.
|
||||||
|======
|
|======
|
||||||
|
|
||||||
|
@ -408,14 +408,14 @@ The `rolling-file` appender writes to a file and rotates it using a rolling stra
|
||||||
|
|
||||||
[cols="2*<"]
|
[cols="2*<"]
|
||||||
|======
|
|======
|
||||||
| `xpack.security.audit.appender.path`
|
| `xpack.security.audit.appender.fileName`
|
||||||
| Required. Full file path the log file should be written to.
|
| Required. Full file path the log file should be written to.
|
||||||
|
|
||||||
| `xpack.security.audit.appender.policy.kind`
|
| `xpack.security.audit.appender.policy.type`
|
||||||
| Specifies when a rollover should occur. Allowed values are `size-limit` and `time-interval`. *Default:* `time-interval`.
|
| Specifies when a rollover should occur. Allowed values are `size-limit` and `time-interval`. *Default:* `time-interval`.
|
||||||
|
|
||||||
Refer to <<audit-logging-size-limit-policy>> and <<audit-logging-time-interval-policy>> for policy specific settings.
|
Refer to <<audit-logging-size-limit-policy>> and <<audit-logging-time-interval-policy>> for policy specific settings.
|
||||||
| `xpack.security.audit.appender.strategy.kind`
|
| `xpack.security.audit.appender.strategy.type`
|
||||||
| Specifies how the rollover should occur. Only allowed value is currently `numeric`. *Default:* `numeric`
|
| Specifies how the rollover should occur. Only allowed value is currently `numeric`. *Default:* `numeric`
|
||||||
|
|
||||||
Refer to <<audit-logging-numeric-strategy>> for strategy specific settings.
|
Refer to <<audit-logging-numeric-strategy>> for strategy specific settings.
|
||||||
|
|
|
@ -68,10 +68,10 @@ exports[`#get correctly handles silent logging config. 1`] = `
|
||||||
Object {
|
Object {
|
||||||
"appenders": Object {
|
"appenders": Object {
|
||||||
"default": Object {
|
"default": Object {
|
||||||
"kind": "legacy-appender",
|
|
||||||
"legacyLoggingConfig": Object {
|
"legacyLoggingConfig": Object {
|
||||||
"silent": true,
|
"silent": true,
|
||||||
},
|
},
|
||||||
|
"type": "legacy-appender",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"loggers": undefined,
|
"loggers": undefined,
|
||||||
|
@ -85,12 +85,12 @@ exports[`#get correctly handles verbose file logging config with json format. 1`
|
||||||
Object {
|
Object {
|
||||||
"appenders": Object {
|
"appenders": Object {
|
||||||
"default": Object {
|
"default": Object {
|
||||||
"kind": "legacy-appender",
|
|
||||||
"legacyLoggingConfig": Object {
|
"legacyLoggingConfig": Object {
|
||||||
"dest": "/some/path.log",
|
"dest": "/some/path.log",
|
||||||
"json": true,
|
"json": true,
|
||||||
"verbose": true,
|
"verbose": true,
|
||||||
},
|
},
|
||||||
|
"type": "legacy-appender",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"loggers": undefined,
|
"loggers": undefined,
|
||||||
|
|
|
@ -44,7 +44,7 @@ export class LegacyObjectToConfigAdapter extends ObjectToConfigAdapter {
|
||||||
const loggingConfig = {
|
const loggingConfig = {
|
||||||
appenders: {
|
appenders: {
|
||||||
...appenders,
|
...appenders,
|
||||||
default: { kind: 'legacy-appender', legacyLoggingConfig },
|
default: { type: 'legacy-appender', legacyLoggingConfig },
|
||||||
},
|
},
|
||||||
root: { level: 'info', ...root },
|
root: { level: 'info', ...root },
|
||||||
loggers,
|
loggers,
|
||||||
|
|
|
@ -226,7 +226,7 @@ export class CoreUsageDataService implements CoreService<CoreUsageDataSetup, Cor
|
||||||
logging: {
|
logging: {
|
||||||
appendersTypesUsed: Array.from(
|
appendersTypesUsed: Array.from(
|
||||||
Array.from(this.loggingConfig?.appenders.values() ?? [])
|
Array.from(this.loggingConfig?.appenders.values() ?? [])
|
||||||
.reduce((acc, a) => acc.add(a.kind), new Set<string>())
|
.reduce((acc, a) => acc.add(a.type), new Set<string>())
|
||||||
.values()
|
.values()
|
||||||
),
|
),
|
||||||
loggersConfiguredCount: this.loggingConfig?.loggers.length ?? 0,
|
loggersConfiguredCount: this.loggingConfig?.loggers.length ?? 0,
|
||||||
|
|
|
@ -50,16 +50,16 @@ describe('request logging', () => {
|
||||||
silent: true,
|
silent: true,
|
||||||
appenders: {
|
appenders: {
|
||||||
'test-console': {
|
'test-console': {
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: {
|
layout: {
|
||||||
kind: 'pattern',
|
type: 'pattern',
|
||||||
pattern: '%level|%logger|%message|%meta',
|
pattern: '%level|%logger|%message|%meta',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
loggers: [
|
loggers: [
|
||||||
{
|
{
|
||||||
context: 'http.server.response',
|
name: 'http.server.response',
|
||||||
appenders: ['test-console'],
|
appenders: ['test-console'],
|
||||||
level: 'debug',
|
level: 'debug',
|
||||||
},
|
},
|
||||||
|
@ -96,16 +96,16 @@ describe('request logging', () => {
|
||||||
silent: true,
|
silent: true,
|
||||||
appenders: {
|
appenders: {
|
||||||
'test-console': {
|
'test-console': {
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: {
|
layout: {
|
||||||
kind: 'pattern',
|
type: 'pattern',
|
||||||
pattern: '%level|%logger|%message|%meta',
|
pattern: '%level|%logger|%message|%meta',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
loggers: [
|
loggers: [
|
||||||
{
|
{
|
||||||
context: 'http.server.response',
|
name: 'http.server.response',
|
||||||
appenders: ['test-console'],
|
appenders: ['test-console'],
|
||||||
level: 'debug',
|
level: 'debug',
|
||||||
},
|
},
|
||||||
|
|
|
@ -29,16 +29,16 @@ function createRoot(legacyLoggingConfig: LegacyLoggingConfig = {}) {
|
||||||
// platform config
|
// platform config
|
||||||
appenders: {
|
appenders: {
|
||||||
'test-console': {
|
'test-console': {
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: {
|
layout: {
|
||||||
highlight: false,
|
highlight: false,
|
||||||
kind: 'pattern',
|
type: 'pattern',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
loggers: [
|
loggers: [
|
||||||
{
|
{
|
||||||
context: 'test-file',
|
name: 'test-file',
|
||||||
appenders: ['test-console'],
|
appenders: ['test-console'],
|
||||||
level: 'info',
|
level: 'info',
|
||||||
},
|
},
|
||||||
|
|
|
@ -16,13 +16,13 @@ afterEach(() => (LegacyLoggingServer as any).mockClear());
|
||||||
|
|
||||||
test('`configSchema` creates correct schema.', () => {
|
test('`configSchema` creates correct schema.', () => {
|
||||||
const appenderSchema = LegacyAppender.configSchema;
|
const appenderSchema = LegacyAppender.configSchema;
|
||||||
const validConfig = { kind: 'legacy-appender', legacyLoggingConfig: { verbose: true } };
|
const validConfig = { type: 'legacy-appender', legacyLoggingConfig: { verbose: true } };
|
||||||
expect(appenderSchema.validate(validConfig)).toEqual({
|
expect(appenderSchema.validate(validConfig)).toEqual({
|
||||||
kind: 'legacy-appender',
|
type: 'legacy-appender',
|
||||||
legacyLoggingConfig: { verbose: true },
|
legacyLoggingConfig: { verbose: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
const wrongConfig = { kind: 'not-legacy-appender' };
|
const wrongConfig = { type: 'not-legacy-appender' };
|
||||||
expect(() => appenderSchema.validate(wrongConfig)).toThrow();
|
expect(() => appenderSchema.validate(wrongConfig)).toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { DisposableAppender, LogRecord } from '@kbn/logging';
|
||||||
import { LegacyVars } from '../../types';
|
import { LegacyVars } from '../../types';
|
||||||
|
|
||||||
export interface LegacyAppenderConfig {
|
export interface LegacyAppenderConfig {
|
||||||
kind: 'legacy-appender';
|
type: 'legacy-appender';
|
||||||
legacyLoggingConfig?: any;
|
legacyLoggingConfig?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ export interface LegacyAppenderConfig {
|
||||||
*/
|
*/
|
||||||
export class LegacyAppender implements DisposableAppender {
|
export class LegacyAppender implements DisposableAppender {
|
||||||
public static configSchema = schema.object({
|
public static configSchema = schema.object({
|
||||||
kind: schema.literal('legacy-appender'),
|
type: schema.literal('legacy-appender'),
|
||||||
legacyLoggingConfig: schema.any(),
|
legacyLoggingConfig: schema.any(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ Kibana logging system has three main components: _loggers_, _appenders_ and _lay
|
||||||
messages according to message type and level, and to control how these messages are formatted and where the final logs
|
messages according to message type and level, and to control how these messages are formatted and where the final logs
|
||||||
will be displayed or stored.
|
will be displayed or stored.
|
||||||
|
|
||||||
__Loggers__ define what logging settings should be applied at the particular context.
|
__Loggers__ define what logging settings should be applied at the particular context name.
|
||||||
|
|
||||||
__Appenders__ define where log messages are displayed (eg. stdout or console) and stored (eg. file on the disk).
|
__Appenders__ define where log messages are displayed (eg. stdout or console) and stored (eg. file on the disk).
|
||||||
|
|
||||||
|
@ -33,17 +33,17 @@ __Layouts__ define how log messages are formatted and what type of information t
|
||||||
|
|
||||||
## Logger hierarchy
|
## Logger hierarchy
|
||||||
|
|
||||||
Every logger has its unique name or context that follows hierarchical naming rule. The logger is considered to be an
|
Every logger has its unique context name that follows hierarchical naming rule. The logger is considered to be an
|
||||||
ancestor of another logger if its name followed by a `.` is a prefix of the descendant logger name. For example logger
|
ancestor of another logger if its name followed by a `.` is a prefix of the descendant logger name. For example logger
|
||||||
with `a.b` context is an ancestor of logger with `a.b.c` context. All top-level loggers are descendants of special
|
with `a.b` context name is an ancestor of logger with `a.b.c` context name. All top-level loggers are descendants of special
|
||||||
logger with `root` context that resides at the top of the logger hierarchy. This logger always exists and
|
logger with `root` context name that resides at the top of the logger hierarchy. This logger always exists and
|
||||||
fully configured.
|
fully configured.
|
||||||
|
|
||||||
Developer can configure _log level_ and _appenders_ that should be used within particular context. If logger configuration
|
Developer can configure _log level_ and _appenders_ that should be used within particular context name. If logger configuration
|
||||||
specifies only _log level_ then _appenders_ configuration will be inherited from the ancestor logger.
|
specifies only _log level_ then _appenders_ configuration will be inherited from the ancestor logger.
|
||||||
|
|
||||||
__Note:__ in the current implementation log messages are only forwarded to appenders configured for a particular logger
|
__Note:__ in the current implementation log messages are only forwarded to appenders configured for a particular logger
|
||||||
context or to appenders of the closest ancestor if current logger doesn't have any appenders configured. That means that
|
context name or to appenders of the closest ancestor if current logger doesn't have any appenders configured. That means that
|
||||||
we __don't support__ so called _appender additivity_ when log messages are forwarded to _every_ distinct appender within
|
we __don't support__ so called _appender additivity_ when log messages are forwarded to _every_ distinct appender within
|
||||||
ancestor chain including `root`.
|
ancestor chain including `root`.
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ A log record is being logged by the logger if its level is higher than or equal
|
||||||
the log record is ignored.
|
the log record is ignored.
|
||||||
|
|
||||||
The _all_ and _off_ levels can be used only in configuration and are just handy shortcuts that allow developer to log every
|
The _all_ and _off_ levels can be used only in configuration and are just handy shortcuts that allow developer to log every
|
||||||
log record or disable logging entirely for the specific context.
|
log record or disable logging entirely for the specific context name.
|
||||||
|
|
||||||
## Layouts
|
## Layouts
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ Example of `%date` output:
|
||||||
Outputs the process ID.
|
Outputs the process ID.
|
||||||
|
|
||||||
### JSON layout
|
### JSON layout
|
||||||
With `json` layout log messages will be formatted as JSON strings that include timestamp, log level, context, message
|
With `json` layout log messages will be formatted as JSON strings that include timestamp, log level, context name, message
|
||||||
text and any other metadata that may be associated with the log message itself.
|
text and any other metadata that may be associated with the log message itself.
|
||||||
|
|
||||||
## Appenders
|
## Appenders
|
||||||
|
@ -153,15 +153,15 @@ This policy will rotate the file when it reaches a predetermined size.
|
||||||
logging:
|
logging:
|
||||||
appenders:
|
appenders:
|
||||||
rolling-file:
|
rolling-file:
|
||||||
kind: rolling-file
|
type: rolling-file
|
||||||
path: /var/logs/kibana.log
|
fileName: /var/logs/kibana.log
|
||||||
policy:
|
policy:
|
||||||
kind: size-limit
|
type: size-limit
|
||||||
size: 50mb
|
size: 50mb
|
||||||
strategy:
|
strategy:
|
||||||
//...
|
//...
|
||||||
layout:
|
layout:
|
||||||
kind: pattern
|
type: pattern
|
||||||
```
|
```
|
||||||
|
|
||||||
The options are:
|
The options are:
|
||||||
|
@ -180,16 +180,16 @@ This policy will rotate the file every given interval of time.
|
||||||
logging:
|
logging:
|
||||||
appenders:
|
appenders:
|
||||||
rolling-file:
|
rolling-file:
|
||||||
kind: rolling-file
|
type: rolling-file
|
||||||
path: /var/logs/kibana.log
|
fileName: /var/logs/kibana.log
|
||||||
policy:
|
policy:
|
||||||
kind: time-interval
|
type: time-interval
|
||||||
interval: 10s
|
interval: 10s
|
||||||
modulate: true
|
modulate: true
|
||||||
strategy:
|
strategy:
|
||||||
//...
|
//...
|
||||||
layout:
|
layout:
|
||||||
kind: pattern
|
type: pattern
|
||||||
```
|
```
|
||||||
|
|
||||||
The options are:
|
The options are:
|
||||||
|
@ -225,16 +225,16 @@ and will retains a fixed amount of rolled files.
|
||||||
logging:
|
logging:
|
||||||
appenders:
|
appenders:
|
||||||
rolling-file:
|
rolling-file:
|
||||||
kind: rolling-file
|
type: rolling-file
|
||||||
path: /var/logs/kibana.log
|
fileName: /var/logs/kibana.log
|
||||||
policy:
|
policy:
|
||||||
// ...
|
// ...
|
||||||
strategy:
|
strategy:
|
||||||
kind: numeric
|
type: numeric
|
||||||
pattern: '-%i'
|
pattern: '-%i'
|
||||||
max: 2
|
max: 2
|
||||||
layout:
|
layout:
|
||||||
kind: pattern
|
type: pattern
|
||||||
```
|
```
|
||||||
|
|
||||||
For example, with this configuration:
|
For example, with this configuration:
|
||||||
|
@ -253,7 +253,7 @@ The options are:
|
||||||
The suffix to append to the file path when rolling. Must include `%i`, as this is the value
|
The suffix to append to the file path when rolling. Must include `%i`, as this is the value
|
||||||
that will be converted to the file index.
|
that will be converted to the file index.
|
||||||
|
|
||||||
for example, with `path: /var/logs/kibana.log` and `pattern: '-%i'`, the created rolling files
|
for example, with `fileName: /var/logs/kibana.log` and `pattern: '-%i'`, the created rolling files
|
||||||
will be `/var/logs/kibana-1.log`, `/var/logs/kibana-2.log`, and so on.
|
will be `/var/logs/kibana-1.log`, `/var/logs/kibana-2.log`, and so on.
|
||||||
|
|
||||||
The default value is `-%i`
|
The default value is `-%i`
|
||||||
|
@ -278,49 +278,49 @@ Here is the configuration example that can be used to configure _loggers_, _appe
|
||||||
logging:
|
logging:
|
||||||
appenders:
|
appenders:
|
||||||
console:
|
console:
|
||||||
kind: console
|
type: console
|
||||||
layout:
|
layout:
|
||||||
kind: pattern
|
type: pattern
|
||||||
highlight: true
|
highlight: true
|
||||||
file:
|
file:
|
||||||
kind: file
|
type: file
|
||||||
path: /var/log/kibana.log
|
fileName: /var/log/kibana.log
|
||||||
layout:
|
layout:
|
||||||
kind: pattern
|
type: pattern
|
||||||
custom:
|
custom:
|
||||||
kind: console
|
type: console
|
||||||
layout:
|
layout:
|
||||||
kind: pattern
|
type: pattern
|
||||||
pattern: "[%date][%level] %message"
|
pattern: "[%date][%level] %message"
|
||||||
json-file-appender:
|
json-file-appender:
|
||||||
kind: file
|
type: file
|
||||||
path: /var/log/kibana-json.log
|
fileName: /var/log/kibana-json.log
|
||||||
|
|
||||||
root:
|
root:
|
||||||
appenders: [console, file]
|
appenders: [console, file]
|
||||||
level: error
|
level: error
|
||||||
|
|
||||||
loggers:
|
loggers:
|
||||||
- context: plugins
|
- name: plugins
|
||||||
appenders: [custom]
|
appenders: [custom]
|
||||||
level: warn
|
level: warn
|
||||||
- context: plugins.myPlugin
|
- name: plugins.myPlugin
|
||||||
level: info
|
level: info
|
||||||
- context: server
|
- name: server
|
||||||
level: fatal
|
level: fatal
|
||||||
- context: optimize
|
- name: optimize
|
||||||
appenders: [console]
|
appenders: [console]
|
||||||
- context: telemetry
|
- name: telemetry
|
||||||
level: all
|
level: all
|
||||||
appenders: [json-file-appender]
|
appenders: [json-file-appender]
|
||||||
- context: metrics.ops
|
- name: metrics.ops
|
||||||
level: debug
|
level: debug
|
||||||
appenders: [console]
|
appenders: [console]
|
||||||
```
|
```
|
||||||
|
|
||||||
Here is what we get with the config above:
|
Here is what we get with the config above:
|
||||||
|
|
||||||
| Context | Appenders | Level |
|
| Context name | Appenders | Level |
|
||||||
| ---------------- |:------------------------:| -----:|
|
| ---------------- |:------------------------:| -----:|
|
||||||
| root | console, file | error |
|
| root | console, file | error |
|
||||||
| plugins | custom | warn |
|
| plugins | custom | warn |
|
||||||
|
@ -331,7 +331,7 @@ Here is what we get with the config above:
|
||||||
| metrics.ops | console | debug |
|
| metrics.ops | console | debug |
|
||||||
|
|
||||||
|
|
||||||
The `root` logger has a dedicated configuration node since this context is special and should always exist. By
|
The `root` logger has a dedicated configuration node since this context name is special and should always exist. By
|
||||||
default `root` is configured with `info` level and `default` appender that is also always available. This is the
|
default `root` is configured with `info` level and `default` appender that is also always available. This is the
|
||||||
configuration that all custom loggers will use unless they're re-configured explicitly.
|
configuration that all custom loggers will use unless they're re-configured explicitly.
|
||||||
|
|
||||||
|
@ -391,7 +391,7 @@ The message contains some high-level information, and the corresponding log meta
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Usage is very straightforward, one should just get a logger for a specific context and use it to log messages with
|
Usage is very straightforward, one should just get a logger for a specific context name and use it to log messages with
|
||||||
different log level.
|
different log level.
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
|
@ -409,7 +409,7 @@ loggerWithNestedContext.trace('Message with `trace` log level.');
|
||||||
loggerWithNestedContext.debug('Message with `debug` log level.');
|
loggerWithNestedContext.debug('Message with `debug` log level.');
|
||||||
```
|
```
|
||||||
|
|
||||||
And assuming logger for `server` context with `console` appender and `trace` level was used, console output will look like this:
|
And assuming logger for `server` name with `console` appender and `trace` level was used, console output will look like this:
|
||||||
```bash
|
```bash
|
||||||
[2017-07-25T11:54:41.639-07:00][TRACE][server] Message with `trace` log level.
|
[2017-07-25T11:54:41.639-07:00][TRACE][server] Message with `trace` log level.
|
||||||
[2017-07-25T11:54:41.639-07:00][DEBUG][server] Message with `debug` log level.
|
[2017-07-25T11:54:41.639-07:00][DEBUG][server] Message with `debug` log level.
|
||||||
|
@ -422,7 +422,7 @@ And assuming logger for `server` context with `console` appender and `trace` lev
|
||||||
[2017-07-25T11:54:41.639-07:00][DEBUG][server.http] Message with `debug` log level.
|
[2017-07-25T11:54:41.639-07:00][DEBUG][server.http] Message with `debug` log level.
|
||||||
```
|
```
|
||||||
|
|
||||||
The log will be less verbose with `warn` level for the `server` context:
|
The log will be less verbose with `warn` level for the `server` context name:
|
||||||
```bash
|
```bash
|
||||||
[2017-07-25T11:54:41.639-07:00][WARN ][server] Message with `warn` log level.
|
[2017-07-25T11:54:41.639-07:00][WARN ][server] Message with `warn` log level.
|
||||||
[2017-07-25T11:54:41.639-07:00][ERROR][server] Message with `error` log level.
|
[2017-07-25T11:54:41.639-07:00][ERROR][server] Message with `error` log level.
|
||||||
|
@ -433,7 +433,7 @@ The log will be less verbose with `warn` level for the `server` context:
|
||||||
Compatibility with the legacy logging system is assured until the end of the `v7` version.
|
Compatibility with the legacy logging system is assured until the end of the `v7` version.
|
||||||
All log messages handled by `root` context are forwarded to the legacy logging service. If you re-write
|
All log messages handled by `root` context are forwarded to the legacy logging service. If you re-write
|
||||||
root appenders, make sure that it contains `default` appender to provide backward compatibility.
|
root appenders, make sure that it contains `default` appender to provide backward compatibility.
|
||||||
**Note**: If you define an appender for a context, the log messages aren't handled by the
|
**Note**: If you define an appender for a context name, the log messages aren't handled by the
|
||||||
`root` context anymore and not forwarded to the legacy logging service.
|
`root` context anymore and not forwarded to the legacy logging service.
|
||||||
|
|
||||||
#### logging.dest
|
#### logging.dest
|
||||||
|
@ -442,21 +442,21 @@ define a custom one.
|
||||||
```yaml
|
```yaml
|
||||||
logging:
|
logging:
|
||||||
loggers:
|
loggers:
|
||||||
- context: plugins.myPlugin
|
- name: plugins.myPlugin
|
||||||
appenders: [console]
|
appenders: [console]
|
||||||
```
|
```
|
||||||
Logs in a *file* if given file path. You should define a custom appender with `kind: file`
|
Logs in a *file* if given file path. You should define a custom appender with `type: file`
|
||||||
```yaml
|
```yaml
|
||||||
|
|
||||||
logging:
|
logging:
|
||||||
appenders:
|
appenders:
|
||||||
file:
|
file:
|
||||||
kind: file
|
type: file
|
||||||
path: /var/log/kibana.log
|
fileName: /var/log/kibana.log
|
||||||
layout:
|
layout:
|
||||||
kind: pattern
|
type: pattern
|
||||||
loggers:
|
loggers:
|
||||||
- context: plugins.myPlugin
|
- name: plugins.myPlugin
|
||||||
appenders: [file]
|
appenders: [file]
|
||||||
```
|
```
|
||||||
#### logging.json
|
#### logging.json
|
||||||
|
@ -468,7 +468,7 @@ Suppresses all logging output other than error messages. With new logging, confi
|
||||||
with adjusting minimum required [logging level](#log-level).
|
with adjusting minimum required [logging level](#log-level).
|
||||||
```yaml
|
```yaml
|
||||||
loggers:
|
loggers:
|
||||||
- context: plugins.myPlugin
|
- name: plugins.myPlugin
|
||||||
appenders: [console]
|
appenders: [console]
|
||||||
level: error
|
level: error
|
||||||
# or for all output
|
# or for all output
|
||||||
|
@ -494,32 +494,32 @@ to [specify timezone](#date) for `layout: pattern`. Defaults to host timezone wh
|
||||||
logging:
|
logging:
|
||||||
appenders:
|
appenders:
|
||||||
custom-console:
|
custom-console:
|
||||||
kind: console
|
type: console
|
||||||
layout:
|
layout:
|
||||||
kind: pattern
|
type: pattern
|
||||||
highlight: true
|
highlight: true
|
||||||
pattern: "[%level] [%date{ISO8601_TZ}{America/Los_Angeles}][%logger] %message"
|
pattern: "[%level] [%date{ISO8601_TZ}{America/Los_Angeles}][%logger] %message"
|
||||||
```
|
```
|
||||||
|
|
||||||
#### logging.events
|
#### logging.events
|
||||||
Define a custom logger for a specific context.
|
Define a custom logger for a specific context name.
|
||||||
|
|
||||||
**`logging.events.ops`** outputs sample system and process information at a regular interval.
|
**`logging.events.ops`** outputs sample system and process information at a regular interval.
|
||||||
With the new logging config, these are provided by a dedicated [context](#logger-hierarchy),
|
With the new logging config, these are provided by a dedicated [context name](#logger-hierarchy),
|
||||||
and you can enable them by adjusting the minimum required [logging level](#log-level) to `debug`:
|
and you can enable them by adjusting the minimum required [logging level](#log-level) to `debug`:
|
||||||
```yaml
|
```yaml
|
||||||
loggers:
|
loggers:
|
||||||
- context: metrics.ops
|
- name: metrics.ops
|
||||||
appenders: [console]
|
appenders: [console]
|
||||||
level: debug
|
level: debug
|
||||||
```
|
```
|
||||||
|
|
||||||
**`logging.events.request` and `logging.events.response`** provide logs for each request handled
|
**`logging.events.request` and `logging.events.response`** provide logs for each request handled
|
||||||
by the http service. With the new logging config, these are provided by a dedicated [context](#logger-hierarchy),
|
by the http service. With the new logging config, these are provided by a dedicated [context name](#logger-hierarchy),
|
||||||
and you can enable them by adjusting the minimum required [logging level](#log-level) to `debug`:
|
and you can enable them by adjusting the minimum required [logging level](#log-level) to `debug`:
|
||||||
```yaml
|
```yaml
|
||||||
loggers:
|
loggers:
|
||||||
- context: http.server.response
|
- name: http.server.response
|
||||||
appenders: [console]
|
appenders: [console]
|
||||||
level: debug
|
level: debug
|
||||||
```
|
```
|
||||||
|
@ -532,7 +532,7 @@ TBD
|
||||||
| Parameter | Platform log record in **pattern** format | Legacy Platform log record **text** format |
|
| Parameter | Platform log record in **pattern** format | Legacy Platform log record **text** format |
|
||||||
| --------------- | ------------------------------------------ | ------------------------------------------ |
|
| --------------- | ------------------------------------------ | ------------------------------------------ |
|
||||||
| @timestamp | ISO8601_TZ `2012-01-31T23:33:22.011-05:00` | Absolute `23:33:22.011` |
|
| @timestamp | ISO8601_TZ `2012-01-31T23:33:22.011-05:00` | Absolute `23:33:22.011` |
|
||||||
| context | `parent.child` | `['parent', 'child']` |
|
| context name | `parent.child` | `['parent', 'child']` |
|
||||||
| level | `DEBUG` | `['debug']` |
|
| level | `DEBUG` | `['debug']` |
|
||||||
| meta | stringified JSON object `{"to": "v8"}` | N/A |
|
| meta | stringified JSON object `{"to": "v8"}` | N/A |
|
||||||
| pid | can be configured as `%pid` | N/A |
|
| pid | can be configured as `%pid` | N/A |
|
||||||
|
@ -540,9 +540,9 @@ TBD
|
||||||
| Parameter | Platform log record in **json** format | Legacy Platform log record **json** format |
|
| Parameter | Platform log record in **json** format | Legacy Platform log record **json** format |
|
||||||
| --------------- | ------------------------------------------ | -------------------------------------------- |
|
| --------------- | ------------------------------------------ | -------------------------------------------- |
|
||||||
| @timestamp | ISO8601_TZ `2012-01-31T23:33:22.011-05:00` | ISO8601 `2012-01-31T23:33:22.011Z` |
|
| @timestamp | ISO8601_TZ `2012-01-31T23:33:22.011-05:00` | ISO8601 `2012-01-31T23:33:22.011Z` |
|
||||||
| context | `context: parent.child` | `tags: ['parent', 'child']` |
|
| context name | `log.logger: parent.child` | `tags: ['parent', 'child']` |
|
||||||
| level | `level: DEBUG` | `tags: ['debug']` |
|
| level | `log.level: DEBUG` | `tags: ['debug']` |
|
||||||
| meta | separate property `"meta": {"to": "v8"}` | merged in log record `{... "to": "v8"}` |
|
| meta | separate property `"meta": {"to": "v8"}` | merged in log record `{... "to": "v8"}` |
|
||||||
| pid | `pid: 12345` | `pid: 12345` |
|
| pid | `process.pid: 12345` | `pid: 12345` |
|
||||||
| type | N/A | `type: log` |
|
| type | N/A | `type: log` |
|
||||||
| error | `{ message, name, stack }` | `{ message, name, stack, code, signal }` |
|
| error | `{ message, name, stack }` | `{ message, name, stack, code, signal }` |
|
||||||
|
|
|
@ -84,7 +84,7 @@ Object {
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`uses \`root\` logger if context is not specified. 1`] = `
|
exports[`uses \`root\` logger if context name is not specified. 1`] = `
|
||||||
Array [
|
Array [
|
||||||
Array [
|
Array [
|
||||||
"[2012-01-31T03:33:22.011-05:00][INFO ][root] This message goes to a root context.",
|
"[2012-01-31T03:33:22.011-05:00][INFO ][root] This message goes to a root context.",
|
||||||
|
|
|
@ -12,7 +12,7 @@ jest.mock('../layouts/layouts', () => {
|
||||||
const { schema } = require('@kbn/config-schema');
|
const { schema } = require('@kbn/config-schema');
|
||||||
return {
|
return {
|
||||||
Layouts: {
|
Layouts: {
|
||||||
configSchema: schema.object({ kind: schema.literal('mock') }),
|
configSchema: schema.object({ type: schema.literal('mock') }),
|
||||||
create: mockCreateLayout,
|
create: mockCreateLayout,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,33 +21,33 @@ beforeEach(() => {
|
||||||
|
|
||||||
test('`configSchema` creates correct schema.', () => {
|
test('`configSchema` creates correct schema.', () => {
|
||||||
const appendersSchema = Appenders.configSchema;
|
const appendersSchema = Appenders.configSchema;
|
||||||
const validConfig1 = { kind: 'file', layout: { kind: 'mock' }, path: 'path' };
|
const validConfig1 = { type: 'file', layout: { type: 'mock' }, fileName: 'path' };
|
||||||
expect(appendersSchema.validate(validConfig1)).toEqual({
|
expect(appendersSchema.validate(validConfig1)).toEqual({
|
||||||
kind: 'file',
|
type: 'file',
|
||||||
layout: { kind: 'mock' },
|
layout: { type: 'mock' },
|
||||||
path: 'path',
|
fileName: 'path',
|
||||||
});
|
});
|
||||||
|
|
||||||
const validConfig2 = { kind: 'console', layout: { kind: 'mock' } };
|
const validConfig2 = { type: 'console', layout: { type: 'mock' } };
|
||||||
expect(appendersSchema.validate(validConfig2)).toEqual({
|
expect(appendersSchema.validate(validConfig2)).toEqual({
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: { kind: 'mock' },
|
layout: { type: 'mock' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const wrongConfig1 = {
|
const wrongConfig1 = {
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: { kind: 'mock' },
|
layout: { type: 'mock' },
|
||||||
path: 'path',
|
fileName: 'path',
|
||||||
};
|
};
|
||||||
expect(() => appendersSchema.validate(wrongConfig1)).toThrow();
|
expect(() => appendersSchema.validate(wrongConfig1)).toThrow();
|
||||||
|
|
||||||
const wrongConfig2 = { kind: 'file', layout: { kind: 'mock' } };
|
const wrongConfig2 = { type: 'file', layout: { type: 'mock' } };
|
||||||
expect(() => appendersSchema.validate(wrongConfig2)).toThrow();
|
expect(() => appendersSchema.validate(wrongConfig2)).toThrow();
|
||||||
|
|
||||||
const wrongConfig3 = {
|
const wrongConfig3 = {
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: { kind: 'mock' },
|
layout: { type: 'mock' },
|
||||||
path: 'path',
|
fileName: 'path',
|
||||||
};
|
};
|
||||||
expect(() => appendersSchema.validate(wrongConfig3)).toThrow();
|
expect(() => appendersSchema.validate(wrongConfig3)).toThrow();
|
||||||
});
|
});
|
||||||
|
@ -56,31 +56,31 @@ test('`create()` creates correct appender.', () => {
|
||||||
mockCreateLayout.mockReturnValue({ format: () => '' });
|
mockCreateLayout.mockReturnValue({ format: () => '' });
|
||||||
|
|
||||||
const consoleAppender = Appenders.create({
|
const consoleAppender = Appenders.create({
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: { highlight: true, kind: 'pattern', pattern: '' },
|
layout: { highlight: true, type: 'pattern', pattern: '' },
|
||||||
});
|
});
|
||||||
expect(consoleAppender).toBeInstanceOf(ConsoleAppender);
|
expect(consoleAppender).toBeInstanceOf(ConsoleAppender);
|
||||||
|
|
||||||
const fileAppender = Appenders.create({
|
const fileAppender = Appenders.create({
|
||||||
kind: 'file',
|
type: 'file',
|
||||||
layout: { highlight: true, kind: 'pattern', pattern: '' },
|
layout: { highlight: true, type: 'pattern', pattern: '' },
|
||||||
path: 'path',
|
fileName: 'path',
|
||||||
});
|
});
|
||||||
expect(fileAppender).toBeInstanceOf(FileAppender);
|
expect(fileAppender).toBeInstanceOf(FileAppender);
|
||||||
|
|
||||||
const legacyAppender = Appenders.create({
|
const legacyAppender = Appenders.create({
|
||||||
kind: 'legacy-appender',
|
type: 'legacy-appender',
|
||||||
legacyLoggingConfig: { verbose: true },
|
legacyLoggingConfig: { verbose: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(legacyAppender).toBeInstanceOf(LegacyAppender);
|
expect(legacyAppender).toBeInstanceOf(LegacyAppender);
|
||||||
|
|
||||||
const rollingFileAppender = Appenders.create({
|
const rollingFileAppender = Appenders.create({
|
||||||
kind: 'rolling-file',
|
type: 'rolling-file',
|
||||||
path: 'path',
|
fileName: 'path',
|
||||||
layout: { highlight: true, kind: 'pattern', pattern: '' },
|
layout: { highlight: true, type: 'pattern', pattern: '' },
|
||||||
strategy: { kind: 'numeric', max: 5, pattern: '%i' },
|
strategy: { type: 'numeric', max: 5, pattern: '%i' },
|
||||||
policy: { kind: 'size-limit', size: ByteSizeValue.parse('15b') },
|
policy: { type: 'size-limit', size: ByteSizeValue.parse('15b') },
|
||||||
});
|
});
|
||||||
expect(rollingFileAppender).toBeInstanceOf(RollingFileAppender);
|
expect(rollingFileAppender).toBeInstanceOf(RollingFileAppender);
|
||||||
});
|
});
|
||||||
|
|
|
@ -52,11 +52,11 @@ export class Appenders {
|
||||||
* @returns Fully constructed `Appender` instance.
|
* @returns Fully constructed `Appender` instance.
|
||||||
*/
|
*/
|
||||||
public static create(config: AppenderConfigType): DisposableAppender {
|
public static create(config: AppenderConfigType): DisposableAppender {
|
||||||
switch (config.kind) {
|
switch (config.type) {
|
||||||
case 'console':
|
case 'console':
|
||||||
return new ConsoleAppender(Layouts.create(config.layout));
|
return new ConsoleAppender(Layouts.create(config.layout));
|
||||||
case 'file':
|
case 'file':
|
||||||
return new FileAppender(Layouts.create(config.layout), config.path);
|
return new FileAppender(Layouts.create(config.layout), config.fileName);
|
||||||
case 'rolling-file':
|
case 'rolling-file':
|
||||||
return new RollingFileAppender(config);
|
return new RollingFileAppender(config);
|
||||||
case 'legacy-appender':
|
case 'legacy-appender':
|
||||||
|
|
|
@ -12,7 +12,7 @@ jest.mock('../../layouts/layouts', () => {
|
||||||
return {
|
return {
|
||||||
Layouts: {
|
Layouts: {
|
||||||
configSchema: schema.object({
|
configSchema: schema.object({
|
||||||
kind: schema.literal('mock'),
|
type: schema.literal('mock'),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -23,16 +23,16 @@ import { ConsoleAppender } from './console_appender';
|
||||||
|
|
||||||
test('`configSchema` creates correct schema.', () => {
|
test('`configSchema` creates correct schema.', () => {
|
||||||
const appenderSchema = ConsoleAppender.configSchema;
|
const appenderSchema = ConsoleAppender.configSchema;
|
||||||
const validConfig = { kind: 'console', layout: { kind: 'mock' } };
|
const validConfig = { type: 'console', layout: { type: 'mock' } };
|
||||||
expect(appenderSchema.validate(validConfig)).toEqual({
|
expect(appenderSchema.validate(validConfig)).toEqual({
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: { kind: 'mock' },
|
layout: { type: 'mock' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const wrongConfig1 = { kind: 'not-console', layout: { kind: 'mock' } };
|
const wrongConfig1 = { type: 'not-console', layout: { type: 'mock' } };
|
||||||
expect(() => appenderSchema.validate(wrongConfig1)).toThrow();
|
expect(() => appenderSchema.validate(wrongConfig1)).toThrow();
|
||||||
|
|
||||||
const wrongConfig2 = { kind: 'file', layout: { kind: 'mock' }, path: 'path' };
|
const wrongConfig2 = { type: 'file', layout: { type: 'mock' }, fileName: 'path' };
|
||||||
expect(() => appenderSchema.validate(wrongConfig2)).toThrow();
|
expect(() => appenderSchema.validate(wrongConfig2)).toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { Layouts, LayoutConfigType } from '../../layouts/layouts';
|
||||||
const { literal, object } = schema;
|
const { literal, object } = schema;
|
||||||
|
|
||||||
export interface ConsoleAppenderConfig {
|
export interface ConsoleAppenderConfig {
|
||||||
kind: 'console';
|
type: 'console';
|
||||||
layout: LayoutConfigType;
|
layout: LayoutConfigType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ export interface ConsoleAppenderConfig {
|
||||||
*/
|
*/
|
||||||
export class ConsoleAppender implements DisposableAppender {
|
export class ConsoleAppender implements DisposableAppender {
|
||||||
public static configSchema = object({
|
public static configSchema = object({
|
||||||
kind: literal('console'),
|
type: literal('console'),
|
||||||
layout: Layouts.configSchema,
|
layout: Layouts.configSchema,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ jest.mock('../../layouts/layouts', () => {
|
||||||
return {
|
return {
|
||||||
Layouts: {
|
Layouts: {
|
||||||
configSchema: schema.object({
|
configSchema: schema.object({
|
||||||
kind: schema.literal('mock'),
|
type: schema.literal('mock'),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,24 +20,24 @@ beforeEach(() => {
|
||||||
test('`createConfigSchema()` creates correct schema.', () => {
|
test('`createConfigSchema()` creates correct schema.', () => {
|
||||||
const appenderSchema = FileAppender.configSchema;
|
const appenderSchema = FileAppender.configSchema;
|
||||||
|
|
||||||
const validConfig = { kind: 'file', layout: { kind: 'mock' }, path: 'path' };
|
const validConfig = { type: 'file', layout: { type: 'mock' }, fileName: 'path' };
|
||||||
expect(appenderSchema.validate(validConfig)).toEqual({
|
expect(appenderSchema.validate(validConfig)).toEqual({
|
||||||
kind: 'file',
|
type: 'file',
|
||||||
layout: { kind: 'mock' },
|
layout: { type: 'mock' },
|
||||||
path: 'path',
|
fileName: 'path',
|
||||||
});
|
});
|
||||||
|
|
||||||
const wrongConfig1 = {
|
const wrongConfig1 = {
|
||||||
kind: 'not-file',
|
type: 'not-file',
|
||||||
layout: { kind: 'mock' },
|
layout: { type: 'mock' },
|
||||||
path: 'path',
|
fileName: 'path',
|
||||||
};
|
};
|
||||||
expect(() => appenderSchema.validate(wrongConfig1)).toThrow();
|
expect(() => appenderSchema.validate(wrongConfig1)).toThrow();
|
||||||
|
|
||||||
const wrongConfig2 = { kind: 'file', layout: { kind: 'mock' } };
|
const wrongConfig2 = { type: 'file', layout: { type: 'mock' } };
|
||||||
expect(() => appenderSchema.validate(wrongConfig2)).toThrow();
|
expect(() => appenderSchema.validate(wrongConfig2)).toThrow();
|
||||||
|
|
||||||
const wrongConfig3 = { kind: 'console', layout: { kind: 'mock' } };
|
const wrongConfig3 = { type: 'console', layout: { type: 'mock' } };
|
||||||
expect(() => appenderSchema.validate(wrongConfig3)).toThrow();
|
expect(() => appenderSchema.validate(wrongConfig3)).toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -13,9 +13,9 @@ import { createWriteStream, WriteStream } from 'fs';
|
||||||
import { Layouts, LayoutConfigType } from '../../layouts/layouts';
|
import { Layouts, LayoutConfigType } from '../../layouts/layouts';
|
||||||
|
|
||||||
export interface FileAppenderConfig {
|
export interface FileAppenderConfig {
|
||||||
kind: 'file';
|
type: 'file';
|
||||||
layout: LayoutConfigType;
|
layout: LayoutConfigType;
|
||||||
path: string;
|
fileName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,9 +24,9 @@ export interface FileAppenderConfig {
|
||||||
*/
|
*/
|
||||||
export class FileAppender implements DisposableAppender {
|
export class FileAppender implements DisposableAppender {
|
||||||
public static configSchema = schema.object({
|
public static configSchema = schema.object({
|
||||||
kind: schema.literal('file'),
|
type: schema.literal('file'),
|
||||||
layout: Layouts.configSchema,
|
layout: Layouts.configSchema,
|
||||||
path: schema.string(),
|
fileName: schema.string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -34,7 +34,7 @@ export type TriggeringPolicyConfig =
|
||||||
| TimeIntervalTriggeringPolicyConfig;
|
| TimeIntervalTriggeringPolicyConfig;
|
||||||
|
|
||||||
const defaultPolicy: TimeIntervalTriggeringPolicyConfig = {
|
const defaultPolicy: TimeIntervalTriggeringPolicyConfig = {
|
||||||
kind: 'time-interval',
|
type: 'time-interval',
|
||||||
interval: moment.duration(24, 'hour'),
|
interval: moment.duration(24, 'hour'),
|
||||||
modulate: true,
|
modulate: true,
|
||||||
};
|
};
|
||||||
|
@ -48,7 +48,7 @@ export const createTriggeringPolicy = (
|
||||||
config: TriggeringPolicyConfig,
|
config: TriggeringPolicyConfig,
|
||||||
context: RollingFileContext
|
context: RollingFileContext
|
||||||
): TriggeringPolicy => {
|
): TriggeringPolicy => {
|
||||||
switch (config.kind) {
|
switch (config.type) {
|
||||||
case 'size-limit':
|
case 'size-limit':
|
||||||
return new SizeLimitTriggeringPolicy(config, context);
|
return new SizeLimitTriggeringPolicy(config, context);
|
||||||
case 'time-interval':
|
case 'time-interval':
|
||||||
|
|
|
@ -15,7 +15,7 @@ describe('SizeLimitTriggeringPolicy', () => {
|
||||||
let context: RollingFileContext;
|
let context: RollingFileContext;
|
||||||
|
|
||||||
const createPolicy = (size: ByteSizeValue) =>
|
const createPolicy = (size: ByteSizeValue) =>
|
||||||
new SizeLimitTriggeringPolicy({ kind: 'size-limit', size }, context);
|
new SizeLimitTriggeringPolicy({ type: 'size-limit', size }, context);
|
||||||
|
|
||||||
const createLogRecord = (parts: Partial<LogRecord> = {}): LogRecord => ({
|
const createLogRecord = (parts: Partial<LogRecord> = {}): LogRecord => ({
|
||||||
timestamp: new Date(),
|
timestamp: new Date(),
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { RollingFileContext } from '../../rolling_file_context';
|
||||||
import { TriggeringPolicy } from '../policy';
|
import { TriggeringPolicy } from '../policy';
|
||||||
|
|
||||||
export interface SizeLimitTriggeringPolicyConfig {
|
export interface SizeLimitTriggeringPolicyConfig {
|
||||||
kind: 'size-limit';
|
type: 'size-limit';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The minimum size the file must have to roll over.
|
* The minimum size the file must have to roll over.
|
||||||
|
@ -21,7 +21,7 @@ export interface SizeLimitTriggeringPolicyConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const sizeLimitTriggeringPolicyConfigSchema = schema.object({
|
export const sizeLimitTriggeringPolicyConfigSchema = schema.object({
|
||||||
kind: schema.literal('size-limit'),
|
type: schema.literal('size-limit'),
|
||||||
size: schema.byteSize({ min: '1b', defaultValue: '100mb' }),
|
size: schema.byteSize({ min: '1b', defaultValue: '100mb' }),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ describe('TimeIntervalTriggeringPolicy', () => {
|
||||||
interval: string = '15m',
|
interval: string = '15m',
|
||||||
modulate: boolean = false
|
modulate: boolean = false
|
||||||
): TimeIntervalTriggeringPolicyConfig => ({
|
): TimeIntervalTriggeringPolicyConfig => ({
|
||||||
kind: 'time-interval',
|
type: 'time-interval',
|
||||||
interval: schema.duration().validate(interval),
|
interval: schema.duration().validate(interval),
|
||||||
modulate,
|
modulate,
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { getNextRollingTime } from './get_next_rolling_time';
|
||||||
import { isValidRolloverInterval } from './utils';
|
import { isValidRolloverInterval } from './utils';
|
||||||
|
|
||||||
export interface TimeIntervalTriggeringPolicyConfig {
|
export interface TimeIntervalTriggeringPolicyConfig {
|
||||||
kind: 'time-interval';
|
type: 'time-interval';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* How often a rollover should occur.
|
* How often a rollover should occur.
|
||||||
|
@ -38,7 +38,7 @@ export interface TimeIntervalTriggeringPolicyConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const timeIntervalTriggeringPolicyConfigSchema = schema.object({
|
export const timeIntervalTriggeringPolicyConfigSchema = schema.object({
|
||||||
kind: schema.literal('time-interval'),
|
type: schema.literal('time-interval'),
|
||||||
interval: schema.duration({
|
interval: schema.duration({
|
||||||
defaultValue: '24h',
|
defaultValue: '24h',
|
||||||
validate: (interval) => {
|
validate: (interval) => {
|
||||||
|
|
|
@ -20,20 +20,20 @@ import { LogLevel, LogRecord } from '@kbn/logging';
|
||||||
import { RollingFileAppender, RollingFileAppenderConfig } from './rolling_file_appender';
|
import { RollingFileAppender, RollingFileAppenderConfig } from './rolling_file_appender';
|
||||||
|
|
||||||
const config: RollingFileAppenderConfig = {
|
const config: RollingFileAppenderConfig = {
|
||||||
kind: 'rolling-file',
|
type: 'rolling-file',
|
||||||
path: '/var/log/kibana.log',
|
fileName: '/var/log/kibana.log',
|
||||||
layout: {
|
layout: {
|
||||||
kind: 'pattern',
|
type: 'pattern',
|
||||||
pattern: '%message',
|
pattern: '%message',
|
||||||
highlight: false,
|
highlight: false,
|
||||||
},
|
},
|
||||||
policy: {
|
policy: {
|
||||||
kind: 'time-interval',
|
type: 'time-interval',
|
||||||
interval: moment.duration(4, 'hour'),
|
interval: moment.duration(4, 'hour'),
|
||||||
modulate: true,
|
modulate: true,
|
||||||
},
|
},
|
||||||
strategy: {
|
strategy: {
|
||||||
kind: 'numeric',
|
type: 'numeric',
|
||||||
max: 5,
|
max: 5,
|
||||||
pattern: '-%i',
|
pattern: '-%i',
|
||||||
},
|
},
|
||||||
|
@ -99,7 +99,7 @@ describe('RollingFileAppender', () => {
|
||||||
|
|
||||||
it('constructs its delegates with the correct parameters', () => {
|
it('constructs its delegates with the correct parameters', () => {
|
||||||
expect(RollingFileContextMock).toHaveBeenCalledTimes(1);
|
expect(RollingFileContextMock).toHaveBeenCalledTimes(1);
|
||||||
expect(RollingFileContextMock).toHaveBeenCalledWith(config.path);
|
expect(RollingFileContextMock).toHaveBeenCalledWith(config.fileName);
|
||||||
|
|
||||||
expect(RollingFileManagerMock).toHaveBeenCalledTimes(1);
|
expect(RollingFileManagerMock).toHaveBeenCalledTimes(1);
|
||||||
expect(RollingFileManagerMock).toHaveBeenCalledWith(context);
|
expect(RollingFileManagerMock).toHaveBeenCalledWith(context);
|
||||||
|
|
|
@ -26,7 +26,7 @@ import { RollingFileManager } from './rolling_file_manager';
|
||||||
import { RollingFileContext } from './rolling_file_context';
|
import { RollingFileContext } from './rolling_file_context';
|
||||||
|
|
||||||
export interface RollingFileAppenderConfig {
|
export interface RollingFileAppenderConfig {
|
||||||
kind: 'rolling-file';
|
type: 'rolling-file';
|
||||||
/**
|
/**
|
||||||
* The layout to use when writing log entries
|
* The layout to use when writing log entries
|
||||||
*/
|
*/
|
||||||
|
@ -34,7 +34,7 @@ export interface RollingFileAppenderConfig {
|
||||||
/**
|
/**
|
||||||
* The absolute path of the file to write to.
|
* The absolute path of the file to write to.
|
||||||
*/
|
*/
|
||||||
path: string;
|
fileName: string;
|
||||||
/**
|
/**
|
||||||
* The {@link TriggeringPolicy | policy} to use to determine if a rollover should occur.
|
* The {@link TriggeringPolicy | policy} to use to determine if a rollover should occur.
|
||||||
*/
|
*/
|
||||||
|
@ -51,9 +51,9 @@ export interface RollingFileAppenderConfig {
|
||||||
*/
|
*/
|
||||||
export class RollingFileAppender implements DisposableAppender {
|
export class RollingFileAppender implements DisposableAppender {
|
||||||
public static configSchema = schema.object({
|
public static configSchema = schema.object({
|
||||||
kind: schema.literal('rolling-file'),
|
type: schema.literal('rolling-file'),
|
||||||
layout: Layouts.configSchema,
|
layout: Layouts.configSchema,
|
||||||
path: schema.string(),
|
fileName: schema.string(),
|
||||||
policy: triggeringPolicyConfigSchema,
|
policy: triggeringPolicyConfigSchema,
|
||||||
strategy: rollingStrategyConfigSchema,
|
strategy: rollingStrategyConfigSchema,
|
||||||
});
|
});
|
||||||
|
@ -70,7 +70,7 @@ export class RollingFileAppender implements DisposableAppender {
|
||||||
private readonly buffer: BufferAppender;
|
private readonly buffer: BufferAppender;
|
||||||
|
|
||||||
constructor(config: RollingFileAppenderConfig) {
|
constructor(config: RollingFileAppenderConfig) {
|
||||||
this.context = new RollingFileContext(config.path);
|
this.context = new RollingFileContext(config.fileName);
|
||||||
this.context.refreshFileInfo();
|
this.context.refreshFileInfo();
|
||||||
this.fileManager = new RollingFileManager(this.context);
|
this.fileManager = new RollingFileManager(this.context);
|
||||||
this.layout = Layouts.create(config.layout);
|
this.layout = Layouts.create(config.layout);
|
||||||
|
|
|
@ -19,7 +19,7 @@ export { RollingStrategy } from './strategy';
|
||||||
export type RollingStrategyConfig = NumericRollingStrategyConfig;
|
export type RollingStrategyConfig = NumericRollingStrategyConfig;
|
||||||
|
|
||||||
const defaultStrategy: NumericRollingStrategyConfig = {
|
const defaultStrategy: NumericRollingStrategyConfig = {
|
||||||
kind: 'numeric',
|
type: 'numeric',
|
||||||
pattern: '-%i',
|
pattern: '-%i',
|
||||||
max: 7,
|
max: 7,
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,8 +27,8 @@ describe('NumericRollingStrategy', () => {
|
||||||
let context: ReturnType<typeof rollingFileAppenderMocks.createContext>;
|
let context: ReturnType<typeof rollingFileAppenderMocks.createContext>;
|
||||||
let strategy: NumericRollingStrategy;
|
let strategy: NumericRollingStrategy;
|
||||||
|
|
||||||
const createStrategy = (config: Omit<NumericRollingStrategyConfig, 'kind'>) =>
|
const createStrategy = (config: Omit<NumericRollingStrategyConfig, 'type'>) =>
|
||||||
new NumericRollingStrategy({ ...config, kind: 'numeric' }, context);
|
new NumericRollingStrategy({ ...config, type: 'numeric' }, context);
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
context = rollingFileAppenderMocks.createContext(logFilePath);
|
context = rollingFileAppenderMocks.createContext(logFilePath);
|
||||||
|
|
|
@ -19,10 +19,10 @@ import {
|
||||||
} from './rolling_tasks';
|
} from './rolling_tasks';
|
||||||
|
|
||||||
export interface NumericRollingStrategyConfig {
|
export interface NumericRollingStrategyConfig {
|
||||||
kind: 'numeric';
|
type: 'numeric';
|
||||||
/**
|
/**
|
||||||
* The suffix pattern to apply when renaming a file. The suffix will be applied
|
* The suffix pattern to apply when renaming a file. The suffix will be applied
|
||||||
* after the `appender.path` file name, but before the file extension.
|
* after the `appender.fileName` file name, but before the file extension.
|
||||||
*
|
*
|
||||||
* Must include `%i`, as it is the value that will be converted to the file index
|
* Must include `%i`, as it is the value that will be converted to the file index
|
||||||
*
|
*
|
||||||
|
@ -31,8 +31,8 @@ export interface NumericRollingStrategyConfig {
|
||||||
* logging:
|
* logging:
|
||||||
* appenders:
|
* appenders:
|
||||||
* rolling-file:
|
* rolling-file:
|
||||||
* kind: rolling-file
|
* type: rolling-file
|
||||||
* path: /var/logs/kibana.log
|
* fileName: /var/logs/kibana.log
|
||||||
* strategy:
|
* strategy:
|
||||||
* type: default
|
* type: default
|
||||||
* pattern: "-%i"
|
* pattern: "-%i"
|
||||||
|
@ -52,7 +52,7 @@ export interface NumericRollingStrategyConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const numericRollingStrategyConfigSchema = schema.object({
|
export const numericRollingStrategyConfigSchema = schema.object({
|
||||||
kind: schema.literal('numeric'),
|
type: schema.literal('numeric'),
|
||||||
pattern: schema.string({
|
pattern: schema.string({
|
||||||
defaultValue: '-%i',
|
defaultValue: '-%i',
|
||||||
validate: (pattern) => {
|
validate: (pattern) => {
|
||||||
|
@ -73,8 +73,8 @@ export const numericRollingStrategyConfigSchema = schema.object({
|
||||||
* logging:
|
* logging:
|
||||||
* appenders:
|
* appenders:
|
||||||
* rolling-file:
|
* rolling-file:
|
||||||
* kind: rolling-file
|
* type: rolling-file
|
||||||
* path: /kibana.log
|
* fileName: /kibana.log
|
||||||
* strategy:
|
* strategy:
|
||||||
* type: numeric
|
* type: numeric
|
||||||
* pattern: "-%i"
|
* pattern: "-%i"
|
||||||
|
|
|
@ -17,22 +17,22 @@ function createRoot() {
|
||||||
silent: true, // set "true" in kbnTestServer
|
silent: true, // set "true" in kbnTestServer
|
||||||
appenders: {
|
appenders: {
|
||||||
'test-console': {
|
'test-console': {
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: {
|
layout: {
|
||||||
highlight: false,
|
highlight: false,
|
||||||
kind: 'pattern',
|
type: 'pattern',
|
||||||
pattern: '%level|%logger|%message',
|
pattern: '%level|%logger|%message',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
loggers: [
|
loggers: [
|
||||||
{
|
{
|
||||||
context: 'parent',
|
name: 'parent',
|
||||||
appenders: ['test-console'],
|
appenders: ['test-console'],
|
||||||
level: 'warn',
|
level: 'warn',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
context: 'parent.child',
|
name: 'parent.child',
|
||||||
appenders: ['test-console'],
|
appenders: ['test-console'],
|
||||||
level: 'error',
|
level: 'error',
|
||||||
},
|
},
|
||||||
|
@ -42,7 +42,7 @@ function createRoot() {
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('logging service', () => {
|
describe('logging service', () => {
|
||||||
describe('logs according to context hierarchy', () => {
|
describe('logs according to context name hierarchy', () => {
|
||||||
let root: ReturnType<typeof createRoot>;
|
let root: ReturnType<typeof createRoot>;
|
||||||
let mockConsoleLog: jest.SpyInstance;
|
let mockConsoleLog: jest.SpyInstance;
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
|
@ -61,7 +61,7 @@ describe('logging service', () => {
|
||||||
await root.shutdown();
|
await root.shutdown();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('uses the most specific context', () => {
|
it('uses the most specific context name', () => {
|
||||||
const logger = root.logger.get('parent.child');
|
const logger = root.logger.get('parent.child');
|
||||||
|
|
||||||
logger.error('error from "parent.child" context');
|
logger.error('error from "parent.child" context');
|
||||||
|
@ -74,7 +74,7 @@ describe('logging service', () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('uses parent context', () => {
|
it('uses parent context name', () => {
|
||||||
const logger = root.logger.get('parent.another-child');
|
const logger = root.logger.get('parent.another-child');
|
||||||
|
|
||||||
logger.error('error from "parent.another-child" context');
|
logger.error('error from "parent.another-child" context');
|
||||||
|
@ -104,31 +104,31 @@ describe('logging service', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('custom context configuration', () => {
|
describe('custom context name configuration', () => {
|
||||||
const CUSTOM_LOGGING_CONFIG: LoggerContextConfigInput = {
|
const CUSTOM_LOGGING_CONFIG: LoggerContextConfigInput = {
|
||||||
appenders: {
|
appenders: {
|
||||||
customJsonConsole: {
|
customJsonConsole: {
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: {
|
layout: {
|
||||||
kind: 'json',
|
type: 'json',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
customPatternConsole: {
|
customPatternConsole: {
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: {
|
layout: {
|
||||||
kind: 'pattern',
|
type: 'pattern',
|
||||||
pattern: 'CUSTOM - PATTERN [%logger][%level] %message',
|
pattern: 'CUSTOM - PATTERN [%logger][%level] %message',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
loggers: [
|
loggers: [
|
||||||
{ context: 'debug_json', appenders: ['customJsonConsole'], level: 'debug' },
|
{ name: 'debug_json', appenders: ['customJsonConsole'], level: 'debug' },
|
||||||
{ context: 'debug_pattern', appenders: ['customPatternConsole'], level: 'debug' },
|
{ name: 'debug_pattern', appenders: ['customPatternConsole'], level: 'debug' },
|
||||||
{ context: 'info_json', appenders: ['customJsonConsole'], level: 'info' },
|
{ name: 'info_json', appenders: ['customJsonConsole'], level: 'info' },
|
||||||
{ context: 'info_pattern', appenders: ['customPatternConsole'], level: 'info' },
|
{ name: 'info_pattern', appenders: ['customPatternConsole'], level: 'info' },
|
||||||
{
|
{
|
||||||
context: 'all',
|
name: 'all',
|
||||||
appenders: ['customJsonConsole', 'customPatternConsole'],
|
appenders: ['customJsonConsole', 'customPatternConsole'],
|
||||||
level: 'debug',
|
level: 'debug',
|
||||||
},
|
},
|
||||||
|
|
|
@ -25,7 +25,7 @@ function createRoot(appenderConfig: any) {
|
||||||
},
|
},
|
||||||
loggers: [
|
loggers: [
|
||||||
{
|
{
|
||||||
context: 'test.rolling.file',
|
name: 'test.rolling.file',
|
||||||
appenders: ['rolling-file'],
|
appenders: ['rolling-file'],
|
||||||
level: 'debug',
|
level: 'debug',
|
||||||
},
|
},
|
||||||
|
@ -63,18 +63,18 @@ describe('RollingFileAppender', () => {
|
||||||
describe('`size-limit` policy with `numeric` strategy', () => {
|
describe('`size-limit` policy with `numeric` strategy', () => {
|
||||||
it('rolls the log file in the correct order', async () => {
|
it('rolls the log file in the correct order', async () => {
|
||||||
root = createRoot({
|
root = createRoot({
|
||||||
kind: 'rolling-file',
|
type: 'rolling-file',
|
||||||
path: logFile,
|
fileName: logFile,
|
||||||
layout: {
|
layout: {
|
||||||
kind: 'pattern',
|
type: 'pattern',
|
||||||
pattern: '%message',
|
pattern: '%message',
|
||||||
},
|
},
|
||||||
policy: {
|
policy: {
|
||||||
kind: 'size-limit',
|
type: 'size-limit',
|
||||||
size: '100b',
|
size: '100b',
|
||||||
},
|
},
|
||||||
strategy: {
|
strategy: {
|
||||||
kind: 'numeric',
|
type: 'numeric',
|
||||||
max: 5,
|
max: 5,
|
||||||
pattern: '.%i',
|
pattern: '.%i',
|
||||||
},
|
},
|
||||||
|
@ -108,18 +108,18 @@ describe('RollingFileAppender', () => {
|
||||||
|
|
||||||
it('only keep the correct number of files', async () => {
|
it('only keep the correct number of files', async () => {
|
||||||
root = createRoot({
|
root = createRoot({
|
||||||
kind: 'rolling-file',
|
type: 'rolling-file',
|
||||||
path: logFile,
|
fileName: logFile,
|
||||||
layout: {
|
layout: {
|
||||||
kind: 'pattern',
|
type: 'pattern',
|
||||||
pattern: '%message',
|
pattern: '%message',
|
||||||
},
|
},
|
||||||
policy: {
|
policy: {
|
||||||
kind: 'size-limit',
|
type: 'size-limit',
|
||||||
size: '60b',
|
size: '60b',
|
||||||
},
|
},
|
||||||
strategy: {
|
strategy: {
|
||||||
kind: 'numeric',
|
type: 'numeric',
|
||||||
max: 2,
|
max: 2,
|
||||||
pattern: '-%i',
|
pattern: '-%i',
|
||||||
},
|
},
|
||||||
|
@ -157,19 +157,19 @@ describe('RollingFileAppender', () => {
|
||||||
describe('`time-interval` policy with `numeric` strategy', () => {
|
describe('`time-interval` policy with `numeric` strategy', () => {
|
||||||
it('rolls the log file at the given interval', async () => {
|
it('rolls the log file at the given interval', async () => {
|
||||||
root = createRoot({
|
root = createRoot({
|
||||||
kind: 'rolling-file',
|
type: 'rolling-file',
|
||||||
path: logFile,
|
fileName: logFile,
|
||||||
layout: {
|
layout: {
|
||||||
kind: 'pattern',
|
type: 'pattern',
|
||||||
pattern: '%message',
|
pattern: '%message',
|
||||||
},
|
},
|
||||||
policy: {
|
policy: {
|
||||||
kind: 'time-interval',
|
type: 'time-interval',
|
||||||
interval: '1s',
|
interval: '1s',
|
||||||
modulate: true,
|
modulate: true,
|
||||||
},
|
},
|
||||||
strategy: {
|
strategy: {
|
||||||
kind: 'numeric',
|
type: 'numeric',
|
||||||
max: 2,
|
max: 2,
|
||||||
pattern: '-%i',
|
pattern: '-%i',
|
||||||
},
|
},
|
||||||
|
|
|
@ -63,7 +63,7 @@ const records: LogRecord[] = [
|
||||||
test('`createConfigSchema()` creates correct schema.', () => {
|
test('`createConfigSchema()` creates correct schema.', () => {
|
||||||
const layoutSchema = JsonLayout.configSchema;
|
const layoutSchema = JsonLayout.configSchema;
|
||||||
|
|
||||||
expect(layoutSchema.validate({ kind: 'json' })).toEqual({ kind: 'json' });
|
expect(layoutSchema.validate({ type: 'json' })).toEqual({ type: 'json' });
|
||||||
});
|
});
|
||||||
|
|
||||||
test('`format()` correctly formats record.', () => {
|
test('`format()` correctly formats record.', () => {
|
||||||
|
|
|
@ -14,12 +14,12 @@ import { LogRecord, Layout } from '@kbn/logging';
|
||||||
const { literal, object } = schema;
|
const { literal, object } = schema;
|
||||||
|
|
||||||
const jsonLayoutSchema = object({
|
const jsonLayoutSchema = object({
|
||||||
kind: literal('json'),
|
type: literal('json'),
|
||||||
});
|
});
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
export interface JsonLayoutConfigType {
|
export interface JsonLayoutConfigType {
|
||||||
kind: 'json';
|
type: 'json';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -12,43 +12,43 @@ import { PatternLayout } from './pattern_layout';
|
||||||
|
|
||||||
test('`configSchema` creates correct schema for `pattern` layout.', () => {
|
test('`configSchema` creates correct schema for `pattern` layout.', () => {
|
||||||
const layoutsSchema = Layouts.configSchema;
|
const layoutsSchema = Layouts.configSchema;
|
||||||
const validConfigWithOptional = { kind: 'pattern' };
|
const validConfigWithOptional = { type: 'pattern' };
|
||||||
expect(layoutsSchema.validate(validConfigWithOptional)).toEqual({
|
expect(layoutsSchema.validate(validConfigWithOptional)).toEqual({
|
||||||
highlight: undefined,
|
highlight: undefined,
|
||||||
kind: 'pattern',
|
type: 'pattern',
|
||||||
pattern: undefined,
|
pattern: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const validConfig = {
|
const validConfig = {
|
||||||
highlight: true,
|
highlight: true,
|
||||||
kind: 'pattern',
|
type: 'pattern',
|
||||||
pattern: '%message',
|
pattern: '%message',
|
||||||
};
|
};
|
||||||
expect(layoutsSchema.validate(validConfig)).toEqual({
|
expect(layoutsSchema.validate(validConfig)).toEqual({
|
||||||
highlight: true,
|
highlight: true,
|
||||||
kind: 'pattern',
|
type: 'pattern',
|
||||||
pattern: '%message',
|
pattern: '%message',
|
||||||
});
|
});
|
||||||
|
|
||||||
const wrongConfig2 = { kind: 'pattern', pattern: 1 };
|
const wrongConfig2 = { type: 'pattern', pattern: 1 };
|
||||||
expect(() => layoutsSchema.validate(wrongConfig2)).toThrow();
|
expect(() => layoutsSchema.validate(wrongConfig2)).toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('`createConfigSchema()` creates correct schema for `json` layout.', () => {
|
test('`createConfigSchema()` creates correct schema for `json` layout.', () => {
|
||||||
const layoutsSchema = Layouts.configSchema;
|
const layoutsSchema = Layouts.configSchema;
|
||||||
|
|
||||||
const validConfig = { kind: 'json' };
|
const validConfig = { type: 'json' };
|
||||||
expect(layoutsSchema.validate(validConfig)).toEqual({ kind: 'json' });
|
expect(layoutsSchema.validate(validConfig)).toEqual({ type: 'json' });
|
||||||
});
|
});
|
||||||
|
|
||||||
test('`create()` creates correct layout.', () => {
|
test('`create()` creates correct layout.', () => {
|
||||||
const patternLayout = Layouts.create({
|
const patternLayout = Layouts.create({
|
||||||
highlight: false,
|
highlight: false,
|
||||||
kind: 'pattern',
|
type: 'pattern',
|
||||||
pattern: '[%date][%level][%logger] %message',
|
pattern: '[%date][%level][%logger] %message',
|
||||||
});
|
});
|
||||||
expect(patternLayout).toBeInstanceOf(PatternLayout);
|
expect(patternLayout).toBeInstanceOf(PatternLayout);
|
||||||
|
|
||||||
const jsonLayout = Layouts.create({ kind: 'json' });
|
const jsonLayout = Layouts.create({ type: 'json' });
|
||||||
expect(jsonLayout).toBeInstanceOf(JsonLayout);
|
expect(jsonLayout).toBeInstanceOf(JsonLayout);
|
||||||
});
|
});
|
||||||
|
|
|
@ -27,7 +27,7 @@ export class Layouts {
|
||||||
* @returns Fully constructed `Layout` instance.
|
* @returns Fully constructed `Layout` instance.
|
||||||
*/
|
*/
|
||||||
public static create(config: LayoutConfigType): Layout {
|
public static create(config: LayoutConfigType): Layout {
|
||||||
switch (config.kind) {
|
switch (config.type) {
|
||||||
case 'json':
|
case 'json':
|
||||||
return new JsonLayout();
|
return new JsonLayout();
|
||||||
|
|
||||||
|
|
|
@ -66,28 +66,28 @@ expect.addSnapshotSerializer(stripAnsiSnapshotSerializer);
|
||||||
test('`createConfigSchema()` creates correct schema.', () => {
|
test('`createConfigSchema()` creates correct schema.', () => {
|
||||||
const layoutSchema = PatternLayout.configSchema;
|
const layoutSchema = PatternLayout.configSchema;
|
||||||
|
|
||||||
const validConfigWithOptional = { kind: 'pattern' };
|
const validConfigWithOptional = { type: 'pattern' };
|
||||||
expect(layoutSchema.validate(validConfigWithOptional)).toEqual({
|
expect(layoutSchema.validate(validConfigWithOptional)).toEqual({
|
||||||
highlight: undefined,
|
highlight: undefined,
|
||||||
kind: 'pattern',
|
type: 'pattern',
|
||||||
pattern: undefined,
|
pattern: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const validConfig = {
|
const validConfig = {
|
||||||
highlight: true,
|
highlight: true,
|
||||||
kind: 'pattern',
|
type: 'pattern',
|
||||||
pattern: '%message',
|
pattern: '%message',
|
||||||
};
|
};
|
||||||
expect(layoutSchema.validate(validConfig)).toEqual({
|
expect(layoutSchema.validate(validConfig)).toEqual({
|
||||||
highlight: true,
|
highlight: true,
|
||||||
kind: 'pattern',
|
type: 'pattern',
|
||||||
pattern: '%message',
|
pattern: '%message',
|
||||||
});
|
});
|
||||||
|
|
||||||
const wrongConfig1 = { kind: 'json' };
|
const wrongConfig1 = { type: 'json' };
|
||||||
expect(() => layoutSchema.validate(wrongConfig1)).toThrow();
|
expect(() => layoutSchema.validate(wrongConfig1)).toThrow();
|
||||||
|
|
||||||
const wrongConfig2 = { kind: 'pattern', pattern: 1 };
|
const wrongConfig2 = { type: 'pattern', pattern: 1 };
|
||||||
expect(() => layoutSchema.validate(wrongConfig2)).toThrow();
|
expect(() => layoutSchema.validate(wrongConfig2)).toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ export const patternSchema = schema.string({
|
||||||
|
|
||||||
const patternLayoutSchema = schema.object({
|
const patternLayoutSchema = schema.object({
|
||||||
highlight: schema.maybe(schema.boolean()),
|
highlight: schema.maybe(schema.boolean()),
|
||||||
kind: schema.literal('pattern'),
|
type: schema.literal('pattern'),
|
||||||
pattern: schema.maybe(patternSchema),
|
pattern: schema.maybe(patternSchema),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ const conversions: Conversion[] = [
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
export interface PatternLayoutConfigType {
|
export interface PatternLayoutConfigType {
|
||||||
kind: 'pattern';
|
type: 'pattern';
|
||||||
highlight?: boolean;
|
highlight?: boolean;
|
||||||
pattern?: string;
|
pattern?: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,12 +51,12 @@ test('correctly fills in default config.', () => {
|
||||||
expect(configValue.appenders.size).toBe(2);
|
expect(configValue.appenders.size).toBe(2);
|
||||||
|
|
||||||
expect(configValue.appenders.get('default')).toEqual({
|
expect(configValue.appenders.get('default')).toEqual({
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: { kind: 'pattern', highlight: true },
|
layout: { type: 'pattern', highlight: true },
|
||||||
});
|
});
|
||||||
expect(configValue.appenders.get('console')).toEqual({
|
expect(configValue.appenders.get('console')).toEqual({
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: { kind: 'pattern', highlight: true },
|
layout: { type: 'pattern', highlight: true },
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -65,8 +65,8 @@ test('correctly fills in custom `appenders` config.', () => {
|
||||||
config.schema.validate({
|
config.schema.validate({
|
||||||
appenders: {
|
appenders: {
|
||||||
console: {
|
console: {
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: { kind: 'pattern' },
|
layout: { type: 'pattern' },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -75,13 +75,13 @@ test('correctly fills in custom `appenders` config.', () => {
|
||||||
expect(configValue.appenders.size).toBe(2);
|
expect(configValue.appenders.size).toBe(2);
|
||||||
|
|
||||||
expect(configValue.appenders.get('default')).toEqual({
|
expect(configValue.appenders.get('default')).toEqual({
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: { kind: 'pattern', highlight: true },
|
layout: { type: 'pattern', highlight: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(configValue.appenders.get('console')).toEqual({
|
expect(configValue.appenders.get('console')).toEqual({
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: { kind: 'pattern' },
|
layout: { type: 'pattern' },
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ test('correctly fills in default `loggers` config.', () => {
|
||||||
expect(configValue.loggers.size).toBe(1);
|
expect(configValue.loggers.size).toBe(1);
|
||||||
expect(configValue.loggers.get('root')).toEqual({
|
expect(configValue.loggers.get('root')).toEqual({
|
||||||
appenders: ['default'],
|
appenders: ['default'],
|
||||||
context: 'root',
|
name: 'root',
|
||||||
level: 'info',
|
level: 'info',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -101,24 +101,24 @@ test('correctly fills in custom `loggers` config.', () => {
|
||||||
config.schema.validate({
|
config.schema.validate({
|
||||||
appenders: {
|
appenders: {
|
||||||
file: {
|
file: {
|
||||||
kind: 'file',
|
type: 'file',
|
||||||
layout: { kind: 'pattern' },
|
layout: { type: 'pattern' },
|
||||||
path: 'path',
|
fileName: 'path',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
loggers: [
|
loggers: [
|
||||||
{
|
{
|
||||||
appenders: ['file'],
|
appenders: ['file'],
|
||||||
context: 'plugins',
|
name: 'plugins',
|
||||||
level: 'warn',
|
level: 'warn',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
context: 'plugins.pid',
|
name: 'plugins.pid',
|
||||||
level: 'trace',
|
level: 'trace',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
appenders: ['default'],
|
appenders: ['default'],
|
||||||
context: 'http',
|
name: 'http',
|
||||||
level: 'error',
|
level: 'error',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -128,22 +128,22 @@ test('correctly fills in custom `loggers` config.', () => {
|
||||||
expect(configValue.loggers.size).toBe(4);
|
expect(configValue.loggers.size).toBe(4);
|
||||||
expect(configValue.loggers.get('root')).toEqual({
|
expect(configValue.loggers.get('root')).toEqual({
|
||||||
appenders: ['default'],
|
appenders: ['default'],
|
||||||
context: 'root',
|
name: 'root',
|
||||||
level: 'info',
|
level: 'info',
|
||||||
});
|
});
|
||||||
expect(configValue.loggers.get('plugins')).toEqual({
|
expect(configValue.loggers.get('plugins')).toEqual({
|
||||||
appenders: ['file'],
|
appenders: ['file'],
|
||||||
context: 'plugins',
|
name: 'plugins',
|
||||||
level: 'warn',
|
level: 'warn',
|
||||||
});
|
});
|
||||||
expect(configValue.loggers.get('plugins.pid')).toEqual({
|
expect(configValue.loggers.get('plugins.pid')).toEqual({
|
||||||
appenders: ['file'],
|
appenders: ['file'],
|
||||||
context: 'plugins.pid',
|
name: 'plugins.pid',
|
||||||
level: 'trace',
|
level: 'trace',
|
||||||
});
|
});
|
||||||
expect(configValue.loggers.get('http')).toEqual({
|
expect(configValue.loggers.get('http')).toEqual({
|
||||||
appenders: ['default'],
|
appenders: ['default'],
|
||||||
context: 'http',
|
name: 'http',
|
||||||
level: 'error',
|
level: 'error',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -153,7 +153,7 @@ test('fails if loggers use unknown appenders.', () => {
|
||||||
loggers: [
|
loggers: [
|
||||||
{
|
{
|
||||||
appenders: ['unknown'],
|
appenders: ['unknown'],
|
||||||
context: 'some.nested.context',
|
name: 'some.nested.context',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
@ -167,9 +167,9 @@ describe('extend', () => {
|
||||||
config.schema.validate({
|
config.schema.validate({
|
||||||
appenders: {
|
appenders: {
|
||||||
file1: {
|
file1: {
|
||||||
kind: 'file',
|
type: 'file',
|
||||||
layout: { kind: 'pattern' },
|
layout: { type: 'pattern' },
|
||||||
path: 'path',
|
fileName: 'path',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -179,9 +179,9 @@ describe('extend', () => {
|
||||||
config.schema.validate({
|
config.schema.validate({
|
||||||
appenders: {
|
appenders: {
|
||||||
file2: {
|
file2: {
|
||||||
kind: 'file',
|
type: 'file',
|
||||||
layout: { kind: 'pattern' },
|
layout: { type: 'pattern' },
|
||||||
path: 'path',
|
fileName: 'path',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -200,9 +200,9 @@ describe('extend', () => {
|
||||||
config.schema.validate({
|
config.schema.validate({
|
||||||
appenders: {
|
appenders: {
|
||||||
file1: {
|
file1: {
|
||||||
kind: 'file',
|
type: 'file',
|
||||||
layout: { kind: 'pattern' },
|
layout: { type: 'pattern' },
|
||||||
path: 'path',
|
fileName: 'path',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -212,18 +212,18 @@ describe('extend', () => {
|
||||||
config.schema.validate({
|
config.schema.validate({
|
||||||
appenders: {
|
appenders: {
|
||||||
file1: {
|
file1: {
|
||||||
kind: 'file',
|
type: 'file',
|
||||||
layout: { kind: 'json' },
|
layout: { type: 'json' },
|
||||||
path: 'updatedPath',
|
fileName: 'updatedPath',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(mergedConfigValue.appenders.get('file1')).toEqual({
|
expect(mergedConfigValue.appenders.get('file1')).toEqual({
|
||||||
kind: 'file',
|
type: 'file',
|
||||||
layout: { kind: 'json' },
|
layout: { type: 'json' },
|
||||||
path: 'updatedPath',
|
fileName: 'updatedPath',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -232,7 +232,7 @@ describe('extend', () => {
|
||||||
config.schema.validate({
|
config.schema.validate({
|
||||||
loggers: [
|
loggers: [
|
||||||
{
|
{
|
||||||
context: 'plugins',
|
name: 'plugins',
|
||||||
level: 'warn',
|
level: 'warn',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -243,7 +243,7 @@ describe('extend', () => {
|
||||||
config.schema.validate({
|
config.schema.validate({
|
||||||
loggers: [
|
loggers: [
|
||||||
{
|
{
|
||||||
context: 'plugins.pid',
|
name: 'plugins.pid',
|
||||||
level: 'trace',
|
level: 'trace',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -258,7 +258,7 @@ describe('extend', () => {
|
||||||
config.schema.validate({
|
config.schema.validate({
|
||||||
loggers: [
|
loggers: [
|
||||||
{
|
{
|
||||||
context: 'plugins',
|
name: 'plugins',
|
||||||
level: 'warn',
|
level: 'warn',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -270,7 +270,7 @@ describe('extend', () => {
|
||||||
loggers: [
|
loggers: [
|
||||||
{
|
{
|
||||||
appenders: ['console'],
|
appenders: ['console'],
|
||||||
context: 'plugins',
|
name: 'plugins',
|
||||||
level: 'trace',
|
level: 'trace',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -279,7 +279,7 @@ describe('extend', () => {
|
||||||
|
|
||||||
expect(mergedConfigValue.loggers.get('plugins')).toEqual({
|
expect(mergedConfigValue.loggers.get('plugins')).toEqual({
|
||||||
appenders: ['console'],
|
appenders: ['console'],
|
||||||
context: 'plugins',
|
name: 'plugins',
|
||||||
level: 'trace',
|
level: 'trace',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -51,7 +51,7 @@ const levelSchema = schema.oneOf(
|
||||||
*/
|
*/
|
||||||
export const loggerSchema = schema.object({
|
export const loggerSchema = schema.object({
|
||||||
appenders: schema.arrayOf(schema.string(), { defaultValue: [] }),
|
appenders: schema.arrayOf(schema.string(), { defaultValue: [] }),
|
||||||
context: schema.string(),
|
name: schema.string(),
|
||||||
level: levelSchema,
|
level: levelSchema,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -148,15 +148,15 @@ export class LoggingConfig {
|
||||||
[
|
[
|
||||||
'default',
|
'default',
|
||||||
{
|
{
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: { kind: 'pattern', highlight: true },
|
layout: { type: 'pattern', highlight: true },
|
||||||
} as AppenderConfigType,
|
} as AppenderConfigType,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'console',
|
'console',
|
||||||
{
|
{
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: { kind: 'pattern', highlight: true },
|
layout: { type: 'pattern', highlight: true },
|
||||||
} as AppenderConfigType,
|
} as AppenderConfigType,
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
@ -182,8 +182,8 @@ export class LoggingConfig {
|
||||||
public extend(contextConfig: LoggerContextConfigType) {
|
public extend(contextConfig: LoggerContextConfigType) {
|
||||||
// Use a Map to de-dupe any loggers for the same context. contextConfig overrides existing config.
|
// Use a Map to de-dupe any loggers for the same context. contextConfig overrides existing config.
|
||||||
const mergedLoggers = new Map<string, LoggerConfigType>([
|
const mergedLoggers = new Map<string, LoggerConfigType>([
|
||||||
...this.configType.loggers.map((l) => [l.context, l] as [string, LoggerConfigType]),
|
...this.configType.loggers.map((l) => [l.name, l] as [string, LoggerConfigType]),
|
||||||
...contextConfig.loggers.map((l) => [l.context, l] as [string, LoggerConfigType]),
|
...contextConfig.loggers.map((l) => [l.name, l] as [string, LoggerConfigType]),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const mergedConfig: LoggingConfigType = {
|
const mergedConfig: LoggingConfigType = {
|
||||||
|
@ -204,13 +204,10 @@ export class LoggingConfig {
|
||||||
private fillLoggersConfig(loggingConfig: LoggingConfigType) {
|
private fillLoggersConfig(loggingConfig: LoggingConfigType) {
|
||||||
// Include `root` logger into common logger list so that it can easily be a part
|
// Include `root` logger into common logger list so that it can easily be a part
|
||||||
// of the logger hierarchy and put all the loggers in map for easier retrieval.
|
// of the logger hierarchy and put all the loggers in map for easier retrieval.
|
||||||
const loggers = [
|
const loggers = [{ name: ROOT_CONTEXT_NAME, ...loggingConfig.root }, ...loggingConfig.loggers];
|
||||||
{ context: ROOT_CONTEXT_NAME, ...loggingConfig.root },
|
|
||||||
...loggingConfig.loggers,
|
|
||||||
];
|
|
||||||
|
|
||||||
const loggerConfigByContext = new Map(
|
const loggerConfigByContext = new Map(
|
||||||
loggers.map((loggerConfig) => toTuple(loggerConfig.context, loggerConfig))
|
loggers.map((loggerConfig) => toTuple(loggerConfig.name, loggerConfig))
|
||||||
);
|
);
|
||||||
|
|
||||||
for (const [loggerContext, loggerConfig] of loggerConfigByContext) {
|
for (const [loggerContext, loggerConfig] of loggerConfigByContext) {
|
||||||
|
@ -247,7 +244,7 @@ function getAppenders(
|
||||||
loggerConfig: LoggerConfigType,
|
loggerConfig: LoggerConfigType,
|
||||||
loggerConfigByContext: Map<string, LoggerConfigType>
|
loggerConfigByContext: Map<string, LoggerConfigType>
|
||||||
) {
|
) {
|
||||||
let currentContext = loggerConfig.context;
|
let currentContext = loggerConfig.name;
|
||||||
let appenders = loggerConfig.appenders;
|
let appenders = loggerConfig.appenders;
|
||||||
|
|
||||||
while (appenders.length === 0) {
|
while (appenders.length === 0) {
|
||||||
|
|
|
@ -30,11 +30,11 @@ describe('LoggingService', () => {
|
||||||
it('forwards configuration changes to logging system', () => {
|
it('forwards configuration changes to logging system', () => {
|
||||||
const config1: LoggerContextConfigType = {
|
const config1: LoggerContextConfigType = {
|
||||||
appenders: new Map(),
|
appenders: new Map(),
|
||||||
loggers: [{ context: 'subcontext', appenders: ['console'], level: 'warn' }],
|
loggers: [{ name: 'subcontext', appenders: ['console'], level: 'warn' }],
|
||||||
};
|
};
|
||||||
const config2: LoggerContextConfigType = {
|
const config2: LoggerContextConfigType = {
|
||||||
appenders: new Map(),
|
appenders: new Map(),
|
||||||
loggers: [{ context: 'subcontext', appenders: ['default'], level: 'all' }],
|
loggers: [{ name: 'subcontext', appenders: ['default'], level: 'all' }],
|
||||||
};
|
};
|
||||||
|
|
||||||
setup.configure(['test', 'context'], of(config1, config2));
|
setup.configure(['test', 'context'], of(config1, config2));
|
||||||
|
@ -54,11 +54,11 @@ describe('LoggingService', () => {
|
||||||
const updates$ = new Subject<LoggerContextConfigType>();
|
const updates$ = new Subject<LoggerContextConfigType>();
|
||||||
const config1: LoggerContextConfigType = {
|
const config1: LoggerContextConfigType = {
|
||||||
appenders: new Map(),
|
appenders: new Map(),
|
||||||
loggers: [{ context: 'subcontext', appenders: ['console'], level: 'warn' }],
|
loggers: [{ name: 'subcontext', appenders: ['console'], level: 'warn' }],
|
||||||
};
|
};
|
||||||
const config2: LoggerContextConfigType = {
|
const config2: LoggerContextConfigType = {
|
||||||
appenders: new Map(),
|
appenders: new Map(),
|
||||||
loggers: [{ context: 'subcontext', appenders: ['default'], level: 'all' }],
|
loggers: [{ name: 'subcontext', appenders: ['default'], level: 'all' }],
|
||||||
};
|
};
|
||||||
|
|
||||||
setup.configure(['test', 'context'], updates$);
|
setup.configure(['test', 'context'], updates$);
|
||||||
|
@ -78,7 +78,7 @@ describe('LoggingService', () => {
|
||||||
const updates$ = new Subject<LoggerContextConfigType>();
|
const updates$ = new Subject<LoggerContextConfigType>();
|
||||||
const config1: LoggerContextConfigType = {
|
const config1: LoggerContextConfigType = {
|
||||||
appenders: new Map(),
|
appenders: new Map(),
|
||||||
loggers: [{ context: 'subcontext', appenders: ['console'], level: 'warn' }],
|
loggers: [{ name: 'subcontext', appenders: ['console'], level: 'warn' }],
|
||||||
};
|
};
|
||||||
|
|
||||||
setup.configure(['test', 'context'], updates$);
|
setup.configure(['test', 'context'], updates$);
|
||||||
|
|
|
@ -31,7 +31,7 @@ export interface LoggingServiceSetup {
|
||||||
* core.logging.configure(
|
* core.logging.configure(
|
||||||
* of({
|
* of({
|
||||||
* appenders: new Map(),
|
* appenders: new Map(),
|
||||||
* loggers: [{ context: 'search', appenders: ['default'] }]
|
* loggers: [{ name: 'search', appenders: ['default'] }]
|
||||||
* })
|
* })
|
||||||
* )
|
* )
|
||||||
* ```
|
* ```
|
||||||
|
|
|
@ -46,7 +46,7 @@ test('uses default memory buffer logger until config is provided', () => {
|
||||||
const logger = system.get('test', 'context');
|
const logger = system.get('test', 'context');
|
||||||
logger.trace('trace message');
|
logger.trace('trace message');
|
||||||
|
|
||||||
// We shouldn't create new buffer appender for another context.
|
// We shouldn't create new buffer appender for another context name.
|
||||||
const anotherLogger = system.get('test', 'context2');
|
const anotherLogger = system.get('test', 'context2');
|
||||||
anotherLogger.fatal('fatal message', { some: 'value' });
|
anotherLogger.fatal('fatal message', { some: 'value' });
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ test('flushes memory buffer logger and switches to real logger once config is pr
|
||||||
// Switch to console appender with `info` level, so that `trace` message won't go through.
|
// Switch to console appender with `info` level, so that `trace` message won't go through.
|
||||||
await system.upgrade(
|
await system.upgrade(
|
||||||
config.schema.validate({
|
config.schema.validate({
|
||||||
appenders: { default: { kind: 'console', layout: { kind: 'json' } } },
|
appenders: { default: { type: 'console', layout: { type: 'json' } } },
|
||||||
root: { level: 'info' },
|
root: { level: 'info' },
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -102,12 +102,12 @@ test('appends records via multiple appenders.', async () => {
|
||||||
await system.upgrade(
|
await system.upgrade(
|
||||||
config.schema.validate({
|
config.schema.validate({
|
||||||
appenders: {
|
appenders: {
|
||||||
default: { kind: 'console', layout: { kind: 'pattern' } },
|
default: { type: 'console', layout: { type: 'pattern' } },
|
||||||
file: { kind: 'file', layout: { kind: 'pattern' }, path: 'path' },
|
file: { type: 'file', layout: { type: 'pattern' }, fileName: 'path' },
|
||||||
},
|
},
|
||||||
loggers: [
|
loggers: [
|
||||||
{ appenders: ['file'], context: 'tests', level: 'warn' },
|
{ appenders: ['file'], name: 'tests', level: 'warn' },
|
||||||
{ context: 'tests.child', level: 'error' },
|
{ name: 'tests.child', level: 'error' },
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -121,10 +121,10 @@ test('appends records via multiple appenders.', async () => {
|
||||||
expect(mockStreamWrite.mock.calls[1][0]).toMatchSnapshot('file logs');
|
expect(mockStreamWrite.mock.calls[1][0]).toMatchSnapshot('file logs');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('uses `root` logger if context is not specified.', async () => {
|
test('uses `root` logger if context name is not specified.', async () => {
|
||||||
await system.upgrade(
|
await system.upgrade(
|
||||||
config.schema.validate({
|
config.schema.validate({
|
||||||
appenders: { default: { kind: 'console', layout: { kind: 'pattern' } } },
|
appenders: { default: { type: 'console', layout: { type: 'pattern' } } },
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ test('uses `root` logger if context is not specified.', async () => {
|
||||||
test('`stop()` disposes all appenders.', async () => {
|
test('`stop()` disposes all appenders.', async () => {
|
||||||
await system.upgrade(
|
await system.upgrade(
|
||||||
config.schema.validate({
|
config.schema.validate({
|
||||||
appenders: { default: { kind: 'console', layout: { kind: 'json' } } },
|
appenders: { default: { type: 'console', layout: { type: 'json' } } },
|
||||||
root: { level: 'info' },
|
root: { level: 'info' },
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -156,7 +156,7 @@ test('asLoggerFactory() only allows to create new loggers.', async () => {
|
||||||
|
|
||||||
await system.upgrade(
|
await system.upgrade(
|
||||||
config.schema.validate({
|
config.schema.validate({
|
||||||
appenders: { default: { kind: 'console', layout: { kind: 'json' } } },
|
appenders: { default: { type: 'console', layout: { type: 'json' } } },
|
||||||
root: { level: 'all' },
|
root: { level: 'all' },
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -180,7 +180,7 @@ test('setContextConfig() updates config with relative contexts', async () => {
|
||||||
|
|
||||||
await system.upgrade(
|
await system.upgrade(
|
||||||
config.schema.validate({
|
config.schema.validate({
|
||||||
appenders: { default: { kind: 'console', layout: { kind: 'json' } } },
|
appenders: { default: { type: 'console', layout: { type: 'json' } } },
|
||||||
root: { level: 'info' },
|
root: { level: 'info' },
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -189,10 +189,10 @@ test('setContextConfig() updates config with relative contexts', async () => {
|
||||||
appenders: new Map([
|
appenders: new Map([
|
||||||
[
|
[
|
||||||
'custom',
|
'custom',
|
||||||
{ kind: 'console', layout: { kind: 'pattern', pattern: '[%level][%logger] %message' } },
|
{ type: 'console', layout: { type: 'pattern', pattern: '[%level][%logger] %message' } },
|
||||||
],
|
],
|
||||||
]),
|
]),
|
||||||
loggers: [{ context: 'grandchild', appenders: ['default', 'custom'], level: 'debug' }],
|
loggers: [{ name: 'grandchild', appenders: ['default', 'custom'], level: 'debug' }],
|
||||||
});
|
});
|
||||||
|
|
||||||
testsLogger.warn('tests log to default!');
|
testsLogger.warn('tests log to default!');
|
||||||
|
@ -235,7 +235,7 @@ test('setContextConfig() updates config for a root context', async () => {
|
||||||
|
|
||||||
await system.upgrade(
|
await system.upgrade(
|
||||||
config.schema.validate({
|
config.schema.validate({
|
||||||
appenders: { default: { kind: 'console', layout: { kind: 'json' } } },
|
appenders: { default: { type: 'console', layout: { type: 'json' } } },
|
||||||
root: { level: 'info' },
|
root: { level: 'info' },
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -244,10 +244,10 @@ test('setContextConfig() updates config for a root context', async () => {
|
||||||
appenders: new Map([
|
appenders: new Map([
|
||||||
[
|
[
|
||||||
'custom',
|
'custom',
|
||||||
{ kind: 'console', layout: { kind: 'pattern', pattern: '[%level][%logger] %message' } },
|
{ type: 'console', layout: { type: 'pattern', pattern: '[%level][%logger] %message' } },
|
||||||
],
|
],
|
||||||
]),
|
]),
|
||||||
loggers: [{ context: '', appenders: ['custom'], level: 'debug' }],
|
loggers: [{ name: '', appenders: ['custom'], level: 'debug' }],
|
||||||
});
|
});
|
||||||
|
|
||||||
testsLogger.warn('tests log to default!');
|
testsLogger.warn('tests log to default!');
|
||||||
|
@ -273,21 +273,21 @@ test('setContextConfig() updates config for a root context', async () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('custom context configs are applied on subsequent calls to update()', async () => {
|
test('custom context name configs are applied on subsequent calls to update()', async () => {
|
||||||
await system.setContextConfig(['tests', 'child'], {
|
await system.setContextConfig(['tests', 'child'], {
|
||||||
appenders: new Map([
|
appenders: new Map([
|
||||||
[
|
[
|
||||||
'custom',
|
'custom',
|
||||||
{ kind: 'console', layout: { kind: 'pattern', pattern: '[%level][%logger] %message' } },
|
{ type: 'console', layout: { type: 'pattern', pattern: '[%level][%logger] %message' } },
|
||||||
],
|
],
|
||||||
]),
|
]),
|
||||||
loggers: [{ context: 'grandchild', appenders: ['default', 'custom'], level: 'debug' }],
|
loggers: [{ name: 'grandchild', appenders: ['default', 'custom'], level: 'debug' }],
|
||||||
});
|
});
|
||||||
|
|
||||||
// Calling upgrade after setContextConfig should not throw away the context-specific config
|
// Calling upgrade after setContextConfig should not throw away the context-specific config
|
||||||
await system.upgrade(
|
await system.upgrade(
|
||||||
config.schema.validate({
|
config.schema.validate({
|
||||||
appenders: { default: { kind: 'console', layout: { kind: 'json' } } },
|
appenders: { default: { type: 'console', layout: { type: 'json' } } },
|
||||||
root: { level: 'info' },
|
root: { level: 'info' },
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -310,10 +310,10 @@ test('custom context configs are applied on subsequent calls to update()', async
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('subsequent calls to setContextConfig() for the same context override the previous config', async () => {
|
test('subsequent calls to setContextConfig() for the same context name override the previous config', async () => {
|
||||||
await system.upgrade(
|
await system.upgrade(
|
||||||
config.schema.validate({
|
config.schema.validate({
|
||||||
appenders: { default: { kind: 'console', layout: { kind: 'json' } } },
|
appenders: { default: { type: 'console', layout: { type: 'json' } } },
|
||||||
root: { level: 'info' },
|
root: { level: 'info' },
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -322,10 +322,10 @@ test('subsequent calls to setContextConfig() for the same context override the p
|
||||||
appenders: new Map([
|
appenders: new Map([
|
||||||
[
|
[
|
||||||
'custom',
|
'custom',
|
||||||
{ kind: 'console', layout: { kind: 'pattern', pattern: '[%level][%logger] %message' } },
|
{ type: 'console', layout: { type: 'pattern', pattern: '[%level][%logger] %message' } },
|
||||||
],
|
],
|
||||||
]),
|
]),
|
||||||
loggers: [{ context: 'grandchild', appenders: ['default', 'custom'], level: 'debug' }],
|
loggers: [{ name: 'grandchild', appenders: ['default', 'custom'], level: 'debug' }],
|
||||||
});
|
});
|
||||||
|
|
||||||
// Call again, this time with level: 'warn' and a different pattern
|
// Call again, this time with level: 'warn' and a different pattern
|
||||||
|
@ -334,12 +334,12 @@ test('subsequent calls to setContextConfig() for the same context override the p
|
||||||
[
|
[
|
||||||
'custom',
|
'custom',
|
||||||
{
|
{
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: { kind: 'pattern', pattern: '[%level][%logger] second pattern! %message' },
|
layout: { type: 'pattern', pattern: '[%level][%logger] second pattern! %message' },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
]),
|
]),
|
||||||
loggers: [{ context: 'grandchild', appenders: ['default', 'custom'], level: 'warn' }],
|
loggers: [{ name: 'grandchild', appenders: ['default', 'custom'], level: 'warn' }],
|
||||||
});
|
});
|
||||||
|
|
||||||
const logger = system.get('tests', 'child', 'grandchild');
|
const logger = system.get('tests', 'child', 'grandchild');
|
||||||
|
@ -360,10 +360,10 @@ test('subsequent calls to setContextConfig() for the same context override the p
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('subsequent calls to setContextConfig() for the same context can disable the previous config', async () => {
|
test('subsequent calls to setContextConfig() for the same context name can disable the previous config', async () => {
|
||||||
await system.upgrade(
|
await system.upgrade(
|
||||||
config.schema.validate({
|
config.schema.validate({
|
||||||
appenders: { default: { kind: 'console', layout: { kind: 'json' } } },
|
appenders: { default: { type: 'console', layout: { type: 'json' } } },
|
||||||
root: { level: 'info' },
|
root: { level: 'info' },
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -372,10 +372,10 @@ test('subsequent calls to setContextConfig() for the same context can disable th
|
||||||
appenders: new Map([
|
appenders: new Map([
|
||||||
[
|
[
|
||||||
'custom',
|
'custom',
|
||||||
{ kind: 'console', layout: { kind: 'pattern', pattern: '[%level][%logger] %message' } },
|
{ type: 'console', layout: { type: 'pattern', pattern: '[%level][%logger] %message' } },
|
||||||
],
|
],
|
||||||
]),
|
]),
|
||||||
loggers: [{ context: 'grandchild', appenders: ['default', 'custom'], level: 'debug' }],
|
loggers: [{ name: 'grandchild', appenders: ['default', 'custom'], level: 'debug' }],
|
||||||
});
|
});
|
||||||
|
|
||||||
// Call again, this time no customizations (effectively disabling)
|
// Call again, this time no customizations (effectively disabling)
|
||||||
|
|
|
@ -79,7 +79,7 @@ export class LoggingSystem implements LoggerFactory {
|
||||||
* loggingSystem.setContextConfig(
|
* loggingSystem.setContextConfig(
|
||||||
* ['plugins', 'data'],
|
* ['plugins', 'data'],
|
||||||
* {
|
* {
|
||||||
* loggers: [{ context: 'search', appenders: ['default'] }]
|
* loggers: [{ name: 'search', appenders: ['default'] }]
|
||||||
* }
|
* }
|
||||||
* )
|
* )
|
||||||
* ```
|
* ```
|
||||||
|
@ -95,9 +95,7 @@ export class LoggingSystem implements LoggerFactory {
|
||||||
// Automatically prepend the base context to the logger sub-contexts
|
// Automatically prepend the base context to the logger sub-contexts
|
||||||
loggers: contextConfig.loggers.map((l) => ({
|
loggers: contextConfig.loggers.map((l) => ({
|
||||||
...l,
|
...l,
|
||||||
context: LoggingConfig.getLoggerContext(
|
name: LoggingConfig.getLoggerContext(l.name.length > 0 ? [context, l.name] : [context]),
|
||||||
l.context.length > 0 ? [context, l.context] : [context]
|
|
||||||
),
|
|
||||||
})),
|
})),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -45,16 +45,16 @@ describe('migration v2', () => {
|
||||||
logging: {
|
logging: {
|
||||||
appenders: {
|
appenders: {
|
||||||
file: {
|
file: {
|
||||||
kind: 'file',
|
type: 'file',
|
||||||
path: join(__dirname, 'migration_test_kibana.log'),
|
fileName: join(__dirname, 'migration_test_kibana.log'),
|
||||||
layout: {
|
layout: {
|
||||||
kind: 'json',
|
type: 'json',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
loggers: [
|
loggers: [
|
||||||
{
|
{
|
||||||
context: 'root',
|
name: 'root',
|
||||||
appenders: ['file'],
|
appenders: ['file'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -47,16 +47,16 @@ describe.skip('migration from 7.7.2-xpack with 100k objects', () => {
|
||||||
logging: {
|
logging: {
|
||||||
appenders: {
|
appenders: {
|
||||||
file: {
|
file: {
|
||||||
kind: 'file',
|
type: 'file',
|
||||||
path: join(__dirname, 'migration_test_kibana.log'),
|
fileName: join(__dirname, 'migration_test_kibana.log'),
|
||||||
layout: {
|
layout: {
|
||||||
kind: 'json',
|
type: 'json',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
loggers: [
|
loggers: [
|
||||||
{
|
{
|
||||||
context: 'root',
|
name: 'root',
|
||||||
appenders: ['file'],
|
appenders: ['file'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -76,9 +76,9 @@ describe('#setup', () => {
|
||||||
config: {
|
config: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
appender: {
|
appender: {
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: {
|
layout: {
|
||||||
kind: 'pattern',
|
type: 'pattern',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -102,9 +102,9 @@ describe('#setup', () => {
|
||||||
config: {
|
config: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
appender: {
|
appender: {
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: {
|
layout: {
|
||||||
kind: 'pattern',
|
type: 'pattern',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -251,9 +251,9 @@ describe('#createLoggingConfig', () => {
|
||||||
createLoggingConfig({
|
createLoggingConfig({
|
||||||
enabled: true,
|
enabled: true,
|
||||||
appender: {
|
appender: {
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: {
|
layout: {
|
||||||
kind: 'pattern',
|
type: 'pattern',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -264,10 +264,10 @@ describe('#createLoggingConfig', () => {
|
||||||
Object {
|
Object {
|
||||||
"appenders": Object {
|
"appenders": Object {
|
||||||
"auditTrailAppender": Object {
|
"auditTrailAppender": Object {
|
||||||
"kind": "console",
|
|
||||||
"layout": Object {
|
"layout": Object {
|
||||||
"kind": "pattern",
|
"type": "pattern",
|
||||||
},
|
},
|
||||||
|
"type": "console",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"loggers": Array [
|
"loggers": Array [
|
||||||
|
@ -275,8 +275,8 @@ describe('#createLoggingConfig', () => {
|
||||||
"appenders": Array [
|
"appenders": Array [
|
||||||
"auditTrailAppender",
|
"auditTrailAppender",
|
||||||
],
|
],
|
||||||
"context": "audit.ecs",
|
|
||||||
"level": "info",
|
"level": "info",
|
||||||
|
"name": "audit.ecs",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
@ -293,9 +293,9 @@ describe('#createLoggingConfig', () => {
|
||||||
createLoggingConfig({
|
createLoggingConfig({
|
||||||
enabled: false,
|
enabled: false,
|
||||||
appender: {
|
appender: {
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: {
|
layout: {
|
||||||
kind: 'pattern',
|
type: 'pattern',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -331,9 +331,9 @@ describe('#createLoggingConfig', () => {
|
||||||
createLoggingConfig({
|
createLoggingConfig({
|
||||||
enabled: true,
|
enabled: true,
|
||||||
appender: {
|
appender: {
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: {
|
layout: {
|
||||||
kind: 'pattern',
|
type: 'pattern',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -224,16 +224,16 @@ export const createLoggingConfig = (config: ConfigType['audit']) =>
|
||||||
map<Pick<SecurityLicenseFeatures, 'allowAuditLogging'>, LoggerContextConfigInput>((features) => ({
|
map<Pick<SecurityLicenseFeatures, 'allowAuditLogging'>, LoggerContextConfigInput>((features) => ({
|
||||||
appenders: {
|
appenders: {
|
||||||
auditTrailAppender: config.appender ?? {
|
auditTrailAppender: config.appender ?? {
|
||||||
kind: 'console',
|
type: 'console',
|
||||||
layout: {
|
layout: {
|
||||||
kind: 'pattern',
|
type: 'pattern',
|
||||||
highlight: true,
|
highlight: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
loggers: [
|
loggers: [
|
||||||
{
|
{
|
||||||
context: 'audit.ecs',
|
name: 'audit.ecs',
|
||||||
level: config.enabled && config.appender && features.allowAuditLogging ? 'info' : 'off',
|
level: config.enabled && config.appender && features.allowAuditLogging ? 'info' : 'off',
|
||||||
appenders: ['auditTrailAppender'],
|
appenders: ['auditTrailAppender'],
|
||||||
},
|
},
|
||||||
|
|
|
@ -1558,21 +1558,21 @@ describe('createConfig()', () => {
|
||||||
ConfigSchema.validate({
|
ConfigSchema.validate({
|
||||||
audit: {
|
audit: {
|
||||||
appender: {
|
appender: {
|
||||||
kind: 'file',
|
type: 'file',
|
||||||
path: '/path/to/file.txt',
|
fileName: '/path/to/file.txt',
|
||||||
layout: {
|
layout: {
|
||||||
kind: 'json',
|
type: 'json',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}).audit.appender
|
}).audit.appender
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
Object {
|
Object {
|
||||||
"kind": "file",
|
"fileName": "/path/to/file.txt",
|
||||||
"layout": Object {
|
"layout": Object {
|
||||||
"kind": "json",
|
"type": "json",
|
||||||
},
|
},
|
||||||
"path": "/path/to/file.txt",
|
"type": "file",
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
@ -1583,12 +1583,12 @@ describe('createConfig()', () => {
|
||||||
audit: {
|
audit: {
|
||||||
// no layout configured
|
// no layout configured
|
||||||
appender: {
|
appender: {
|
||||||
kind: 'file',
|
type: 'file',
|
||||||
path: '/path/to/file.txt',
|
path: '/path/to/file.txt',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
).toThrow('[audit.appender.2.kind]: expected value to equal [legacy-appender]');
|
).toThrow('[audit.appender.2.type]: expected value to equal [legacy-appender]');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('rejects an ignore_filter when no appender is configured', () => {
|
it('rejects an ignore_filter when no appender is configured', () => {
|
||||||
|
|
|
@ -52,6 +52,117 @@ describe('Config Deprecations', () => {
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('renames audit.appender.kind to audit.appender.type', () => {
|
||||||
|
const config = {
|
||||||
|
xpack: {
|
||||||
|
security: {
|
||||||
|
audit: {
|
||||||
|
appender: {
|
||||||
|
kind: 'console',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const { messages, migrated } = applyConfigDeprecations(cloneDeep(config));
|
||||||
|
expect(migrated.xpack.security.audit.appender.kind).not.toBeDefined();
|
||||||
|
expect(migrated.xpack.security.audit.appender.type).toEqual('console');
|
||||||
|
expect(messages).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
"\\"xpack.security.audit.appender.kind\\" is deprecated and has been replaced by \\"xpack.security.audit.appender.type\\"",
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renames audit.appender.layout.kind to audit.appender.layout.type', () => {
|
||||||
|
const config = {
|
||||||
|
xpack: {
|
||||||
|
security: {
|
||||||
|
audit: {
|
||||||
|
appender: {
|
||||||
|
layout: { kind: 'pattern' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const { messages, migrated } = applyConfigDeprecations(cloneDeep(config));
|
||||||
|
expect(migrated.xpack.security.audit.appender.layout.kind).not.toBeDefined();
|
||||||
|
expect(migrated.xpack.security.audit.appender.layout.type).toEqual('pattern');
|
||||||
|
expect(messages).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
"\\"xpack.security.audit.appender.layout.kind\\" is deprecated and has been replaced by \\"xpack.security.audit.appender.layout.type\\"",
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renames audit.appender.policy.kind to audit.appender.policy.type', () => {
|
||||||
|
const config = {
|
||||||
|
xpack: {
|
||||||
|
security: {
|
||||||
|
audit: {
|
||||||
|
appender: {
|
||||||
|
policy: { kind: 'time-interval' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const { messages, migrated } = applyConfigDeprecations(cloneDeep(config));
|
||||||
|
expect(migrated.xpack.security.audit.appender.policy.kind).not.toBeDefined();
|
||||||
|
expect(migrated.xpack.security.audit.appender.policy.type).toEqual('time-interval');
|
||||||
|
expect(messages).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
"\\"xpack.security.audit.appender.policy.kind\\" is deprecated and has been replaced by \\"xpack.security.audit.appender.policy.type\\"",
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renames audit.appender.strategy.kind to audit.appender.strategy.type', () => {
|
||||||
|
const config = {
|
||||||
|
xpack: {
|
||||||
|
security: {
|
||||||
|
audit: {
|
||||||
|
appender: {
|
||||||
|
strategy: { kind: 'numeric' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const { messages, migrated } = applyConfigDeprecations(cloneDeep(config));
|
||||||
|
expect(migrated.xpack.security.audit.appender.strategy.kind).not.toBeDefined();
|
||||||
|
expect(migrated.xpack.security.audit.appender.strategy.type).toEqual('numeric');
|
||||||
|
expect(messages).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
"\\"xpack.security.audit.appender.strategy.kind\\" is deprecated and has been replaced by \\"xpack.security.audit.appender.strategy.type\\"",
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renames audit.appender.path to audit.appender.fileName', () => {
|
||||||
|
const config = {
|
||||||
|
xpack: {
|
||||||
|
security: {
|
||||||
|
audit: {
|
||||||
|
appender: {
|
||||||
|
type: 'file',
|
||||||
|
path: './audit.log',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const { messages, migrated } = applyConfigDeprecations(cloneDeep(config));
|
||||||
|
expect(migrated.xpack.security.audit.appender.path).not.toBeDefined();
|
||||||
|
expect(migrated.xpack.security.audit.appender.fileName).toEqual('./audit.log');
|
||||||
|
expect(messages).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
"\\"xpack.security.audit.appender.path\\" is deprecated and has been replaced by \\"xpack.security.audit.appender.fileName\\"",
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
it(`warns that 'authorization.legacyFallback.enabled' is unused`, () => {
|
it(`warns that 'authorization.legacyFallback.enabled' is unused`, () => {
|
||||||
const config = {
|
const config = {
|
||||||
xpack: {
|
xpack: {
|
||||||
|
|
|
@ -12,6 +12,13 @@ export const securityConfigDeprecationProvider: ConfigDeprecationProvider = ({
|
||||||
unused,
|
unused,
|
||||||
}) => [
|
}) => [
|
||||||
rename('sessionTimeout', 'session.idleTimeout'),
|
rename('sessionTimeout', 'session.idleTimeout'),
|
||||||
|
|
||||||
|
rename('audit.appender.kind', 'audit.appender.type'),
|
||||||
|
rename('audit.appender.layout.kind', 'audit.appender.layout.type'),
|
||||||
|
rename('audit.appender.policy.kind', 'audit.appender.policy.type'),
|
||||||
|
rename('audit.appender.strategy.kind', 'audit.appender.strategy.type'),
|
||||||
|
rename('audit.appender.path', 'audit.appender.fileName'),
|
||||||
|
|
||||||
unused('authorization.legacyFallback.enabled'),
|
unused('authorization.legacyFallback.enabled'),
|
||||||
unused('authc.saml.maxRedirectURLSize'),
|
unused('authc.saml.maxRedirectURLSize'),
|
||||||
// Deprecation warning for the old array-based format of `xpack.security.authc.providers`.
|
// Deprecation warning for the old array-based format of `xpack.security.authc.providers`.
|
||||||
|
|
|
@ -29,9 +29,9 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
||||||
...xPackAPITestsConfig.get('kbnTestServer.serverArgs'),
|
...xPackAPITestsConfig.get('kbnTestServer.serverArgs'),
|
||||||
`--plugin-path=${auditLogPlugin}`,
|
`--plugin-path=${auditLogPlugin}`,
|
||||||
'--xpack.security.audit.enabled=true',
|
'--xpack.security.audit.enabled=true',
|
||||||
'--xpack.security.audit.appender.kind=file',
|
'--xpack.security.audit.appender.type=file',
|
||||||
`--xpack.security.audit.appender.path=${auditLogPath}`,
|
`--xpack.security.audit.appender.fileName=${auditLogPath}`,
|
||||||
'--xpack.security.audit.appender.layout.kind=json',
|
'--xpack.security.audit.appender.layout.type=json',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue