New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

log-segment

Package Overview
Dependencies
Maintainers
1
Versions
32
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

log-segment - npm Package Compare versions

Comparing version 1.0.9 to 1.0.10

230

main.js

@@ -5,21 +5,15 @@ 'use strict'

const chalk = require('chalk')
const fs = require('fs')
const fs = require('fs-extra')
const nodemailer = require('nodemailer')
// @todo transport for each level
// console, file, stream, email (telegram, sms ...)
// @todo custom format messages
const mode = {
CONSOLE: 0,
FILE: 1
// STREAM
// EMAIL
// OTHERS (telegram, sms ...)
FILE: 1,
EMAIL: 2
}
/**
* @todo params.format
* @class
*/
const Log = function (params) {
// default console
let __levels = {

@@ -35,3 +29,3 @@ '*': {

color: 'green',
marker: '✔' // ✔ ✔️
marker: '✔'
},

@@ -48,3 +42,3 @@ warning: {

color: 'magenta',
marker: '😱' // ☠'
marker: '😱'
}

@@ -66,3 +60,11 @@ }

function __init (params) {
const __memoize = {
check: {}
}
/**
* @constructor
* @param {Object} params
*/
const __init = function (params) {
__markers = {}

@@ -72,3 +74,6 @@ __setLevels(__levels)

function set (params) {
/**
* @param {Object} params
*/
const set = function (params) {
if (!params) {

@@ -78,2 +83,4 @@ return

__reset()
if (params.segments) {

@@ -103,6 +110,17 @@ __setSegments(params.segments)

/**
* @return current settings
*/
const get = function () {
return {
levels: Object.assign({}, __levels),
segments: Object.assign({}, __segments),
enabled: Object.assign({}, __enabled)
}
}
/**
* add segment: if already exists, override
* add level: if already exists, override
*/
function add (params) {
const add = function (params) {
if (!params) {

@@ -120,5 +138,15 @@ return

function value (label, value) {
/**
* @param {string} label
* @param {*} value
*/
const value = function (label, value) {
return function () {
if (typeof value === 'object') {
if (value instanceof Error) {
return value.stack
}
if (value instanceof Date) {
return value.toISOString()
}
try {

@@ -135,3 +163,3 @@ return `[${label}=${JSON.stringify(value)}]`

function __setSegments (segments) {
const __setSegments = function (segments) {
__segments = {}

@@ -141,3 +169,3 @@ __addSegments(segments)

function __addSegments (segments) {
const __addSegments = function (segments) {
for (const i in segments) {

@@ -148,5 +176,3 @@ if (__segments[i]) {

let _segment = segments[i]
if (!chalk[_segment.color]) {
console.warn('log-segment, unknown color', _segment.color, 'for segment', i)
}
__checkSetting(_segment, 'segment')
__segments[i] = _segment

@@ -156,3 +182,3 @@ }

function __setLevels (levels) {
const __setLevels = function (levels) {
// remove current levels

@@ -168,3 +194,3 @@ for (const i in __levels) {

function __addLevels (levels) {
const __addLevels = function (levels) {
for (const i in levels) {

@@ -177,8 +203,5 @@ let _level = levels[i]

Log.prototype[i] = __print(i)
__checkSetting(_level, 'level')
// cache markers
if (_level.marker) {
if (!chalk[_level.color]) {
console.warn('log-segment, unknown color', _level.color, 'for level', i)
}
if (_level.color && chalk[_level.color]) {

@@ -194,7 +217,64 @@ __markers[i] = chalk[_level.color](_level.marker)

const __checkSetting = function (setting, part) {
switch (setting.mode) {
case mode.EMAIL:
if (!setting.email) {
console.warn('log-segment, mode is EMAIL but email settings missing for', part, 'fallback to console')
setting.mode = mode.CONSOLE
}
break
case mode.FILE:
if (!setting.file) {
console.warn('log-segment, mode is FILE but no file specified for', part, 'fallback to console')
setting.mode = mode.CONSOLE
}
break
case mode.CONSOLE:
default:
if (setting.color && !chalk[setting.color]) {
console.warn('log-segment, unknown color', setting.color, 'for', part)
}
break
}
}
const __reset = function () {
__memoize.check = {}
__resetFiles()
}
/**
* clear file streams
*/
const __resetFiles = function () {
for (const _file in __files) {
__files[_file].stream.end()
process.removeListener('beforeExit', __files[_file].onProcessExit)
delete __files[_file]
}
}
/**
* memoized
* @param {string} segment
* @param {string} level
* @return bool
*/
const __check = function (segment, level) {
if (!__memoize.check[segment + level]) {
__memoize.check[segment + level] = ((segment === '*') ||
__enabled.segments === '*' ||
tools.array.contains(__enabled.segments, segment)) &&
((__enabled.levels === '*') ||
tools.array.contains(__enabled.levels, level))
}
return __memoize.check[segment + level]
}
/**
*
* @param {string} level level name
*/
function __print (level) {
const __print = function (level) {
return function (segment) {

@@ -236,4 +316,15 @@ if (!__check(segment, level)) {

function __output (segment, level, data) {
// @todo custom format
/**
* @todo custom format
*/
const __output = function (segment, level, data) {
// email
if (__segments[segment] && __segments[segment].mode === mode.EMAIL) {
return __outputEmail(__segments[segment].email, data)
}
if (__levels[level] && __levels[level].mode === mode.EMAIL) {
return __outputEmail(__levels[level].email, data)
}
// file
if (__segments[segment] && __segments[segment].mode === mode.FILE) {

@@ -243,6 +334,10 @@ return __outputFile(__segments[segment].file, data)

if (__levels[level].mode === mode.FILE) {
return __outputFile(__segments[segment].file, data)
return __outputFile(__levels[level].file, data)
}
// mode console
// console
return __outputConsole(data)
}
const __outputConsole = function (data) {
console.log.apply(console, data)

@@ -253,41 +348,59 @@ return true

/**
* @todo open file err
* @param {string} file /path/to/file
* @param {string[]} data
*/
function __outputFile (file, data) {
const __outputFile = function (file, data) {
// open stream, if not already opened
if (!__files[file]) {
__files[file] = fs.createWriteStream(file, {flags: 'a', defaultEncoding: 'utf8'})
/* debug
__files[file].on('finish', function () {
console.log('file has been written')
})
__files[file].on('open', function () {
console.log('file has been open')
})
*/
process.on('beforeExit', () => {
if (__files[file]) {
__files[file].end()
fs.ensureFile(file, (err) => {
if (err) {
throw new Error('unable to write', file)
}
__files[file] = {
stream: fs.createWriteStream(file, {flags: 'a', defaultEncoding: 'utf8'}),
onProcessExit: () => {
if (__files[file].stream) {
__files[file].stream.end()
}
}
}
process.on('beforeExit', __files[file].onProcessExit)
/* debug
__files[file].on('finish', function () {
console.log('file has been written')
})
__files[file].on('open', function () {
console.log('file has been open')
})
*/
__outputFile(file, data)
})
return true
}
data.push('\n')
return __files[file].write(data.join(' '))
__files[file].stream.write(data.join(' '))
return true
}
/**
* @param {string} segment
* @param {string} level
* @todo html
* @param {*} email
* @param {*} data
*/
function __check (segment, level) {
return ((segment === '*') ||
__enabled.segments === '*' ||
tools.array.contains(__enabled.segments, segment)) &&
((__enabled.levels === '*') ||
tools.array.contains(__enabled.levels, level))
const __outputEmail = function (email, data) {
if (!email._transporter) {
email._transporter = nodemailer.createTransport(email.transporter)
}
const _options = Object.assign(email.options)
_options.text = data.join('\n')
email._transporter.sendMail(_options, (err, info) => {
if (err) {
__outputConsole(['ERROR SENDING EMAIL', _options])
__outputConsole([data])
}
})
return true
}

@@ -313,2 +426,3 @@

Log.prototype.set = set
Log.prototype.get = get
Log.prototype.add = add

@@ -315,0 +429,0 @@ Log.prototype.value = Log.prototype.val = Log.prototype.v = value

{
"name": "log-segment",
"version": "1.0.9",
"version": "1.0.10",
"description": "logger with partition",
"main": "main.js",
"dependencies": {
"a-toolbox": "^x",
"chalk": "^x"
"a-toolbox": "^0.1.x",
"chalk": "^1.x",
"fs-extra": "^2.x",
"nodemailer": "^4.x"
},
"devDependencies": {
"standard": "^x",
"pre-commit": "^x",
"tap": "^x"
"tap": "^x",
"standard": "^x"
},
"engines": {
"node": ">4.x"
"node": ">6.x"
},

@@ -28,3 +30,3 @@ "files": [

"type": "git",
"url": "git+https://github.com/simone-sanfratello/log-segment.git"
"url": "git+https://github.com/braceslab/log-segment.git"
},

@@ -36,4 +38,4 @@ "keywords": [

],
"author": "Simone Sanfratello <simone.sanfra@gmail.com>",
"author": "Simone Sanfratello <simone@braceslab.com>",
"license": "MIT"
}
}
# log-segment
Node.js logger with partition
[![NPM Version](http://img.shields.io/npm/v/log-segment.svg?style=flat)](https://www.npmjs.org/package/log-segment)
[![NPM Downloads](https://img.shields.io/npm/dm/log-segment.svg?style=flat)](https://www.npmjs.org/package/log-segment)
[![NPM](https://nodei.co/npm-dl/log-segment.png)](https://nodei.co/npm/log-segment/)
[![JS Standard Style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/)
[![NPM](https://nodei.co/npm-dl/log-segment.png)](https://nodei.co/npm/log-segment/)
Javascript logger with partition
### Description
## Purpose
````log-segment```` provide a lightweight logger full customizable to quickly enable and disable segments and levels.
Why Another Log Module? Because not all logs are equal.
I'd like to use a pliable tool that allow to easy and quickly manage logs by two factors: **level** and **segment**.
### Install
## Installing
````bash
npm install log-segment --save
$ npm i -g log-segment
````
### Usage
### Quick start
#### Default
``log-segment`` is single-ton, so just require and use everywhere.
````js
const log = require('log-segment')
log.info('*', 'info message')
log.success('*', 'success message')
log.warning('*', 'warning message')
log.error('*', 'error message')
log.panic('*', 'panic message')
const sql = 'INSERT INTO table ...'
log.info('sql', 'executing query ...', log.value('sql', sql))
db.query(sql)
.then(() => {
log.success('sql', 'query done.', log.value('sql', sql))
})
.catch((err) => {
log.error('sql', 'query error', log.value('sql', sql))
})
````
output
(attach screenshot)
````js
const log = require('log-segment')
<!--
#### Customize
require('express')().all('/*', (request, response) => {
log.info('http', 'request', request.method, request.baseUrl)
doSomething(request)
.then((output) => {
response.send(output)
log.success('http', 'response on request', request.method, request.baseUrl)
})
.catch((err) => {
response.sendStatus(500)
log.error('http', 'response on request', request.method, request.baseUrl, log.value('err', err))
})
})
````
![quickstart](./doc/img/quickstart.jpg "quickstart")
#### Default settings
Default settings provide any levels and segments enabled to console output.
Default levels are: *info, success, warning, error, panic*.
There is no hierarchy by levels.
````json
{
levels: {
'*': { color: 'white' },
info: { color: 'blue', marker: 'ℹ️' },
success: { color: 'green', marker: '✔' },
warning: { color: 'yellow', marker: '❗️️' },
error: { color: 'red', marker: '✗️' },
panic: { color: 'magenta', marker: '😱' }
},
segments: { '*': { color: 'white' } },
enabled: { segments: '*', levels: '*' } }
````
##### Custom segments
````js
const log = require('log-segment')
log.set({
segments: {
http: {
color: 'white'
color: 'cyan'
},
html: {
color: 'magenta'
},
sql: {
color: 'magenta'
mode: log.mode.FILE,
file: '/tmp/myapp/sql.log'
}
}
})
const sql = 'INSERT INTO table ...'
log.info('sql', 'executing query ...', log.value('sql', sql))
log.success('sql', 'query done.', log.value('sql', sql))
const request = {
method: 'GET',
baseUrl: '/it/4x/api.html#req'
}
const err = new Error('file not found')
log.info('http', 'request', request.method, request.baseUrl)
log.error('http', 'response on request', request.method, request.baseUrl, log.value('err', err))
let username = null
log.warning('html', 'rendering missing value', log.value('username', username))
````
![custom segments](./doc/img/custom-segments.jpg "custom segments")
#### Custom levels
````js
const log = require('log-segment')
log.set({
segments: {
http: {
color: 'yellow'
},
sql: {
color: 'white'
}
},
levels: {
info: {
color: 'blue',
marker: 'ℹ️'
trace: {
marker: '[TRACE]'
},
success: {
color: 'green',
marker: '✔'
},
warning: {
color: 'yellow',
marker: '❗️️'
marker: '[WARN]'
},
error: {
color: 'red',
marker: '✗️'
marker: '[ERR]'
}

@@ -72,19 +150,130 @@ }

log.info('*', 'info message')
log.success('*', 'success message')
log.warning('*', 'warning message')
log.error('*', 'error message')
const sql = 'INSERT INTO table ...'
log.trace('sql', 'executing query ...', log.value('sql', sql))
log.trace('sql', 'query done.', log.value('sql', sql))
const request = {
method: 'GET',
baseUrl: '/it/4x/api.html#req'
}
const err = new Error('file not found')
log.trace('http', 'request', request.method, request.baseUrl)
log.error('http', 'response on request', request.method, request.baseUrl, log.value('err', err))
let username = null
log.warning('html', 'rendering missing value', log.value('username', username))
````
-->
### API
...
![custom levels](./doc/img/custom-levels.jpg "custom levels")
### Roadmap
### Use Cases
````js
log.set({
segments: {
http: { color: 'cyan' },
network: { color: 'blue' },
db: { color: 'yellow' },
sql: { }
}
})
````
**Development**
Just enable everything on console
````js
log.set({ enabled: { segments: '*', levels: '*' } })
````
**Debug**
Enable only segments to focus on, at any levels, to find that bug
````js
log.set({ enabled: { segments: ['sql', 'network'] } })
````
**Production**
Different behaviour for each level:
- disable not interesting parts: success level, template rendering
- different file for each type: *info, warning, error*
and remove marks
- separate sql file
- on panic send email
````js
log.set({
enabled: {
segments: ['sql'],
levels: ['info', 'warning', 'error', 'panic']
},
segments: {
sql: {
mode: log.mode.FILE,
file: '/var/log/myapp/sql'
}
},
levels: {
info: {
marker: '[i]',
mode: log.mode.FILE,
file: '/var/log/myapp/info'
},
warning: {
marker: '[warn]',
mode: log.mode.FILE,
file: '/var/log/myapp/warn'
},
error: {
marker: '[err]',
mode: log.mode.FILE,
file: '/var/log/myapp/error'
},
panic: {
mode: log.mode.MAIL,
email: {
transporter: {
service: 'gmail',
auth: {
user: '***@gmail.com',
pass: '***'
}
}
}
options: {
from: '"log-segment" <log-segment@test.test>',
to: 'sys-admin@gmail.com',
subject: 'myapp PANIC'
}
}
}
}
})
````
## Documentation
See [documentation](./doc/README.md) for further informations.
## Changelog
v. 1.1.0
- Add support for email mode
## TODO
- add message info: trace, timestamp, chrono
- custom format in message
- custom format in log.value
- custom transport by segment and level: console, file, stream, email (sms, telegram and whatever)
- custom mode: stream, (sms, telegram and whatever)
- multiple mode for each setting (example: on panic send email, log to file, send sms, call mom)
- customizable action (example: on error run function)
- browser support (browserify?)
- .test() test settings: write files, send emails ...
- (evaluate) support workers (as transport)

@@ -96,2 +285,4 @@ - [pino](https://github.com/pinojs/pino)

- [debug](https://github.com/visionmedia/debug)
- [log](https://github.com/tj/log.js)
- [bunyan](https://github.com/trentm/node-bunyan)
- others?

@@ -105,3 +296,3 @@

Copyright (c) 2016-2017 Simone Sanfratello
Copyright (c) 2017, [braces lab](https://braceslab.com)

@@ -108,0 +299,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc