{"id":16675827,"url":"https://github.com/mpyw/cloudwatch-front-logger","last_synced_at":"2025-03-21T18:31:36.235Z","repository":{"id":48913473,"uuid":"226575627","full_name":"mpyw/cloudwatch-front-logger","owner":"mpyw","description":"Save your browser console logs to AWS CloudWatch (Inspired by agea/console-cloud-watch)","archived":true,"fork":false,"pushed_at":"2023-01-20T07:26:54.000Z","size":49,"stargazers_count":17,"open_issues_count":6,"forks_count":6,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-15T01:51:49.469Z","etag":null,"topics":["aws-cloudwatch","cloudwatch","cloudwatch-logs","javascript","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/mpyw.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}},"created_at":"2019-12-07T21:01:51.000Z","updated_at":"2025-03-05T10:06:19.000Z","dependencies_parsed_at":"2023-02-12T00:25:13.003Z","dependency_job_id":null,"html_url":"https://github.com/mpyw/cloudwatch-front-logger","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpyw%2Fcloudwatch-front-logger","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpyw%2Fcloudwatch-front-logger/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpyw%2Fcloudwatch-front-logger/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mpyw%2Fcloudwatch-front-logger/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mpyw","download_url":"https://codeload.github.com/mpyw/cloudwatch-front-logger/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244848584,"owners_count":20520550,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["aws-cloudwatch","cloudwatch","cloudwatch-logs","javascript","typescript"],"created_at":"2024-10-12T13:08:04.336Z","updated_at":"2025-03-21T18:31:35.875Z","avatar_url":"https://github.com/mpyw.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CloudWatch Front Logger [![npm version](https://badge.fury.io/js/cloudwatch-front-logger.svg)](https://badge.fury.io/js/cloudwatch-front-logger) [![Build Status](https://github.com/mpyw/cloudwatch-front-logger/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/mpyw/cloudwatch-front-logger/actions) [![Coverage Status](https://coveralls.io/repos/github/mpyw/cloudwatch-front-logger/badge.svg?branch=master)](https://coveralls.io/github/mpyw/cloudwatch-front-logger?branch=master) [![npm](https://img.shields.io/npm/dt/cloudwatch-front-logger.svg)](https://www.npmjs.com/package/cloudwatch-front-logger)\n\nSave your browser console logs to AWS CloudWatch (Inspired by [agea/console-cloud-watch](https://github.com/agea/console-cloud-watch))\n\n- Demo: [mpyw/cloudwatch-front-logger-demo](https://github.com/mpyw/cloudwatch-front-logger-demo)\n\n## Installing\n\n```\nnpm i cloudwatch-front-logger\n```\n\n## Preparation\n\n### 1. Create Public Log Group\n\nGo to [CloudWatch console](https://console.aws.amazon.com/cloudwatch) and create Log Group for this purpose.\n\n### 2. Create Policy\n\nGo to [IAM Console](https://console.aws.amazon.com/iam/home) and create restricted policy for CloudWatch Logs.\n\n- `logs:CreateLogStream`\n- `logs:PutLogEvents`\n\n```json5\n{\n    \"Version\": \"2019-12-08\",\n    \"Statement\": [\n        {\n            \"Sid\": \"CloudWatchFrontLoggerSid\",\n            \"Effect\": \"Allow\",\n            \"Action\": [\n                \"logs:CreateLogStream\",\n                \"logs:PutLogEvents\"\n            ],\n            \"Resource\": [\n                \"arn:aws:logs:*:*:log-group:\u003cLOG_GROUP_NAME\u003e:*:*\",\n                \"arn:aws:logs:*:*:log-group:\u003cLOG_GROUP_NAME\u003e\"\n            ]\n        }\n    ]\n}\n```\n\n### 3. Create IAM user\n\nGo to [IAM Console](https://console.aws.amazon.com/iam/home) and create user with the restricted policy.\n\n## Basic Usage\n\n```js\nimport { Logger } from 'cloudwatch-front-logger'\n\nconst accessKeyId = 'XXXXXXXXXXXXXXXXXXXX'\nconst secretAccessKey = 'YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY'\nconst region = 'ap-northeast-1'\nconst logGroupName = '\u003cLOG_GROUP_NAME\u003e'\n\nconst logger = new Logger(accessKeyId, secretAccessKey, region, logGroupName)\nlogger.install()\n```\n\nLogs are collected from the following sources.\n\n- Uncaught Error\n- `console.error()` call\n- Manual `logger.onError()` call\u003cbr\u003e(See integration examples)\n\n## Advanced Usage\n\n### Personalize LogStream\n\nBy default, `\"anonymous\"` is used for `logStreamName` value.\nIf you wish allocating a unique stream for each user, you can use a method such as [Canvas Fingerprint](https://github.com/Valve/fingerprintjs2).\nPass a resolver function as **`logStreamNameResolver`** option value on `install()` call.\n\n```js\nimport FingerprintJS from 'fingerprintjs'\n\nlogger.install({\n  async logStreamNameResolver() {\n    const fp = await FingerprintJS.load()\n    const { visitorId } = await fp.get()\n    return visitorId\n  },\n})\n```\n\n### Customize Formatted Message\u003cbr\u003eFilter Errors\n\nBy default, messages are formatted into **JSON** string which has `message` and `type`.\n\n```json5\n{\n  \"message\": \"Err: Something went wrong\",\n  \"type\": \"uncaught\"\n}\n```\n\n```json5\n{\n  \"message\": \"Something went wrong\",\n  \"type\": \"console\",\n  \"level\": \"error\"\n}\n```\n\nIf you wish formatting them by yourself, pass a formatter function as **`messageFormatter`** option value on `install()` call. Note that you can cancel by returning **`null`** from the fuunction.\n\n```js\nimport StackTrace from 'stacktrace-js'\n\nlogger.install({\n  async messageFormatter(e, info = { type: 'unknown' }) {\n    if (!e.message) {\n      return null\n    }\n    \n    let stack = null\n    if (e.stack) {\n      stack = e.stack\n      try {\n        stack = await StackTrace.fromError(e, { offline: true })\n      } catch (_) {\n      }\n    }\n\n    return JSON.stringify({\n      message: e.message,\n      timestamp: new Date().getTime(),\n      userAgent: window.navigator.userAgent,\n      stack,\n      ...info,\n    })\n  },\n})\n```\n\n### Use Asynchronous Storage instead of `localStorage`\n\nBy default, **`localStorage`** is used for caching `logStreamName` and `nextSequenceToken`.\nStill `localStorage` has only synchronous API, asynchronous interfaces are also supported.\nIf you need to change storage implementation from `localStorage`, pass an instance as **`storage`** option value on `install()` call.\n\n```js\nimport { AsyncStorage } from 'react-native'\n\nlogger.install({\n  storage: AsyncStorage,\n})\n```\n\n## Integration Examples\n\n### React (Component)\n\n```jsx\nclass LoggerComponent extends React.component {\n\n  componentDidCatch(e, info) {\n    this.props.logger.onError(e, {\n      ...info,\n      type: 'react',\n    })\n  }\n\n  render() {\n    return this.props.children\n  }\n}\n```\n\n```jsx\n\u003cLoggerComponent logger={logger}\u003e\n  \u003cApp /\u003e\n\u003c/LoggerComponent\u003e\n```\n\n### Redux (Middleware)\n\n```js\nconst createLoggerMiddleware = (logger) =\u003e (store) =\u003e (next) =\u003e (action) =\u003e {\n  try {\n    return next(action)\n  } catch (e) {\n    logger.onError(e, {\n      action,\n      type: 'redux',\n    })\n  }\n}\n```\n\n```js\nconst store = createStore(\n  combineReducers(reducers),\n  applyMiddleware(createLoggerMiddleware(logger))\n)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmpyw%2Fcloudwatch-front-logger","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmpyw%2Fcloudwatch-front-logger","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmpyw%2Fcloudwatch-front-logger/lists"}