From abab9fc8c5a35d007f13fd5a81c23843ee996ee7 Mon Sep 17 00:00:00 2001 From: Spencer Date: Wed, 8 Nov 2017 08:43:52 -0700 Subject: [PATCH] [server/logging] Allow opting out of UTC (#14705) * [server/logging] make use of UTC configurable * [server/logging/tests] try removing TZ from moment * [server/log/formatJson] use strict equality checks * [server/log/format] note in method name that time is extracted (cherry picked from commit b79ba98889f54f21507f68236a8f73413f05a10f) --- src/server/config/schema.js | 4 +- .../logging/__tests__/log_format_json.js | 49 +++++++++++++++++++ .../logging/__tests__/log_format_string.js | 49 +++++++++++++++++++ src/server/logging/configuration.js | 2 + src/server/logging/log_format.js | 11 ++++- src/server/logging/log_format_json.js | 1 + src/server/logging/log_format_string.js | 5 +- 7 files changed, 116 insertions(+), 5 deletions(-) create mode 100644 src/server/logging/__tests__/log_format_json.js create mode 100644 src/server/logging/__tests__/log_format_string.js diff --git a/src/server/config/schema.js b/src/server/config/schema.js index 5a8e14d16e58a..e3438e23b611b 100644 --- a/src/server/config/schema.js +++ b/src/server/config/schema.js @@ -108,7 +108,9 @@ export default () => Joi.object({ is: 'stdout', then: Joi.default(!process.stdout.isTTY), otherwise: Joi.default(true) - }) + }), + + useUTC: Joi.boolean().default(true), }) .default(), diff --git a/src/server/logging/__tests__/log_format_json.js b/src/server/logging/__tests__/log_format_json.js new file mode 100644 index 0000000000000..1d698acebe565 --- /dev/null +++ b/src/server/logging/__tests__/log_format_json.js @@ -0,0 +1,49 @@ +import moment from 'moment'; +import expect from 'expect.js'; + +import { + createListStream, + createPromiseFromStreams, +} from '../../../utils'; + +import KbnLoggerJsonFormat from '../log_format_json'; + +const time = +moment('2010-01-01T05:15:59Z', moment.ISO_8601); + +const makeEvent = () => ({ + event: 'log', + timestamp: time, + tags: ['tag'], + pid: 1, + data: 'my log message' +}); + +describe('KbnLoggerJsonFormat', () => { + it('logs in UTC when useUTC is true', async () => { + const format = new KbnLoggerJsonFormat({ + useUTC: true + }); + + const result = await createPromiseFromStreams([ + createListStream([makeEvent()]), + format + ]); + + const { '@timestamp': timestamp } = JSON.parse(result); + expect(timestamp).to.be(moment.utc(time).format()); + }); + + it('logs in local timezone when useUTC is false', async () => { + const format = new KbnLoggerJsonFormat({ + useUTC: false + }); + + const result = await createPromiseFromStreams([ + createListStream([makeEvent()]), + format + ]); + + const { '@timestamp': timestamp } = JSON.parse(result); + expect(timestamp).to.be(moment(time).format()); + }); +}); diff --git a/src/server/logging/__tests__/log_format_string.js b/src/server/logging/__tests__/log_format_string.js new file mode 100644 index 0000000000000..bb9cfbbdad86f --- /dev/null +++ b/src/server/logging/__tests__/log_format_string.js @@ -0,0 +1,49 @@ +import moment from 'moment'; +import expect from 'expect.js'; + +import { + createListStream, + createPromiseFromStreams, +} from '../../../utils'; + +import KbnLoggerStringFormat from '../log_format_string'; + +const time = +moment('2010-01-01T05:15:59Z', moment.ISO_8601); + +const makeEvent = () => ({ + event: 'log', + timestamp: time, + tags: ['tag'], + pid: 1, + data: 'my log message' +}); + +describe('KbnLoggerStringFormat', () => { + it('logs in UTC when useUTC is true', async () => { + const format = new KbnLoggerStringFormat({ + useUTC: true + }); + + const result = await createPromiseFromStreams([ + createListStream([makeEvent()]), + format + ]); + + expect(String(result)) + .to.contain(moment.utc(time).format('HH:mm:ss.SSS')); + }); + + it('logs in local timezone when useUTC is false', async () => { + const format = new KbnLoggerStringFormat({ + useUTC: false + }); + + const result = await createPromiseFromStreams([ + createListStream([makeEvent()]), + format + ]); + + expect(String(result)).to + .contain(moment(time).format('HH:mm:ss.SSS')); + }); +}); diff --git a/src/server/logging/configuration.js b/src/server/logging/configuration.js index be66a2e738c8b..eb6855ca23f09 100644 --- a/src/server/logging/configuration.js +++ b/src/server/logging/configuration.js @@ -42,6 +42,8 @@ export default function loggingConfiguration(config) { config: { json: config.get('logging.json'), dest: config.get('logging.dest'), + useUTC: config.get('logging.useUTC'), + // I'm adding the default here because if you add another filter // using the commandline it will remove authorization. I want users // to have to explicitly set --logging.filter.authorization=none or diff --git a/src/server/logging/log_format.js b/src/server/logging/log_format.js index 5eca51b846aaa..4e5f7cc70eb3a 100644 --- a/src/server/logging/log_format.js +++ b/src/server/logging/log_format.js @@ -46,10 +46,19 @@ export default class TransformObjStream extends Stream.Transform { next(); } + extractAndFormatTimestamp(data, format) { + const { useUTC } = this.config; + const date = moment(data['@timestamp']); + if (useUTC) { + date.utc(); + } + return date.format(format); + } + readEvent(event) { const data = { type: event.event, - '@timestamp': moment.utc(event.timestamp).format(), + '@timestamp': event.timestamp, tags: [].concat(event.tags || []), pid: event.pid }; diff --git a/src/server/logging/log_format_json.js b/src/server/logging/log_format_json.js index a94a463912e48..9fa4e7fa088b1 100644 --- a/src/server/logging/log_format_json.js +++ b/src/server/logging/log_format_json.js @@ -8,6 +8,7 @@ const stripColors = function (string) { export default class KbnLoggerJsonFormat extends LogFormat { format(data) { data.message = stripColors(data.message); + data['@timestamp'] = this.extractAndFormatTimestamp(data); return stringify(data); } } diff --git a/src/server/logging/log_format_string.js b/src/server/logging/log_format_string.js index 873f77a910898..0cc68be93e024 100644 --- a/src/server/logging/log_format_string.js +++ b/src/server/logging/log_format_string.js @@ -1,6 +1,5 @@ import _ from 'lodash'; import ansicolors from 'ansicolors'; -import moment from 'moment'; import LogFormat from './log_format'; @@ -44,9 +43,9 @@ const type = _.memoize(function (t) { const workerType = process.env.kbnWorkerType ? `${type(process.env.kbnWorkerType)} ` : ''; -export default class KbnLoggerJsonFormat extends LogFormat { +export default class KbnLoggerStringFormat extends LogFormat { format(data) { - const time = color('time')(moment(data.timestamp).utc().format('HH:mm:ss.SSS')); + const time = color('time')(this.extractAndFormatTimestamp(data, 'HH:mm:ss.SSS')); const msg = data.error ? color('error')(data.error.stack) : color('message')(data.message); const tags = _(data.tags)