Giter Club home page Giter Club logo

node-systemd-journald's Introduction

node-systemd-journald

Build Status

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

Example

This example will start an ExpressJS server. Open your browser and visit: http://localhost:3000/{a}/{b}

The server will return the result of a divided by b. You feel subversive and may want to try b equals zero?! ;)

// npm install express systemd-journald
const Journald = require('systemd-journald');
const app = require('express')();

// This creates a new logging instance. The stated object defines default
// journal fields attached to every logging entry. syslog_identifier is the
// name displayed along with the log lines.
const log = new Journald({syslog_identifier: 'awesome-divide'});

app.get('/:a/:b', (req, res) => {
  try {

    // Convert numbers
    let a = parseInt(req.params.a);
    let b = parseInt(req.params.b);

    // Divide a by b
    let q = a / b;

    // Throw an error if the result is not a number
    // Funny side fact: In the first place I checked:
    // if( typeof q != 'number' ) ...
    // Well, this was not working. Infinity is recognised as 'number' and, you
    // might already guessed it, NaN as well! Javascript as we know and love it.
    if(isNaN(q) || q === Infinity ) throw new Error('No number!');

    // Send the result to the client
    res.end(q.toString());

    // Log this request with priority 7
    log.debug('Just answered a request', {
      'dividend'   : a,
      'divisor'    : b,
      'quotient'   : q,
      'remote_addr': req.connection.remoteAddress
    });

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

  } catch(e) {

    // The user screwed up! This will write the error message and stack trace to
    // the journal with priority 3. Checkout your journal:
    // $ journalctl -t awesome-divide -p 3 -o json-pretty
    log.err(e);

    res.status(400).end(e.message);

  }
});

app.listen(3000);

Installation

Install build dependencies

Debian-flavoured Linux distributions:

sudo apt-get install build-essential \
                     pkg-config \
                     libsystemd-dev

RHEL 7 flavoured Linux distributions:

sudo yum install gcc gcc-c++ make git \
                 systemd-devel

NPM Install

In all cases, once the build dependencies are installed:

npm install systemd-journald --save

API

const Journald = require( 'systemd-journald' );
const log = new Journald( defaultFields );

                                // Corresponding syslog level:
log.emerg( message, fields );   // - LOG_EMERG
log.alert( message, fields );   // - LOG_ALERT
log.crit( message, fields );    // - LOG_CRIT
log.err( message, fields );     // - LOG_ERR
log.warning( message, fields ); // - LOG_WARNING
log.notice( message, fields );  // - LOG_NOTICE
log.info( message, fields );    // - LOG_INFO
log.debug( message, fields );   // - LOG_DEBUG
  • message: String or instance of Error.
  • fields: Further key-value data attached to the journal. Nested objects will be also included in the journal. Keys will be converted to upper-case. {'obj': {'nested': 'Chuck Norris'}} will become OBJ_NESTED=Chuck Norris. Quite handy for filtering the journal.
  • defaultFields: Fields attached to every entry. They may be overridden by fields.

Acknowledgement

Sepcial thanks to:

  • ianare for improving compatibility with older systemd versions.
  • jez9999 for making this module immune to future changes of syslog levels.
  • Z3TA is responsible for CODE_FILE, CODE_FUNC and CODE_LINE being settable by the fields parameter.
  • bryanburgers introduced the idea of default fields.
  • spion for introducing compatibility with NodeJS 12 while preserving compatibility down to Node 0.10.
  • GaikwadPratik for porting this module from NAN to Node-API.

I owe you a drink!

Why?

This module has been written after some unsuccessful attempts to get the module 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 ;)

Update: They've kept the promise - but we've changed to the on-board solution for native modules: Node-API. We hope to have even less problems with keeping this module compatible to NodeJS.

node-systemd-journald's People

Contributors

bryanburgers avatar gaikwadpratik avatar jez9999 avatar jue89 avatar spion avatar wyplay-portal avatar z3ta avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

node-systemd-journald's Issues

Is it possible to merge this into `systemd/node-systemd`?

As a developer I'm really confused because there are "official" bindings for node provided on github.com/systemd account and there is your lib which works on newer node versions (as far as I understand your README.Why section).

Have you considered proposing your bindings as a replacement for github.com/systemd/node-systemd? I mean something like opening pull request or issue there.

Fails to install on Mint 17.3

npm install 

> [email protected] install /home/myproject/node_modules/systemd-journald
> node-gyp rebuild

