Skip to content

Commit f8d8dd2

Browse files
authored
Merge pull request #49 from codex-team/feature/context
Custom context implemented
2 parents d4e277d + 809e28b commit f8d8dd2

13 files changed

+160
-42
lines changed

README.md

+22-3
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ Create `HawkCatcher` class instance when script will be ready and pass your Inte
5656
```js
5757
const hawk = new HawkCatcher({token: 'INTEGRATION_TOKEN'});
5858
59-
// or
59+
// or
6060
6161
const hawk = new HawkCatcher('INTEGRATION_TOKEN');
6262
```
@@ -74,10 +74,29 @@ Initialization settings:
7474
| `token` | string | **required** | Your project's Integration Token |
7575
| `release` | string/number | optional | Unique identifier of the release. Used for source map consuming (see below) |
7676
| `user` | {id: string, name?: string, image?: string, url?: string} | optional | Current authenticated user |
77+
| `context` | object | optional | Any data you want to pass with every message. |
7778
| `vue` | Vue constructor | optional | Pass Vue constructor to set up the [Vue integration](#integrate-to-vue-application) |
7879

7980
Other available [initial settings](types/hawk-initial-settings.d.ts) are described at the type definition.
8081

82+
## Manual sending
83+
84+
You can send errors or other messages to the Hawk manually, for example at your `catch` blocks or any debug conditions.
85+
86+
Use the `.send(message, context)` method for that. This method accepts the `message` of type `Error` or `string`
87+
as the first parameter. The second parameter is optional, it allows passing any additional data with the event.
88+
If you specify the `context` with the `HawkCatcher` constructor, it will be merged with the context passed to the `send` method.
89+
90+
```js
91+
// init Hawk Catcher instance
92+
const hawk = new HawkCatcher({token: 'INTEGRATION_TOKEN'});
93+
94+
// somewhere in try-catch block or other custom place
95+
hawk.send(new Error('Something went wrong'), {
96+
myOwnDebugInfo: '1234'
97+
}))
98+
```
99+
81100
## Source maps consuming
82101
83102
If your bundle is minified, it is useful to pass source-map files to the Hawk. After that you will see beautiful original source code lines in Hawk Garage instead of minified code.
@@ -105,7 +124,7 @@ const hawk = new HawkCatcher({
105124
token: 'INTEGRATION_TOKEN',
106125
vue: Vue // the Vue constructor you tweak
107126
});
108-
```
127+
```
109128
110129
or pass it any moment after Hawk Catcher was instantiated:
111130
@@ -118,4 +137,4 @@ const hawk = new HawkCatcher({
118137
});
119138

120139
hawk.connectVue(Vue)
121-
```
140+
```

dist/catcher.d.ts

+20-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { HawkInitialSettings } from '../types/hawk-initial-settings';
2+
import { HawkEventContext } from '../types/hawk-event';
23
/**
34
* Hawk JavaScript Catcher
45
* Module for errors and exceptions tracking
@@ -26,6 +27,10 @@ export default class Catcher {
2627
* Current authenticated user
2728
*/
2829
private readonly user;
30+
/**
31+
* Any additional data passed by user for sending with all messages
32+
*/
33+
private readonly context;
2934
/**
3035
* Transport for dialog between Catcher and Collector
3136
* (WebSocket decorator)
@@ -41,17 +46,23 @@ export default class Catcher {
4146
* @param {HawkInitialSettings|string} settings - If settings is a string, it means an Integration Token
4247
*/
4348
constructor(settings: HawkInitialSettings | string);
49+
/**
50+
* Generates user if no one provided via HawkCatcher settings
51+
* After generating, stores user for feature requests
52+
*/
53+
private static getGeneratedUser;
4454
/**
4555
* Send test event from client
4656
*/
4757
test(): void;
4858
/**
49-
* This method prepares and sends an Error to Hawk
50-
* User can fire it manually on try-catch
59+
* Public method for manual sending messages to the Hawk
60+
* Can be called in user's try-catch blocks or by other custom logic
5161
*
52-
* @param error - error to catch
62+
* @param message - what to send
63+
* @param [context] - any additional data to send
5364
*/
54-
catchError(error: Error): void;
65+
send(message: Error | string, context?: HawkEventContext): void;
5566
/**
5667
* Add error handing to the passed Vue app
5768
*
@@ -72,7 +83,8 @@ export default class Catcher {
7283
* Format and send an error
7384
*
7485
* @param error - error to send
75-
* @param {object} integrationAddons - addons spoiled by Integration
86+
* @param integrationAddons - addons spoiled by Integration
87+
* @param context - any additional data passed by user
7688
*/
7789
private formatAndSend;
7890
/**
@@ -85,6 +97,7 @@ export default class Catcher {
8597
* Formats the event
8698
*
8799
* @param error - error to format
100+
* @param context - any additional data passed by user
88101
*/
89102
private prepareErrorFormatted;
90103
/**
@@ -105,6 +118,8 @@ export default class Catcher {
105118
private getRelease;
106119
/**
107120
* Collects additional information
121+
*
122+
* @param context - any additional data passed by user
108123
*/
109124
private getContext;
110125
/**

dist/hawk.js

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/utils.d.ts

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/**
2+
* Returns random string
3+
*/
4+
export declare function generateRandomId(): string;

example/index.html

+34-8
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,19 @@
3939
h2 {
4040
font-weight: 500;
4141
margin: 0 0 10px;
42-
font-size: 17px;
42+
font-size: 13px;
4343
color: rgba(219,230,255,0.60);
44-
letter-spacing: 0.2px;
44+
letter-spacing: 0.24px;
4545
text-align: left;
46-
font-variant: all-petite-caps;
46+
text-transform: uppercase;
47+
}
48+
49+
h2 small {
50+
text-transform: none;
51+
font-size: 14px;
52+
opacity: .6;
53+
font-weight: normal;
54+
margin-left: 15px;
4755
}
4856

4957
button {
@@ -99,6 +107,21 @@ <h2>Send Unhandled promise rejection error</h2>
99107
Unhandled promise rejection
100108
</button>
101109
</section>
110+
<section>
111+
<h2>
112+
Send event manually
113+
<small>
114+
Through the <code>.send(error, context)</code> method
115+
</small>
116+
</h2>
117+
<label for="errorContext">Error context</label>
118+
<input type="text" id="errorContext" placeholder="Any data you want">
119+
<br>
120+
<br>
121+
<button id="btn-manual-sending">
122+
Send manual message
123+
</button>
124+
</section>
102125
<section>
103126
<h2>Send the specified number of errors</h2>
104127
<label for="errorsNumber">Enter the number of errors to send</label>
@@ -203,11 +226,14 @@ <h2>Test Vue integration: &lt;test-component&gt;</h2>
203226
<script src="assets/hawk.js"></script>
204227
<script src="sample-errors.js"></script>
205228
<script>
206-
window.hawk = new HawkCatcher({
207-
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwcm9qZWN0SWQiOiI1ZWFmZWIwN2M3NjU2NDAwMjJmY2IwMjQiLCJpYXQiOjE1ODg1ODcyNzF9.mKBbgyynEApfh4I8VKRMTHR8lJpoauUcyeUfPQMGTO4',
208-
collectorEndpoint: 'ws://localhost:3000/ws',
209-
vue: window.Vue,
210-
})
229+
window.hawk = new HawkCatcher({
230+
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwcm9qZWN0SWQiOiI1ZTVhNzVjNzNlM2E5ZDE2YjUzMzczOTMiLCJpYXQiOjE1ODI5ODY2OTV9.oK_LPRxcpRuZE8eSbmdObRX712YXO_Twpq7mgg7-9pw',
231+
collectorEndpoint: 'ws://localhost:3000/ws',
232+
vue: window.Vue,
233+
context: {
234+
rootContextSample: '12345'
235+
}
236+
})
211237
</script>
212238
</body>
213239
</html>

example/sample-errors.js

+18-2
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ buttonSendMany.addEventListener('click', function sendManyErrors() {
4242
const errorsNumber = inputElement.value;
4343

4444
for (let i = 0; i < errorsNumber; i++) {
45-
window.hawk.catchError(new window[errorType]('Test many error'));
45+
window.hawk.send(new window[errorType]('Test many error'));
4646
}
4747
});
4848

@@ -56,4 +56,20 @@ buttonConsoleTest.addEventListener('click', function consoleLogPrint() {
5656
const text = document.getElementById('consoleCatcherTestTextInput').value;
5757

5858
console[consoleMethod](text);
59-
});
59+
});
60+
61+
/**
62+
* Button for the manual sending
63+
*/
64+
const buttonManualSending = document.getElementById('btn-manual-sending');
65+
66+
buttonManualSending.addEventListener('click', () => {
67+
const contextSample = document.getElementById('errorContext').value;
68+
69+
window.hawk.send(
70+
new Error('Manual sending example'),
71+
contextSample.trim().length
72+
? { contextSample }
73+
: undefined
74+
);
75+
});

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@hawk.so/javascript",
3-
"version": "2.4.0",
3+
"version": "2.5.0",
44
"description": "JavaScript errors tracking for Hawk.so",
55
"main": "./dist/hawk.js",
66
"types": "./dist/index.d.ts",

