Skip to content

Server and client for udp logging with possibility to encrypt data. Zero-dependency. CJS & ESM

License

Notifications You must be signed in to change notification settings

JerryCauser/udp-logger

Repository files navigation

Udp Logger

npm tests LGTM Grade JavaScript Style Guide GitHub

Socket and Client for udp logging with possibility to encrypt data.

  • Fast — little overhead above UDP to send messages
  • Secure — built-in encryption for sensitive logs
  • Simple — used well-known Node streams to manipulate and move data
  • ESM and CJS

Install

npm i --save udp-logger

Fast Start

//app.js
import { logger } from 'udp-logger'

function main () {
  /* ... */
  logger.log('some data to log')
  /* ... */
}

main()
//logger-client.js
import { UdpLoggerClient } from 'udp-logger'

export const logger = new UdpLoggerClient({ encryption: '11223344556677889900aabbccddeeff11223344556677889900aabbccddeeff' })
//logger-server.js
import { UdpLoggerServer } from 'udp-logger'

const server = new UdpLoggerServer({
  filePath: './my-app.log',
  decryption: '11223344556677889900aabbccddeeff11223344556677889900aabbccddeeff'
})

await server.start()

After just start the logger server node logger-server.js and start your app node app.js. That's all and everything works.

Documentation

class UdpLoggerClient

Extends EventEmitter

Arguments:

  • options <object> – optional
    • type <'udp4' | 'udp6'> – optional. Default 'udp4'
    • port <string | number> – optional. Default 44002
    • host <string> – optional. Default '127.0.0.1' or '::1'
    • packetSize <number> – optional. Number of bytes in each packet (chunk). Default 1280
    • isAsync <boolean> – optional. Enables delayed message sending. Useful if you don't want to wait even for some ns in your business flow for logging. Default false
    • encryption <string> | <(payload: Buffer) => Buffer> – optional. Default undefined
      • if passed string - will be applied aes-256-ctr encryption with passed string as a secret, so it should be 64char long;
      • if passed function - will be used that function to encrypt every message;
      • if passed undefined - will not use any kind of encryption.
    • serializer <(payload: any) => Buffer> - optional. Default v8.serialize
      • Used v8.serialize, but you could use something like bson, or great avsc if you could make all your logs are perfectly typed. Or you even can use JSON.stringify/JSON.parse if your logs are simple. It will be faster than v8 serialize/deserialize. Check this Binary serialization comparison, it is cool.

Methods:

  • log (...args: any): <void> – just log whatever you need.

Events:

  • 'ready': <void> – emitted when the client "establishes" udp connection.

Usage

Simple example with encryption
import { UdpLoggerClient } from 'udp-logger'

const logger = new UdpLoggerClient({
  port: 44002,
  // encryption: (buf) => buf.map(byte => byte ^ 83) // not safe at all, but better than nothing
  encryption: '11223344556677889900aabbccddeeff11223344556677889900aabbccddeeff'
})

logger.log('Hello, world!')
logger.log(new Error('Goodbye, world...'))
Example of several levels of logging with encryption
import { UdpLoggerClient } from 'udp-logger'

const encryption = '11223344556677889900aabbccddeeff11223344556677889900aabbccddeeff'

const logs = new UdpLoggerClient({ port: 45001, encryption })
const errors = new UdpLoggerClient({ port: 45002, encryption })
const statistics = new UdpLoggerClient({ port: 45003, encryption })

const logger = {
  log: logs.log,
  error: errors.log,
  stat: statistics.log
}

logger.log('logger created')

export default logger

class UdpLoggerServer

Extends EventEmitter

It is a simple wrapper around UdpLoggerSocket and UdpLoggerWriter created to simplify rapid start

Arguments:

  • options <object> – optional
    • filePath <string> – optional. Supports absolute and relative paths. If passed relative path then will use process.cwd() as a base path. Default ./udp-port-${port}.log
    • encoding <string> — optional. Encoding for writer to your disk. Default 'utf8',
    • flags <string> – optional. More info about flags you can check on NodeJS File System Flags. Default 'a'
    • type <'udp4' | 'udp6'> – optional. Default 'udp4'
    • port <string> | <number> – optional. Default 44002
    • host <string> – optional Default '127.0.0.1' or '::1'
    • decryption <string> | <(payload: Buffer) => Buffer> – optional. For more details check UdpLoggerSocket Arguments Section Default undefined
    • deserializer <(payload: Buffer) => any> - optional. For more details check UdpLoggerSocket Arguments Section Default v8.deserialize
    • formatMessage <(data:any, date:Date, id:number|string) => string | Buffer | Uint8Array> - optional. Default DEFAULT_MESSAGE_FORMATTER from constants

Fields:

  • socket: <UdpLoggerSocket> – instance of socket.
  • writer: <UdpLoggerWriter> – instance of writer.

Methods:

  • start (): <Promise<UdpLoggerServer>>
  • stop (): <Promise<UdpLoggerServer>>

Events:

  • 'ready': <void> – emitted when server started
  • 'close': <void> – emitted when server closed
  • 'error': <Error~object> – emitted when some error occurs in socket or writer. Requires you to handle errors on instance of server.
  • 'warning': <any> – emitted when warning occurs. For more details check UdpLoggerSocket Events Sections

Usage

import { UdpLoggerServer } from 'udp-logger'

