diff --git a/README.md b/README.md index ba5c7a7b..6d6d77d3 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ clasp - `clasp version [description]` - `clasp versions` - `clasp list` +- `clasp logs [--json] [--open]` ## How To... @@ -121,6 +122,33 @@ helloworld3 (xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx) This shows your most recent 10 scripts. +### See your Clasp Logs + +Use `clasp logs` to see the 5 most recent log messages from StackDriver. For example: + +``` +clasp logs +ERROR Sat Apr 07 2018 10:58:31 GMT-0700 (PDT) myFunction my log error +INFO Sat Apr 07 2018 10:58:31 GMT-0700 (PDT) myFunction info message +DEBUG Sat Apr 07 2018 10:58:31 GMT-0700 (PDT) myFunction debugging now +ERROR Sat Apr 07 2018 10:58:30 GMT-0700 (PDT) myFunction another error +INFO Sat Apr 07 2018 10:58:30 GMT-0700 (PDT) myFunction more info +``` + +You can also use `clasp logs --json` to see the information in JSON format. +You can also use `clasp logs --open` to open the StackDriver logs in your browser. + +### [Get Project ID](#get-project-id) + +First, you'll need to edit your .clasp.json file to put in the Google Cloud projectId. You can find it by running clasp open then in the top click Resources -> Cloud Platform project... Copy the projectId (including the part project-id), so something like: project-id-xxxxxxxxxxxxxxxxxxx Put that in your .clasp.json file, which should now look something like: + +``` + { + "scriptId":"14Ht4FoesbNDhRbbTMI_IyM9uQ27EXIP_p2rK8xCOECg5s9XKpHp4fh3d", + "projectId": "project-id-xxxxxxxxxxxxxxxxxxx" + } +``` + ### Ignore Files Create a file called `.claspignore` in the root directory of your Apps Script project. Add patterns as if it were a .gitignore, and they will be excluded from `clasp push`. diff --git a/index.ts b/index.ts index 55c474a1..cc2595d4 100755 --- a/index.ts +++ b/index.ts @@ -44,6 +44,8 @@ import * as url from 'url'; const readline = require('readline'); import * as Promise from 'bluebird'; import { Server } from "http"; +const logging = require('@google-cloud/logging'); +const chalk = require('chalk'); // Debug const DEBUG = false; @@ -84,6 +86,7 @@ interface ClaspSettings { interface ProjectSettings { scriptId: string; rootDir: string; + projectId: string; } // An Apps Script API File @@ -97,6 +100,11 @@ interface LoginOptions { localhost: boolean; } +interface LogOptions { + json: boolean; + open: boolean; +} + // Used to receive files tracked by current project interface FilesCallback { ( @@ -200,8 +208,13 @@ Forgot ${PROJECT_NAME} commands? Get help:\n ${PROJECT_NAME} --help`, LOGGED_OUT: `\nCommand failed. Please login. (${PROJECT_NAME} login)`, OFFLINE: 'Error: Looks like you are offline.', ONE_DEPLOYMENT_CREATE: 'Currently just one deployment can be created at a time.', + NO_FUNCTION_NAME: 'N/A', + NO_GCLOUD_PROJECT: `\nPlease set your projectId in your .clasp.json file to your Google Cloud project ID. \n + You can find your projectId by following the instructions in the README here: \n + https://github.com/google/clasp#get-project-id`, NO_NESTED_PROJECTS: '\nNested clasp projects are not supported.', READ_ONLY_DELETE: 'Unable to delete read-only deployment.', + PAYLOAD_UNKNOWN: 'Unknown StackDriver payload.', PERMISSION_DENIED: `Error: Permission denied. Enable the Apps Script API: https://script.google.com/home/usersettings`, SCRIPT_ID: '\n> Did you provide the correct scriptId?\n', @@ -1048,6 +1061,64 @@ commander }); }); +/** + * Prints out 5 most recent the StackDriver logs + * Use --json for output in json format + * Use --open to open logs in StackDriver + */ +commander + .command('logs') + .description('Shows the StackDriver Logs') + .option('--json', "Show logs in JSON form") + .option('--open', 'Open the StackDriver logs in browser') + .action((cmd: LogOptions) => { + function printLogs([entries]) { + for (let i = 0; i < 5; i++) { + const metadata = entries[i].metadata; + const { severity, timestamp, payload } = metadata; + + let functionName = entries[i].metadata.resource.labels.function_name; + functionName = functionName ? functionName.padEnd(15) : ERROR.NO_FUNCTION_NAME; + let payloadData = ''; + if (cmd.json) { + payloadData = JSON.stringify(entries[i], null, 2); + } else { + payloadData = ({ + textPayload: metadata.textPayload, + jsonPayload: metadata.jsonPayload ? metadata.jsonPayload.fields.message.stringValue : '', + protoPayload: metadata.protoPayload + })[payload] || ERROR.PAYLOAD_UNKNOWN; + + if (payloadData && typeof(payloadData) === 'string') { + payloadData = payloadData.padEnd(20); + } + } + let coloredSeverity = ({ + ERROR: chalk.red(severity), + INFO: chalk.blue(severity), + DEBUG: chalk.yellow(severity) + })[severity] || severity; + coloredSeverity = String(coloredSeverity).padEnd(15); + console.log(`${coloredSeverity} ${timestamp} ${functionName} ${payloadData}`); + } + } + + getProjectSettings().then(({ projectId }: ProjectSettings) => { + if (!projectId) { + console.error(ERROR.NO_GCLOUD_PROJECT); + return process.exit(-1); + } + if (cmd.open) { + const stackdriverURL = `https://console.cloud.google.com/logs/viewer?project=${projectId}&resource=app_script_function`; + open(stackdriverURL); + process.exit(0); + } + const logger = new logging({ projectId }); + logger.getEntries().then(printLogs); + }); + + }); + /** * Displays the help function */ diff --git a/package.json b/package.json index dac45031..cf9df110 100644 --- a/package.json +++ b/package.json @@ -27,8 +27,10 @@ "author": "Grant Timmerman", "license": "Apache-2.0", "dependencies": { + "@google-cloud/logging": "^1.2.0", "anymatch": "^1.3.2", "bluebird": "^3.5.1", + "chalk": "^2.3.2", "cli-spinner": "^0.2.6", "commander": "^2.11.0", "connect": "^3.6.5",