Skip to content

Commit f589de1

Browse files
committed
Merge branch 'develop'
2 parents 987f684 + 38289de commit f589de1

File tree

6 files changed

+102
-44
lines changed

6 files changed

+102
-44
lines changed

README.md

+25-15
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Node.js module for native bindings to the ~~dearly beloved~~ systemd-journald.
44

5-
Successfully tested under NodeJS v0.10.36, v0.11.16, v0.12.12, v4.4.1, v5.9.1.
5+
Successfully tested under NodeJS v0.10.47, v0.12.16, v4.6.0, v6.7.0
66

77

88
## Example
@@ -43,14 +43,15 @@ app.get( '/:a/:b', ( req, res ) => {
4343

4444
// Log this request with priority 7
4545
log.debug( "Just answered a request", {
46-
'DIVIDEND' : a,
47-
'DIVISOR' : b,
48-
'QUOTIENT' : q,
49-
'REMOTE_ADDR': req.connection.remoteAddress
46+
'dividend' : a,
47+
'divisor' : b,
48+
'quotient' : q,
49+
'remote_addr': req.connection.remoteAddress
5050
} );
5151

5252
// Are you interested in the requests of a specific IP? Try:
5353
// $ journalctl -t awesome-devide REMOTE_ADDR={IP}
54+
// As you can see, you have to enter the field names in capital letters.
5455

5556
} catch( e ) {
5657

@@ -79,7 +80,7 @@ sudo apt-get install build-essential \
7980
libsystemd-dev
8081
```
8182

82-
If the above doesn't work, it is likely that you are using an older version of systemd as it is shipped with Ubuntu <= 14.04 or Mint <= 17. No problem - [ianare](https://github.com/ianare) fixed that for you - just try this instead:
83+
If the above doesn't work, it is likely that you are using an older version of systemd as it is shipped with Ubuntu <= 14.04 or Mint <= 17. No problem just try this instead:
8384

8485
```bash
8586
sudo apt-get install build-essential \
@@ -107,21 +108,30 @@ npm install systemd-journald --save
107108
```javascript
108109
const log = require( 'systemd-journald' );
109110

110-
// Log level:
111-
log.emerg( message, fields ); // - 0
112-
log.alert( message, fields ); // - 1
113-
log.crit( message, fields ); // - 2
114-
log.err( message, fields ); // - 3
115-
log.warning( message, fields ); // - 4
116-
log.notice( message, fields ); // - 5
117-
log.info( message, fields ); // - 6
118-
log.debug( message, fields ); // - 7
111+
// Corresponding syslog level:
112+
log.emerg( message, fields ); // - LOG_EMERG
113+
log.alert( message, fields ); // - LOG_ALERT
114+
log.crit( message, fields ); // - LOG_CRIT
115+
log.err( message, fields ); // - LOG_ERR
116+
log.warning( message, fields ); // - LOG_WARNING
117+
log.notice( message, fields ); // - LOG_NOTICE
118+
log.info( message, fields ); // - LOG_INFO
119+
log.debug( message, fields ); // - LOG_DEBUG
119120
```
120121

121122
* ```message```: String or instance of Error.
122123
* ```fields```: Further key-value data attached to the journal. Nested objects will be also included in the journal. ```{ "OBJ": { "NESTED": "Chuck Norris" } }``` will become ```OBJ_NESTED=Chuck Norris```. Quite handy for filtering the journal.
123124

124125

126+
## Acknowledgement
127+
128+
Sepcial thanks to:
129+
* [ianare](https://github.com/ianare) for improving compatibility with older systemd versions.
130+
* [jez9999](https://github.com/jez9999) for making this module immune to future changes of syslog levels.
131+
132+
I owe you a drink!
133+
134+
125135
## Why?
126136

127137
This module has been written after some unsuccessful attempts to get the module [journald](https://www.npmjs.com/package/journald) version 0.0.5 working under NodeJS 4.x / 5.x. Due to massive API changes of the v8 engine this module is fully broken from the point of view of recent NodeJS releases. So I rewrote it - this time with a little help of *Native Abstractions for Node.js* (nan). The nice guys from nan promised to ensure compatibility even on future API changes of v8. We will see ;)

index.js

+5-6
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ function obj2iovec( iovec, obj, prefix ) {
88

99
// Go through all fields
1010
for( var o in obj ) {
11+
var name = o.toUpperCase();
1112
if( typeof obj[o] == 'object' ) {
12-
obj2iovec( iovec, obj[o], prefix + o + "_" );
13-
} else {
14-
iovec.push( prefix + o + '=' + obj[o].toString() );
13+
obj2iovec( iovec, obj[o], prefix + name + "_" );
14+
} else if( prefix.length > 0 || (name != 'PRIORITY' && name != 'MESSAGE') ) {
15+
iovec.push( prefix + name + '=' + obj[o].toString() );
1516
}
1617
}
1718

@@ -40,15 +41,13 @@ function log( priority, message, fields ) {
4041
var iovec = [];
4142

4243
// Add default fields
43-
iovec.push( "PRIORITY=" + priority );
4444
iovec.push( "MESSAGE=" + message );
4545

4646
// Add additional fields
4747
obj2iovec( iovec, fields );
4848

4949
// Send it to out beloved journald
50-
51-
journal.send.apply( null, iovec );
50+
journal.send.apply( null, [ parseInt( priority ) ].concat( iovec ) );
5251

5352
}
5453

package.json

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "systemd-journald",
3-
"version": "1.1.2",
3+
"version": "1.1.3",
44
"description": "Native bindings to journald",
55
"keywords": [
66
"logging",
@@ -22,12 +22,12 @@
2222
"pretest": "jshint *.js"
2323
},
2424
"dependencies": {
25-
"nan": "^2.2.1"
25+
"nan": "^2.4.0"
2626
},
2727
"devDependencies": {
28-
"jshint": "^2.9.1",
29-
"mocha": "^2.4.5",
30-
"mockery": "^1.4.1"
28+
"jshint": "^2.9.3",
29+
"mocha": "^2.5.3",
30+
"mockery": "^1.7.0"
3131
},
3232
"os": [
3333
"linux"

src/journal_send.cc

+53-6
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,73 @@
22
// Internet. It just copies an ordinary JavaScript string array into an iovec
33
// and then finally calls sd_journal_sendv. Rocket science included!
44

5+
// Priority is a special case as it needs to be taken from the syslog.h
6+
// preprocessor definitions, which aren't available from JavaScript.
7+
58
#include <nan.h>
69
#include <systemd/sd-journal.h>
10+
#include <syslog.h>
11+
12+
// Macros for int to string conversion
13+
#define TO_STR_H(x) "" #x
14+
#define TO_STR(x) TO_STR_H(x)
15+
16+
// Create an array of all Syslog priority numbers
17+
#define SYSLOG_PRIO_CNT 8
18+
const char *const syslogPrio[] = {
19+
TO_STR( LOG_EMERG ), // jsPrio: 0
20+
TO_STR( LOG_ALERT ), // jsPrio: 1
21+
TO_STR( LOG_CRIT ), // jsPrio: 2
22+
TO_STR( LOG_ERR ), // jsPrio: 3
23+
TO_STR( LOG_WARNING ), // jsPrio: 4
24+
TO_STR( LOG_NOTICE ), // jsPrio: 5
25+
TO_STR( LOG_INFO ), // jsPrio: 6
26+
TO_STR( LOG_DEBUG ) // jsPrio: 7
27+
};
28+
29+
#define PRIO_FIELD_NAME "PRIORITY="
30+
#define PRIO_FIELD_NAME_LEN 9
31+
732

833
void send( const Nan::FunctionCallbackInfo<v8::Value>& args ) {
934

1035
int argc = args.Length();
1136
struct iovec iov[ argc ];
1237

38+
1339
// Make sure nobody forgot the arguments
14-
if( argc == 0 ) {
15-
Nan::ThrowTypeError( "Wrong number of arguments" );
40+
if( argc < 2 ) {
41+
Nan::ThrowTypeError( "Not enough arugments" );
1642
return;
1743
}
1844

19-
// Copy all arguments to an iovec
20-
for( int i = 0; i < argc; i++ ) {
45+
// Make sure first argument is a number
46+
if( ! args[0]->IsNumber() ) {
47+
Nan::ThrowTypeError( "First argument must be a number" );
48+
return;
49+
}
50+
51+
// Get the priority
52+
int64_t jsPrio = ( args[0]->ToInteger() )->Value();
53+
if( jsPrio < 0 || jsPrio >= SYSLOG_PRIO_CNT ) {
54+
Nan::ThrowTypeError( "Unknown priority" );
55+
return;
56+
}
57+
58+
// Convert JavaScript priority to Syslog priority
59+
size_t strLen = PRIO_FIELD_NAME_LEN + strlen( syslogPrio[jsPrio] );
60+
iov[0].iov_len = strLen;
61+
iov[0].iov_base = (char*) malloc( strLen + 1 );
62+
snprintf( (char*) iov[0].iov_base, strLen + 1,
63+
"%s%s", PRIO_FIELD_NAME, syslogPrio[jsPrio] );
64+
65+
66+
// Copy all remaining arguments to the iovec
67+
for( int i = 1; i < argc; i++ ) {
2168

2269
// First ensure that the argument is a string
23-
if( ! args[0]->IsString() ) {
24-
Nan::ThrowTypeError( "Arguments must be string" );
70+
if( ! args[i]->IsString() ) {
71+
Nan::ThrowTypeError( "Arguments must be strings" );
2572
return;
2673
}
2774

test/index.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,11 @@ describe( "node-systemd-journald", function() {
161161
it( "should append specified fields", function( done ) {
162162

163163
log.debug( 'Test', {
164-
NUMBER: 3,
165-
BOOLEAN: true,
166-
STRING: 'Chuck Norris',
164+
number: 3,
165+
boolean: true,
166+
string: 'Chuck Norris',
167167
OBJ: {
168-
NUMBER: 4
168+
nUmBer: 4
169169
},
170170
ARR: [ 5 ]
171171
} );

test/mocks/journal_send.js

+10-8
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,32 @@
11
"use strict";
22

3-
var last = {};
3+
var lastField = {};
4+
var lastPrio = 0;
45

5-
function send() {
6+
function send( prio ) {
67

7-
last = {};
8+
lastField = {};
89

9-
for( var i = 0; i < arguments.length; i++ ) {
10+
lastField['PRIORITY'] = prio.toString();
11+
12+
for( var i = 1; i < arguments.length; i++ ) {
1013
var line = arguments[i];
1114

1215
var delimiterPosition = line.indexOf( '=' );
1316
var name = line.substr( 0, delimiterPosition );
1417
var value = line.substr( delimiterPosition + 1 );
1518

16-
last[ name ] = value;
19+
lastField[ name ] = value;
1720

1821
}
1922

2023
}
2124

2225
function getField( name ) {
23-
24-
return last[ name ];
25-
26+
return lastField[ name ];
2627
}
2728

29+
2830
module.exports = {
2931
send: send,
3032
getField: getField

0 commit comments

Comments
 (0)