{"id":48502164,"url":"https://github.com/zerodep/pino-applicationinsights","last_synced_at":"2026-04-07T15:02:34.928Z","repository":{"id":206147230,"uuid":"715957573","full_name":"zerodep/pino-applicationinsights","owner":"zerodep","description":"Pino transport to Application Insights","archived":false,"fork":false,"pushed_at":"2025-11-14T04:50:29.000Z","size":88,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"default","last_synced_at":"2025-11-14T05:00:03.097Z","etag":null,"topics":["applicationinsights","fake","mock","pino"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zerodep.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-11-08T07:16:57.000Z","updated_at":"2025-11-14T04:48:26.000Z","dependencies_parsed_at":"2024-03-06T20:33:16.182Z","dependency_job_id":null,"html_url":"https://github.com/zerodep/pino-applicationinsights","commit_stats":null,"previous_names":["zerodep/pino-applicationinsights"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/zerodep/pino-applicationinsights","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerodep%2Fpino-applicationinsights","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerodep%2Fpino-applicationinsights/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerodep%2Fpino-applicationinsights/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerodep%2Fpino-applicationinsights/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zerodep","download_url":"https://codeload.github.com/zerodep/pino-applicationinsights/tar.gz/refs/heads/default","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zerodep%2Fpino-applicationinsights/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31516839,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-07T03:10:19.677Z","status":"ssl_error","status_checked_at":"2026-04-07T03:10:13.982Z","response_time":105,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["applicationinsights","fake","mock","pino"],"created_at":"2026-04-07T15:02:34.067Z","updated_at":"2026-04-07T15:02:34.917Z","avatar_url":"https://github.com/zerodep.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pino applicationinsights transport\n\n[![Build](https://github.com/zerodep/pino-applicationinsights/actions/workflows/build.yaml/badge.svg)](https://github.com/zerodep/pino-applicationinsights/actions/workflows/build.yaml)[![Coverage Status](https://coveralls.io/repos/github/zerodep/pino-applicationinsights/badge.svg?branch=default)](https://coveralls.io/github/zerodep/pino-applicationinsights?branch=default)\n\nForward pino logger to Application Insights.\n\nHave a look in [Example app](/example) to get inspiration of how to use this lib.\n\nShips with [fake applicationinsights](#class-fakeapplicationinsightssetupstring) helper test class.\n\n## Usage\n\n```javascript\nimport { pino } from 'pino';\nimport compose from '@0dep/pino-applicationinsights';\nimport { Contracts } from 'applicationinsights';\n\nconst tagKeys = new Contracts.ContextTagKeys();\n\nconst transport = compose({\n  track(chunk) {\n    const { time, severity, msg: message, properties, exception } = chunk;\n    this.trackTrace({ time, severity, message, properties });\n    if (exception) this.trackException({ time, exception, severity });\n  },\n  connectionString: process.env.APPLICATIONINSIGHTS_CONNECTION_STRING,\n  config: { maxBatchSize: 1 },\n});\n\nconst logger = pino(\n  {\n    level: 'trace',\n    mixin(context) {\n      return {\n        tagOverrides: {\n          [tagKeys.userId]: 'someUserIdPickedFromRequest',\n          ...context.tagOverrides,\n        },\n      };\n    },\n  },\n  transport,\n);\n```\n\nor as multi transport:\n\n```javascript\nimport { pino } from 'pino';\n\nconst transport = pino.transport({\n  targets: [\n    {\n      level: 'info',\n      target: '@0dep/pino-applicationinsights',\n      options: {\n        connectionString: process.env.APPLICATIONINSIGHTS_CONNECTION_STRING,\n        config: {\n          disableStatsbeat: true,\n        },\n      },\n    },\n    {\n      level: 'debug',\n      target: 'pino-pretty',\n      options: {\n        colorize: true,\n        ignore: 'pid,hostname',\n        translateTime: \"yyyy-mm-dd'T'HH:MM:ss.l\",\n      },\n    },\n  ],\n});\n\nconst logger = pino({ level: 'trace' }, transport);\n```\n\n## API\n\n### `compose(opts[, TelemetryTransformation]) =\u003e Stream`\n\nBuild transport stream function.\n\n- `opts`:\n  - `connectionString`: Application Insights connection string or instrumentation key\n  - `track(chunk)`: optional track function called with Telemetry client context, defaults to tracking trace and exception\n    - `chunk`: [Telemetry:ish](#telemetrish-object) object\n  - `config`: optional Application Insights Telemetry client config\n  - `destination`: optional destination stream, makes compose ignore the above options\n  - `ignoreKeys`: optional pino ignore keys, used to filter telemetry properties, defaults to `['hostname', 'pid', 'level', 'time', 'msg']`\n- `TelemetryTransformation`: optional transformation stream extending [TelemetryTransformation](#class-telemetrytransformationoptions-config)\n\n### `class TelemetryTransformation(options[, config])`\n\nTelemetry transformation stream. Transforms pino log record to [Telemetry:ish](#telemetrish-object) object.\n\n- `constructor(options[, config])`\n  - `options`: transform stream options, `{ objectMode: true }` is always set\n  - `config`: optional config object\n    - `ignoreKeys`: optional pino ignore keys as string array\n- `_transform(chunk, encoding, callback)`\n- `convertToTelemetry(chunk)`: convert pino log record string or object to [telemetry:ish object](#telemetrish-object)\n- `convertLevel(level)`: map pino log level number to `Contracts.SeverityLevel`\n- `extractProperties(line, ignoreKeys)`: extract properties from log line\n  - `line`: log line record object\n  - `ignoreKeys`: configured ignore keys\n- properties:\n  - `ignoreKeys`: configured ignore keys, defaults to `['hostname', 'pid', 'level', 'time', 'msg']`\n\n#### Telemetrish object\n\n- `severity`: pino log level mapped to application insights severeity level, i.e. `Contracts.SeverityLevel`\n- `msg`: log message string\n- `properties`: telemetry properties object, filtered through ignore keys\n- `exception?`: logged Error if any\n- `[k: string]`: any other properties that facilitate telemetry logging\n\n### `class FakeApplicationInsights(setupString)`\n\nIntercept calls to application insights.\n\n- `constructor(setupString);`\n  - `setupString`: Fake application insights connection string\n- `expectMessageData()`: Expect tracked message, returns [`Promise\u003cFakeCollectData\u003e`](#fakecollectdata)\n- `expectEventData()`: Expect tracked event, returns [`Promise\u003cFakeCollectData\u003e`](#fakecollectdata)\n- `expectExceptionData()`: Expect tracked exception, returns [`Promise\u003cFakeCollectData\u003e`](#fakecollectdata)\n- `expectEventType(telemetryType: string)`: Expect tracked telemetry type, returns [`Promise\u003cFakeCollectData\u003e`](#fakecollectdata)\n  - `telemetryType`: Telemetry type string\n- `expect(count = 1)`: Expect tracked telemetrys, returns promise with list of [`FakeCollectData`](#fakecollectdata)\n  - `count`: wait for at least tracked telemetrys before returning, default is 1\n- `reset()`: Reset expected faked Application Insights calls, calls `nock.cleanAll`\n- properties:\n  - `client`: TelemetryClient, used to get endpoint URL\n  - `_endpointURL`: endpoint URL\n  - `_scope`: nock Scope\n\n#### Example\n\n```javascript\nimport { randomUUID } from 'node:crypto';\nimport 'mocha';\nimport { pino } from 'pino';\n\nimport compose from '@0dep/pino-applicationinsights';\nimport { FakeApplicationInsights } from '@0dep/pino-applicationinsights/fake-applicationinsights';\n\ndescribe('test logger', () =\u003e {\n  const connectionString = `InstrumentationKey=${randomUUID()};IngestionEndpoint=https://ingestion.local;LiveEndpoint=https://livemonitor.local/`;\n\n  let fakeAI;\n  before(() =\u003e {\n    fakeAI = new FakeApplicationInsights(connectionString);\n  });\n  after(() =\u003e {\n    fakeAI.reset();\n  });\n\n  it('log event track event', async () =\u003e {\n    const transport = compose({\n      track(chunk) {\n        const { time, properties } = chunk;\n        this.trackEvent({ name: 'my event', time, properties, measurements: { logins: 1 } });\n      },\n      connectionString,\n      config: { maxBatchSize: 1, disableStatsbeat: true },\n    });\n    const logger = pino(transport);\n\n    const expectMessage = fakeAI.expectEventData();\n\n    logger.info({ bar: 'baz' }, 'foo');\n\n    const msg = await expectMessage;\n\n    expect(msg.body.data.baseData).to.deep.include({\n      properties: { bar: 'baz' },\n      measurements: { logins: 1 },\n      name: 'my event',\n    });\n\n    transport.destroy();\n  });\n});\n```\n\n#### `FakeCollectData`\n\nAn object representing the request sent to application insights.\n\n- `uri`: request uri\n- `method`: request method\n- `headers`: request headers object\n- `body`:\n  - `ver`: some version number, usually 1\n  - `sampleRate`: sample rate number, usually 100\n  - `tags`: object with tags, tag names can be inspected under `TelemetryClient.context.keys`, e.g:\n    - `ai.application.ver`: your package.json version\n    - `ai.device.id`: ?\n    - `ai.cloud.roleInstance`: computer hostname?\n    - `ai.device.osVersion`: computer os\n    - `ai.cloud.role`: Web maybe?\n    - `ai.device.osArchitecture`: probably x64\n    - `ai.device.osPlatform`: os platform, as the name says\n    - `ai.internal.sdkVersion`: applicationinsights package version, e.g. `node:2.9.1`\n    - `[tag name]`: any other tag found under `TelemetryClient.context.keys`\n  - `data`:\n    - `baseType`: telemetry type string\n    - `baseData`:\n      - `ver`: some version number, usually 2 for some reason\n      - `properties`: telemetry properties object\n      - `[message]`: logged message when tracking trace\n      - `[severityLevel]`: applicationinsights severity level number when tracking trace and exception\n      - `[exceptions]`: list of exceptions when tracking exception\n        - `message`: error message\n        - `hasFullStack`: boolean, true\n        - `parsedStack`: stack parsed as objects\n      - `[x: string]`: any other telemetry property\n  - `iKey`: applicationinsights instrumentation key\n  - `name`: some ms name with iKey and the tracked type\n  - `time`: log time\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzerodep%2Fpino-applicationinsights","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzerodep%2Fpino-applicationinsights","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzerodep%2Fpino-applicationinsights/lists"}