Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Version 1.0.0 #233

Merged
merged 18 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
d8ec309
refactor: #197 Refactor to use Promises internally (#200)
miquelbeltran May 9, 2024
f4ae131
refactor: #205 Setup eslint style (#207)
miquelbeltran May 9, 2024
e14deec
docs: Update status badge in README.md (#209)
miquelbeltran May 10, 2024
61a9539
chore(deps-dev): bump semver from 7.6.0 to 7.6.2 (#211)
dependabot[bot] May 13, 2024
fc09498
chore(deps-dev): bump @types/node from 20.12.8 to 20.12.11 (#212)
dependabot[bot] May 13, 2024
641bb4c
chore(deps-dev): bump tap from 18.7.2 to 18.8.0 (#213)
dependabot[bot] May 13, 2024
a95d14c
chore(deps-dev): bump @stylistic/eslint-plugin from 2.0.0 to 2.1.0 (#…
dependabot[bot] May 13, 2024
57ceec3
feat: Breadcrumbs (#210)
miquelbeltran May 15, 2024
77b8229
feat: #219 Better Send parameters (#221)
miquelbeltran May 17, 2024
ed8aee9
chore: apply prettier to all files in examples (#226)
miquelbeltran May 19, 2024
c322f01
fix: #138 New APM Bridge Setup (#222)
miquelbeltran May 20, 2024
a80e8dd
chore: code cleanup (#225)
miquelbeltran May 20, 2024
9ebcc4e
chore(deps-dev): bump @types/node from 20.12.11 to 20.12.12 (#227)
dependabot[bot] May 20, 2024
d147888
chore(deps-dev): bump @eslint/js from 9.2.0 to 9.3.0 (#228)
dependabot[bot] May 20, 2024
3fb1482
chore(deps-dev): bump typescript-eslint from 7.8.0 to 7.9.0 (#229)
dependabot[bot] May 20, 2024
8e37c10
chore: Prepare Release 1.0.0 (#230)
miquelbeltran May 23, 2024
f5c1307
fix: Fixes in 1.0.0 release candidate (#234)
miquelbeltran May 24, 2024
188d9c9
chore: Revert PR #222 (fix: #138 New APM Bridge Setup) (#235)
miquelbeltran May 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,29 @@
## 1.0.0

- feat: #219 Better Send parameters (#221) (2024-05-17)
- feat: Breadcrumbs (#210) (2024-05-15)
- fix: #138 New APM Bridge Setup (#222) (2024-05-20)
- docs: Update status badge in README.md (#209) (2024-05-10)
- refactor: #205 Setup eslint style (#207) (2024-05-09)
- refactor: #197 Refactor to use Promises internally (#200) (2024-05-09)
- refactor: #184 Cleanup debug/log messages and styles (#194) (2024-05-08)
- chore(deps-dev): bump typescript-eslint from 7.8.0 to 7.9.0 (#229) (2024-05-20)
- chore(deps-dev): bump @eslint/js from 9.2.0 to 9.3.0 (#228) (2024-05-20)
- chore(deps-dev): bump @types/node from 20.12.11 to 20.12.12 (#227) (2024-05-20)
- chore(deps-dev): bump @stylistic/eslint-plugin from 2.0.0 to 2.1.0 (#214) (2024-05-13)
- chore(deps-dev): bump tap from 18.7.2 to 18.8.0 (#213) (2024-05-13)
- chore(deps-dev): bump @types/node from 20.12.8 to 20.12.11 (#212) (2024-05-13)
- chore(deps-dev): bump semver from 7.6.0 to 7.6.2 (#211) (2024-05-13)
- chore: code cleanup (#225) (2024-05-20)
- chore: apply prettier to all files in examples (#226) (2024-05-19)

**BREAKING CHANGES**
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we support a backwards-compatible but deprecated (and to be removed next) send method? With some additional checking logic, it could as simple as function send(error, customData={}, request,={} tags={}){ return send(error, {customData: customData, request: request, tags: tags});}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it makes sense to add in the deprecation, we could do this now whilst we discuss the final decision. It looks like we've done something in the past about deprecating (which we may need to remove -

// This function is deprecated, is provided for legacy apps and will be
)

Copy link
Contributor Author

@miquelbeltran miquelbeltran May 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We provide a backwards compatible method, is sendWithCallback().

raygun4node/lib/raygun.ts

Lines 292 to 318 in 8e37c10

/**
* @deprecated sendWithCallback is a deprecated method. Instead, use send, which supports async/await calls.
*/
sendWithCallback(
exception: Error | string,
customData?: CustomData,
callback?: Callback<IncomingMessage>,
request?: RequestParams,
tags?: Tag[],
) {
// call async send but redirect response to provided legacy callback
this.send(exception, {
customData,
request,
tags,
})
.then((response) => {
if (callback) {
callVariadicCallback(callback, null, response);
}
})
.catch((error) => {
if (callback) {
callVariadicCallback(callback, error, null);
}
});
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it could as simple as function send(error, customData={}, request,={} tags={}){ return send(error, {customData: customData, request: request, tags: tags});}

JavaScript doesn't support overloading methods. There ware some workarounds but have limitations.


- `send()` method signature changed.
- APM Bridge setup process changed.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What were we doing before and as above, can we support a deprecated version?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous setup process was causing compilation errors to some users and was not possible to properly unit test it, it is explained in detail here: #222


See README.md for more information.

## 0.15.0-0
- async/await `send()` support
- Upgrade dependencies
Expand Down
91 changes: 85 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Raygun4Node

[![Build Status](https://travis-ci.org/MindscapeHQ/raygun4node.svg?branch=master)](https://travis-ci.org/MindscapeHQ/raygun4node)
[![GitHub CI](https://github.com/MindscapeHQ/raygun4node/actions/workflows/node.js.yml/badge.svg)](https://github.com/MindscapeHQ/raygun4node/actions)

Raygun.io package for Node, written in TypeScript.
Raygun.com package for Node, written in TypeScript.

# Where is my app API key?

Expand Down Expand Up @@ -141,12 +141,23 @@ The callback should be a node-style callback: `function(err, response) { /*...*/
it will only be called when the transmission is successful. This is included for
backwards compatibility; the Node-style callback should be preferred.

### Send Parameters

The `send()` method accepts a series of optional named parameters, defined as follows:

```js
client.send(error, { customData, request, tags });
```

Each one of these parameters is optional.
They are explained in detail the following sections.

miquelbeltran marked this conversation as resolved.
Show resolved Hide resolved
### Sending custom data

You can pass custom data in on the Send() function, as the second parameter. For instance (based off the call in test/raygun_test.js):

```javascript
client.send(new Error(), { 'mykey': 'beta' });
client.send(new Error(), { customData: { 'mykey': 'beta' } });
```

#### Sending custom data with Expressjs
Expand All @@ -165,7 +176,7 @@ raygunClient.expressCustomData = function (err, req) {

You can send the request data in the Send() function, as the fourth parameter. For example:
```javascript
client.send(new Error(), {}, request);
client.send(new Error(), { request: request });
```

If you want to filter any of the request data then you can pass in an array of keys to filter when
Expand All @@ -179,7 +190,7 @@ const raygunClient = new raygun.Client().init({ apiKey: 'YOUR_API_KEY', filters:

You can add tags to your error in the Send() function, as the fifth parameter. For example:
```javascript
client.send(new Error(), {}, {}, ['Custom Tag 1', 'Important Error']);
client.send(new Error(), { tags: ['Custom Tag 1', 'Important Error'] });
```

Tags can also be set globally using setTags
Expand Down Expand Up @@ -266,7 +277,7 @@ This feature is preferable to using the `domains` module for this purpose, as `d

### Changing the API endpoint

You can change the endpoint that error messages are sent to by specifying the `host`, `port`, and `useSSL` properties in the `raygunClient.init()` options hash. By default, `host` is `api.raygun.io`, `port` is `443`, and `useSSL` is `true`.
You can change the endpoint that error messages are sent to by specifying the `host`, `port`, and `useSSL` properties in the `raygunClient.init()` options hash. By default, `host` is `api.raygun.com`, `port` is `443`, and `useSSL` is `true`.

### onBeforeSend

Expand All @@ -291,6 +302,60 @@ const myBeforeSend = function (payload, exception, customData, request, tags) {
Raygun.onBeforeSend(myBeforeSend);
```

### Breadcrumbs

Breadcrumbs can be sent to Raygun to provide additional information to look into and debug issues stemming from crash reports.

Breadcrumbs can be created in two ways.

#### Simple string:

Call `client.addBreadcrumb(message)`, where message is just a string:

```js
client.addBreadcrumb('test breadcrumb');
```

#### Using `BreadcrumbMessage`:

Create your own `BreadcrumbMessage` object and send more than just a message with `client.addBreadcrumb(BreadcrumbMessage)`.

The structure of the type `BreadcrumbMessage` is as shown here:

```js
BreadcrumbMessage: {
level: "debug" | "info" | "warning" | "error";
category: string;
message: string;
customData?: CustomData;
}
```

Breadcrumbs can be cleared with `client.clearBreadcrumbs()`.
miquelbeltran marked this conversation as resolved.
Show resolved Hide resolved

#### Breadcrumbs and ExpressJS

Raygun4Node provides a custom ExpressJS middleware that helps to scope Breadcrumbs to a specific request.
As well, this middleware will add a Breadcrumb with information about the performed request.

To set up, add the Raygun Breadcrumbs ExpressJS handler before configuring any endpoints.

```js
// Add the Raygun Breadcrumb ExpressJS handler
app.use(raygunClient.expressHandlerBreadcrumbs);

// Setup the rest of the app, e.g.
app.use("/", routes);
```

This middleware can be used together with the provided ExpressJS error handler `expressHandler`.
The order in which the middlewares are configured is important. `expressHandlerBreadcrumbs` should go first to scope breadcrumbs correctly.
miquelbeltran marked this conversation as resolved.
Show resolved Hide resolved

```js
app.use(raygunClient.expressHandlerBreadcrumbs);
app.use(raygunClient.expressHandler);
```

### Batched error transport

You can enable a batched transport mode for the Raygun client by passing `{batch: true}` when initializing.
Expand Down Expand Up @@ -419,6 +484,20 @@ const raygunClient = new raygun.Client().init({

Including column numbers can enable source mapping if you have minified or transpiled code in your stack traces.

### APM Bridge Setup

Raygun4Node can be used in conjunction with Raygun APM for Node.js.

Follow the instructions on https://raygun.com/platform/apm to set up your application.

Then, call to `setApmBridge()` to connect both packages:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a full example of how this works. Something like:
require('raygun-apm/http'); const raygun = require('raygun'); raygun.setApmBridge();

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is already in examples/apm-sample/app.js

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah you mean in the README, got it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I think the current text is correct. In other parts of the readme, we don't reference to the require for raygun client, and also the require('raygun-apm/http') is not required to set up the APM bridge. I also link to the official APM setup process.


```js
raygunClient.setApmBridge(require("raygun-apm/lib/src/crash_reporting"));
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That looks like a nasty setup. Can we make it without arguments and infer it? Still have the explicit call with the argument as fallback

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you take a look at the PR where we introduced this and review it? #222

```

When this package sends an error report to Raygun, it will notify automatically the Raygun APM package, and attach a Correlation ID to the error sent.

### Source maps

Raygun supports source mapping for Node.js stacktraces which include column numbers. To enable this feature you will need to upload your map files to the JavaScript Source Map Center and enable the processing of Node.js error stacktraces.
Expand Down
30 changes: 30 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
// @ts-check

import eslint from '@eslint/js';
import stylistic from '@stylistic/eslint-plugin';
import stylisticTs from '@stylistic/eslint-plugin-ts';
import tseslint from 'typescript-eslint';

export default tseslint.config(
// Basic eslint rules
eslint.configs.recommended,
// Codestyle rules for JS
stylistic.configs["recommended-flat"],
// Codestyle rules for TS
stylisticTs.configs["all-flat"],
// Eslint rules for TS
...tseslint.configs.recommended,
{
languageOptions: {
// Add node globals to ignore undefined
globals: {
"__dirname": false,
"__filename": false,
"console": false,
"module": false,
"process": false,
Expand All @@ -29,6 +38,27 @@ export default tseslint.config(
],
// Required to import JS modules
"@typescript-eslint/no-var-requires": "off",
// Always require semicolons
"@stylistic/semi": ["error", "always"],
// Stick to double quotes
"@stylistic/quotes": ["error", "double"],
// Always indent with two spaces
'@stylistic/ts/indent': ['error', 2],
// Enforce curly braces spacing
"@stylistic/ts/object-curly-spacing": ["error", "always"],
// Enforce "one true brace style"
"@stylistic/brace-style": ["error", "1tbs"],
// Enforce parenthesis in functions: "(a) => a"
"@stylistic/arrow-parens": ["error", "always"],
// Disabled rules that collide with Prettier formatter
"@stylistic/member-delimiter-style": ["off", 0],
"@stylistic/no-mixed-operators": ["off", 0],
"@stylistic/operator-linebreak": ["off", 0],
"@stylistic/quote-props": ["off", 0],
"@stylistic/ts/comma-dangle": ["off", 0],
"@stylistic/ts/no-extra-parens": ["off", 0],
"@stylistic/ts/quote-props": ["off", 0],
"@stylistic/ts/space-before-function-paren": ["off", 0],
}
}
);
33 changes: 33 additions & 0 deletions examples/apm-sample/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Logs
logs
*.log

# Runtime data
pids
*.pid
*.seed

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# node-waf configuration
.lock-wscript

# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release

# Dependency directory
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git-
node_modules

# Debug log from npm
npm-debug.log

# Ignore SASS cache
public/.sass-cache/*
23 changes: 23 additions & 0 deletions examples/apm-sample/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Raygun Crash Reporting + APM Sample

This is a sample application to show how to use Raygun4Node and Raygun-APM together.

This example uses the local `raygun4node` package in the project root directory by simply pointing to the root directory as a dependency in package.json:

```
"raygun": "file:../..",
```

## Run the sample

First, install the `raygun4node` package.

To do so, navigate to the project root directory, then:

npm install
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A customer yesterday was asking if we support pnpm instead. Investigate and please add to the docs as an alternative

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make this an issue to resolved outside of this release


Once the package is installed, set your API key in the sample's `config/default.json` and run:

npm install && node app

in the subdirectory where you found this README.md file.
25 changes: 25 additions & 0 deletions examples/apm-sample/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
var config = require("config");

if (config.Raygun.Key === "YOUR_API_KEY") {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be encouraging no API keys in code to set a good standard? Could be via .env

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because this is an example app, I would think this is not necessary to add in

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

raygun-apm gets the api key from env variable, which we should probably do as well eventually, out of scope for this release IMO.

console.error(
"[Raygun4Node-Domains-Sample] You need to set your Raygun API key in the config file",
);
process.exit(1);
}

// Setup Raygun
var raygun = require("raygun");
var raygunClient = new raygun.Client().init({ apiKey: config.Raygun.Key });

// Setup APM Bridge
raygunClient.setApmBridge(require("raygun-apm/lib/src/crash_reporting"));

// Send Raygun error
raygunClient
.send("Sending error with APM bridge")
.then((message) => {
console.log(`Sent message: ${message.statusCode}`);
})
.catch((error) => {
console.error(`Failed to send message: ${error}`);
});
5 changes: 5 additions & 0 deletions examples/apm-sample/config/default.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"Raygun": {
"Key": "YOUR_API_KEY"
}
}
5 changes: 5 additions & 0 deletions examples/apm-sample/config/production.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"Raygun": {
"Key": "YOUR_PRODUCTION_API_KEY"
}
}
Loading
Loading