src/catcher.ts

+40-15
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import Sanitizer from './modules/sanitizer';
33
import log from './modules/logger';
44
import StackParser from './modules/stackParser';
55
import { HawkInitialSettings } from '../types/hawk-initial-settings';
6-
import { BacktraceFrame, HawkEvent, HawkUser } from '../types/hawk-event';
6+
import { BacktraceFrame, HawkEvent, HawkEventContext, HawkUser } from '../types/hawk-event';
77
import { VueIntegration, VueIntegrationAddons } from './integrations/vue';
88
import { generateRandomId } from './utils';
99

@@ -44,6 +44,11 @@ export default class Catcher {
4444
*/
4545
private readonly user: HawkUser;
4646

47+
/**
48+
* Any additional data passed by user for sending with all messages
49+
*/
50+
private readonly context: HawkEventContext;
51+
4752
/**
4853
* Transport for dialog between Catcher and Collector
4954
* (WebSocket decorator)
@@ -70,6 +75,7 @@ export default class Catcher {
7075
this.token = settings.token;
7176
this.release = settings.release;
7277
this.user = settings.user || Catcher.getGeneratedUser();
78+
this.context = settings.context || undefined;
7379

7480
if (!this.token) {
7581
log(
@@ -132,17 +138,18 @@ export default class Catcher {
132138
public test(): void {
133139
const fakeEvent = new Error('Hawk JavaScript Catcher test message.');
134140

135-
this.catchError(fakeEvent);
141+
this.send(fakeEvent);
136142
}
137143

138144
/**
139-
* This method prepares and sends an Error to Hawk
140-
* User can fire it manually on try-catch
145+
* Public method for manual sending messages to the Hawk
146+
* Can be called in user's try-catch blocks or by other custom logic
141147
*
142-
* @param error - error to catch
148+
* @param message - what to send
149+
* @param [context] - any additional data to send
143150
*/
144-
public catchError(error: Error): void {
145-
this.formatAndSend(error);
151+
public send(message: Error | string, context?: HawkEventContext): void {
152+
this.formatAndSend(message, undefined, context);
146153
}
147154

148155
/**
@@ -196,12 +203,17 @@ export default class Catcher {
196203
* Format and send an error
197204
*
198205
* @param error - error to send
199-
* @param {object} integrationAddons - addons spoiled by Integration
206+
* @param integrationAddons - addons spoiled by Integration
207+
* @param context - any additional data passed by user
200208
*/
201-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
202-
private async formatAndSend(error: Error | string, integrationAddons?: { [key: string]: any }): Promise<void> {
209+
private async formatAndSend(
210+
error: Error | string,
211+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
212+
integrationAddons?: { [key: string]: any },
213+
context?: HawkEventContext
214+
): Promise<void> {
203215
try {
204-
const errorFormatted = await this.prepareErrorFormatted(error);
216+
const errorFormatted = await this.prepareErrorFormatted(error, context);
205217

206218
/**
207219
* If this event catched by integration (Vue or other), it can pass extra addons
@@ -232,16 +244,17 @@ export default class Catcher {
232244
* Formats the event
233245
*
234246
* @param error - error to format
247+
* @param context - any additional data passed by user
235248
*/
236-
private async prepareErrorFormatted(error: Error | string): Promise<HawkEvent> {
249+
private async prepareErrorFormatted(error: Error | string, context?: HawkEventContext): Promise<HawkEvent> {
237250
return {
238251
token: this.token,
239252
catcherType: this.type,
240253
payload: {
241254
title: this.getTitle(error),
242255
type: this.getType(error),
243256
release: this.getRelease(),
244-
context: this.getContext(),
257+
context: this.getContext(context),
245258
user: this.getUser(),
246259
get: this.getGetParams(),
247260
addons: this.getAddons(),
@@ -297,9 +310,21 @@ export default class Catcher {
297310

298311
/**
299312
* Collects additional information
313+
*
314+
* @param context - any additional data passed by user
300315
*/
301-
private getContext(): object {
302-
return Sanitizer.sanitize({});
316+
private getContext(context?: HawkEventContext): object {
317+
const contextMerged = {};
318+
319+
if (this.context !== undefined) {
320+
Object.assign(contextMerged, this.context);
321+
}
322+
323+
if (context !== undefined) {
324+
Object.assign(contextMerged, context);
325+
}
326+
327+
return Sanitizer.sanitize(contextMerged);
303328
}
304329

305330
/**

src/modules/sanitizer.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -262,9 +262,10 @@ export default class Sanitizer {
262262
/**
263263
* Represent big object as a "<big object>"
264264
*
265-
* @param _target - object ot format
265+
* @param target - object ot format
266266
*/
267-
private static formatBigObject(_target: any): string {
267+
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-unused-vars-experimental
268+
private static formatBigObject(target: any): string {
268269
return '<big object>';
269270
}
270271
}

src/modules/socket.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ export default class Socket {
5858
*/
5959
constructor({
6060
collectorEndpoint,
61-
// eslint-disable-next-line @typescript-eslint/no-empty-function
62-
onMessage = (_message: MessageEvent): void => {},
61+
// eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars, @typescript-eslint/no-unused-vars-experimental
62+
onMessage = (message: MessageEvent): void => {},
6363
// eslint-disable-next-line @typescript-eslint/no-empty-function
6464
onClose = (): void => {},
6565
// eslint-disable-next-line @typescript-eslint/no-empty-function

stats.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11

2-
Size: 6.86 KB with all dependencies, minified and gzipped
2+
Size: 7.1 KB with all dependencies, minified and gzipped
33

types/hawk-event.d.ts

+7
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,13 @@ export interface EventData {
7777
addons?: object;
7878
}
7979

80+
/**
81+
* Any additional data passed by user
82+
*/
83+
export interface HawkEventContext {
84+
[key: string]: any,
85+
}
86+
8087
/**
8188
* Single item of backtrace
8289
*/

0 commit comments

Comments
 (0)