├── .codeclimate.yml ├── LICENCE ├── ProcessApp.js └── README.md /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | --- 2 | engines: 3 | duplication: 4 | enabled: true 5 | config: 6 | languages: 7 | - ruby 8 | - javascript 9 | - python 10 | - php 11 | eslint: 12 | enabled: true 13 | fixme: 14 | enabled: true 15 | ratings: 16 | paths: 17 | - "**.inc" 18 | - "**.js" 19 | - "**.jsx" 20 | - "**.module" 21 | - "**.php" 22 | - "**.py" 23 | - "**.rb" 24 | exclude_paths: 25 | - "tests/" 26 | - "spec/" 27 | - "**/vendor/" 28 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2019 Kanshi TANAIKE 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /ProcessApp.js: -------------------------------------------------------------------------------- 1 | /** 2 | * GitHub https://github.com/tanaikech/ProcessApp
3 | * Retrieve total execution time of time-driven trigger.
4 | * @param {Object} object Object 5 | * @return {Object} Total execution time of time-driven trigger 6 | */ 7 | function getExecutionTimeOfTrigger(object) { 8 | return new ProcessApp(1).GetExecutionTimeOfTrigger(object); 9 | } 10 | 11 | /** 12 | * Retrieve endpoint of dev mode for Web Apps.
13 | * @param {String} projectId Project ID 14 | * @return {String} URL of dev mode 15 | */ 16 | function getDevUrl(projectId) { 17 | return new ProcessApp(2).GetDevUrl(projectId); 18 | } 19 | 20 | /** 21 | * Retrieve functions which are running.
22 | * @return {String} URL of dev mode 23 | */ 24 | function getRunningFunctions() { 25 | return new ProcessApp(1).GetRunningFunctions(); 26 | } 27 | 28 | /** 29 | * Retrieve total execution time of the specific process type.
30 | * @param {Object} object Object 31 | * @return {Object} Total execution time of the specific process type 32 | */ 33 | function getExecutionTimeOfProcessType(object) { 34 | return new ProcessApp(1).GetExecutionTimeOfProcessType(object); 35 | } 36 | ; 37 | (function(r) { 38 | var ProcessApp; 39 | ProcessApp = (function() { 40 | var addQuery, defaultStartEndTime, parseData; 41 | 42 | ProcessApp.name = "ProcessApp"; 43 | 44 | function ProcessApp(method_) { 45 | switch (method_) { 46 | case 1: 47 | this.url = "https://script.googleapis.com/v1/processes"; 48 | break; 49 | case 2: 50 | this.url = "https://script.googleapis.com/v1/projects/{projectId}/deployments?fields=deployments"; 51 | } 52 | this.at = ScriptApp.getOAuthToken(); 53 | } 54 | 55 | ProcessApp.prototype.GetExecutionTimeOfTrigger = function(p_) { 56 | var data, e, endTime, endpoint, nextPageToken, params, q, ref, startTime; 57 | try { 58 | if (p_ == null) { 59 | p_ = {}; 60 | } 61 | params = { 62 | headers: { 63 | Authorization: 'Bearer ' + this.at 64 | } 65 | }; 66 | ref = defaultStartEndTime.call(this, p_), startTime = ref[0], endTime = ref[1]; 67 | data = []; 68 | nextPageToken = ""; 69 | while (true) { 70 | q = { 71 | pageToken: nextPageToken, 72 | fields: "*", 73 | "userProcessFilter.functionName": p_.functionName || "", 74 | "userProcessFilter.scriptId": p_.projectId || "", 75 | "userProcessFilter.startTime": startTime, 76 | "userProcessFilter.endTime": endTime, 77 | "userProcessFilter.types": "TIME_DRIVEN" 78 | }; 79 | endpoint = addQuery.call(this, this.url, q); 80 | r = UrlFetchApp.fetch(endpoint, params); 81 | r = JSON.parse(r.getContentText()); 82 | Array.prototype.push.apply(data, r.processes); 83 | nextPageToken = r.nextPageToken || ""; 84 | if (!nextPageToken) { 85 | break; 86 | } 87 | } 88 | return parseData.call(this, data); 89 | } catch (error) { 90 | e = error; 91 | throw new Error(e); 92 | } 93 | }; 94 | 95 | ProcessApp.prototype.GetDevUrl = function(p_) { 96 | var e, params, projectId; 97 | if (p_ == null) { 98 | throw new Error("Please set projectId."); 99 | } 100 | try { 101 | projectId = typeof p_ === "object" ? p_.projectId : p_; 102 | this.url = this.url.replace("{projectId}", projectId); 103 | params = { 104 | headers: { 105 | Authorization: 'Bearer ' + this.at 106 | } 107 | }; 108 | r = UrlFetchApp.fetch(this.url, params); 109 | r = JSON.parse(r.getContentText()); 110 | return "https://script.google.com/macros/s/" + r.deployments[0].deploymentId + "/dev"; 111 | } catch (error) { 112 | e = error; 113 | throw new Error(e); 114 | } 115 | }; 116 | 117 | ProcessApp.prototype.GetRunningFunctions = function() { 118 | var e, endpoint, params, q; 119 | try { 120 | params = { 121 | headers: { 122 | Authorization: 'Bearer ' + this.at 123 | } 124 | }; 125 | q = { 126 | fields: "*", 127 | "userProcessFilter.statuses": "RUNNING" 128 | }; 129 | endpoint = addQuery.call(this, this.url, q); 130 | r = UrlFetchApp.fetch(endpoint, params); 131 | r = JSON.parse(r.getContentText()); 132 | return r.processes || []; 133 | } catch (error) { 134 | e = error; 135 | throw new Error(e); 136 | } 137 | }; 138 | 139 | ProcessApp.prototype.GetExecutionTimeOfProcessType = function(p_) { 140 | var data, e, endTime, endpoint, nextPageToken, params, q, ref, startTime; 141 | try { 142 | if (p_ == null) { 143 | p_ = {}; 144 | } 145 | params = { 146 | headers: { 147 | Authorization: 'Bearer ' + this.at 148 | } 149 | }; 150 | ref = defaultStartEndTime.call(this, p_), startTime = ref[0], endTime = ref[1]; 151 | data = []; 152 | nextPageToken = ""; 153 | while (true) { 154 | q = { 155 | pageToken: nextPageToken, 156 | fields: "*", 157 | "userProcessFilter.functionName": p_.functionName || "", 158 | "userProcessFilter.scriptId": p_.projectId || "", 159 | "userProcessFilter.types": p_.processType || "EDITOR", 160 | "userProcessFilter.startTime": startTime, 161 | "userProcessFilter.endTime": endTime 162 | }; 163 | endpoint = addQuery.call(this, this.url, q); 164 | r = UrlFetchApp.fetch(endpoint, params); 165 | r = JSON.parse(r.getContentText()); 166 | Array.prototype.push.apply(data, r.processes); 167 | nextPageToken = r.nextPageToken || ""; 168 | if (!nextPageToken) { 169 | break; 170 | } 171 | } 172 | return parseData.call(this, data); 173 | } catch (error) { 174 | e = error; 175 | throw new Error(e); 176 | } 177 | }; 178 | 179 | defaultStartEndTime = function(p_) { 180 | var endTime, startTime, t; 181 | startTime = ""; 182 | endTime = ""; 183 | if (p_.startTime && p_.endTime) { 184 | startTime = p_.startTime; 185 | endTime = p_.endTime; 186 | } else { 187 | t = new Date(); 188 | endTime = t.toISOString(); 189 | t.setDate(t.getDate() - 1); 190 | startTime = t.toISOString(); 191 | } 192 | return [startTime, endTime]; 193 | }; 194 | 195 | parseData = function(data) { 196 | var r1, r2, statistics; 197 | r1 = data.reduce(function(obj, e) { 198 | obj[e.functionName] = obj[e.functionName] ? obj[e.functionName] + Number(e.duration.replace("s", "")) : Number(e.duration.replace("s", "")); 199 | return obj; 200 | }, {}); 201 | r2 = Object.keys(r1).map(function(e) { 202 | return { 203 | functionName: e, 204 | totalExecutionTimeSec: Math.round(r1[e] * 100) / 100, 205 | totalExecutionTimeMin: Math.round((r1[e] / 60) * 100) / 100 206 | }; 207 | }); 208 | statistics = r2.reduce(function(obj, e) { 209 | obj.allFunctions = obj.allFunctions ? obj.allFunctions.concat(e.functionName) : [e.functionName]; 210 | obj.totalExecutionTimeSec = obj.totalExecutionTimeSec ? obj.totalExecutionTimeSec + e.totalExecutionTimeSec : e.totalExecutionTimeSec; 211 | obj.totalExecutionTimeMin = obj.totalExecutionTimeMin ? obj.totalExecutionTimeMin + e.totalExecutionTimeMin : e.totalExecutionTimeMin; 212 | return obj; 213 | }, {}); 214 | statistics.totalExecutionTimeSec = Math.round(statistics.totalExecutionTimeSec * 100) / 100; 215 | statistics.totalExecutionTimeMin = Math.round(statistics.totalExecutionTimeMin * 100) / 100; 216 | return { 217 | statistics: statistics, 218 | eachFunction: r2 219 | }; 220 | }; 221 | 222 | addQuery = function(url_, obj_) { 223 | return url_ + Object.keys(obj_).reduce(function(p, e, i) { 224 | return p + (i === 0 ? "?" : "&") + e + "=" + encodeURIComponent(obj_[e]); 225 | }, ""); 226 | }; 227 | 228 | return ProcessApp; 229 | 230 | })(); 231 | return r.ProcessApp = ProcessApp; 232 | })(this); 233 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ProcessApp 2 | ===== 3 | 4 | 5 | [![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENCE) 6 | 7 | 8 | # Overview 9 | **This is a library for retrieving the process and information of Google Apps Script.** 10 | 11 | 12 | # Methods 13 | 1. [getExecutionTimeOfTrigger()](#getexecutiontimeoftrigger) : This method retrieves the total execution time of all functions executed by the time-driven trigger at owner's account. For example, you can know the total execution time of all functions executed by the time-driven trigger in 24 h. 14 | 1. [getDevUrl()](#getdevurl) : This method retrieves the endpoint of developer mode for Web Apps like ``https://script.google.com/macros/s/#####/dev``. 15 | 1. [getRunningFunctions()](#getrunningfunctions) : This method retrieves the functions which are running now. 16 | 1. [getExecutionTimeOfProcessType()](#getexecutiontimeofprocesstype) : This method retrieves the total execution time of all functions by filtering the process type. For example, the total execution time of Web Apps can be retrieved. 17 | 18 | I would like to add more methods in the future. 19 | 20 | # Library's project key 21 | ~~~ 22 | 1y3BjeYyJUdI9U2JZ97POIXRTaYnjsbH6SUapd43s8S8vh2Io5pho6xZ6 23 | ~~~ 24 | 25 | # How to install 26 | - Open Script Editor. And please operate follows by click. 27 | - -> Resource 28 | - -> Library 29 | - -> Input Script ID to text box. Script ID is **``1y3BjeYyJUdI9U2JZ97POIXRTaYnjsbH6SUapd43s8S8vh2Io5pho6xZ6``**. 30 | - -> Add library 31 | - -> Please select latest version 32 | - -> Developer mode ON (If you don't want to use latest version, please select others.) 33 | - -> Identifier is "**``ProcessApp``**". This is set under the default. 34 | 35 | [If you want to read about Libraries, please check this.](https://developers.google.com/apps-script/guide_libraries). 36 | 37 | # Enable Apps Script API 38 | This library uses [Apps Script API](https://developers.google.com/apps-script/api/reference/rest/). So please enable Apps Script API at API console as follows. 39 | 40 | - On script editor 41 | - Resources -> Cloud Platform project 42 | - View API console 43 | - At Getting started, click "Explore and enable APIs". 44 | - At left side, click Library. 45 | - At Search for APIs & services, input "apps script". And click Apps Script API. 46 | - Click Enable button. 47 | - If this API has already been enabled, please don't turn off. 48 | 49 | ## About scopes 50 | This library uses the following 3 scopes. These are installed in the library. So users are not required to do anything for this. 51 | 52 | - ``https://www.googleapis.com/auth/script.external_request`` 53 | - ``https://www.googleapis.com/auth/script.processes`` 54 | - ``https://www.googleapis.com/auth/script.deployments.readonly`` 55 | 56 | # Methods 57 | 58 | ## 1. getExecutionTimeOfTrigger() 59 | ### Overview 60 | This method retrieves the total execution time of all functions executed by the time-driven trigger at owner's account. For example, you can know the total execution time of all functions executed by the time-driven trigger in 24 h. 61 | 62 | ### Description 63 | There are [quotas for "Triggers total runtime"](https://developers.google.com/apps-script/guides/services/quotas). For example, it's 90 min/day for the consumer account. So when users use the time-driven trigger, it is very important to know the current total execution time of all functions by the time-driven trigger. But there were no methods for directly retrieving the total execution time before. When Apps Script API was updated, the method of ["processes"](https://developers.google.com/apps-script/api/reference/rest/v1/processes) was also added. I thought that this might be able to be used for this situation, and I had experimented about this. As the result, it was found that this method can be used for directly retrieving the total execution time of all functions executed by the time-driven trigger. So I published this. 64 | 65 | ### Sample script 66 | This method can be used simply like below. In this case, as the default setting, the total execution time from now to 24 h ago is retrieved. 67 | 68 | ~~~javascript 69 | var res = ProcessApp.getExecutionTimeOfTrigger(); 70 | ~~~ 71 | 72 | Of course, you can see the period for retrieving the total execution time can be set using as follows. In this sample script, the total execution time from ``2019-02-01T00:00:00.000Z`` to ``2019-02-02T00:00:00.000Z`` of a function of ``myFunction1`` in the project ID of ``#####`` is retrieved. 73 | 74 | ~~~javascript 75 | var object = { 76 | projectId: "#####", // Project ID 77 | functionName: "myFunction1", // function name that you want to know the total execution time. 78 | startTime: "2019-02-01T00:00:00.000Z", 79 | endTime: "2019-02-02T00:00:00.000Z", 80 | }; 81 | var res = ProcessApp.getExecutionTimeOfTrigger(object); 82 | ~~~ 83 | 84 | - About ``startTime`` and ``endTime`` 85 | - A timestamp in RFC3339 UTC "Zulu" format, accurate to nanoseconds. Example: "2014-10-02T15:01:23.045123456Z". [Ref](https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#google.protobuf.Timestamp) 86 | 87 | #### Result 88 | For example, when 2 functions of ``myFunction1()`` and ``myFunction2()`` are run by the time-driven trigger and the script is ``var res = ProcessApp.getExecutionTimeOfTrigger()``, this method returns the following result. From the result, it is found that the total execution time of both functions from now to 24 h ago is 1380 s. The breakdown of this is 1200 s and 180 s for ``myFunction1()`` and ``myFunction2()``, respectively. 89 | 90 | ~~~ 91 | { 92 | "statistics": { 93 | "allFunctions": [ 94 | "myFunction1", 95 | "myFunction2" 96 | ], 97 | "totalExecutionTimeSec": 1380.00, 98 | "totalExecutionTimeMin": 23.00 99 | }, 100 | "eachFunction": [ 101 | { 102 | "functionName": "myFunction1", 103 | "totalExecutionTimeSec": 1200.00, 104 | "totalExecutionTimeMin": 20.00 105 | }, 106 | { 107 | "functionName": "myFunction2", 108 | "totalExecutionTimeSec": 180.00, 109 | "totalExecutionTimeMin": 3.00 110 | } 111 | ] 112 | } 113 | ~~~ 114 | 115 | [Also this method was posted to Stackoverflow as an answer.](https://stackoverflow.com/a/54604118) 116 | 117 | 118 | ## 2. getDevUrl() 119 | ### Overview 120 | This method retrieves the endpoint of developer mode for Web Apps like ``https://script.google.com/macros/s/#####/dev``. 121 | 122 | ### Description 123 | There is the method in Class ScriptApp for retrieving the endpoint of Web Apps. It's ``ScriptApp.getService().getUrl()``. This method returns the endpoint of the deployed Web Apps like ``https://script.google.com/macros/s/#####/exec``. It's not the endpoint of developer mode like ``https://script.google.com/macros/s/#####/dev``. So I created this method of ``getDevUrl()``. 124 | 125 | ### Sample script 126 | ~~~javascript 127 | var projectId = "#####"; 128 | var res = ProcessApp.getDevUrl(projectId); 129 | ~~~ 130 | 131 | #### Result 132 | ~~~ 133 | https://script.google.com/macros/s/#####/dev 134 | ~~~ 135 | 136 | 137 | ## 3. getRunningFunctions() 138 | ### Overview 139 | This method retrieves the functions which are running now. 140 | 141 | ### Description 142 | For example, it supposes that there is a a function is run by the time-driven trigger and the execution time of function is long. At that time, I had a case that it is required to know whether the function is running now. So I created this method of ``getRunningFunctions()``. This method can be also used the event trigger and Web Apps. 143 | 144 | ### Sample script 145 | ~~~javascript 146 | var res = ProcessApp.getRunningFunctions(); 147 | ~~~ 148 | 149 | #### Result 150 | The process information of the running function is returned. 151 | 152 | ~~~json 153 | [ 154 | { 155 | "projectName": "sample project", 156 | "functionName": "myFunction", 157 | "processType": "EDITOR", 158 | "processStatus": "RUNNING", 159 | "userAccessLevel": "OWNER", 160 | "startTime": "2000-01-01T00:00:00.000Z", 161 | "duration": "12.345s" 162 | } 163 | ] 164 | ~~~ 165 | 166 | 167 | ## 4. getExecutionTimeOfProcessType() 168 | ### Overview 169 | This method retrieves the endpoint of developer mode for Web Apps like ``https://script.google.com/macros/s/#####/dev``. 170 | 171 | ### Description 172 | There is the method in Class ScriptApp for retrieving the endpoint of Web Apps. It's ``ScriptApp.getService().getUrl()``. This method returns the endpoint of the deployed Web Apps like ``https://script.google.com/macros/s/#####/exec``. It's not the endpoint of developer mode like ``https://script.google.com/macros/s/#####/dev``. So I created this method of ``getDevUrl()``. 173 | 174 | ### Sample script 175 | The basic usage is almost the same with [getExecutionTimeOfTrigger()](#getexecutiontimeoftrigger). In this method, the result is filtered by the process type. You can select the process type from [here](https://developers.google.com/apps-script/api/reference/rest/v1/processes#ProcessType) 176 | 177 | | Process type | Description | 178 | |:---|:---| 179 | | PROCESS_TYPE_UNSPECIFIED | Unspecified type. | 180 | | ADD_ON | The process was started from an add-on entry point. | 181 | | EXECUTION_API | The process was started using the Apps Script API. | 182 | | TIME_DRIVEN | The process was started from a time-based trigger. | 183 | | TRIGGER | The process was started from an event-based trigger. | 184 | | WEBAPP | The process was started from a web app entry point. | 185 | | EDITOR | The process was started using the Apps Script IDE. | 186 | | SIMPLE_TRIGGER | The process was started from a G Suite simple trigger. | 187 | | MENU | The process was started from a G Suite menu item. | 188 | 189 | This method can be used simply like below. In this case, as the default setting, the total execution time from now to 24 h ago is retrieved. And the process type of "EDITOR" is used. "EDITOR" means that the total execution time of functions executed by the script editor is retrieved. 190 | 191 | ~~~javascript 192 | var res = ProcessApp.getExecutionTimeOfTrigger(); 193 | ~~~ 194 | 195 | Of course, you can see the period for retrieving the total execution time can be set using as follows. In this sample script, the total execution time from ``2019-02-01T00:00:00.000Z`` to ``2019-02-02T00:00:00.000Z`` of a function of ``doGet`` executed by Web Apps in the project ID of ``#####`` is retrieved. 196 | 197 | ~~~javascript 198 | var object = { 199 | projectId: "#####", // Project ID 200 | functionName: "doGet", // function name that you want to know the total execution time. 201 | processType: "WEBAPP", 202 | startTime: "2019-02-01T00:00:00.000Z", 203 | endTime: "2019-02-02T00:00:00.000Z", 204 | }; 205 | var res = ProcessApp.getExecutionTimeOfTrigger(object); 206 | ~~~ 207 | 208 | #### Result 209 | 210 | ~~~ 211 | { 212 | "statistics": { 213 | "allFunctions": [ 214 | "doGet", 215 | ], 216 | "totalExecutionTimeSec": 1200.00, 217 | }, 218 | "eachFunction": [ 219 | { 220 | "functionName": "doGet", 221 | "totalExecutionTimeSec": 1200.00, 222 | "totalExecutionTimeMin": 20.00 223 | } 224 | ] 225 | } 226 | ~~~ 227 | 228 | ----- 229 | 230 | 231 | # Licence 232 | [MIT](LICENCE) 233 | 234 | 235 | # Author 236 | [Tanaike](https://tanaikech.github.io/about/) 237 | 238 | If you have any questions and commissions for me, feel free to contact me. 239 | 240 | 241 | # Update History 242 | * v1.0.0 (February 9, 2019) 243 | 244 | 1. Initial release. 245 | 246 | * v1.0.1 (February 10, 2019) 247 | 248 | 1. New method of [getExecutionTimeOfProcessType()](#getexecutiontimeofprocesstype) was added. 249 | - This method retrieves the total execution time of all functions by filtering the process type. For example, the total execution time of Web Apps can be retrieved. 250 | 251 | 252 | [TOP](#top) 253 | --------------------------------------------------------------------------------