npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

logs-thread

v1.0.4

Published

This express utility creates log threads in a db and displays them in a HTML GUI.

Downloads

4

Readme

LogsThread

This library will save your logs into a database and later show them in a GUI on your browser. By default, it is integrated with express, mongo and mongoose but it's possible to write plugins for other dbs.

In short, logThreads creates a new thread for each express request and closes it at the response or response timeout. You can add as many logs to each thread as you want, each log containing a specific piece of information about the current process stage or about a specific error. The logs are flattened into a single registry which is automatically saved into your database when the thread is closed.

LogsThread generates GUI files under your project's directory to help you visualize the logs. Access http://localhost:12970 to open it.

Here is a basic example of LogsThread implementation

const mongoose = require("mongoose");
const express = require("express");
const app = express();

const reqLog = require("logs-thread");
reqLog.setModules({ express, app, mongoose });
reqLog.setCustomSettings("customSettings.json");
reqLog.start();

app.get("/", function(req, res) {
	req.thread.log("note").setMsg("Hello World")
	res.send("Hello World!");
});

app.listen(3000, function() {
	console.log("Example app listening on port 3000");
});

This is all you need to create, save and visualize logs.

GUI

LogsThread offers a friendly Graphic User Interface to display all the logs. Among other functionalities, this GUI offers the possibility to:

  • view many logs at once, on a summary list.
  • expand the log information
  • filter the logs with combos personalized with your own information

The available filters are created on the fly using the information from the groups property of both the defaultSettings and your customSettings.

By default the available groups are

groups:{
	type: { options: []},
	level: { options: ["error", "warn", "log"]},
	importance: { options: ["high", "normal", "low"]}
}

meaning you will find 3 drop-down menus as soon as you enter the GUI. The groups.type.options will be auto filled according to the information found on types, by default note and unexpected:

types: {
	note: {	level:"log",importance:"normal"},
	unexpected:{message:"unexpected error",level:"error",importance:"high"}
}

Automatic Information

The thread automatically collects information about both the request and the response: method, path, query, body and the response itself. It also saves the time and the stack at the log creation's moment (only the most relevant parts). You may exclude any of those properties using your own custom settings. The GUI will not show those properties on the summary list unless you click on a log to load its full information.

Customization

LogsThread allows high customization of your logs structures and most of its configurations

// it accepts an object or the route to a json file (absolute or relative to the main module)
reqLog.setCustomSettings("customSettings.json");

For example, your company has clients and you want to save the current client's name into the thread to later filter the logs accordingly. In your custom settings you must add the client group and its available options:

{groups: {
	client: { 
		options: ["Susan", "John", "Paul"], 
		overlap: "push" 
	}
}}

This will create a client drop-down menu on the GUI to help you filter the logs. To add the information to a thread, use one of the following options at any point of the request flow:

req.thread.log("note", {client:"John"}, "Client has logged in.")
// or
req.thread.log("note").setInfo({client:"John"}).setMsg("Client has logged in.")

Note that group has the overlap property. It indicates how the Thread should flatten this group in case multiple information is found. For example:

req.thread.log("note", {client:"John"})
req.thread.log("note", {client:"Susan"})
res.send("ok")

You can choose the behaviour by setting one of the following operations:

  • push, pull -> keeps a copy of each value. You can also pass an Array to the log.
  • sum, min, max - for numbers
  • first, last - chooses one, considering the log order
  • minIndex, maxIndex -> chooses one, considering the group.options order
  • merge -> merge objects

Debug

You don't need to create a group to add information to the thread. For example, if you have an endPoint to receive questions from your clients, you could just save the question into the debug object:

req.thread
	.log("question")
	.setInfo({client:"John"})
	.setDebug({text:req.query.question})

This information will be available at GUI when you open the log details.

Errors

Errors can be logged using the error function:

try{
	//... something bad
}catch(err){
	req.log("unexpected").error(err)
}

