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

girok

v0.4.0

Published

girok is a lightweight and highly customizable JavaScript logger

Downloads

19

Readme

girok

Build & Test License: MIT npm version

girok is a lightweight and highly customizable logger library.

Install

Using npm:

npm install girok

Using bun:

bun add girok

Usage

import { logger } from "girok"
import { formatText } from "girok/formatters"

let log = logger({
  level: "info",
  formatter: formatText("[%lvl%] %ctx% %args%"),
  outputs: ["stdout", "file://./logs"],
})

log.info("Hello World!") // [INFO]  Hello World!

log = log.context({ key: "value" })

log.info("Hello again!") // [INFO] key="value" Hello again!

Documentation

Basics

Instanciate a logger

To instanciate a logger you can use the logger function:

import { logger } from "girok"

const log = logger()

log.info("Hello World!")

Level

The level option allows you to set the minimum level that will be logged. By default, the level option is set to info.

import { logger } from "girok"

const log = logger({
  level: "warn",
})

log.trace("trace") // Not printed
log.debug("debug") // Not printed
log.info("info") // Not printed
log.warn("warn") // prints "warn"
log.error("error") // prints "error"
log.fatal("fatal") // prints "fatal" and exit process

The following levels are available:

trace < debug < info < warn < error < fatal

Context

To add context properties to your logs, you can use the logger context function. This function takes a new contex in entry and returns a new logger with the defined context.

import { logger } from "girok"

let log = logger()

log.info("Message without context") // [INFO] Message without context

log = log.context({ foo: "bar" })

log.info("Message with context") // [INFO] foo="bar" Message with context

log = log.context({ test: 42 })

log.info("Message with context") // [INFO] foo="bar", test=42 Message with context

Formatting

Predefined formatters

You can use the formatter option to define the format of your logs. There are two predefined formatters, text and json. The text formatter is the default one.

import { logger } from "girok"

let logTxt = logger({ formatter: "text" })

let logJson = logger({ formatter: "json" })

logTxt.info("Hello World")
// [INFO] 1970-01-01 00:00:00.000 (index.ts:6:8)  Hello World

logJson.info("Hello World")
// {"level":"INFO","caller":"index.ts:7:9","ts":0,"message":"Hello World"}

Custom formatters

You can use the formatter option to define your own formatter function. Here is the signature of the formatter function:

type LogMeta = {
  level: Level
  caller?: string
  ts: number
  context: Record<string, any>
}
type Formatter = (meta: LogMeta, ...args: any[]) => string

There are two predefined formatters functions, formatText and formatJson. Those are the formatters used by the default text and json formatters, respectively. Each of these can be customized.

import { logger } from "girok"
import { formatText, formatJson } from "girok/formatters"

const logTxt = logger({
  formatter: formatText(), // alias for 'text'
})

const logJson = logger({
  formatter: formatJson(), // alias for 'json'
})
formatText()

Format log message as text.

Signature:

type FormatText = (
  fmt: string,
  meta: { ansi?: boolean; inline?: boolean; depth?: number | null }
) => Formatter

Example:

let log = formatText("[%lvl%] %date% (%caller%) %args%", {
  depth: 4,
  ansi: false,
  inline: true,
})
log.info("Hello World!")
// [INFO] 2022-01-01 00:00:00.000 (index.js) Hello World!
log = formatText(
  "[%lvl%] %date.format(YYYY-MM-DD HH:mm:ss.SSS).utc% %ctx% %args%"
)
log.warn("Hello World!")
// [WARN] 2022-01-01 00:00:00.000  Hello World!
formatJson()

Format log as JSON object. Each argument is treated as a sequence of alternating keys and values. If there is only one argument passed, it gets the default "message" key.

Signature:

type FormatJson = (
  filter?: string[], // default is  ['level', 'caller', 'ts', 'context', 'args']
  opt?: { tsFormat?: string; utc?: boolean }
) => Formatter

