├── .github ├── dependabot.yml └── workflows │ └── ci.yml ├── .gitignore ├── LICENSE ├── README.md ├── examples ├── .gitignore ├── index.js ├── module-ts.ts ├── module.js ├── package-lock.json └── package.json ├── index.d.ts ├── index.js ├── index.test-d.ts ├── package.json ├── tests ├── .gitignore ├── test-ts.ts └── test.js └── tsconfig.json /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "monthly" 7 | open-pull-requests-limit: 10 8 | 9 | - package-ecosystem: "npm" 10 | directory: "/" 11 | schedule: 12 | interval: "weekly" 13 | open-pull-requests-limit: 10 14 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | paths-ignore: 6 | - 'docs/**' 7 | - '*.md' 8 | pull_request: 9 | paths-ignore: 10 | - 'docs/**' 11 | - '*.md' 12 | 13 | # This allows a subsequently queued workflow run to interrupt previous runs 14 | concurrency: 15 | group: "${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}" 16 | cancel-in-progress: true 17 | 18 | jobs: 19 | dependency-review: 20 | name: Dependency Review 21 | if: github.event_name == 'pull_request' 22 | runs-on: ubuntu-latest 23 | permissions: 24 | contents: read 25 | steps: 26 | - name: Check out repo 27 | uses: actions/checkout@v3 28 | with: 29 | persist-credentials: false 30 | 31 | - name: Dependency review 32 | uses: actions/dependency-review-action@v3 33 | 34 | test: 35 | name: Test 36 | runs-on: ${{ matrix.os }} 37 | permissions: 38 | contents: read 39 | strategy: 40 | matrix: 41 | node-version: [20, 22] 42 | os: [macos-latest, ubuntu-latest] 43 | steps: 44 | - name: Check out repo 45 | uses: actions/checkout@v3 46 | with: 47 | persist-credentials: false 48 | 49 | - name: Setup Node ${{ matrix.node-version }} 50 | uses: actions/setup-node@v3 51 | with: 52 | node-version: ${{ matrix.node-version }} 53 | 54 | - name: Install dependencies 55 | run: npm i --ignore-scripts 56 | 57 | - name: Run tests 58 | run: npm run test:ci 59 | 60 | automerge: 61 | name: Automerge Dependabot PRs 62 | if: > 63 | github.event_name == 'pull_request' && 64 | github.event.pull_request.user.login == 'dependabot[bot]' 65 | needs: test 66 | permissions: 67 | pull-requests: write 68 | contents: write 69 | runs-on: ubuntu-latest 70 | steps: 71 | - uses: fastify/github-action-merge-dependabot@v3 72 | with: 73 | github-token: ${{ secrets.GITHUB_TOKEN }} 74 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # Snowpack dependency directory (https://snowpack.dev/) 46 | web_modules/ 47 | 48 | # TypeScript cache 49 | *.tsbuildinfo 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Optional stylelint cache 58 | .stylelintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variable files 76 | .env 77 | .env.development.local 78 | .env.test.local 79 | .env.production.local 80 | .env.local 81 | 82 | # parcel-bundler cache (https://parceljs.org/) 83 | .cache 84 | .parcel-cache 85 | 86 | # Next.js build output 87 | .next 88 | out 89 | 90 | # Nuxt.js build / generate output 91 | .nuxt 92 | dist 93 | 94 | # Gatsby files 95 | .cache/ 96 | # Comment in the public line in if your project uses Gatsby and not Next.js 97 | # https://nextjs.org/blog/next-9-1#public-directory-support 98 | # public 99 | 100 | # vuepress build output 101 | .vuepress/dist 102 | 103 | # vuepress v2.x temp and cache directory 104 | .temp 105 | .cache 106 | 107 | # Docusaurus cache and generated files 108 | .docusaurus 109 | 110 | # Serverless directories 111 | .serverless/ 112 | 113 | # FuseBox cache 114 | .fusebox/ 115 | 116 | # DynamoDB Local files 117 | .dynamodb/ 118 | 119 | # TernJS port file 120 | .tern-port 121 | 122 | # Stores VSCode versions used for testing VSCode extensions 123 | .vscode-test 124 | 125 | # yarn v2 126 | .yarn/cache 127 | .yarn/unplugged 128 | .yarn/build-state.yml 129 | .yarn/install-state.gz 130 | .pnp.* 131 | 132 | # Vim swap files 133 | *.swp 134 | 135 | # macOS files 136 | .DS_Store 137 | 138 | # editor files 139 | .vscode 140 | .idea 141 | 142 | # lock files 143 | package-lock.json 144 | pnpm-lock.yaml 145 | yarn.lock 146 | 147 | # 0x 148 | .__browserify* 149 | profile-* -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-2019 Matteo Collina, David Mark Clements and the Pino contributors 4 | 5 | Pino contributors listed at https://github.com/pinojs/pino#the-team and in 6 | the README file. 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## pino-caller 2 | [![npm version](https://img.shields.io/npm/v/pino-caller)](https://www.npmjs.com/package/pino-caller) 3 | [![Build Status](https://img.shields.io/github/actions/workflow/status/pinojs/pino-caller/ci.yml?branch=master)](https://github.com/pinojs/pino-caller/actions) 4 | [![Coverage Status](https://coveralls.io/repos/github/pinojs/pino-caller/badge.svg?branch=master)](https://coveralls.io/github/pinojs/pino-caller?branch=master) 5 | [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://standardjs.com/) 6 | 7 | ### Description 8 | `pino-caller` is a wrapper for [pino](https://github.com/pinojs/pino) which adds the call site of each log message to the log output. 9 | This can be useful when developing with large codebases in order to locate the exact point where pino is invoked. 10 | 11 | ### Install 12 | 13 | For Pino v4 and below use the v2 line, which can be installed with the `@legacy` tag: 14 | 15 | ```sh 16 | npm install pino-caller@legacy 17 | ``` 18 | 19 | For Pino v5 and above use the v3+ line, which will install using the usual command: 20 | 21 | ``` 22 | npm install pino-caller 23 | ``` 24 | 25 | **WARNING: THIS IS A DEVELOPMENT TOOL AVOID PRODUCTION USE!** 26 | 27 | ### Usage 28 | 29 | #### Basic 30 | ```js 31 | 'use strict' 32 | 33 | const pino = require('pino')() // it will print as usual 34 | const pinoCaller = require('pino-caller')(pino) // it will print also the calling site 35 | 36 | pinoCaller.info('info1') 37 | pinoCaller.error('error1') 38 | pinoCaller.debug('debug1') 39 | ``` 40 | 41 | #### Advanced 42 | ```js 43 | 'use strict' 44 | // dynamically load the plugin if in development environment, output paths relative to __dirname 45 | const pino = process.env.NODE_ENV === 'development' ? require('pino-caller')(require('pino')(), { relativeTo: __dirname }) : require('pino')() 46 | 47 | pino.info('info1') 48 | pino.error('error1') 49 | pino.debug('debug1') 50 | ``` 51 | 52 | You can find also a working example in the `examples` directory and you can run it with `npm run example` 53 | 54 | ##### Options 55 | 56 | - **relativeTo** - Remove path prefixes from log messages to make them easier to read. 57 | - **stackAdjustment** - For those who've wrapped pino, make pino-caller move N stackframes up to get a meaningful message. 58 | 59 | ```js 60 | 'use strict' 61 | const pino = require('pino')() 62 | const pinoCaller = require('pino-caller')(pino, { relativeTo: __dirname, stackAdjustment: 1 }) 63 | 64 | // People who have wrapped pino like in the contrived example below 65 | // will want to use stackAdjustment. 66 | // Most people will NOT need this. See issue #90 for details. 67 | const log = { 68 | info: function(message) { pinoCaller.info(message) } 69 | } 70 | ``` 71 | 72 | ### Example output 73 | 74 | ``` 75 | ╭─phra at debian in /home/phra/git/pino-caller (master ✔) 76 | ╰─λ npm run example 77 | 78 | > pino-caller@1.0.0 example /home/phra/git/pino-caller 79 | > env NODE_ENV=development node examples/index.js 80 | 81 | {"pid":44837,"hostname":"debian","level":30,"time":1487873713227,"msg":"hello from the module!","caller":"Object. (/home/phra/git/pino-caller/examples/module.js:4:12)","v":1} 82 | {"pid":44837,"hostname":"debian","level":30,"time":1487873713230,"msg":"info1","caller":"Object. (index.js:8:12)","v":1} 83 | {"pid":44837,"hostname":"debian","level":50,"time":1487873713230,"msg":"error1","caller":"Object. (index.js:9:12)","v":1} 84 | ``` 85 | -------------------------------------------------------------------------------- /examples/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | .nyc_output 4 | module-ts.js 5 | module-ts.js.map 6 | -------------------------------------------------------------------------------- /examples/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const pino = process.env.NODE_ENV === 'development' ? require('../')(require('pino')(), { relativeTo: __dirname }) : require('pino')() 4 | 5 | require('./module') 6 | 7 | pino.info('info1') 8 | pino.error('error1') 9 | pino.debug('debug1') 10 | -------------------------------------------------------------------------------- /examples/module-ts.ts: -------------------------------------------------------------------------------- 1 | const pino = process.env.NODE_ENV === 'development' ? require('../')(require('pino')()) : require('pino')() 2 | 3 | function add(n: number, m: number) { 4 | return n + m 5 | } 6 | 7 | async function main() { 8 | pino.info(add(2, 3)) 9 | } 10 | 11 | main() 12 | 13 | -------------------------------------------------------------------------------- /examples/module.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const pino = process.env.NODE_ENV === 'development' ? require('../')(require('pino')()) : require('pino')() 4 | 5 | pino.info('hello from the module!') 6 | -------------------------------------------------------------------------------- /examples/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "examples", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@types/node": { 8 | "version": "12.7.5", 9 | "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.5.tgz", 10 | "integrity": "sha512-9fq4jZVhPNW8r+UYKnxF1e2HkDWOWKM5bC2/7c9wPV835I0aOrVbS/Hw/pWPk2uKrNXQqg9Z959Kz+IYDd5p3w==" 11 | }, 12 | "typescript": { 13 | "version": "3.6.3", 14 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.3.tgz", 15 | "integrity": "sha512-N7bceJL1CtRQ2RiG0AQME13ksR7DiuQh/QehubYcghzv20tnh+MQnQIuJddTmsbqYj+dztchykemz0zFzlvdQw==" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "examples", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "compile": "tsc -sourcemap module-ts.ts", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "@types/node": "^12.7.5", 15 | "typescript": "^3.6.3" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for pino-caller 3.1 2 | // Project: https://github.com/pinojs/pino-caller#readme 3 | // Definitions by: Austin Ziegler 4 | // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped 5 | 6 | import { Logger } from 'pino'; 7 | 8 | interface Options { 9 | relativeTo?: string; 10 | stackAdjustment?: number; 11 | } 12 | 13 | declare function pinoCaller(logger: Logger, options?: Options): Logger; 14 | 15 | export default pinoCaller 16 | export { pinoCaller } 17 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | require('source-map-support/register') 4 | const NODEJS_VERSION = parseInt(process.version.slice(1).split('.')[0], 10) 5 | const STACKTRACE_OFFSET = NODEJS_VERSION && NODEJS_VERSION > 6 ? 0 : 1 6 | const LINE_OFFSET = 7 7 | const { symbols } = require('pino') 8 | const { asJsonSym } = symbols 9 | 10 | function traceCaller (pinoInstance, options = {relativeTo: null, stackAdjustment: 0}) { 11 | const adjustment = options.stackAdjustment || 0 12 | 13 | function get (target, name) { 14 | return name === asJsonSym ? asJson : target[name] 15 | } 16 | 17 | function asJson (...args) { 18 | args[0] = args[0] || Object.create(null) 19 | args[0].caller = Error().stack.split('\n').slice(2).filter(s => !s.includes('node_modules/pino') && !s.includes('node_modules\\pino'))[STACKTRACE_OFFSET + adjustment].substr(LINE_OFFSET) 20 | if (options && typeof options.relativeTo === 'string') { 21 | const lastChar = options.relativeTo[options.relativeTo.length - 1] 22 | const hasTrailingSlash = lastChar === '/' || lastChar === '\\' 23 | 24 | args[0].caller = args[0].caller 25 | .replace(hasTrailingSlash ? options.relativeTo : options.relativeTo + '/', '') 26 | .replace(hasTrailingSlash ? options.relativeTo : options.relativeTo + '\\', '') 27 | } 28 | return pinoInstance[asJsonSym].apply(this, args) 29 | } 30 | 31 | return new Proxy(pinoInstance, { get }) 32 | } 33 | 34 | /** 35 | * These export configurations enable JS and TS developers 36 | * to consumer pino-caller in whatever way best suits their needs. 37 | * Some examples of supported import syntax includes: 38 | * - `const pinoCaller = require('pino-caller')` 39 | * - `const { pinoCaller } = require('pino-caller')` 40 | * - `import * as pinoCaller from 'pino-caller'` 41 | * - `import { pinoCaller } from 'pino-caller'` 42 | * - `import pinoCaller from 'pino-caller'` 43 | */ 44 | traceCaller.pinoCaller = traceCaller 45 | traceCaller.default = traceCaller 46 | module.exports = traceCaller 47 | -------------------------------------------------------------------------------- /index.test-d.ts: -------------------------------------------------------------------------------- 1 | import pino, {Logger} from 'pino' 2 | import pinoCaller, { pinoCaller as pinoCallerNamed } from "."; 3 | import pinoCallerDefault from "."; 4 | import * as pinoCallerStar from "."; 5 | import pinoCallerCjsImport = require ("."); 6 | import {expectType} from "tsd"; 7 | const pinoCallerCjs = require("."); 8 | const { pinoCaller: pinoCallerCjsNamed } = require('pino-caller') 9 | 10 | const log = pino() 11 | const callerLog = pinoCaller(log) 12 | 13 | callerLog.info('hello') 14 | callerLog.error('error!') 15 | 16 | pinoCaller(log, { relativeTo: 'pwd' }).error('error!') 17 | 18 | expectType(pinoCallerNamed(log)); 19 | expectType( pinoCallerDefault(log)); 20 | expectType(pinoCallerStar.pinoCaller(log)); 21 | expectType(pinoCallerStar.default(log)); 22 | expectType( pinoCallerCjsImport.pinoCaller(log)); 23 | expectType( pinoCallerCjsImport.default(log)); 24 | expectType( new pinoCallerCjs(log)); 25 | expectType( new pinoCallerCjsNamed(log)); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pino-caller", 3 | "version": "4.0.0", 4 | "description": "print the filename and line number of the caller (use only in development environment)", 5 | "main": "index.js", 6 | "types": "index.d.ts", 7 | "repository": "https://github.com/pinojs/pino-caller.git", 8 | "author": "phra ", 9 | "license": "MIT", 10 | "watch": { 11 | "test-watch": { 12 | "patterns": [ 13 | "." 14 | ], 15 | "extensions": [ 16 | "js", 17 | "ts" 18 | ] 19 | } 20 | }, 21 | "devDependencies": { 22 | "@types/pino": "^7.0.4", 23 | "@types/through2": "^2.0.41", 24 | "npm-watch": "^0.11.0", 25 | "pino": "^9.6.0", 26 | "pino-debug": "^3.0.0", 27 | "standard": "^8.6.0", 28 | "through2": "^4.0.2", 29 | "ts-node": "^10.2.1", 30 | "tsd": "^0.32.0", 31 | "typescript": "~5.8.3" 32 | }, 33 | "engines": { 34 | "node": ">6.0.0" 35 | }, 36 | "scripts": { 37 | "lint-fix": "standard --fix index.js examples/*js tests/*.js", 38 | "pretest": "npm run lint-fix", 39 | "test": "node --test ./tests/test.js && npm run test-ts && npm run test-types", 40 | "test-ts": "ts-node tests/test-ts.ts", 41 | "test:ci": "npm run pretest && node -r \"source-map-support/register\" tests/*.js tests/*.ts && npm run test-types", 42 | "test-types": "tsc && tsd", 43 | "example": "env NODE_ENV=development node examples/index.js", 44 | "watch": "npm-watch" 45 | }, 46 | "dependencies": { 47 | "source-map-support": "^0.5.13" 48 | }, 49 | "standard": { 50 | "ignore": [ 51 | "examples/module-ts.js" 52 | ] 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | test-ts.js 2 | test-ts.js.map 3 | -------------------------------------------------------------------------------- /tests/test-ts.ts: -------------------------------------------------------------------------------- 1 | import {test, type TestContext} from 'node:test' 2 | import pino from 'pino' 3 | import * as through2 from 'through2' 4 | import pinoCaller from '../' 5 | 6 | test('pino caller works with sourcemaps (typescript)', function (t: TestContext) { 7 | t.plan(3) 8 | 9 | const pinoInstance = pinoCaller(pino(through2(function (chunk, enc, callback) { 10 | const res = JSON.parse(chunk.toString('utf8')) 11 | const regex = /TestContext. \(\/(.)*tests\/test-ts.ts/ 12 | t.assert.ok(res.caller, 'caller property is set') 13 | t.assert.equal(typeof res.caller, 'string', 'caller property is a string') 14 | t.assert.ok(regex.test(res.caller), 'caller property matches the test regex') 15 | }))) 16 | 17 | pinoInstance.info('test') 18 | }) 19 | -------------------------------------------------------------------------------- /tests/test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const path = require('node:path') 4 | const { test } = require('node:test') 5 | const pino = require('pino') 6 | const pinoDebug = require('pino-debug') 7 | const through2 = require('through2') 8 | const pinoCaller = require('../') 9 | 10 | test('pino caller works', function (t) { 11 | t.plan(3) 12 | 13 | const pinoInstance = pinoCaller(pino(through2(function (chunk, enc, callback) { 14 | const res = JSON.parse(chunk.toString('utf8')) 15 | const regex = /TestContext. \(\/(.)*tests\/test.js/ 16 | t.assert.ok(res.caller, 'caller property is set') 17 | t.assert.equal(typeof res.caller, 'string', 'caller property is a string') 18 | t.assert.ok(regex.test(res.caller), 'caller property matches the test regex') 19 | }))) 20 | 21 | pinoInstance.info('test') 22 | }) 23 | 24 | test('pino caller works also when adding level', function (t) { 25 | t.plan(3) 26 | 27 | const pinoInstance = pinoCaller(pino(through2(function (chunk, enc, callback) { 28 | const res = JSON.parse(chunk.toString('utf8')) 29 | const regex = /TestContext. \(\/(.)*tests\/test.js/ 30 | t.assert.ok(res.caller, 'caller property is set') 31 | t.assert.equal(typeof res.caller, 'string', 'caller property is a string') 32 | t.assert.ok(regex.test(res.caller), 'caller property matches the test regex') 33 | }))) 34 | 35 | pinoInstance.level = 'fatal' 36 | pinoInstance.level = 'trace' 37 | pinoInstance.level = 'fatal' 38 | pinoInstance.trace('test') 39 | pinoInstance.fatal('test') 40 | }) 41 | 42 | test('pino caller works also when switching level', function (t) { 43 | t.plan(3) 44 | 45 | const pinoInstance = pinoCaller(pino({ 46 | customLevels: { 47 | myLevel: 100 48 | } 49 | }, through2(function (chunk, enc, callback) { 50 | const res = JSON.parse(chunk.toString('utf8')) 51 | const regex = /TestContext. \(\/(.)*tests\/test.js/ 52 | t.assert.ok(res.caller, 'caller property is set') 53 | t.assert.equal(typeof res.caller, 'string', 'caller property is a string') 54 | t.assert.ok(regex.test(res.caller), 'caller property matches the test regex') 55 | }))) 56 | pinoInstance.level = 'myLevel' 57 | pinoInstance.level = 'trace' 58 | pinoInstance.level = 'myLevel' 59 | pinoInstance.trace('test') 60 | pinoInstance.myLevel('test') 61 | }) 62 | 63 | test('pino caller works also with pino plugins', function (t) { 64 | t.plan(3) 65 | 66 | const pinoInstance = pinoCaller(pino({ 67 | customLevels: { 68 | myLevel: 100 69 | } 70 | }, through2(function (chunk, enc, callback) { 71 | const res = JSON.parse(chunk.toString('utf8')) 72 | const regex = /TestContext. \(\/(.)*tests\/test.js/ 73 | t.assert.ok(res.caller, 'caller property is set') 74 | t.assert.equal(typeof res.caller, 'string', 'caller property is a string') 75 | t.assert.ok(regex.test(res.caller), 'caller property matches the test regex') 76 | }))) 77 | 78 | pinoDebug(pinoInstance, { map: { '*': 'trace' } }) 79 | 80 | pinoInstance.info('test') 81 | }) 82 | 83 | test('pino caller works also with relativeTo parameter set', function (t) { 84 | t.plan(3) 85 | 86 | const pinoInstance = pinoCaller(pino(through2(function (chunk, enc, callback) { 87 | const res = JSON.parse(chunk.toString('utf8')) 88 | const regex = /TestContext. \(test.js/ 89 | t.assert.ok(res.caller, 'caller property is set') 90 | t.assert.equal(typeof res.caller, 'string', 'caller property is a string') 91 | t.assert.ok(regex.test(res.caller), 'caller property matches the test regex') 92 | })), { relativeTo: __dirname }) 93 | 94 | pinoInstance.info('test') 95 | }) 96 | 97 | test('pino caller works also when relativeTo has a trailing slash', function (t) { 98 | t.plan(3) 99 | 100 | const pinoInstance = pinoCaller(pino(through2(function (chunk, enc, callback) { 101 | const res = JSON.parse(chunk.toString('utf8')) 102 | const regex = /TestContext. \(test.js/ 103 | t.assert.ok(res.caller, 'caller property is set') 104 | t.assert.equal(typeof res.caller, 'string', 'caller property is a string') 105 | t.assert.ok(regex.test(res.caller), 'caller property matches the test regex') 106 | })), { relativeTo: path.join(__dirname, '/') }) 107 | 108 | pinoInstance.info('test') 109 | }) 110 | 111 | test('pino caller can make stack adjustments', function (t) { 112 | t.plan(3) 113 | 114 | const pinoInstance = pinoCaller(pino(through2(function (chunk, enc, callback) { 115 | const res = JSON.parse(chunk.toString('utf8')) 116 | const regex = /TestContext. \(\/(.)*tests\/test.js/ 117 | t.assert.ok(res.caller, 'caller property is set') 118 | t.assert.equal(typeof res.caller, 'string', 'caller property is a string') 119 | t.assert.ok(regex.test(res.caller), 'caller property matches the test regex') 120 | })), { stackAdjustment: 1 }) 121 | 122 | // Create a wrapper around pino so that we can show that stackAdjustment can bypass this stack frame. 123 | const log = { 124 | info: function (message) { 125 | pinoInstance.info(message) 126 | } 127 | } 128 | log.info('test') 129 | }) 130 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "lib": ["es2015"], 5 | "module": "commonjs", 6 | "noEmit": true, 7 | "strict": true 8 | }, 9 | "include": ["./*.d.ts"] 10 | } 11 | --------------------------------------------------------------------------------