Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: RomainVialard/ErrorHandler
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.0.0
Choose a base ref
...
head repository: RomainVialard/ErrorHandler
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref

Commits on Mar 30, 2018

  1. Copy the full SHA
    8d42816 View commit details
  2. 1.0.1

    JeanRemiDelteil committed Mar 30, 2018
    Copy the full SHA
    931a40d View commit details
  3. Retry on UrlFetch calls with muteHttpExceptions

    * Check if response is from a UrlFetch call with muteHttpExceptions activated
    * Check responseCode
    * if 500, perform exponential backoff
    * in case of failure after exponential backoff, don't throw an error, return response & log issue in Stackdriver
    RomainVialard authored Mar 30, 2018
    Copy the full SHA
    182272f View commit details
  4. Add expBackOffFetch(): helper function to automatically handles expon…

    …ential backoff on UrlFetch use
    JeanRemiDelteil committed Mar 30, 2018
    Copy the full SHA
    cb4a995 View commit details
  5. clearer logic

    JeanRemiDelteil committed Mar 30, 2018
    Copy the full SHA
    6d02626 View commit details

Commits on Apr 4, 2018

  1. Copy the full SHA
    cde94a1 View commit details
  2. Merge pull request #1 from RomainVialard/RomainVialard-patch-1

    Retry on UrlFetch calls with muteHttpExceptions
    RomainVialard authored Apr 4, 2018
    Copy the full SHA
    e259f2e View commit details
  3. 1.1.0

    JeanRemiDelteil committed Apr 4, 2018
    Copy the full SHA
    6729ad9 View commit details
  4. Copy the full SHA
    7940fb3 View commit details

Commits on Apr 5, 2018

  1. Merge pull request #2 from RomainVialard/RomainVialard-patch-1

    Fix issue where response is undefined
    JeanRemiDelteil authored Apr 5, 2018
    Copy the full SHA
    3a4c63d View commit details
  2. 1.1.1

    JeanRemiDelteil committed Apr 5, 2018
    Copy the full SHA
    93bed1e View commit details
  3. Update changeLog

    JeanRemiDelteil committed Apr 5, 2018
    Copy the full SHA
    0ddaa80 View commit details
  4. Update README.md

    RomainVialard authored Apr 5, 2018
    Copy the full SHA
    ac17f04 View commit details
  5. Update README.md

    RomainVialard authored Apr 5, 2018
    Copy the full SHA
    3dfaabd View commit details
  6. Update README.md

    RomainVialard authored Apr 5, 2018
    Copy the full SHA
    12e41eb View commit details
  7. Avoid ReferenceError

    RomainVialard authored Apr 5, 2018
    Copy the full SHA
    14c4838 View commit details
  8. add explanation

    JeanRemiDelteil committed Apr 5, 2018
    Copy the full SHA
    d70433e View commit details
  9. Copy the full SHA
    c3c3e7d View commit details
  10. v1.1.2

    JeanRemiDelteil committed Apr 5, 2018
    Copy the full SHA
    50d7de7 View commit details

Commits on Apr 17, 2018

  1. Proposal to add translated error messages

    Need to find the best way to list translations and find them.
    RomainVialard authored Apr 17, 2018
    Copy the full SHA
    0863b23 View commit details
  2. Copy the full SHA
    e162d49 View commit details

Commits on Apr 18, 2018

  1. return '' on unknown translation,

    add translated flag in logged error object context
    JeanRemiDelteil committed Apr 18, 2018
    Copy the full SHA
    57cc084 View commit details
  2. New translations

    RomainVialard authored Apr 18, 2018
    Copy the full SHA
    66a8d54 View commit details
  3. Add partial matching

    JeanRemiDelteil committed Apr 18, 2018
    Copy the full SHA
    103f4cd View commit details
  4. Added one translation

    RomainVialard authored Apr 18, 2018
    Copy the full SHA
    a4690eb View commit details

Commits on Apr 19, 2018

  1. Added several translations

    Specific attention on Document XXX is missing (perhaps it was deleted?)
    RomainVialard authored Apr 19, 2018
    Copy the full SHA
    ca24afc View commit details
  2. Copy the full SHA
    90c4a91 View commit details
  3. Copy the full SHA
    ee0236a View commit details
  4. Copy the full SHA
    697e60d View commit details