Example:

const log = formatJson(["level", "ts"])
log.info("key1", "val1", "key2", 42, "key3", { foo: "bar" })
// {"level":"info","ts":123456789,"key1":"val1","key2":42,"key3":{"foo":"bar"}}
log.info("Hey!")
// {"level":"info","ts":123456790,"message":"Hey!"}

Outputs

The outputs option allows you to define a list of target outputs for your logs. The default output is ["stdout"]. Acceptable values are:

  • stdout - write logs to standard output
  • file://<filePath> - appends logs to a file located at <filePath>
  • Transporter function - see next section for more details
import { logger } from "girok"

const log = logger({
  outputs: ["stdout", "file://./logs"],
})

Transporters

You can alson define a Transporter function as an output. This allows you to send logs to custom destinations.

The signature of a Transporter function is:

type Transporter = (buffer: string[]) => void

Girok provides the following default Transporter functions:

stdout

This is the default transporter. It writes logs to the standard output. This is the transporter used by the "stdout" alias.

import { logger } from "girok"
import { stdout } from "girok/transporters"

const log = logger({
  outputs: [stdout], // same as ["stdout"]
})

file

This transporter write logs to a file. This is the transporter used by the "file" alias.

  • path - path to the file
  • flag - flag to open the file. The default is "a", which means append.
import { logger } from "girok"
import { file } from "girok/transporters"

const log = logger({
  outputs: [file({ path: "./logs", flag: "a" })], // same as ["file://./logs"]
})

http

This transporter sends logs to an HTTP server. By default the logs in the buffer are concatened and written in the body of the request. You can configure the parser option to parse the response before sending it.

Signature:

type HttpTransporter = (config: {
  url: string
  method?: string // default is POST
  headers?: Record<string, string>
  onError?: (error: any) => void
  parser?: (data: string[]) => any // tr
}) => Transporter

here is an example of using the http transporter:

import { logger } from "girok"
import { http } from "girok/transporters"

const log = logger({
  outputs: [http({ url: "http://localhost:7357" })],
})

logstash

This transporter sends logs to a Logstash server.

Signature:

type LogstashTransporter = (config: {
  url?: string // default is http://localhost:5044
  onError?: (error: any) => void
})

Example:

import { logger } from "girok"
import { logstash } from "girok/transporters"

const log = logger({
  outputs: [logstash()],
})

splunk

This transporter sends logs to a Splunk server.

Signature:

type SplunkTransporter = (config: {
  url?: string // default is http://localhost:8088/services/collector
  token?: string
  metadata?: {
    time?: number
    host?: string
    source?: string
    sourcetype?: string
    index?: string
  }
  onError?: (e: Error) => void
})

Example:

import { logger } from "girok"
import { splunk } from "girok/transporters"

const log = logger({
  outputs: [splunk()],
})

Other options

Buffer size

The bufferSize option defines the maximum number of logs in the buffer before flushing. The default is 1, which means logs will be flushed after each log.

import { logger } from "girok"

const log = logger({
  bufferSize: 5,
})

log.info("1") // No output
log.info("2") // No output
log.info("3") // No output
log.info("4") // No output
log.info("5") // output: 1\n2\n3\n4\n5\n

Flush interval

The flushInterval option defines the interval in milliseconds between two flushes. The default is undefined. Meaning that logs will be flushed after each buffer completion.

import { logger } from "girok"

const log = logger({
  flushInterval: 10_000, // logs are flushed every 10 seconds
})

Override console

The overrideConsole option defines whether the console object should be overridden by the current logger. The default is false.

import { logger } from "girok"

const log = logger({
  overrideConsole: true,
})

console.log("Hello, World!") // alias for log.info("Hello World")
// [INFO] 1970-01-01 00:00:00.000 (index.ts:7:9)  Hello World!
console.warn("Test", 42)
// [WARN] 1970-01-01 00:00:00.000 (index.ts:9:9)  Test 42