That will create a log of type "unexpected" to save the error information. If you want to create other error types, read the next session.

Types

Each log you create must be from one of the types defined at settings. The default settings file has two pre defined types, note and unexpected, but you can add your own types at the custom settings. The types have some initial information which will be used to setup the new log.

types: {
	note:{level:"log",importance:"normal"},
	unexpected:{message:"unexpected error",level:"error",importance:"high"},
	question:{level:"log",importance:"high"},
	complain:{level:"warn",importance:"high"},
	login:{level:"log",importance:"low"}
}

For example, a note log will always come with level set to "log" and importance set to "normal". Unexpected logs are used by LogsThread to log the errors found by itself.

Messages

Messages will let you identify a log more easily at the GUI. It will use the last message found on the thread's logs unless you define a message to the thread itself, which can be done in two different ways:

req.thread.setMsg("This is a thread's messaged")
req.thread.log("note").setMsg("This is a log's message that will overwrite the thread's messaged", true) 
// the true parameter here indicates it is an important message.

GUI Files

LogsThread will generate the needed files on your project's directory and will auto regenerate any missing file if you erase them. Once they are created, they will not be overwritten and you can change them as you wish.

GUI CSS

When a log is shown in the summary, it will have classes added according to the information specified by their groups. For example, a log from John will have the class John added to both the log row and the client column, allowing you to add, for example, these CSS rules:

log-summary.john{
	background-color: orange;
}

log-tab.john{
	background-color: yellow;
	color: red;
	font-weight: 600;
}

That will make all the threads row containing john as a client to be viewed in orange and the specific client column to be seen in yellow with red letters.

Full Settings

This is the full defaultSettings file with some brief explanations in case you want to overwrite them with your own custom settings

module.exports  = {
	db: {
		type:  "mongoose", // right now mongoose is the only option, also meaning mongo is the only db option 
		host:  "mongodb://localhost:27017/logs",  // the collection where to save the logs
		group:  "week"  // day, week, month, year, none -> to avoid huge collections we split the logs in groups over time. The GUI allows you to choose which collection to look at. 
	},
	GUI: {
		port:  12970, // the port where the GUI server will be listening
		root:  "./logsThread/" // the path where the files are going to be created inside your project
	},
	express: {
		// create entries for different methods if you want
		get: {
			log: ["method", "path", "query", "response", "time", "stack"], // the information you want to save from get requests
			blackList: [], // not working yet
			whiteList: [] // not working yet
		},
		post: {
			log: ["method", "path", "query", /*"body",*/  "response", "time", "stack"],
			blackList: [],
			whiteList: []
		}
	},
	stackRoot:  "./", // the stack lines are absolute, so we will ignore the parts that are above this relative root. Lines containg node_modules in their path will be fully ignored.
	groups: {
		type: { options: [], overlap:  "push", optional:  false }, // autofill from settings.types[k]
		level: { options: ["error", "warn", "log"], overlap:  "minIndex" },
		//set groups.level = null if you don't want to use level on your logs
		importance: { options: ["high", "normal", "low"], overlap:  "minIndex" }
	},
	types: {
		// create any type you want but don't delete the "unexpected" type
		note: {
			level:  "log",
			importance:  "normal",
		},
		unexpected: {
			message:  "unexpected error",
			level:  "error",
			importance:  "high"
		}
	}
};

Example of custom settings:

{
	GUI:{
		port:3001
	},
	db:{
		host: "mongodb://localhost:27017/logsThread"
	},
	groups: {
		developer: { 
			options: ["Tie", "Tomas", "Sergio", "Jesus"], 
			overlap: "push" 
		},
		team: { 
			options: ["developers", "analytics", "support"], 
			overlap: "push" 
		}
	}
	types: {
		login: {
			message: "login",
			level: "log",
			importance: "normal"
		}
	},
	team: {
		message: "Team in the house",
		level: "warning",
		importance: "low"
	}
}