Skip to content

Commit e4beebb

Browse files
robyte-ctrlRoman UNTILOV
andauthored
fix support for elasticsearch v7 + add types (#169)
* fix support for elasticsearch v7 + add types * add tests for types + minor improvements * add back tls option --------- Co-authored-by: Roman UNTILOV <[email protected]>
1 parent 2610f4d commit e4beebb

File tree

10 files changed

+422
-148
lines changed

10 files changed

+422
-148
lines changed

README.md

Lines changed: 26 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ npm install pino-elasticsearch -g
2727
-t | --type the name of the type to use; default: log
2828
-f | --flush-bytes the number of bytes for each bulk insert; default: 1000
2929
-t | --flush-interval time that the helper will wait before flushing; default: 30000
30-
-b | --bulk-size the number of documents for each bulk insert [DEPRECATED]
3130
-l | --trace-level trace level for the elasticsearch client, default 'error' (info, debug, trace).
3231
| --es-version specify the major version number of Elasticsearch (eg: 5, 6, 7)
3332
(this is needed only if you are using Elasticsearch <= 7)
@@ -50,10 +49,9 @@ const pinoElastic = require('pino-elasticsearch')
5049

5150
const streamToElastic = pinoElastic({
5251
index: 'an-index',
53-
consistency: 'one',
5452
node: 'http://localhost:9200',
55-
'es-version': 7,
56-
'flush-bytes': 1000
53+
esVersion: 7,
54+
flushBytes: 1000
5755
})
5856

5957
const logger = pino({ level: 'info' }, streamToElastic)
@@ -72,10 +70,9 @@ const pinoMultiStream = require('pino-multi-stream').multistream;
7270

7371
const streamToElastic = pinoElastic({
7472
index: 'an-index',
75-
consistency: 'one',
7673
node: 'http://localhost:9200',
77-
'es-version': 7,
78-
'flush-bytes': 1000
74+
esVersion: 7,
75+
flushBytes: 1000
7976
});
8077

8178
const pinoOptions = {};
@@ -100,10 +97,9 @@ const Connection = <custom Connection>
10097

10198
const streamToElastic = pinoElastic({
10299
index: 'an-index',
103-
consistency: 'one',
104100
node: 'http://localhost:9200',
105-
'es-version': 7,
106-
'flush-bytes': 1000,
101+
esVersion: 7,
102+
flushBytes: 1000,
107103
Connection
108104
})
109105

@@ -124,10 +120,9 @@ const pinoElastic = require('pino-elasticsearch');
124120

125121
const streamToElastic = pinoElastic({
126122
index: 'an-index',
127-
consistency: 'one',
128123
node: 'http://localhost:9200',
129-
'es-version': 7,
130-
'flush-bytes': 1000
124+
esVersion: 7,
125+
flushBytes: 1000
131126
})
132127

133128
streamToElastic.on('<event>', (error) => console.log(event));
@@ -137,7 +132,7 @@ The following table lists the events emitted by the stream handler:
137132

138133
| Event | Callback Signature | Description |
139134
| ----- | ------------------ | ----------- |
140-
| `unknown` | `(line: string, error: string) => void` | Event received by `pino-elasticsearch` is unparseable (via `JSON.parse`) |
135+
| `unknown` | `(line: string, error: string) => void` | Event received by `pino-elasticsearch` is unparsable (via `JSON.parse`) |
141136
| `insertError` | `(error: Error & { document: Record<string, any> }) => void` | The bulk insert request to Elasticsearch failed (records dropped). |
142137
| `insert` | `(stats: Record<string, any>) => void` | Called when an insert was successfully performed |
143138
| `error` | `(error: Error) => void` | Called when the Elasticsearch client fails for some other reason |
@@ -154,10 +149,9 @@ const pinoElastic = require('pino-elasticsearch');
154149

155150
const streamToElastic = pinoElastic({
156151
index: 'an-index',
157-
consistency: 'one',
158152
node: 'http://localhost:9200',
159-
'es-version': 7,
160-
'flush-bytes': 1000
153+
esVersion: 7,
154+
flushBytes: 1000
161155
})
162156

163157
streamToElastic.on(
@@ -198,10 +192,9 @@ const pinoElastic = require('pino-elasticsearch')
198192

199193
const streamToElastic = pinoElastic({
200194
index: 'an-index',
201-
consistency: 'one',
202195
node: 'http://localhost:9200',
203-
'es-version': 7,
204-
'flush-bytes': 1000
196+
esVersion: 7,
197+
flushBytes: 1000
205198
})
206199

207200
const logger = pino({ level: 'info', ...ecsFormat }, streamToElastic)
@@ -227,7 +220,6 @@ const streamToElastic = pinoElastic({
227220
// the logTime is a ISO 8601 formatted string of the log line
228221
return `awesome-app-${logTime.substring(5, 10)}`
229222
},
230-
consistency: 'one',
231223
node: 'http://localhost:9200'
232224
})
233225
// ...
@@ -237,44 +229,42 @@ The function **must** be sync, doesn't throw and return a string.
237229

238230
#### Datastreams
239231

240-
Indexing to datastreams requires the `op_type` to be set to `create`:
232+
Indexing to datastreams requires the `opType` to be set to `create`:
241233
```js
242234
const pino = require('pino')
243235
const pinoElastic = require('pino-elasticsearch')
244236

245237
const streamToElastic = pinoElastic({
246238
index: "type-dataset-namespace",
247-
consistency: 'one',
248239
node: 'http://localhost:9200',
249-
op_type: 'create'
240+
opType: 'create'
250241
})
251242
// ...
252243
```
253244

254245
#### Error handling
255246
```js
256247
const pino = require('pino')
257-
const ecsFormat = require('@elastic/ecs-pino-format')()
248+
const ecsFormat = require('@elastic/ecs-pino-format')
258249
const pinoElastic = require('pino-elasticsearch')
259250

260251
const streamToElastic = pinoElastic({
261252
index: 'an-index',
262-
consistency: 'one',
263253
node: 'http://localhost:9200',
264-
'es-version': 7,
265-
'flush-bytes': 1000
254+
esVersion: 7,
255+
flushBytes: 1000
266256
})
267257

268258
// Capture errors like unable to connect Elasticsearch instance.
269259
streamToElastic.on('error', (error) => {
270260
console.error('Elasticsearch client error:', error);
271261
})
272-
// Capture errors returned from Elasticsearch, "it will be called for everytime a document can't be indexed".
262+
// Capture errors returned from Elasticsearch, "it will be called every time a document can't be indexed".
273263
streamToElastic.on('insertError', (error) => {
274264
console.error('Elasticsearch server error:', error);
275265
})
276266

277-
const logger = pino({ level: 'info', ...ecsFormat }, streamToElastic)
267+
const logger = pino({ level: 'info', ...ecsFormat() }, streamToElastic)
278268

279269
logger.info('hello world')
280270
```
@@ -306,14 +296,13 @@ const pinoElastic = require('pino-elasticsearch')
306296

307297
const streamToElastic = pinoElastic({
308298
index: 'an-index',
309-
consistency: 'one',
310299
node: 'http://localhost:9200',
311300
auth: {
312301
username: 'user',
313302
password: 'pwd'
314303
},
315-
'es-version': 7,
316-
'flush-bytes': 1000
304+
esVersion: 7,
305+
flushBytes: 1000
317306
})
318307
```
319308

@@ -323,16 +312,15 @@ const pinoElastic = require('pino-elasticsearch')
323312

324313
const streamToElastic = pinoElastic({
325314
index: 'an-index',
326-
consistency: 'one',
327315
node: 'http://localhost:9200',
328316
cloud: {
329317
id: 'name:bG9jYWxob3N0JGFiY2QkZWZnaA=='
330318
},
331319
auth: {
332320
apiKey: 'apikey123'
333321
},
334-
'es-version': 7,
335-
'flush-bytes': 1000
322+
esVersion: 7,
323+
flushBytes: 1000
336324
})
337325
```
338326

@@ -345,9 +333,8 @@ use pino-elasticsearch as a module is simple, use [pino-multi-stream](https://ww
345333
```js
346334
const pinoms = require('pino-multi-stream')
347335
const pinoEs = require('pino-elasticsearch')({
348-
host: '192.168.1.220',
349-
index: 'zb',
350-
port: '9200'
336+
node: 'http://192.168.1.220:9200',
337+
index: 'zb'
351338
})
352339

353340
const logger = pinoms({
@@ -366,8 +353,6 @@ logger.error('error')
366353

367354
```
368355

369-
*** Notice, the `host` and `port` parameters of `pino-elasticsearch` are required ***
370-
371356
## Setup and Testing
372357

373358
Setting up pino-elasticsearch is easy, and you can use the bundled

cli.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ const flags = minimist(process.argv.slice(2), {
5757
help: 'h',
5858
node: 'n',
5959
index: 'i',
60-
'bulk-size': 'b',
6160
'flush-bytes': 'f',
6261
'flush-interval': 't',
6362
'trace-level': 'l',
@@ -72,7 +71,7 @@ const flags = minimist(process.argv.slice(2), {
7271
}
7372
})
7473

75-
const allowedProps = ['node', 'index', 'bulk-size', 'flush-btyes', 'flush-interval', 'trace-level', 'username', 'password', 'api-key', 'cloud', 'es-version', 'rejectUnauthorized']
74+
const allowedProps = ['node', 'index', 'flush-bytes', 'flush-interval', 'trace-level', 'username', 'password', 'api-key', 'cloud', 'es-version', 'rejectUnauthorized']
7675

7776
if (flags['read-config']) {
7877
if (flags['read-config'].match(/.*\.json$/) !== null) {

example.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@ const elastic = require('./lib')({
77
auth: {
88
apiKey: 'someKey'
99
},
10-
consistency: 'one',
11-
'es-version': 7,
12-
'flush-bytes': 1000
10+
esVersion: 7,
11+
flushBytes: 1000
1312
})
1413

1514
const level = 'trace'

lib.d.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import type { Transform } from 'stream'
2+
import type { ClientOptions } from '@elastic/elasticsearch'
3+
4+
export default pinoElasticsearch
5+
6+
declare function pinoElasticsearch(options?: Options): DestinationStream
7+
8+
export type DestinationStream = Transform & {
9+
/**
10+
* when something, that cannot be parsed, is encountered
11+
*/
12+
on(event: 'unknown', handler: (line: string, error: string) => void): void
13+
/**
14+
* when a bulk insert request failed which resulted in logs being dropped
15+
*/
16+
on(event: 'insertError', handler: (error: Error & { document: Record<string, any> }) => void): void
17+
/**
18+
* when a batch of logs was sent successfully
19+
*/
20+
on(event: 'insert', handler: (stats: Record<string, any>) => void): void
21+
/**
22+
* when some other kind of error happened, e.g. connection issues
23+
*/
24+
on(event: 'error', handler: (error: Error) => void): void
25+
}
26+
27+
export type Options = Pick<ClientOptions, 'node' | 'auth' | 'cloud' | 'caFingerprint' | 'Connection' | 'ConnectionPool'> & {
28+
index?: Index
29+
30+
type?: string
31+
32+
/** @deprecated use `opType` instead */
33+
op_type?: OpType;
34+
opType?: OpType;
35+
36+
/** @deprecated use `flushBytes` instead */
37+
'flush-bytes'?: number | undefined
38+
flushBytes?: number | undefined
39+
40+
/** @deprecated use `flushInterval` instead */
41+
'flush-interval'?: number | undefined
42+
flushInterval?: number | undefined
43+
44+
/** @deprecated use `esVersion` instead */
45+
'es-version'?: number | undefined
46+
esVersion?: number | undefined
47+
48+
/** @deprecated use `tls.rejectUnauthorized` instead */
49+
rejectUnauthorized?: boolean
50+
51+
tls?: ClientOptions['ssl'];
52+
}
53+
54+
export type Index = string | `${string | ''}%{DATE}${string | ''}` | ((logTime: string) => string)
55+
56+
export type OpType = 'create' | 'index'

lib.js

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,14 @@
33
/* eslint no-prototype-builtins: 0 */
44

55
const split = require('split2')
6-
const {
7-
Client,
8-
ClusterConnectionPool,
9-
HttpConnection
10-
} = require('@elastic/elasticsearch')
6+
const { Client } = require('@elastic/elasticsearch')
117

128
function initializeBulkHandler (opts, client, splitter) {
13-
const esVersion = Number(opts['es-version']) || 7
9+
const esVersion = Number(opts.esVersion || opts['es-version']) || 7
1410
const index = opts.index || 'pino'
1511
const buildIndexName = typeof index === 'function' ? index : null
1612
const type = esVersion >= 7 ? undefined : (opts.type || 'log')
17-
const opType = esVersion >= 7 ? opts.op_type : undefined
13+
const opType = esVersion >= 7 ? (opts.opType || opts.op_type) : undefined
1814

1915
// Resurrect connection pool on destroy
2016
splitter.destroy = () => {
@@ -25,8 +21,8 @@ function initializeBulkHandler (opts, client, splitter) {
2521

2622
const bulkInsert = client.helpers.bulk({
2723
datasource: splitter,
28-
flushBytes: opts['flush-bytes'] || 1000,
29-
flushInterval: opts['flush-interval'] || 30000,
24+
flushBytes: opts.flushBytes || opts['flush-bytes'] || 1000,
25+
flushInterval: opts.flushInterval || opts['flush-interval'] || 30000,
3026
refreshOnCompletion: getIndexName(),
3127
onDocument (doc) {
3228
const date = doc.time || doc['@timestamp']
@@ -62,9 +58,21 @@ function initializeBulkHandler (opts, client, splitter) {
6258
}
6359
}
6460

65-
function pinoElasticSearch (opts) {
61+
function pinoElasticSearch (opts = {}) {
62+
if (opts['flush-bytes']) {
63+
process.emitWarning('The "flush-bytes" option has been deprecated, use "flushBytes" instead')
64+
}
65+
66+
if (opts['flush-interval']) {
67+
process.emitWarning('The "flush-interval" option has been deprecated, use "flushInterval" instead')
68+
}
69+
70+
if (opts['es-version']) {
71+
process.emitWarning('The "es-version" option has been deprecated, use "esVersion" instead')
72+
}
73+
6674
if (opts['bulk-size']) {
67-
process.emitWarning('The "bulk-size" option has been deprecated, "flush-bytes" instead')
75+
process.emitWarning('The "bulk-size" option has been removed, use "flushBytes" instead')
6876
delete opts['bulk-size']
6977
}
7078

@@ -115,13 +123,7 @@ function pinoElasticSearch (opts) {
115123
node: opts.node,
116124
auth: opts.auth,
117125
cloud: opts.cloud,
118-
ssl: { rejectUnauthorized: opts.rejectUnauthorized },
119-
Connection: HttpConnection,
120-
ConnectionPool: ClusterConnectionPool
121-
}
122-
123-
if (opts.tls) {
124-
clientOpts.tls = opts.tls
126+
ssl: { rejectUnauthorized: opts.rejectUnauthorized, ...opts.tls }
125127
}
126128

127129
if (opts.caFingerprint) {
@@ -138,7 +140,7 @@ function pinoElasticSearch (opts) {
138140

139141
const client = new Client(clientOpts)
140142

141-
client.diagnostic.on('resurrect', () => {
143+
client.on('resurrect', () => {
142144
initializeBulkHandler(opts, client, splitter)
143145
})
144146

0 commit comments

Comments
 (0)