heroku 11.0.2 → 11.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +14 -16
- package/bin/run.js +13 -49
- package/dist/commands/domains/add.d.ts +1 -1
- package/dist/commands/pg/backups/schedule.d.ts +1 -1
- package/dist/commands/spaces/index.d.ts +1 -1
- package/dist/commands/spaces/vpn/connections.d.ts +1 -1
- package/dist/hooks/command_not_found/performance_analytics.js +5 -4
- package/dist/hooks/finally/sentry.d.ts +3 -0
- package/dist/hooks/finally/sentry.js +42 -0
- package/dist/hooks/init/performance_analytics.js +5 -4
- package/dist/hooks/postrun/performance_analytics.js +6 -6
- package/dist/hooks/prerun/analytics.js +14 -7
- package/dist/lib/analytics-telemetry/global-telemetry.d.ts +30 -0
- package/dist/lib/analytics-telemetry/global-telemetry.js +103 -0
- package/dist/lib/analytics-telemetry/honeycomb-client.d.ts +15 -0
- package/dist/lib/analytics-telemetry/honeycomb-client.js +135 -0
- package/dist/lib/analytics-telemetry/sentry-client.d.ts +9 -0
- package/dist/lib/analytics-telemetry/sentry-client.js +58 -0
- package/dist/lib/analytics-telemetry/telemetry-utils.d.ts +68 -0
- package/dist/lib/analytics-telemetry/telemetry-utils.js +115 -0
- package/dist/lib/analytics-telemetry/telemetry-worker.d.ts +5 -0
- package/dist/lib/analytics-telemetry/telemetry-worker.js +37 -0
- package/dist/lib/analytics-telemetry/worker-client.d.ts +15 -0
- package/dist/lib/analytics-telemetry/worker-client.js +44 -0
- package/dist/lib/api.d.ts +1 -1
- package/dist/lib/apps/app-transfer.d.ts +1 -1
- package/dist/lib/apps/error_info.d.ts +1 -1
- package/dist/lib/apps/generation.d.ts +3 -3
- package/dist/lib/buildpacks/buildpacks.d.ts +1 -1
- package/dist/lib/container/docker_helper.d.ts +4 -4
- package/dist/lib/data/types.d.ts +37 -37
- package/dist/lib/domains/domains.js +15 -8
- package/dist/lib/pg/download.d.ts +1 -1
- package/dist/lib/pg/push_pull.d.ts +1 -1
- package/dist/lib/pg/setter.d.ts +1 -1
- package/dist/lib/pg/types.d.ts +31 -31
- package/dist/lib/pipelines/setup/validate.d.ts +1 -1
- package/dist/lib/redis/api.d.ts +7 -7
- package/dist/lib/spaces/hosts.d.ts +1 -1
- package/dist/lib/types/app_errors.d.ts +1 -1
- package/dist/lib/types/completion.d.ts +1 -1
- package/dist/lib/types/favorites.d.ts +2 -2
- package/dist/lib/types/notifications.d.ts +3 -3
- package/dist/lib/utils/multisort.d.ts +1 -1
- package/npm-shrinkwrap.json +837 -842
- package/oclif.manifest.json +1018 -1018
- package/package.json +7 -5
- package/dist/global_telemetry.d.ts +0 -62
- package/dist/global_telemetry.js +0 -216
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "heroku",
|
|
3
3
|
"description": "CLI to interact with Heroku",
|
|
4
|
-
"version": "11.0
|
|
4
|
+
"version": "11.1.0",
|
|
5
5
|
"author": "Heroku",
|
|
6
6
|
"bin": "./bin/run.js",
|
|
7
7
|
"bugs": "https://github.com/heroku/cli/issues",
|
|
@@ -66,12 +66,12 @@
|
|
|
66
66
|
"phoenix": "^1.6.14",
|
|
67
67
|
"portfinder": "^1.0.32",
|
|
68
68
|
"printf": "0.6.1",
|
|
69
|
-
"psl": "^1.15.0",
|
|
70
69
|
"redis-parser": "^3.0.0",
|
|
71
70
|
"shell-quote": "^1.8.1",
|
|
72
71
|
"ssh2": "^1.16.0",
|
|
73
72
|
"strftime": "^0.10.0",
|
|
74
73
|
"term-img": "^7.1.0",
|
|
74
|
+
"tldts": "^7.0.27",
|
|
75
75
|
"tmp": "^0.2.5",
|
|
76
76
|
"true-myth": "4.1.1",
|
|
77
77
|
"tsheredoc": "^1.0.1",
|
|
@@ -100,10 +100,9 @@
|
|
|
100
100
|
"@types/node-fetch": "^2.6.11",
|
|
101
101
|
"@types/node-forge": "^1.3.14",
|
|
102
102
|
"@types/phoenix": "^1.4.0",
|
|
103
|
-
"@types/psl": "1.1.3",
|
|
104
103
|
"@types/redis-parser": "^3.0.3",
|
|
105
104
|
"@types/shell-quote": "^1.7.5",
|
|
106
|
-
"@types/sinon": "^
|
|
105
|
+
"@types/sinon": "^21.0.0",
|
|
107
106
|
"@types/ssh2": "^1.15.4",
|
|
108
107
|
"@types/std-mocks": "^1.0.4",
|
|
109
108
|
"@types/strftime": "^0.9.8",
|
|
@@ -142,7 +141,7 @@
|
|
|
142
141
|
"std-mocks": "^2.0.0",
|
|
143
142
|
"stdout-stderr": "^0.1.13",
|
|
144
143
|
"ts-node": "^10.9.2",
|
|
145
|
-
"typescript": "4.
|
|
144
|
+
"typescript": "4.9.5"
|
|
146
145
|
},
|
|
147
146
|
"oclif": {
|
|
148
147
|
"additionalHelpFlags": [
|
|
@@ -185,6 +184,9 @@
|
|
|
185
184
|
"command_not_found": [
|
|
186
185
|
"./dist/hooks/command_not_found/performance_analytics"
|
|
187
186
|
],
|
|
187
|
+
"finally": [
|
|
188
|
+
"./dist/hooks/finally/sentry"
|
|
189
|
+
],
|
|
188
190
|
"init": [
|
|
189
191
|
"./dist/hooks/init/version",
|
|
190
192
|
"./dist/hooks/init/terms-of-service",
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
|
|
2
|
-
export interface TelemetryGlobal extends NodeJS.Global {
|
|
3
|
-
cliTelemetry?: Telemetry;
|
|
4
|
-
}
|
|
5
|
-
interface CLIError extends Error {
|
|
6
|
-
cliRunDuration?: string;
|
|
7
|
-
}
|
|
8
|
-
interface Telemetry {
|
|
9
|
-
cliRunDuration: number;
|
|
10
|
-
command: string;
|
|
11
|
-
commandRunDuration: number;
|
|
12
|
-
exitCode: number;
|
|
13
|
-
exitState: string;
|
|
14
|
-
isVersionOrHelp: boolean;
|
|
15
|
-
lifecycleHookCompletion: {
|
|
16
|
-
command_not_found: boolean;
|
|
17
|
-
init: boolean;
|
|
18
|
-
postrun: boolean;
|
|
19
|
-
prerun: boolean;
|
|
20
|
-
};
|
|
21
|
-
os: string;
|
|
22
|
-
version: string;
|
|
23
|
-
}
|
|
24
|
-
export declare function computeDuration(cmdStartTime: any): number;
|
|
25
|
-
export declare function getProcessor(): BatchSpanProcessor;
|
|
26
|
-
export declare function initializeInstrumentation(): void;
|
|
27
|
-
export declare function reportCmdNotFound(config: any): {
|
|
28
|
-
cliRunDuration: number;
|
|
29
|
-
command: string;
|
|
30
|
-
commandRunDuration: number;
|
|
31
|
-
exitCode: number;
|
|
32
|
-
exitState: string;
|
|
33
|
-
isVersionOrHelp: boolean;
|
|
34
|
-
lifecycleHookCompletion: {
|
|
35
|
-
command_not_found: boolean;
|
|
36
|
-
init: boolean;
|
|
37
|
-
postrun: boolean;
|
|
38
|
-
prerun: boolean;
|
|
39
|
-
};
|
|
40
|
-
os: any;
|
|
41
|
-
version: any;
|
|
42
|
-
};
|
|
43
|
-
export declare function sendTelemetry(currentTelemetry: any): Promise<void>;
|
|
44
|
-
export declare function sendToHoneycomb(data: CLIError | Telemetry): Promise<void>;
|
|
45
|
-
export declare function sendToSentry(data: CLIError): Promise<void>;
|
|
46
|
-
export declare function setupTelemetry(config: any, opts: any): {
|
|
47
|
-
cliRunDuration: number;
|
|
48
|
-
command: any;
|
|
49
|
-
commandRunDuration: number;
|
|
50
|
-
exitCode: number;
|
|
51
|
-
exitState: string;
|
|
52
|
-
isVersionOrHelp: boolean;
|
|
53
|
-
lifecycleHookCompletion: {
|
|
54
|
-
command_not_found: boolean;
|
|
55
|
-
init: boolean;
|
|
56
|
-
postrun: boolean;
|
|
57
|
-
prerun: boolean;
|
|
58
|
-
};
|
|
59
|
-
os: any;
|
|
60
|
-
version: string;
|
|
61
|
-
};
|
|
62
|
-
export {};
|
package/dist/global_telemetry.js
DELETED
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
import { APIClient } from '@heroku-cli/command';
|
|
2
|
-
import { Config } from '@oclif/core/config';
|
|
3
|
-
import opentelemetry, { SpanStatusCode } from '@opentelemetry/api';
|
|
4
|
-
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
|
|
5
|
-
import { registerInstrumentations } from '@opentelemetry/instrumentation';
|
|
6
|
-
import { Resource } from '@opentelemetry/resources';
|
|
7
|
-
import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
|
|
8
|
-
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
|
|
9
|
-
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
|
|
10
|
-
import * as Sentry from '@sentry/node';
|
|
11
|
-
import { SentryPropagator, SentrySampler, } from '@sentry/opentelemetry';
|
|
12
|
-
import debug from 'debug';
|
|
13
|
-
import path from 'path';
|
|
14
|
-
import { fileURLToPath } from 'url';
|
|
15
|
-
import { PII_PATTERNS } from './lib/data-scrubber/patterns.js';
|
|
16
|
-
import { GDPR_FIELDS, HEROKU_FIELDS, PCI_FIELDS } from './lib/data-scrubber/presets.js';
|
|
17
|
-
import { Scrubber } from './lib/data-scrubber/scrubber.js';
|
|
18
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
19
|
-
const __dirname = path.dirname(__filename);
|
|
20
|
-
const root = path.resolve(__dirname, '../package.json');
|
|
21
|
-
const isDev = process.env.IS_DEV_ENVIRONMENT === 'true';
|
|
22
|
-
const isTelemetryDisabled = process.env.DISABLE_TELEMETRY === 'true';
|
|
23
|
-
// Lazy-loaded state
|
|
24
|
-
let isInitialized = false;
|
|
25
|
-
let version;
|
|
26
|
-
let provider;
|
|
27
|
-
let processor;
|
|
28
|
-
let sentryClient;
|
|
29
|
-
export function computeDuration(cmdStartTime) {
|
|
30
|
-
// calculate time duration from start time till now
|
|
31
|
-
const now = new Date();
|
|
32
|
-
const cmdFinishTime = now.getTime();
|
|
33
|
-
return cmdFinishTime - cmdStartTime;
|
|
34
|
-
}
|
|
35
|
-
// Export processor getter for backward compatibility
|
|
36
|
-
export function getProcessor() {
|
|
37
|
-
ensureInitialized();
|
|
38
|
-
return processor;
|
|
39
|
-
}
|
|
40
|
-
export function initializeInstrumentation() {
|
|
41
|
-
if (isTelemetryDisabled) {
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
ensureInitialized();
|
|
45
|
-
provider.register({
|
|
46
|
-
contextManager: new Sentry.SentryContextManager(),
|
|
47
|
-
propagator: new SentryPropagator(),
|
|
48
|
-
});
|
|
49
|
-
// provider.register()
|
|
50
|
-
}
|
|
51
|
-
export function reportCmdNotFound(config) {
|
|
52
|
-
return {
|
|
53
|
-
cliRunDuration: 0,
|
|
54
|
-
command: 'invalid_command',
|
|
55
|
-
commandRunDuration: 0,
|
|
56
|
-
exitCode: 0,
|
|
57
|
-
exitState: 'command_not_found',
|
|
58
|
-
isVersionOrHelp: false,
|
|
59
|
-
lifecycleHookCompletion: {
|
|
60
|
-
command_not_found: true,
|
|
61
|
-
init: true,
|
|
62
|
-
postrun: false,
|
|
63
|
-
prerun: false,
|
|
64
|
-
},
|
|
65
|
-
os: config.platform,
|
|
66
|
-
version: config.version,
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
export async function sendTelemetry(currentTelemetry) {
|
|
70
|
-
// send telemetry to honeycomb
|
|
71
|
-
if (isTelemetryDisabled) {
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
const telemetry = currentTelemetry;
|
|
75
|
-
if (telemetry instanceof Error) {
|
|
76
|
-
await Promise.all([
|
|
77
|
-
sendToHoneycomb(telemetry),
|
|
78
|
-
sendToSentry(telemetry),
|
|
79
|
-
]);
|
|
80
|
-
}
|
|
81
|
-
else {
|
|
82
|
-
await sendToHoneycomb(telemetry);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
export async function sendToHoneycomb(data) {
|
|
86
|
-
ensureInitialized();
|
|
87
|
-
try {
|
|
88
|
-
const tracer = opentelemetry.trace.getTracer('heroku-cli', getVersion());
|
|
89
|
-
const span = tracer.startSpan('node_app_execution');
|
|
90
|
-
if (data instanceof Error) {
|
|
91
|
-
span.recordException(data);
|
|
92
|
-
span.setStatus({
|
|
93
|
-
code: SpanStatusCode.ERROR,
|
|
94
|
-
message: data.message,
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
span.setAttribute('heroku_client.command', data.command);
|
|
99
|
-
span.setAttribute('heroku_client.os', data.os);
|
|
100
|
-
span.setAttribute('heroku_client.version', data.version);
|
|
101
|
-
span.setAttribute('heroku_client.exit_code', data.exitCode);
|
|
102
|
-
span.setAttribute('heroku_client.exit_state', data.exitState);
|
|
103
|
-
span.setAttribute('heroku_client.cli_run_duration', data.cliRunDuration);
|
|
104
|
-
span.setAttribute('heroku_client.command_run_duration', data.commandRunDuration);
|
|
105
|
-
span.setAttribute('heroku_client.lifecycle_hook.init', data.lifecycleHookCompletion.init);
|
|
106
|
-
span.setAttribute('heroku_client.lifecycle_hook.prerun', data.lifecycleHookCompletion.prerun);
|
|
107
|
-
span.setAttribute('heroku_client.lifecycle_hook.postrun', data.lifecycleHookCompletion.postrun);
|
|
108
|
-
span.setAttribute('heroku_client.lifecycle_hook.command_not_found', data.lifecycleHookCompletion.command_not_found);
|
|
109
|
-
}
|
|
110
|
-
span.end();
|
|
111
|
-
await getProcessor().forceFlush();
|
|
112
|
-
}
|
|
113
|
-
catch {
|
|
114
|
-
debug('could not send telemetry');
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
export async function sendToSentry(data) {
|
|
118
|
-
ensureInitialized();
|
|
119
|
-
try {
|
|
120
|
-
Sentry.captureException(data);
|
|
121
|
-
// ensures all events are sent to Sentry before exiting.
|
|
122
|
-
await Sentry.flush();
|
|
123
|
-
}
|
|
124
|
-
catch {
|
|
125
|
-
debug('Could not send error report');
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
export function setupTelemetry(config, opts) {
|
|
129
|
-
// Store version from config (eliminates need to read package.json)
|
|
130
|
-
if (!version) {
|
|
131
|
-
version = config.version;
|
|
132
|
-
}
|
|
133
|
-
const now = new Date();
|
|
134
|
-
const cmdStartTime = now.getTime();
|
|
135
|
-
const isRegularCmd = Boolean(opts.Command);
|
|
136
|
-
const mcpMode = process.env.HEROKU_MCP_MODE === 'true';
|
|
137
|
-
const mcpServerVersion = process.env.HEROKU_MCP_SERVER_VERSION || 'unknown';
|
|
138
|
-
const irregularTelemetryObject = {
|
|
139
|
-
cliRunDuration: 0,
|
|
140
|
-
command: opts.id,
|
|
141
|
-
commandRunDuration: cmdStartTime,
|
|
142
|
-
exitCode: 0,
|
|
143
|
-
exitState: 'successful',
|
|
144
|
-
isVersionOrHelp: true,
|
|
145
|
-
lifecycleHookCompletion: {
|
|
146
|
-
command_not_found: false,
|
|
147
|
-
init: true,
|
|
148
|
-
postrun: false,
|
|
149
|
-
prerun: false,
|
|
150
|
-
},
|
|
151
|
-
os: config.platform,
|
|
152
|
-
version: `${config.version}${mcpMode ? ` (MCP ${mcpServerVersion})` : ''}`,
|
|
153
|
-
};
|
|
154
|
-
if (isRegularCmd) {
|
|
155
|
-
return {
|
|
156
|
-
...irregularTelemetryObject,
|
|
157
|
-
command: opts.Command.id,
|
|
158
|
-
isVersionOrHelp: false,
|
|
159
|
-
lifecycleHookCompletion: {
|
|
160
|
-
...irregularTelemetryObject.lifecycleHookCompletion,
|
|
161
|
-
prerun: true,
|
|
162
|
-
},
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
return irregularTelemetryObject;
|
|
166
|
-
}
|
|
167
|
-
function ensureInitialized() {
|
|
168
|
-
if (isInitialized || isTelemetryDisabled) {
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
isInitialized = true;
|
|
172
|
-
registerInstrumentations({
|
|
173
|
-
instrumentations: [],
|
|
174
|
-
});
|
|
175
|
-
const scrubber = new Scrubber({
|
|
176
|
-
fields: [...HEROKU_FIELDS, ...GDPR_FIELDS, ...PCI_FIELDS],
|
|
177
|
-
patterns: [...PII_PATTERNS],
|
|
178
|
-
});
|
|
179
|
-
sentryClient = Sentry.init({
|
|
180
|
-
beforeSend(event) {
|
|
181
|
-
return scrubber.scrub(event).data;
|
|
182
|
-
},
|
|
183
|
-
dsn: 'https://76530569188e7ee2961373f37951d916@o4508609692368896.ingest.us.sentry.io/4508767754846208',
|
|
184
|
-
environment: isDev ? 'development' : 'production',
|
|
185
|
-
release: getVersion(),
|
|
186
|
-
skipOpenTelemetrySetup: true,
|
|
187
|
-
tracesSampleRate: 1, // needed to ensure we send OTEL data to Honeycomb
|
|
188
|
-
});
|
|
189
|
-
const resource = Resource
|
|
190
|
-
.default()
|
|
191
|
-
.merge(new Resource({
|
|
192
|
-
[SemanticResourceAttributes.SERVICE_NAME]: 'heroku-cli',
|
|
193
|
-
[SemanticResourceAttributes.SERVICE_VERSION]: undefined, // will be set later
|
|
194
|
-
}));
|
|
195
|
-
provider = new NodeTracerProvider({
|
|
196
|
-
resource,
|
|
197
|
-
sampler: sentryClient ? new SentrySampler(sentryClient) : undefined,
|
|
198
|
-
});
|
|
199
|
-
// eslint-disable-next-line no-negated-condition, unicorn/no-negated-condition
|
|
200
|
-
const headers = { Authorization: `Bearer ${process.env.IS_HEROKU_TEST_ENV !== 'true' ? getToken() : ''}` };
|
|
201
|
-
const exporter = new OTLPTraceExporter({
|
|
202
|
-
compression: undefined,
|
|
203
|
-
headers,
|
|
204
|
-
url: isDev ? 'https://backboard.staging.herokudev.com/otel/v1/traces' : 'https://backboard.heroku.com/otel/v1/traces',
|
|
205
|
-
});
|
|
206
|
-
processor = new BatchSpanProcessor(exporter);
|
|
207
|
-
provider.addSpanProcessor(processor);
|
|
208
|
-
}
|
|
209
|
-
function getToken() {
|
|
210
|
-
const config = new Config({ root });
|
|
211
|
-
const heroku = new APIClient(config);
|
|
212
|
-
return heroku.auth;
|
|
213
|
-
}
|
|
214
|
-
function getVersion() {
|
|
215
|
-
return version || 'unknown';
|
|
216
|
-
}
|