const server = new UdpLoggerServer({
  filePath: './my-app.log',
  port: 44002,
  // decryption: (buf) => buf.map(byte => byte ^ 83) // not safe at all, but better than nothing
  decryption: '11223344556677889900aabbccddeeff11223344556677889900aabbccddeeff'
})

await server.start()

console.log('log udp server started')

class UdpLoggerSocket

Extends Readable Stream

It is a UDP socket in readable stream form.

Arguments:

  • options <object>required
    • type <'udp4' | 'udp6'> – optional. Default 'udp4'
    • port <string | number> – optional. Default 44002
    • host <string> – optional Default '127.0.0.1' or '::1'
    • decryption <string> | <(payload: Buffer) => Buffer> – optional. Default undefined
      • if passed string - will be applied aes-256-ctr decryption with passed string as a secret, so it should be 64char long;
      • if passed function - will be used that function to decrypt every message;
      • if passed undefined - will not use any kind of decryption.
    • deserializer <(payload: Buffer) => any> - optional. Default v8.deserialize
      • Used v8.deserialize, but you could use something like bson, or great avsc if you could make all your logs are perfectly typed. Or you even can use JSON.stringify/JSON.parse if your logs are simple. It will be faster than v8 serialize/deserialize. Check this Binary serialization comparison, it is cool.
    • formatMessage <(data: any, date:Date, id:number|string) => string | Buffer | Uint8Array> - optional. Default DEFAULT_MESSAGE_FORMATTER from constants
    • gcIntervalTime <number> — optional. How often instance will check internal buffer to delete expired messages (in ms). Default 5000
    • gcExpirationTime <number>— optional. How long chunks can await all missing chunks in internal buffer (in ms). Default 10000

Fields:

  • port: <number>
  • address: <string>

Events:

All Readable events of course and:

Event: 'ready'

Emitted when socket started and ready to receive data.

Event: 'message'

Emitted right after a message was compiled and formatted. Can be used for creating some business logic based on logs (for example pushing some data into google statistics)

  • message <string> - message
  • ctx <object>
    • body <any> - deserialized delivered body
    • date <Date>
    • id <string>
Event: 'warning'

Emitted when warning occurs.

  • payload <object | Error>
    • message <string>
    • id <string> – optional
    • date <Date> – optional

A message might be:

  • missing_message – when some messages didn't receive all chunks and got expired.
  • compile_message_error – when some messages failed to be compiled from chunks.

Usage

Example how to use pure socket as async generator
import { UdpLoggerSocket } from 'udp-logger'

const socket = new UdpLoggersocket({
  port: 44002,
  // decryption: (buf) => buf.map(byte => byte ^ 83) // not safe at all, but better than nothing
  decryption: '11223344556677889900aabbccddeeff11223344556677889900aabbccddeeff'
})

for await (const message of socket) {
  /*handle messages*/
}
Example how to use socket and use UdpLoggerWriter
import { UdpLoggerSocket, UdpLoggerWriter } from 'udp-logger'

const socket = new UdpLoggersocket()
const writer = new UdpLoggerWriter({ filePath: './my-app.log' })

socket.pipe(writer)
Example with [file-stream-rotator][https://github.com/rogerc/file-stream-rotator]
import { UdpLoggerSocket, UdpLoggerWriter } from 'udp-logger'

const socket = new UdpLoggersocket()
const fileStreamWithRotating = (await import('file-stream-rotator'))
        .getStream({ filename: '/tmp/test-%DATE%.log', frequency: 'daily', verbose: false, date_format: 'YYYY-MM-DD' })

socket.pipe(fileStreamWithRotating)

class UdpLoggerWriter

Extends Writable Stream

UdpLoggerWriter handles file moving, renaming, etc.. and keeps working after all. Usable if you will use any kind of logrotating (linux logrotate for example)

Arguments:

  • options <object>required
    • filePath <string>required. Supports absolute and relative paths. If passed relative path then will use process.cwd() as a base path
    • encoding <string> — optional. Encoding for writer to your disk. Default 'utf8'
    • flags string – optional. More info about flags you can check on NodeJS File System Flags. Default 'a'

Fields:

  • path: <string>
  • fd: <number>
  • bytesWritten: <number>
  • pending: <boolean>

Events:

  • 'ready': <void> – emitted when write stream ready

Usage

Example how to use socket and use UdpLoggerSocket
import { UdpLoggerSocket, UdpLoggerWriter } from 'udp-logger'

const socket = new UdpLoggersocket()
const writer = new UdpLoggerWriter({ filePath: './my-app.log' })

socket.pipe(writer)

Additional Exposed variables and functions

function DEFAULT_MESSAGE_FORMATTER(data, date, id)

  • data <any[]> — deserialized arguments of log function from UdpLoggerClient
  • date <Date>
  • id <string>
  • Returns: <Buffer> | <string> | <Uint8Array>

Default format function to write logs. Underhood it uses util-inspect function. For more info, you can check the source files.

constant DEFAULT_PORT

  • <number> : 44002

There are _identifier and _constants exposed also, but they are used for internal needs. They could be removed in next releases, so it is not recommended to use it in your project.


License (MIT)

About

Server and client for udp logging with possibility to encrypt data. Zero-dependency. CJS & ESM

Resources

License

Stars

Watchers

Forks

Packages

No packages published