Package libsystemd was not found in the pkg-config search path.
Perhaps you should add the directory containing `libsystemd.pc'
to the PKG_CONFIG_PATH environment variable
No package 'libsystemd' found
gyp: Call to 'pkg-config --libs-only-l libsystemd' returned exit status 1 while in binding.gyp. while trying to load binding.gyp

The problem is that on Mint 17.3, the package libsystemd-dev doesn't exist, it's actually split up into systemct-*-dev packages:

sudo aptitude search libsystemd-

i   libsystemd-daemon-dev                             - systemd utility library - development files                 
p   libsystemd-daemon-dev:i386                        - systemd utility library - development files                 
i   libsystemd-daemon0                                - systemd utility library                                     
p   libsystemd-daemon0:i386                           - systemd utility library                                     
i A libsystemd-id128-0                                - systemd 128 bit ID utility library                          
p   libsystemd-id128-0:i386                           - systemd 128 bit ID utility library                          
i A libsystemd-id128-dev                              - systemd 128 bit ID utility library - development files      
p   libsystemd-id128-dev:i386                         - systemd 128 bit ID utility library - development files      
i   libsystemd-journal-dev                            - systemd journal utility library - development files         
p   libsystemd-journal-dev:i386                       - systemd journal utility library - development files         
i A libsystemd-journal0                               - systemd journal utility library                             
p   libsystemd-journal0:i386                          - systemd journal utility library                             
i   libsystemd-login-dev                              - systemd login utility library - development files           
p   libsystemd-login-dev:i386                         - systemd login utility library - development files           
i   libsystemd-login0                                 - systemd login utility library                               
p   libsystemd-login0:i386                            - systemd login utility library

Expose log command

The convenience functions are nice, however it would be great if the log command would also be exposed, for easier incorporation in other logging libraries.

Allow the syslog identifier to be passed without setting process.title

process.title is limited, according to the node docs.

The process.title property returns the current process title (i.e. returns the current value of ps). Assigning a new value to process.title modifies the current value of ps.

Note: When a new value is assigned, different platforms will impose different maximum length restrictions on the title. Usually such restrictions are quite limited. For instance, on Linux and OS X, process.title is limited to the size of the binary name plus the length of the command line arguments because setting the process.title overwrites the argv memory of the process. Node.js v0.8 allowed for longer process title strings by also overwriting the environ memory but that was potentially insecure and confusing in some (rather obscure) cases.

It would be awesome if there was a way to specify the syslog identifier without mucking with process.title.

One idea would be to allow

const log = require('systemd-journald')
log.identifier = 'my-identifier';
log.debug(...)

I did some very light testing on one machine, and I was able to set the syslog identifier with the following code:

log.debug('My message', { syslog_identifier: 'my-identifier' })

which makes me think it might be as easy as checking if log.identifier is defined and, if it is, adding fields.SYSLOG_IDENTIFIER = log.identifier, but I didn't test that.

Thoughts?

Display NULL instead of just ignoring it?

Actually null is an Object for Javascript.

With that in mind fields would not be flattened down to some entry in the Journal. They are just ignored by the converter function - and this more by accident - tbh:

function obj2journalFields( journalFields, obj, prefix ) {
if( prefix === undefined ) prefix = '';
// Go through all fields
for( var o in obj ) {
var name = o.toUpperCase();
if( obj[o] instanceof Buffer ) {
journalFields[ prefix + name ] = obj[o].toString('hex');
} else if( typeof obj[o] == 'object' ) {
obj2journalFields( journalFields, obj[o], prefix + name + "_" );
} else if( obj[o] !== undefined && ( prefix.length > 0 || name != 'PRIORITY' ) ) {
journalFields[ prefix + name ] = obj[o].toString();
}
}
}

This is maybe not the best behaviour.

Propose: Display fields that are null with the string "null" in the Journal? Any different opinions on that?

Typescript definitions

Thanks for this great lib, I stumbled upon it after getting annoyed by all log entries having different PIDs using my previous method, which was piping the log message into logger --journald.
It would be great if you could add Typescript definitions to the package, for cleaner code in Typescript projects!

Display instances of Buffer in a nice way

If buffers are included in the fields object, something like this is put into the journal:

{
...
        "PAYLOAD_0" : "1",
        "PAYLOAD_1" : "2",
        "PAYLOAD_2" : "3",
        "PAYLOAD_3" : "4",
        "PAYLOAD_4" : "5",
        "PAYLOAD_5" : "6",
        "PAYLOAD_6" : "7",
        "PAYLOAD_7" : "8",
        "PAYLOAD_8" : "9",
        "PAYLOAD_9" : "0",
        "PAYLOAD_ASCIISLICE" : "function asciiSlice() { [native code] }",
        "PAYLOAD_BASE64SLICE" : "function base64Slice() { [native code] }",
        "PAYLOAD_LATIN1SLICE" : "function latin1Slice() { [native code] }",
        "PAYLOAD_HEXSLICE" : "function hexSlice() { [native code] }",
        "PAYLOAD_UCS2SLICE" : "function ucs2Slice() { [native code] }",
        "PAYLOAD_UTF8SLICE" : "function utf8Slice() { [native code] }",
        "PAYLOAD_ASCIIWRITE" : "function asciiWrite() { [native code] }",
        "PAYLOAD_BASE64WRITE" : "function base64Write() { [native code] }",
        "PAYLOAD_LATIN1WRITE" : "function latin1Write() { [native code] }",
        "PAYLOAD_HEXWRITE" : "function hexWrite() { [native code] }",
        "PAYLOAD_UCS2WRITE" : "function ucs2Write() { [native code] }",
        "PAYLOAD_UTF8WRITE" : "function utf8Write() { [native code] }",
        "PAYLOAD_COPY" : "function copy() { [native code] }",
...
}

Maybe that's a better way to display them:

{
...
        "PAYLOAD" : "<Buffer 01 02 03 04 05 06 07 08 09 00>",
...
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.