Commits on Apr 20, 2018

  1. Copy the full SHA
    939b923 View commit details
  2. Silent failure on exponential backoff,also added options: verbose, lo…

    …gError, retryNumber,
    
    log as warning with logError
    JeanRemiDelteil committed Apr 20, 2018
    Copy the full SHA
    db7863b View commit details
  3. pluralize

    JeanRemiDelteil committed Apr 20, 2018
    Copy the full SHA
    2e14773 View commit details
  4. Copy the full SHA
    df23f60 View commit details
  5. moved to silent failure by default, return ErrorHandler_.CustomError …

    …object,
    
    add options.throwOnFailure to expBackoff()
    JeanRemiDelteil committed Apr 20, 2018
    Copy the full SHA
    f0151ae View commit details
  6. Copy the full SHA
    9969553 View commit details
  7. Merge pull request #4 from RomainVialard/RomainVialard-patch-1

    Proposal to add translated error messages
    JeanRemiDelteil authored Apr 20, 2018
    Copy the full SHA
    78c9c57 View commit details

Commits on Apr 22, 2018

  1. Wrong condition order

    RomainVialard authored Apr 22, 2018
    Copy the full SHA
    857fde5 View commit details

Commits on Apr 23, 2018

  1. Copy the full SHA
    263f37e View commit details
  2. Merge pull request #7 from RomainVialard/RomainVialard-patch-1

    Wrong condition order
    RomainVialard authored Apr 23, 2018
    Copy the full SHA
    12b9e3e View commit details
  3. Copy the full SHA
    0ada882 View commit details
  4. Fixed issue on nb of retries + direct link to file

    The exponential backoff was actually perform 4 times with delays of approximately 1, 2, 4 and 8s.
    The last retry (after 16s) was skipped.
    It also means that asking for 1 retry only with retryNumber actually meant performing 0 retry.
    
    I also added a direct link to the right line of the right file in the Apps Script project with "directLink".
    RomainVialard authored Apr 23, 2018
    Copy the full SHA
    8acf26a View commit details
  5. Added new known errors

    I aggregated "Invalid to header" & "Invalid cc header" under NORMALIZED_ERRORS.INVALID_EMAIL - not sure if it's a good idea, might be useful to know / differentiate which field (to or cc) is impacted
    RomainVialard authored Apr 23, 2018
    Copy the full SHA
    bbfba4f View commit details
  6. New errors

    RomainVialard authored Apr 23, 2018
    Copy the full SHA
    ce5b591 View commit details
  7. Removed addonName from fileName

    The addonName was in the stack trace but also in fileName, which breaks the ability to create a direct link to the source code.
    RomainVialard authored Apr 23, 2018
    Copy the full SHA
    f5fcd05 View commit details

Commits on Apr 24, 2018

  1. clean a little

    JeanRemiDelteil committed Apr 24, 2018
    Copy the full SHA
    12f7dcd View commit details
  2. Merge pull request #8 from RomainVialard/RomainVialard-patch-2

    Fixed issue on nb of retries + direct link to file
    JeanRemiDelteil authored Apr 24, 2018
    Copy the full SHA
    542517b View commit details
  3. fix error fileName for directLink,

    Update Changelog for v2.0.0,
    Update ReadMe
    JeanRemiDelteil committed Apr 24, 2018
    Copy the full SHA
    cd5bda6 View commit details

Commits on Apr 27, 2018

  1. add Licence

    JeanRemiDelteil committed Apr 27, 2018
    Copy the full SHA
    99a772e View commit details
  2. New translations

    RomainVialard authored Apr 27, 2018
    Copy the full SHA
    e359e74 View commit details

Commits on Apr 30, 2018

  1. New error translations

    RomainVialard authored Apr 30, 2018
    Copy the full SHA
    f4a907c View commit details
Showing with 1,434 additions and 99 deletions.
  1. +32 −0 CHANGELOG.md
  2. +201 −4 README.md
  3. +2 −1 package.json
  4. +1,199 −94 src/ErrorHandler.gs.js
32 changes: 32 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -9,5 +9,37 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
<!-- Add new, unreleased changes here. -->
* none


## [2.1.1] - 2018-06-07
* new Translations & Errors
* Fix #10

