UNPKG

2.46 kBJavaScriptView Raw
1const Transport = require('winston-transport')
2const Batcher = require('./src/batcher')
3const { MESSAGE } = require('triple-beam')
4
5/**
6 * A Winston transport for Grafana Loki.
7 *
8 * @class LokiTransport
9 * @extends {Transport}
10 */
11class LokiTransport extends Transport {
12 /**
13 * Creates an instance of LokiTransport.
14 * @param {*} options
15 * @memberof LokiTransport
16 */
17 constructor (options) {
18 super(options)
19
20 // Pass all the given options to batcher
21 this.batcher = new Batcher({
22 host: options.host,
23 basicAuth: options.basicAuth,
24 headers: options.headers || {},
25 interval: options.interval,
26 json: options.json,
27 batching: options.batching !== false,
28 clearOnError: options.clearOnError,
29 replaceOnError: options.replaceOnError,
30 replaceTimestamp: options.replaceTimestamp,
31 gracefulShutdown: options.gracefulShutdown !== false,
32 timeout: options.timeout
33 })
34
35 this.useCustomFormat = options.format !== undefined
36 this.labels = options.labels
37 }
38
39 /**
40 * An overwrite of winston-transport's log(),
41 * which the Winston logging library uses
42 * when pushing logs to a transport.
43 *
44 * @param {*} info
45 * @param {*} callback
46 * @memberof LokiTransport
47 */
48 log (info, callback) {
49 // Immediately tell Winston that this transport has received the log.
50 setImmediate(() => {
51 this.emit('logged', info)
52 })
53
54 // Deconstruct the log
55 const { label, labels, timestamp, level, message, ...rest } = info
56
57 // build custom labels if provided
58 let lokiLabels = { level: level }
59 lokiLabels = Object.assign(lokiLabels, labels)
60
61 if (this.labels) {
62 lokiLabels = Object.assign(lokiLabels, this.labels)
63 } else {
64 lokiLabels['job'] = label
65 }
66
67 // follow the format provided
68 const line = this.useCustomFormat ? info[MESSAGE] : `${message} ${
69 rest && Object.keys(rest).length > 0 ? JSON.stringify(rest) : ''
70 }`
71
72 // Construct the log to fit Grafana Loki's accepted format
73 const logEntry = {
74 labels: lokiLabels,
75 entries: [
76 {
77 ts: timestamp || Date.now().valueOf(),
78 line
79 }
80 ]
81 }
82
83 // Pushes the log to the batcher
84 this.batcher.pushLogEntry(logEntry)
85
86 // Trigger the optional callback
87 callback()
88 }
89
90 /**
91 * Send batch to loki when clean up
92 */
93 close () {
94 this.batcher.close()
95 }
96}
97
98module.exports = LokiTransport