@@ -5,6 +5,60 @@ const extractTokenRegEx = /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9
55const tokenFormatRegEx = / [ 0 - 9 a - f ] { 8 } - [ 0 - 9 a - f ] { 4 } - [ 0 - 9 a - f ] { 4 } - [ 0 - 9 a - f ] { 4 } - [ 0 - 9 a - f ] { 12 } /
66const maxIndexingErrors = 1 // failures before blacklisting tokens
77var LRU = require ( 'lru-cache' )
8+ // journald fields for lowercase access
9+ const __CURSOR = '__CURSOR'
10+ const __REALTIME_TIMESTAMP = '__realtime_timestamp'
11+ const __SOURCE_REALTIME_TIMESTAMP = '_source_realtime_timestamp'
12+ const SYSLOG_IDENTIFIER = 'syslog_identifier'
13+ const _HOSTNAME = '_hostname'
14+ const _SYSTEMD_UNIT = '_systemd_unit'
15+ const PRIORITY = 'priority'
16+ const SYSLOG_FACILITY = 'syslog_facility'
17+ // field mapping for Sematext Common Schema
18+ const processFields = {
19+ '_pid' : 'pid' ,
20+ '_uid' : 'uid' ,
21+ '_gid' : 'gid' ,
22+ '_cmdline' : 'cmd' ,
23+ '_systemd_cgroup' : 'cgroup'
24+ }
25+ // mapping for syslog priority and facility values
26+ const SEVERITY = [
27+ 'emerg' ,
28+ 'alert' ,
29+ 'crit' ,
30+ 'err' ,
31+ 'warning' ,
32+ 'notice' ,
33+ 'info' ,
34+ 'debug'
35+ ]
36+ const FACILITY = [
37+ 'kern' ,
38+ 'user' ,
39+ 'mail' ,
40+ 'daemon' ,
41+ 'auth' ,
42+ 'syslog' ,
43+ 'lpr' ,
44+ 'news' ,
45+ 'uucp' ,
46+ 'cron' ,
47+ 'authpriv' ,
48+ 'ftp' ,
49+ 'ntp' ,
50+ 'logaudit' ,
51+ 'logalert' ,
52+ 'clock' ,
53+ 'local0' ,
54+ 'local1' ,
55+ 'local2' ,
56+ 'local3' ,
57+ 'local4' ,
58+ 'local5' ,
59+ 'local6' ,
60+ 'local7'
61+ ]
862
963function JournaldUpload ( config , eventEmitter ) {
1064 this . config = config
@@ -14,10 +68,12 @@ function JournaldUpload (config, eventEmitter) {
1468 max : 5000 ,
1569 maxAge : 10 * 60 * 1000
1670 } )
17-
71+ if ( config . useSematextCommonSchema === undefined ) {
72+ config . useSematextCommonSchema = true
73+ }
1874 if ( config . removeFields ) {
1975 for ( var i = 0 ; i < config . removeFields . length ; i ++ ) {
20- this . removeFields [ config . removeFields [ i ] ] = true
76+ this . removeFields [ config . removeFields [ i ] . toLowerCase ( ) ] = true
2177 }
2278 }
2379 // set default filter
@@ -45,7 +101,7 @@ function JournaldUpload (config, eventEmitter) {
45101 self . invalidTokens . set ( match [ 1 ] , self . invalidTokens . get ( match [ 1 ] ) )
46102 }
47103 if ( self . invalidTokens . get ( match [ 1 ] ) >= maxIndexingErrors ) {
48- consoleLogger . log ( `Invalid token added to blacklist ${ match [ 1 ] } ` )
104+ consoleLogger . log ( `Invalid token added to blacklist ${ match [ 1 ] } ` )
49105 }
50106 }
51107 } )
@@ -66,31 +122,44 @@ JournaldUpload.prototype.stop = function (cb) {
66122 cb ( )
67123}
68124
125+ // Transforming fields to Sematext Common Schema https://sematext.com/docs/tags/common-schema/
69126// see https://sematext.com/docs/agents/sematext-agent/processes/metadata/
70127JournaldUpload . prototype . applySematextCommonSchema = function ( log ) {
71- var fields = {
72- '_PID' : 'pid' ,
73- '_UID' : 'uid' ,
74- '_GID' : 'gid' ,
75- '_CMDLINE' : 'cmd'
128+ // use Sematext common schema os.host = hostname
129+ let hostname = log [ _HOSTNAME ]
130+ if ( hostname ) {
131+ log . os = { host : hostname }
132+ delete log [ _HOSTNAME ]
133+ }
134+ let timestamp = log [ __REALTIME_TIMESTAMP ] || log [ __SOURCE_REALTIME_TIMESTAMP ]
135+ if ( timestamp ) {
136+ var d = new Date ( Number ( fieldValue ) / 1000 )
137+ if ( d instanceof Date && ! isNaN ( d ) ) {
138+ log [ '@timestamp' ] = d
139+ }
76140 }
77- if ( log [ '_PID' ] ) {
141+ let prio = log [ PRIORITY ]
142+ let facility = log [ log [ SYSLOG_FACILITY ] ]
143+ // handling syslog priorit and facility values
144+ if ( prio || facility ) {
145+ log . facility = FACILITY [ facility ] || String ( facility )
146+ log . severity = SEVERITY [ prio ] || String ( prio )
147+ }
148+ if ( log [ '_pid' ] ) {
78149 log . process = { }
79150 } else {
80- return
151+ return
81152 }
82- for ( field in fields ) {
153+ for ( field in processFields ) {
83154 if ( log [ field ] ) {
84- if ( ! log . process ) {
85- log . process = { }
86- }
87- log . process [ fields [ field ] ] = log [ field ]
155+ log . process [ processFields [ field ] ] = log [ field ]
88156 delete log [ field ]
89157 }
90158 }
91159}
160+
92161JournaldUpload . prototype . emitEvent = function ( log , token ) {
93- let systemdUnit = log [ ' _SYSTEMD_UNIT' ]
162+ let systemdUnit = log [ _SYSTEMD_UNIT ]
94163 let config = this . config
95164 if ( systemdUnit ) {
96165 if ( config . systemdUnitFilter !== undefined && config . systemdUnitFilter . include && ! config . systemdUnitFilter . include . test ( log [ '_SYSTEMD_UNIT' ] ) ) {
@@ -101,16 +170,18 @@ JournaldUpload.prototype.emitEvent = function (log, token) {
101170 }
102171 }
103172 this . addTags ( log )
104- let context = {
105- sourceName : log [ ' _SYSTEMD_UNIT' ] || log [ ' SYSLOG_IDENTIFIER' ] || 'journald' ,
173+ let context = {
174+ sourceName : log [ _SYSTEMD_UNIT ] || log [ SYSLOG_IDENTIFIER ] || 'journald' ,
106175 name : 'journald'
107176 }
108-
177+
109178 if ( token ) {
110179 // set index, for elasticsearch output plugin
111180 context . index = token
112181 }
113- this . applySematextCommonSchema ( log )
182+ if ( this . config . useSematextCommonSchema ) {
183+ this . applySematextCommonSchema ( log )
184+ }
114185 this . eventEmitter . emit ( 'data.object' , log , context )
115186}
116187
@@ -148,33 +219,15 @@ JournaldUpload.prototype.parseBody = function (body, token) {
148219 let lines = body . split ( '\n' )
149220 let log = null
150221 for ( var i = 0 ; i < lines . length ; i ++ ) {
151- if ( lines [ i ] . indexOf ( ' __CURSOR' ) > - 1 ) {
222+ if ( lines [ i ] . indexOf ( __CURSOR ) > - 1 ) {
152223 log = { }
153224 }
154225 var index = lines [ i ] . indexOf ( '=' )
155226 if ( index > - 1 && lines [ i ] . length > 0 ) {
156227 var fieldName = lines [ i ] . substr ( 0 , index )
157228 var fieldValue = lines [ i ] . substr ( index + 1 , lines [ i ] . length )
158- if ( fieldName === '__REALTIME_TIMESTAMP' || fieldName === '_SOURCE_REALTIME_TIMESTAMP' ) {
159- var d = new Date ( Number ( fieldValue ) / 1000 )
160- if ( d instanceof Date && ! isNaN ( d ) ) {
161- log [ '@timestamp' ] = d
162- }
163- }
164- // use Sematext common schema os.host = hostname
165- if ( fieldName === '_HOSTNAME' ) {
166- log . os = { host : fieldValue }
167- }
168- // use Sematext common schema process.pid = _PID
169- if ( fieldName === '_PID' ) {
170- log . process = { pid : fieldValue }
171- }
172- if ( fieldName === 'MESSAGE' ) {
173- log [ 'message' ] = fieldValue
174- } else {
175- if ( ! self . removeFields [ fieldName ] ) {
176- log [ fieldName ] = fieldValue
177- }
229+ if ( ! self . removeFields [ fieldName ] ) {
230+ log [ fieldName . toLowerCase ( ) ] = fieldValue
178231 }
179232 } else {
180233 if ( lines [ i ] === '' && log !== null ) {
@@ -208,15 +261,14 @@ JournaldUpload.prototype.journaldHttpHandler = function (req, res) {
208261 }
209262 }
210263
211- if ( ( self . config . useIndexFromUrlPath === true && ! token ) || self . invalidTokens . get ( token ) >= maxIndexingErrors ) {
264+ if ( ( self . config . useIndexFromUrlPath === true && ! token ) || self . invalidTokens . get ( token ) >= maxIndexingErrors ) {
212265 res . statusCode = 401
213- res . end ( `invalid logs token in url ${ req . url } \n ` )
266+ res . end ( `invalid logs token in url ${ req . url } ` )
214267 return
215268 }
216-
269+
217270 req . on ( 'data' , function ( data ) {
218271 bodyIn += String ( data )
219- // onsole.log(data)
220272 } )
221273
222274 req . on ( 'end' , function endHandler ( ) {
0 commit comments