## [2.1.0] - 2018-05-30
* FIX: remove explicit Google Apps Script servine names in comments: avoid auto-adding unused scopes
* possibility to include script version number in logs
* new Translations

## [2.0.0] - 2018-04-24
* Breaking changes: expBackoff(): use options to specify its behavior (throw on fail, verbose, retryNumber, doNotLogKnownErrors)
* Leverage Normalized GAS error in logError()
* Leverage Normalized GAS error in expBackoff()
* new function: getNormalizedError(): Return the english version of the error if listed in this library
* new function: getErrorLocale(): Try to find the locale of the localized thrown error
* Normalize GAS error messages across language and variable messages (eg: when containing a document ID or a variable part)
* List known GAS error message

## [1.1.2] - 2018-04-05
* Fix issue for global Add-on name reference error

## [1.1.1] - 2018-04-05
* Fix issue where response is undefined

## [1.1.0] - 2018-04-04
* Add Exponential backoff for UrlFetch call
* Add urlFetchWithExpBackOff() method

## [1.0.1] - 2018-03-30
* Fix destructuring not accepted by GAS

## [1.0.0] - 2018-03-30
* Initial npm version
205 changes: 201 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,203 @@
# ErrorHandler
This is a library for **Google Apps Script** projects. It provides methods to perform an [Exponential backoff](https://developers.google.com/drive/v3/web/handle-errors#exponential-backoff) logic whenever it is needed and rewrite error objects before sending them to Stackdriver Logging.

Methods to handle error and exponential back off in GAS

- expBackoff(func)
- logError(error, additionalParams)
## Methods


### expBackoff(func, options)

In some cases, Google APIs can return errors on which it make sense to retry, like '_We're sorry, a server error occurred. Please wait a bit and try again._'.

In such cases, it make sense to wrap the call to the API in an Exponential backoff logic to retry multiple times.

Note that most Google Apps Script services, like GmailApp and SpreadsheetApp already have an Exponential backoff logic implemented by Google. Thus it does not make sense to wrap every call to those services in an Exponential backoff logic.

Things are different for Google Apps Script [advanced services](https://developers.google.com/apps-script/guides/services/advanced#enabling_advanced_services) where such logic is not implemented. Thus this method is mostly useful for calls linked to Google Apps Script advanced services.


#### Example

```javascript

// Calls an anonymous function that gets the subject of the vacation responder in Gmail for the currently authenticated user.

var responseSubject = ErrorHandler.expBackoff(function(){return Gmail.Users.Settings.getVacation("me").responseSubject;});

```


#### Parameters

Name | Type | Default value | Description
--------|----------|---------------|------------
func | Function | | The anonymous or named function to call.
options | Object | {} | OPTIONAL, options for exponential backoff
options.throwOnFailure | boolean | false | If true, throw a CustomError on failure
options.doNotLogKnownErrors | boolean | false | If true, will not log known errors to stackdriver
options.verbose | boolean | false | If true, will log a warning on a successful call that failed at least once
options.retryNumber | number | 5 | Maximum number of retry on error

#### Return

The value returned by the called function, or a CustomError on failure if options.throwOnFailure == false

CustomError is an instance of Error


### urlFetchWithExpBackOff(url, params)

This method works exactly like the [fetch()](https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app#fetchurl-params) method of Apps Script UrlFetchApp service.

It simply wraps the fetch() call in an Exponential backoff logic.

We advise to replace all existing calls to `UrlFetchApp.fetch()` by this new method.

`UrlFetchApp.fetch(url, params)` => `ErrorHandler.urlFetchWithExpBackOff(url, params)`


### logError(error, additionalParams)

When exception logging is enabled, unhandled exceptions are automatically sent to Stackdriver Logging with a stack trace ([see official documentation](https://developers.google.com/apps-script/guides/logging#exception_logging)).

But if you wrap your code in a try...catch statement and use `console.error(error)` to send the exception to Stackdriver Logging, only the error message will be logged and not the stack trace.
This method will also leverage the list of known errors and their translation to better aggregate on Stackdriver Logging: the message will be the English version if available.

We advise to replace all existing calls to `console.error(error)` by this new method to correctly log the stack trace, in the exact same format used for unhandled exceptions.

`console.error(error)` => `ErrorHandler.logError(error)`


#### Parameters

Name | Type | Default value | Description
--------|----------|---------------|------------
error | String, Error, or { lineNumber: number, fileName: string, responseCode: string} | | A standard error object retrieved in a try...catch statement or created with new Error() or a simple error message or an object
additionalParams | Object, {addonName: string} | {} | Add custom values to the logged Error, the 'addonName' property will pass the AddonName to remove from error fileName
options | Object | {} | Options for logError
options.asWarning | boolean | false | If true, use console.warn instead console.error
options.doNotLogKnownErrors | booleab | false | if true, will not log known errors to stackdriver


#### Return

Return the CustomError, which is an Error, with a property 'context', as defined below:
```javascript
/**
* @typedef {Error} CustomError
*
* @property {{
* locale: string,
* originalMessage: string,
* knownError: boolean,
* variables: Array<{}>,
* errorName: string,
* reportLocation: {
* lineNumber: number,
* filePath: string,
* directLink: string,
* },
* }} context
*/
```


### getNormalizedError(localizedErrorMessage, partialMatches)

Try to get the corresponding english version of the error if listed in this library.

There are Error match exactly, and Errors that can be partially matched, for example when it contains a variable part (eg: a document ID, and email)

To get variable part, use the following pattern:
```javascript
var variables = []; // The empty array will be filled if necessary in the function
var normalizedError = ErrorHandler.getNormalizedError('Documento 1234567890azerty mancante (forse è stato eliminato?)', variables);

// The normalized Error, with its message in English, or '' of no match are found:
// normalizedError = 'Document is missing (perhaps it was deleted?)'

// the variable part:
// variables = [{variable: 'docId', value: '1234567890azerty'}]
```


#### Parameters

Name | Type | Default value | Description
----------------------|----------|---------------|------------
localizedErrorMessage | String | | The Error message in the user's locale
partialMatches | Array<{ variable: string, value: string }> | [] | OPTIONAL, Pass an empty array, getNormalizedError() will populate it with found extracted variables in case of a partial match


The value returned is the error in English or '' if no matching error was found


### getErrorLocale(localizedErrorMessage)

Try to find the locale of the localized thrown error


#### Parameters

Name | Type | Default value | Description
----------------------|----------|---------------|------------
localizedErrorMessage | String | | The Error message in the user's locale


#### Return

The locale ('en', 'it', ...) or '' if no matching error found

### NORMALIZED_ERRORS
constant

List all known Errors in a fixed explicit English message.
Serves as reference for locallizing Errors.

Use this to check which error a normalized error is:
```javascript
var normalizedError = ErrorHandler.getNormalizedError('Documento 1234567890azerty mancante (forse è stato eliminato?)');

if (normalizedError === ErrorHandler.NORMALIZED_ERRORS.DOCUMENT_MISSING) {
// Do something on document missing error
}
```

### NORETRY_ERRORS
constant

List all Errors for which there are no benefit in re-trying

## Setup

You can copy the code of this library in your own Google Apps Script project or reuse it as a [standard library](https://developers.google.com/apps-script/guides/libraries). In both cases, methods are called using the ErrorHandler class / namespace, meaning you will use them exactly in the same way.

To install it as a library, use the following script ID and select the latest version:

`1mpYgNprGHnJW0BSPclqNIIErVaTyXQ7AjdmLaaE5O9s9bAOrsY14PMCy`

To copy the code in your project, simply copy-past the content of this file in a new script file in your project:

`https://github.com/RomainVialard/ErrorHandler/blob/master/src/ErrorHandler.gs.js`

NPM install:

To be documented


## Warning

This library contains 5 methods directly available as functions and callable without using the ErrorHandler class / namespace:

* expBackoff()
* urlFetchWithExpBackOff()
* logError()
* getNormalizedError()
* getErrorLocale()

and 2 Object constant

* NORMALIZED_ERRORS
* NORETRY_ERRORS


For this reason, if you copy the code in your project, make sure you don't have any other function with the exact same name.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"name": "@scriptaddicts/gas-error-handler",
"version": "1.0.0",
"version": "2.1.2",
"description": "Methods to handle error in GAS",
"license": "Apache-2.0",
"author": {
"name": "Romain Vialard",
"email": "romain.vialard@gmail.com"
1,293 changes: 1,199 additions & 94 deletions src/ErrorHandler.gs.js

Large diffs are not rendered by default.