@datadog/datadog-ci 2.18.0 → 2.19.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/dist/cli.d.ts +3 -1
- package/dist/cli.js +9 -2
- package/dist/cli.js.map +1 -1
- package/dist/commands/cloud-run/cli.d.ts +1 -0
- package/dist/commands/cloud-run/cli.js +5 -0
- package/dist/commands/cloud-run/cli.js.map +1 -0
- package/dist/commands/cloud-run/constants.d.ts +1 -0
- package/dist/commands/cloud-run/constants.js +22 -0
- package/dist/commands/cloud-run/constants.js.map +1 -0
- package/dist/commands/cloud-run/flare.d.ts +91 -0
- package/dist/commands/cloud-run/flare.js +634 -0
- package/dist/commands/cloud-run/flare.js.map +1 -0
- package/dist/commands/cloud-run/interfaces.d.ts +27 -0
- package/dist/commands/cloud-run/interfaces.js +3 -0
- package/dist/commands/cloud-run/interfaces.js.map +1 -0
- package/dist/commands/cloud-run/renderer.d.ts +4 -0
- package/dist/commands/cloud-run/renderer.js +42 -0
- package/dist/commands/cloud-run/renderer.js.map +1 -0
- package/dist/commands/dsyms/renderer.js +6 -6
- package/dist/commands/dsyms/renderer.js.map +1 -1
- package/dist/commands/dsyms/upload.d.ts +5 -5
- package/dist/commands/dsyms/upload.js +66 -42
- package/dist/commands/dsyms/upload.js.map +1 -1
- package/dist/commands/dsyms/utils.d.ts +1 -1
- package/dist/commands/dsyms/utils.js +3 -3
- package/dist/commands/dsyms/utils.js.map +1 -1
- package/dist/commands/flutter-symbols/helpers.js +8 -4
- package/dist/commands/flutter-symbols/helpers.js.map +1 -1
- package/dist/commands/flutter-symbols/renderer.js +2 -2
- package/dist/commands/flutter-symbols/renderer.js.map +1 -1
- package/dist/commands/flutter-symbols/upload.d.ts +13 -13
- package/dist/commands/flutter-symbols/upload.js +66 -66
- package/dist/commands/flutter-symbols/upload.js.map +1 -1
- package/dist/commands/gate/api.js +4 -2
- package/dist/commands/gate/api.js.map +1 -1
- package/dist/commands/gate/evaluate.d.ts +18 -6
- package/dist/commands/gate/evaluate.js +116 -40
- package/dist/commands/gate/evaluate.js.map +1 -1
- package/dist/commands/gate/interfaces.d.ts +5 -0
- package/dist/commands/gate/renderer.js +16 -14
- package/dist/commands/gate/renderer.js.map +1 -1
- package/dist/commands/gate/utils.d.ts +1 -0
- package/dist/commands/gate/utils.js +8 -4
- package/dist/commands/gate/utils.js.map +1 -1
- package/dist/commands/git-metadata/git.d.ts +1 -1
- package/dist/commands/git-metadata/git.js +7 -3
- package/dist/commands/git-metadata/git.js.map +1 -1
- package/dist/commands/git-metadata/gitdb.d.ts +1 -1
- package/dist/commands/git-metadata/gitdb.js +7 -7
- package/dist/commands/git-metadata/gitdb.js.map +1 -1
- package/dist/commands/git-metadata/index.js +5 -1
- package/dist/commands/git-metadata/index.js.map +1 -1
- package/dist/commands/git-metadata/library.d.ts +1 -1
- package/dist/commands/git-metadata/library.js +13 -13
- package/dist/commands/git-metadata/library.js.map +1 -1
- package/dist/commands/git-metadata/upload.d.ts +5 -5
- package/dist/commands/git-metadata/upload.js +30 -32
- package/dist/commands/git-metadata/upload.js.map +1 -1
- package/dist/commands/junit/api.js +4 -4
- package/dist/commands/junit/api.js.map +1 -1
- package/dist/commands/junit/id.js +1 -1
- package/dist/commands/junit/id.js.map +1 -1
- package/dist/commands/junit/renderer.d.ts +1 -1
- package/dist/commands/junit/renderer.js +3 -3
- package/dist/commands/junit/renderer.js.map +1 -1
- package/dist/commands/junit/upload.d.ts +12 -11
- package/dist/commands/junit/upload.js +74 -63
- package/dist/commands/junit/upload.js.map +1 -1
- package/dist/commands/junit/utils.d.ts +1 -2
- package/dist/commands/junit/utils.js +5 -10
- package/dist/commands/junit/utils.js.map +1 -1
- package/dist/commands/lambda/constants.d.ts +13 -11
- package/dist/commands/lambda/constants.js +41 -70
- package/dist/commands/lambda/constants.js.map +1 -1
- package/dist/commands/lambda/flare.d.ts +25 -74
- package/dist/commands/lambda/flare.js +182 -332
- package/dist/commands/lambda/flare.js.map +1 -1
- package/dist/commands/lambda/functions/commons.d.ts +8 -14
- package/dist/commands/lambda/functions/commons.js +57 -69
- package/dist/commands/lambda/functions/commons.js.map +1 -1
- package/dist/commands/lambda/functions/instrument.js +66 -65
- package/dist/commands/lambda/functions/instrument.js.map +1 -1
- package/dist/commands/lambda/functions/uninstrument.js +38 -37
- package/dist/commands/lambda/functions/uninstrument.js.map +1 -1
- package/dist/commands/lambda/functions/versionChecker.d.ts +2 -2
- package/dist/commands/lambda/instrument.d.ts +22 -20
- package/dist/commands/lambda/instrument.js +78 -69
- package/dist/commands/lambda/instrument.js.map +1 -1
- package/dist/commands/lambda/loggroup.js +8 -8
- package/dist/commands/lambda/loggroup.js.map +1 -1
- package/dist/commands/lambda/prompt.d.ts +1 -4
- package/dist/commands/lambda/prompt.js +34 -71
- package/dist/commands/lambda/prompt.js.map +1 -1
- package/dist/commands/lambda/renderers/__mocks__/instrument-uninstrument-renderer.d.ts +2 -0
- package/dist/commands/lambda/renderers/__mocks__/instrument-uninstrument-renderer.js +11 -0
- package/dist/commands/lambda/renderers/__mocks__/instrument-uninstrument-renderer.js.map +1 -0
- package/dist/commands/lambda/renderers/common-renderer.d.ts +0 -26
- package/dist/commands/lambda/renderers/common-renderer.js +4 -32
- package/dist/commands/lambda/renderers/common-renderer.js.map +1 -1
- package/dist/commands/lambda/renderers/instrument-uninstrument-renderer.d.ts +2 -2
- package/dist/commands/lambda/renderers/instrument-uninstrument-renderer.js +57 -49
- package/dist/commands/lambda/renderers/instrument-uninstrument-renderer.js.map +1 -1
- package/dist/commands/lambda/tags.js +7 -7
- package/dist/commands/lambda/tags.js.map +1 -1
- package/dist/commands/lambda/uninstrument.d.ts +25 -7
- package/dist/commands/lambda/uninstrument.js +59 -49
- package/dist/commands/lambda/uninstrument.js.map +1 -1
- package/dist/commands/metric/metric.d.ts +4 -3
- package/dist/commands/metric/metric.js +10 -9
- package/dist/commands/metric/metric.js.map +1 -1
- package/dist/commands/react-native/codepush.d.ts +11 -10
- package/dist/commands/react-native/codepush.js +17 -19
- package/dist/commands/react-native/codepush.js.map +1 -1
- package/dist/commands/react-native/interfaces.d.ts +1 -1
- package/dist/commands/react-native/renderer.js +6 -6
- package/dist/commands/react-native/renderer.js.map +1 -1
- package/dist/commands/react-native/upload.d.ts +12 -12
- package/dist/commands/react-native/upload.js +67 -45
- package/dist/commands/react-native/upload.js.map +1 -1
- package/dist/commands/react-native/utils.js +2 -1
- package/dist/commands/react-native/utils.js.map +1 -1
- package/dist/commands/react-native/validation.js +1 -1
- package/dist/commands/react-native/validation.js.map +1 -1
- package/dist/commands/react-native/xcode.d.ts +6 -6
- package/dist/commands/react-native/xcode.js +25 -29
- package/dist/commands/react-native/xcode.js.map +1 -1
- package/dist/commands/sarif/api.js +6 -22
- package/dist/commands/sarif/api.js.map +1 -1
- package/dist/commands/sarif/renderer.d.ts +1 -1
- package/dist/commands/sarif/renderer.js +1 -1
- package/dist/commands/sarif/renderer.js.map +1 -1
- package/dist/commands/sarif/upload.d.ts +6 -6
- package/dist/commands/sarif/upload.js +46 -37
- package/dist/commands/sarif/upload.js.map +1 -1
- package/dist/commands/sbom/api.d.ts +7 -0
- package/dist/commands/sbom/api.js +49 -0
- package/dist/commands/sbom/api.js.map +1 -0
- package/dist/commands/sbom/cli.d.ts +1 -0
- package/dist/commands/sbom/cli.js +5 -0
- package/dist/commands/sbom/cli.js.map +1 -0
- package/dist/commands/sbom/constants.d.ts +2 -0
- package/dist/commands/sbom/constants.js +6 -0
- package/dist/commands/sbom/constants.js.map +1 -0
- package/dist/commands/sbom/json-schema/cyclonedx/bom-1.4.schema.json +1687 -0
- package/dist/commands/sbom/json-schema/jsf/jsf-0.82.schema.json +244 -0
- package/dist/commands/sbom/json-schema/spdx/spdx.schema.json +507 -0
- package/dist/commands/sbom/protobuf/bom-1.4.d.ts +11788 -0
- package/dist/commands/sbom/protobuf/bom-1.4.js +5161 -0
- package/dist/commands/sbom/protobuf/bom-1.4.js.map +1 -0
- package/dist/commands/sbom/protobuf/custom_message.d.ts +11 -0
- package/dist/commands/sbom/protobuf/custom_message.js +3 -0
- package/dist/commands/sbom/protobuf/custom_message.js.map +1 -0
- package/dist/commands/sbom/protobuf/google/protobuf/duration.d.ts +110 -0
- package/dist/commands/sbom/protobuf/google/protobuf/duration.js +126 -0
- package/dist/commands/sbom/protobuf/google/protobuf/duration.js.map +1 -0
- package/dist/commands/sbom/protobuf/google/protobuf/timestamp.d.ts +139 -0
- package/dist/commands/sbom/protobuf/google/protobuf/timestamp.js +126 -0
- package/dist/commands/sbom/protobuf/google/protobuf/timestamp.js.map +1 -0
- package/dist/commands/sbom/protobuf/sbom_intake.d.ts +53 -0
- package/dist/commands/sbom/protobuf/sbom_intake.js +383 -0
- package/dist/commands/sbom/protobuf/sbom_intake.js.map +1 -0
- package/dist/commands/sbom/types.d.ts +4 -0
- package/dist/commands/sbom/types.js +3 -0
- package/dist/commands/sbom/types.js.map +1 -0
- package/dist/commands/sbom/upload.d.ts +16 -0
- package/dist/commands/sbom/upload.js +134 -0
- package/dist/commands/sbom/upload.js.map +1 -0
- package/dist/commands/sbom/validation.d.ts +12 -0
- package/dist/commands/sbom/validation.js +51 -0
- package/dist/commands/sbom/validation.js.map +1 -0
- package/dist/commands/sourcemaps/renderer.js +6 -6
- package/dist/commands/sourcemaps/renderer.js.map +1 -1
- package/dist/commands/sourcemaps/upload.d.ts +10 -10
- package/dist/commands/sourcemaps/upload.js +61 -38
- package/dist/commands/sourcemaps/upload.js.map +1 -1
- package/dist/commands/sourcemaps/validation.js +4 -4
- package/dist/commands/sourcemaps/validation.js.map +1 -1
- package/dist/commands/stepfunctions/awsCommands.js +10 -10
- package/dist/commands/stepfunctions/awsCommands.js.map +1 -1
- package/dist/commands/stepfunctions/helpers.d.ts +4 -4
- package/dist/commands/stepfunctions/helpers.js +4 -4
- package/dist/commands/stepfunctions/helpers.js.map +1 -1
- package/dist/commands/stepfunctions/instrument.d.ts +5 -4
- package/dist/commands/stepfunctions/instrument.js +30 -31
- package/dist/commands/stepfunctions/instrument.js.map +1 -1
- package/dist/commands/stepfunctions/uninstrument.d.ts +6 -1
- package/dist/commands/stepfunctions/uninstrument.js +23 -23
- package/dist/commands/stepfunctions/uninstrument.js.map +1 -1
- package/dist/commands/synthetics/api.d.ts +1 -1
- package/dist/commands/synthetics/api.js +11 -11
- package/dist/commands/synthetics/api.js.map +1 -1
- package/dist/commands/synthetics/errors.d.ts +3 -3
- package/dist/commands/synthetics/index.js +5 -1
- package/dist/commands/synthetics/index.js.map +1 -1
- package/dist/commands/synthetics/interfaces.d.ts +8 -7
- package/dist/commands/synthetics/interfaces.js +2 -2
- package/dist/commands/synthetics/interfaces.js.map +1 -1
- package/dist/commands/synthetics/mobile.d.ts +1 -1
- package/dist/commands/synthetics/mobile.js +26 -20
- package/dist/commands/synthetics/mobile.js.map +1 -1
- package/dist/commands/synthetics/reporters/default.d.ts +2 -2
- package/dist/commands/synthetics/reporters/default.js +17 -19
- package/dist/commands/synthetics/reporters/default.js.map +1 -1
- package/dist/commands/synthetics/reporters/junit.d.ts +2 -2
- package/dist/commands/synthetics/reporters/junit.js +11 -11
- package/dist/commands/synthetics/reporters/junit.js.map +1 -1
- package/dist/commands/synthetics/run-tests-command.d.ts +21 -19
- package/dist/commands/synthetics/run-tests-command.js +108 -42
- package/dist/commands/synthetics/run-tests-command.js.map +1 -1
- package/dist/commands/synthetics/run-tests-lib.d.ts +1 -1
- package/dist/commands/synthetics/run-tests-lib.js +16 -16
- package/dist/commands/synthetics/run-tests-lib.js.map +1 -1
- package/dist/commands/synthetics/tunnel/crypto.js +3 -3
- package/dist/commands/synthetics/tunnel/crypto.js.map +1 -1
- package/dist/commands/synthetics/tunnel/tunnel.js +11 -11
- package/dist/commands/synthetics/tunnel/tunnel.js.map +1 -1
- package/dist/commands/synthetics/tunnel/websocket.d.ts +1 -0
- package/dist/commands/synthetics/tunnel/websocket.js +7 -3
- package/dist/commands/synthetics/tunnel/websocket.js.map +1 -1
- package/dist/commands/synthetics/upload-application-command.d.ts +10 -8
- package/dist/commands/synthetics/upload-application-command.js +36 -13
- package/dist/commands/synthetics/upload-application-command.js.map +1 -1
- package/dist/commands/synthetics/utils.d.ts +12 -12
- package/dist/commands/synthetics/utils.js +52 -47
- package/dist/commands/synthetics/utils.js.map +1 -1
- package/dist/commands/tag/tag.d.ts +4 -3
- package/dist/commands/tag/tag.js +10 -9
- package/dist/commands/tag/tag.js.map +1 -1
- package/dist/commands/trace/api.js +4 -4
- package/dist/commands/trace/api.js.map +1 -1
- package/dist/commands/trace/interfaces.d.ts +1 -1
- package/dist/commands/trace/trace.d.ts +5 -4
- package/dist/commands/trace/trace.js +11 -10
- package/dist/commands/trace/trace.js.map +1 -1
- package/dist/commands/version/cli.js +6 -5
- package/dist/commands/version/cli.js.map +1 -1
- package/dist/constants.d.ts +17 -0
- package/dist/constants.js +65 -1
- package/dist/constants.js.map +1 -1
- package/dist/helpers/api.d.ts +5 -0
- package/dist/helpers/api.js +16 -0
- package/dist/helpers/api.js.map +1 -0
- package/dist/helpers/base-intake-url.d.ts +1 -1
- package/dist/helpers/ci.d.ts +13 -13
- package/dist/helpers/ci.js +17 -17
- package/dist/helpers/ci.js.map +1 -1
- package/dist/helpers/config.d.ts +5 -0
- package/dist/helpers/config.js +3 -0
- package/dist/helpers/config.js.map +1 -0
- package/dist/helpers/flare.d.ts +41 -0
- package/dist/helpers/flare.js +191 -0
- package/dist/helpers/flare.js.map +1 -0
- package/dist/helpers/fs.d.ts +31 -0
- package/dist/helpers/fs.js +117 -0
- package/dist/helpers/fs.js.map +1 -0
- package/dist/helpers/git/format-git-sourcemaps-data.js +7 -3
- package/dist/helpers/git/format-git-sourcemaps-data.js.map +1 -1
- package/dist/helpers/git/format-git-span-data.js +6 -6
- package/dist/helpers/git/format-git-span-data.js.map +1 -1
- package/dist/helpers/git/get-git-data.js +3 -3
- package/dist/helpers/git/get-git-data.js.map +1 -1
- package/dist/helpers/interfaces.d.ts +9 -3
- package/dist/helpers/logger.js +1 -1
- package/dist/helpers/logger.js.map +1 -1
- package/dist/helpers/plist.d.ts +1 -1
- package/dist/helpers/plist.js +1 -1
- package/dist/helpers/plist.js.map +1 -1
- package/dist/helpers/prompt.d.ts +7 -0
- package/dist/helpers/prompt.js +57 -0
- package/dist/helpers/prompt.js.map +1 -0
- package/dist/helpers/renderer.d.ts +60 -0
- package/dist/helpers/renderer.js +98 -0
- package/dist/helpers/renderer.js.map +1 -0
- package/dist/helpers/retry.d.ts +1 -1
- package/dist/helpers/retry.js +3 -3
- package/dist/helpers/retry.js.map +1 -1
- package/dist/helpers/tags.d.ts +8 -0
- package/dist/helpers/tags.js +27 -1
- package/dist/helpers/tags.js.map +1 -1
- package/dist/helpers/upload.js +3 -3
- package/dist/helpers/upload.js.map +1 -1
- package/dist/helpers/user-provided-git.js +6 -6
- package/dist/helpers/user-provided-git.js.map +1 -1
- package/dist/helpers/utils.d.ts +12 -5
- package/dist/helpers/utils.js +57 -25
- package/dist/helpers/utils.js.map +1 -1
- package/dist/helpers/validation.d.ts +3 -1
- package/dist/helpers/validation.js +27 -1
- package/dist/helpers/validation.js.map +1 -1
- package/dist/helpers/version.d.ts +4 -0
- package/dist/helpers/version.js +9 -0
- package/dist/helpers/version.js.map +1 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js +11 -8
- package/dist/index.js.map +1 -1
- package/package.json +28 -13
- package/dist/commands/lambda/renderers/flare-renderer.d.ts +0 -9
- package/dist/commands/lambda/renderers/flare-renderer.js +0 -22
- package/dist/commands/lambda/renderers/flare-renderer.js.map +0 -1
- package/dist/helpers/file.d.ts +0 -1
- package/dist/helpers/file.js +0 -9
- package/dist/helpers/file.js.map +0 -1
|
@@ -0,0 +1,634 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
35
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
36
|
+
};
|
|
37
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
|
+
exports.generateInsightsFile = exports.getRecentRevisions = exports.saveLogsFile = exports.getLogs = exports.summarizeConfig = exports.maskConfig = exports.getCloudRunServiceConfig = exports.checkAuthentication = exports.CloudRunFlareCommand = exports.MAX_LOGS = void 0;
|
|
39
|
+
const fs_1 = __importDefault(require("fs"));
|
|
40
|
+
const path_1 = __importDefault(require("path"));
|
|
41
|
+
const process_1 = __importDefault(require("process"));
|
|
42
|
+
const util_1 = __importDefault(require("util"));
|
|
43
|
+
const logging_1 = require("@google-cloud/logging");
|
|
44
|
+
const run_1 = require("@google-cloud/run");
|
|
45
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
46
|
+
const clipanion_1 = require("clipanion");
|
|
47
|
+
const google_auth_library_1 = require("google-auth-library");
|
|
48
|
+
const constants_1 = require("../../constants");
|
|
49
|
+
const flare_1 = require("../../helpers/flare");
|
|
50
|
+
const fs_2 = require("../../helpers/fs");
|
|
51
|
+
const prompt_1 = require("../../helpers/prompt");
|
|
52
|
+
const helpersRenderer = __importStar(require("../../helpers/renderer"));
|
|
53
|
+
const renderer_1 = require("../../helpers/renderer");
|
|
54
|
+
const utils_1 = require("../../helpers/utils");
|
|
55
|
+
const version_1 = require("../../helpers/version");
|
|
56
|
+
const flare_2 = require("../lambda/flare");
|
|
57
|
+
const constants_2 = require("./constants");
|
|
58
|
+
const renderer_2 = require("./renderer");
|
|
59
|
+
const SERVICE_CONFIG_FILE_NAME = 'service_config.json';
|
|
60
|
+
const FLARE_ZIP_FILE_NAME = 'cloud-run-flare-output.zip';
|
|
61
|
+
const ALL_LOGS_FILE_NAME = 'all_logs.csv';
|
|
62
|
+
const WARNING_LOGS_FILE_NAME = 'warning_logs.csv';
|
|
63
|
+
const ERRORS_LOGS_FILE_NAME = 'error_logs.csv';
|
|
64
|
+
const DEBUG_LOGS_FILE_NAME = 'debug_logs.csv';
|
|
65
|
+
// What's the maximum number of revisions we want to include? Too many revisions will flood the INSIGHTS.md file
|
|
66
|
+
const MAX_REVISIONS = 10;
|
|
67
|
+
// Must be in range 0 - 1000. If more logs are needed, pagination must be implemented
|
|
68
|
+
exports.MAX_LOGS = 1000;
|
|
69
|
+
// How old the logs can be in minutes. Skip older logs
|
|
70
|
+
const MAX_LOG_AGE_MINUTES = 1440;
|
|
71
|
+
const FILTER_ORDER = 'timestamp asc';
|
|
72
|
+
// Types of log files to create
|
|
73
|
+
const LOG_CONFIGS = [
|
|
74
|
+
{ type: 'total', fileName: ALL_LOGS_FILE_NAME },
|
|
75
|
+
{ type: 'warning', severityFilter: ' AND severity>="WARNING"', fileName: WARNING_LOGS_FILE_NAME },
|
|
76
|
+
{ type: 'error', severityFilter: ' AND severity>="ERROR"', fileName: ERRORS_LOGS_FILE_NAME },
|
|
77
|
+
{ type: 'debug', severityFilter: ' AND severity="DEBUG"', fileName: DEBUG_LOGS_FILE_NAME },
|
|
78
|
+
];
|
|
79
|
+
class CloudRunFlareCommand extends clipanion_1.Command {
|
|
80
|
+
constructor() {
|
|
81
|
+
super(...arguments);
|
|
82
|
+
this.isDryRun = clipanion_1.Option.Boolean('-d,--dry,--dry-run', false);
|
|
83
|
+
this.withLogs = clipanion_1.Option.Boolean('--with-logs', false);
|
|
84
|
+
this.service = clipanion_1.Option.String('-s,--service');
|
|
85
|
+
this.project = clipanion_1.Option.String('-p,--project');
|
|
86
|
+
this.region = clipanion_1.Option.String('-r,--region,-l,--location');
|
|
87
|
+
this.caseId = clipanion_1.Option.String('-c,--case-id');
|
|
88
|
+
this.email = clipanion_1.Option.String('-e,--email');
|
|
89
|
+
this.start = clipanion_1.Option.String('--start');
|
|
90
|
+
this.end = clipanion_1.Option.String('--end');
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Entry point for the `cloud-run flare` command.
|
|
94
|
+
* Gathers Cloud Run service configuration and sends it to Datadog.
|
|
95
|
+
* @returns 0 if the command ran successfully, 1 otherwise.
|
|
96
|
+
*/
|
|
97
|
+
execute() {
|
|
98
|
+
var _a;
|
|
99
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
100
|
+
this.context.stdout.write(helpersRenderer.renderFlareHeader('Cloud Run', this.isDryRun));
|
|
101
|
+
const errorMessages = [];
|
|
102
|
+
// Validate service
|
|
103
|
+
if (this.service === undefined) {
|
|
104
|
+
errorMessages.push(helpersRenderer.renderError('No service specified. [-s,--service]'));
|
|
105
|
+
}
|
|
106
|
+
// Validate project
|
|
107
|
+
if (this.project === undefined) {
|
|
108
|
+
errorMessages.push(helpersRenderer.renderError('No project specified. [-p,--project]'));
|
|
109
|
+
}
|
|
110
|
+
// Validate region
|
|
111
|
+
if (this.region === undefined) {
|
|
112
|
+
errorMessages.push(helpersRenderer.renderError('No region specified. [-r,--region]'));
|
|
113
|
+
}
|
|
114
|
+
// Validate Datadog API key
|
|
115
|
+
this.apiKey = (_a = process_1.default.env[constants_1.CI_API_KEY_ENV_VAR]) !== null && _a !== void 0 ? _a : process_1.default.env[constants_1.API_KEY_ENV_VAR];
|
|
116
|
+
if (this.apiKey === undefined) {
|
|
117
|
+
errorMessages.push(helpersRenderer.renderError('No Datadog API key specified. Set an API key with the DATADOG_API_KEY environment variable.'));
|
|
118
|
+
}
|
|
119
|
+
// Validate case ID
|
|
120
|
+
if (this.caseId === undefined) {
|
|
121
|
+
errorMessages.push(helpersRenderer.renderError('No case ID specified. [-c,--case-id]'));
|
|
122
|
+
}
|
|
123
|
+
// Validate email
|
|
124
|
+
if (this.email === undefined) {
|
|
125
|
+
errorMessages.push(helpersRenderer.renderError('No email specified. [-e,--email]'));
|
|
126
|
+
}
|
|
127
|
+
// Validate start/end flags if both are specified
|
|
128
|
+
let startMillis;
|
|
129
|
+
let endMillis;
|
|
130
|
+
try {
|
|
131
|
+
;
|
|
132
|
+
[startMillis, endMillis] = (0, flare_1.validateStartEndFlags)(this.start, this.end);
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
if (err instanceof Error) {
|
|
136
|
+
errorMessages.push(helpersRenderer.renderError(err.message));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
// If there are errors, print them and exit
|
|
140
|
+
if (errorMessages.length > 0) {
|
|
141
|
+
for (const message of errorMessages) {
|
|
142
|
+
this.context.stderr.write(message);
|
|
143
|
+
}
|
|
144
|
+
return 1;
|
|
145
|
+
}
|
|
146
|
+
// Verify GCP credentials
|
|
147
|
+
this.context.stdout.write(chalk_1.default.bold('\n🔑 Verifying GCP credentials...\n'));
|
|
148
|
+
const authenticated = yield (0, exports.checkAuthentication)();
|
|
149
|
+
if (!authenticated) {
|
|
150
|
+
this.context.stderr.write((0, renderer_2.renderAuthenticationInstructions)());
|
|
151
|
+
return 1;
|
|
152
|
+
}
|
|
153
|
+
this.context.stdout.write('GCP credentials verified!\n');
|
|
154
|
+
// Get and print service configuration
|
|
155
|
+
this.context.stdout.write(chalk_1.default.bold('\n🔍 Fetching service configuration...\n'));
|
|
156
|
+
const runClient = new run_1.ServicesClient();
|
|
157
|
+
let config;
|
|
158
|
+
try {
|
|
159
|
+
config = yield (0, exports.getCloudRunServiceConfig)(runClient, this.service, this.project, this.region);
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
if (err instanceof Error) {
|
|
163
|
+
this.context.stderr.write(helpersRenderer.renderError(`Unable to fetch service configuration: ${err.message}`));
|
|
164
|
+
}
|
|
165
|
+
return 1;
|
|
166
|
+
}
|
|
167
|
+
config = (0, exports.maskConfig)(config);
|
|
168
|
+
const summarizedConfig = (0, exports.summarizeConfig)(config);
|
|
169
|
+
// 10 is the depth when inspecting the config file. Cloud-run configs have high depth, so
|
|
170
|
+
// we must raise the depth from the default depth of 2.
|
|
171
|
+
const summarizedConfigStr = util_1.default.inspect(summarizedConfig, false, 10, true);
|
|
172
|
+
this.context.stdout.write(`\n${summarizedConfigStr}\n`);
|
|
173
|
+
this.context.stdout.write(chalk_1.default.italic(`(This is a summary of the configuration. The full configuration will be saved in "${SERVICE_CONFIG_FILE_NAME}".)\n`));
|
|
174
|
+
// Get project files
|
|
175
|
+
this.context.stdout.write(chalk_1.default.bold('\n📁 Searching for project files in current directory...\n'));
|
|
176
|
+
const projectFilePaths = yield (0, flare_1.getProjectFiles)(constants_1.FLARE_PROJECT_FILES);
|
|
177
|
+
this.context.stdout.write((0, renderer_1.renderProjectFiles)(projectFilePaths));
|
|
178
|
+
// Additional files
|
|
179
|
+
this.context.stdout.write('\n');
|
|
180
|
+
const additionalFilePaths = new Set();
|
|
181
|
+
let confirmAdditionalFiles;
|
|
182
|
+
try {
|
|
183
|
+
confirmAdditionalFiles = yield (0, prompt_1.requestConfirmation)('Do you want to specify any additional files to flare?', false);
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
if (err instanceof Error) {
|
|
187
|
+
this.context.stderr.write(helpersRenderer.renderError(err.message));
|
|
188
|
+
}
|
|
189
|
+
return 1;
|
|
190
|
+
}
|
|
191
|
+
while (confirmAdditionalFiles) {
|
|
192
|
+
this.context.stdout.write('\n');
|
|
193
|
+
let filePath;
|
|
194
|
+
try {
|
|
195
|
+
filePath = yield (0, prompt_1.requestFilePath)();
|
|
196
|
+
}
|
|
197
|
+
catch (err) {
|
|
198
|
+
if (err instanceof Error) {
|
|
199
|
+
this.context.stderr.write(helpersRenderer.renderError(err.message));
|
|
200
|
+
}
|
|
201
|
+
return 1;
|
|
202
|
+
}
|
|
203
|
+
if (filePath === '') {
|
|
204
|
+
this.context.stdout.write((0, renderer_1.renderAdditionalFiles)(additionalFilePaths));
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
try {
|
|
208
|
+
filePath = (0, flare_1.validateFilePath)(filePath, projectFilePaths, additionalFilePaths);
|
|
209
|
+
additionalFilePaths.add(filePath);
|
|
210
|
+
const fileName = path_1.default.basename(filePath);
|
|
211
|
+
this.context.stdout.write(`• Added file '${fileName}'\n`);
|
|
212
|
+
}
|
|
213
|
+
catch (err) {
|
|
214
|
+
if (err instanceof Error) {
|
|
215
|
+
this.context.stderr.write(err.message);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// Get recent revisions, which will be used to generate insights file
|
|
220
|
+
this.context.stdout.write(chalk_1.default.bold('\n🌧 Fetching recent revisions...\n'));
|
|
221
|
+
let revisions = [];
|
|
222
|
+
try {
|
|
223
|
+
revisions = yield (0, exports.getRecentRevisions)(this.service, this.region, this.project);
|
|
224
|
+
this.context.stdout.write(`• Found ${revisions.length} revisions\n`);
|
|
225
|
+
}
|
|
226
|
+
catch (err) {
|
|
227
|
+
const errorDetails = err instanceof Error ? err.message : '';
|
|
228
|
+
this.context.stdout.write(helpersRenderer.renderSoftWarning(`Unable to fetch recent revisions. ${errorDetails}`));
|
|
229
|
+
}
|
|
230
|
+
// Get logs
|
|
231
|
+
const logFileMappings = new Map();
|
|
232
|
+
if (this.withLogs) {
|
|
233
|
+
this.context.stdout.write(chalk_1.default.bold('\n📖 Getting logs...\n'));
|
|
234
|
+
const logClient = new logging_1.Logging({ projectId: this.project });
|
|
235
|
+
for (const logConfig of LOG_CONFIGS) {
|
|
236
|
+
try {
|
|
237
|
+
const logs = yield (0, exports.getLogs)(logClient, this.service, this.region, startMillis, endMillis, logConfig.severityFilter);
|
|
238
|
+
if (logs.length === 0) {
|
|
239
|
+
this.context.stdout.write(`• No ${logConfig.type} logs were found\n`);
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
this.context.stdout.write(`• Found ${logs.length} ${logConfig.type} logs\n`);
|
|
243
|
+
logFileMappings.set(logConfig.fileName, logs);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
catch (err) {
|
|
247
|
+
const msg = err instanceof Error ? err.message : '';
|
|
248
|
+
this.context.stderr.write(`• Unable to get ${logConfig.type} logs: ${msg}\n`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
try {
|
|
253
|
+
// Create folders
|
|
254
|
+
const rootFolderPath = path_1.default.join(process_1.default.cwd(), constants_1.FLARE_OUTPUT_DIRECTORY);
|
|
255
|
+
const logsFolderPath = path_1.default.join(rootFolderPath, constants_1.LOGS_DIRECTORY);
|
|
256
|
+
const projectFilesFolderPath = path_1.default.join(rootFolderPath, constants_1.PROJECT_FILES_DIRECTORY);
|
|
257
|
+
const additionalFilesFolderPath = path_1.default.join(rootFolderPath, constants_1.ADDITIONAL_FILES_DIRECTORY);
|
|
258
|
+
this.context.stdout.write(chalk_1.default.bold(`\n💾 Saving files to ${rootFolderPath}...\n`));
|
|
259
|
+
if (fs_1.default.existsSync(rootFolderPath)) {
|
|
260
|
+
(0, fs_2.deleteFolder)(rootFolderPath);
|
|
261
|
+
}
|
|
262
|
+
const subFolders = [];
|
|
263
|
+
if (logFileMappings.size > 0) {
|
|
264
|
+
subFolders.push(logsFolderPath);
|
|
265
|
+
}
|
|
266
|
+
if (projectFilePaths.size > 0) {
|
|
267
|
+
subFolders.push(projectFilesFolderPath);
|
|
268
|
+
}
|
|
269
|
+
if (additionalFilePaths.size > 0) {
|
|
270
|
+
subFolders.push(additionalFilesFolderPath);
|
|
271
|
+
}
|
|
272
|
+
(0, fs_2.createDirectories)(rootFolderPath, subFolders);
|
|
273
|
+
// Write config file
|
|
274
|
+
const configFilePath = path_1.default.join(rootFolderPath, SERVICE_CONFIG_FILE_NAME);
|
|
275
|
+
(0, fs_2.writeFile)(configFilePath, JSON.stringify(config, undefined, 2));
|
|
276
|
+
this.context.stdout.write(`• Saved function config to ./${SERVICE_CONFIG_FILE_NAME}\n`);
|
|
277
|
+
// Write logs
|
|
278
|
+
for (const [fileName, logs] of logFileMappings) {
|
|
279
|
+
const logFilePath = path_1.default.join(logsFolderPath, fileName);
|
|
280
|
+
(0, exports.saveLogsFile)(logs, logFilePath);
|
|
281
|
+
this.context.stdout.write(`• Saved logs to ./${constants_1.LOGS_DIRECTORY}/${fileName}\n`);
|
|
282
|
+
}
|
|
283
|
+
// Write project files
|
|
284
|
+
for (const filePath of projectFilePaths) {
|
|
285
|
+
const fileName = path_1.default.basename(filePath);
|
|
286
|
+
const newFilePath = path_1.default.join(projectFilesFolderPath, fileName);
|
|
287
|
+
fs_1.default.copyFileSync(filePath, newFilePath);
|
|
288
|
+
this.context.stdout.write(`• Copied ${fileName} to ./${constants_1.PROJECT_FILES_DIRECTORY}/${fileName}\n`);
|
|
289
|
+
}
|
|
290
|
+
// Write additional files
|
|
291
|
+
const additionalFilesMap = (0, flare_2.getUniqueFileNames)(additionalFilePaths);
|
|
292
|
+
for (const [originalFilePath, newFileName] of additionalFilesMap) {
|
|
293
|
+
const originalFileName = path_1.default.basename(originalFilePath);
|
|
294
|
+
const newFilePath = path_1.default.join(additionalFilesFolderPath, newFileName);
|
|
295
|
+
fs_1.default.copyFileSync(originalFilePath, newFilePath);
|
|
296
|
+
this.context.stdout.write(`• Copied ${originalFileName} to ./${constants_1.ADDITIONAL_FILES_DIRECTORY}/${newFileName}\n`);
|
|
297
|
+
}
|
|
298
|
+
// Write insights file
|
|
299
|
+
try {
|
|
300
|
+
const insightsFilePath = path_1.default.join(rootFolderPath, constants_1.INSIGHTS_FILE_NAME);
|
|
301
|
+
(0, exports.generateInsightsFile)(insightsFilePath, this.isDryRun, config, this.service, this.region, this.project, revisions);
|
|
302
|
+
this.context.stdout.write(`• Saved insights file to ./${constants_1.INSIGHTS_FILE_NAME}\n`);
|
|
303
|
+
}
|
|
304
|
+
catch (err) {
|
|
305
|
+
const errorDetails = err instanceof Error ? err.message : '';
|
|
306
|
+
this.context.stdout.write(helpersRenderer.renderSoftWarning(`Unable to create INSIGHTS.md file. ${errorDetails}`));
|
|
307
|
+
}
|
|
308
|
+
// Exit if dry run
|
|
309
|
+
const outputMsg = `\nℹ️ Your output files are located at: ${rootFolderPath}\n\n`;
|
|
310
|
+
if (this.isDryRun) {
|
|
311
|
+
this.context.stdout.write('\n🚫 The flare files were not sent because the command was executed in dry run mode.');
|
|
312
|
+
this.context.stdout.write(outputMsg);
|
|
313
|
+
return 0;
|
|
314
|
+
}
|
|
315
|
+
// Confirm before sending
|
|
316
|
+
this.context.stdout.write('\n');
|
|
317
|
+
const confirmSendFiles = yield (0, prompt_1.requestConfirmation)('Are you sure you want to send the flare file to Datadog Support?', false);
|
|
318
|
+
if (!confirmSendFiles) {
|
|
319
|
+
this.context.stdout.write('\n🚫 The flare files were not sent based on your selection.');
|
|
320
|
+
this.context.stdout.write(outputMsg);
|
|
321
|
+
return 0;
|
|
322
|
+
}
|
|
323
|
+
// Zip folder
|
|
324
|
+
const zipPath = path_1.default.join(rootFolderPath, FLARE_ZIP_FILE_NAME);
|
|
325
|
+
yield (0, fs_2.zipContents)(rootFolderPath, zipPath);
|
|
326
|
+
// Send to Datadog
|
|
327
|
+
this.context.stdout.write(chalk_1.default.bold('\n🚀 Sending to Datadog Support...\n'));
|
|
328
|
+
yield (0, flare_1.sendToDatadog)(zipPath, this.caseId, this.email, this.apiKey, rootFolderPath);
|
|
329
|
+
this.context.stdout.write(chalk_1.default.bold('\n✅ Successfully sent flare file to Datadog Support!\n'));
|
|
330
|
+
// Delete contents
|
|
331
|
+
(0, fs_2.deleteFolder)(rootFolderPath);
|
|
332
|
+
}
|
|
333
|
+
catch (err) {
|
|
334
|
+
if (err instanceof Error) {
|
|
335
|
+
this.context.stderr.write(helpersRenderer.renderError(err.message));
|
|
336
|
+
}
|
|
337
|
+
return 1;
|
|
338
|
+
}
|
|
339
|
+
return 0;
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
exports.CloudRunFlareCommand = CloudRunFlareCommand;
|
|
344
|
+
CloudRunFlareCommand.paths = [['cloud-run', 'flare']];
|
|
345
|
+
CloudRunFlareCommand.usage = clipanion_1.Command.Usage({
|
|
346
|
+
category: 'Serverless',
|
|
347
|
+
description: 'Gather Cloud Run service configuration and sends it to Datadog.',
|
|
348
|
+
});
|
|
349
|
+
/**
|
|
350
|
+
* Check if the user is authenticated with GCP.
|
|
351
|
+
* @returns true if the user is authenticated, false otherwise
|
|
352
|
+
*/
|
|
353
|
+
const checkAuthentication = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
354
|
+
const auth = new google_auth_library_1.GoogleAuth();
|
|
355
|
+
try {
|
|
356
|
+
yield auth.getApplicationDefault();
|
|
357
|
+
return true;
|
|
358
|
+
}
|
|
359
|
+
catch (_) {
|
|
360
|
+
return false;
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
exports.checkAuthentication = checkAuthentication;
|
|
364
|
+
/**
|
|
365
|
+
* Call the google-cloud run sdk to get the configuration
|
|
366
|
+
* for the given service.
|
|
367
|
+
* @param runClient the google-cloud run sdk client
|
|
368
|
+
* @param serviceName the name of the service
|
|
369
|
+
* @param projectName the project where the service is deployed
|
|
370
|
+
* @param region the region where the service is deployed
|
|
371
|
+
* @returns the configuration for the given service
|
|
372
|
+
*/
|
|
373
|
+
const getCloudRunServiceConfig = (runClient, serviceName, projectName, region) => __awaiter(void 0, void 0, void 0, function* () {
|
|
374
|
+
const request = {
|
|
375
|
+
name: runClient.servicePath(projectName, region, serviceName),
|
|
376
|
+
};
|
|
377
|
+
const [response] = yield runClient.getService(request);
|
|
378
|
+
return response;
|
|
379
|
+
});
|
|
380
|
+
exports.getCloudRunServiceConfig = getCloudRunServiceConfig;
|
|
381
|
+
/**
|
|
382
|
+
* Masks environment variables in a Cloud Run service configuration.
|
|
383
|
+
* Makes a copy as to not modify the config in place.
|
|
384
|
+
* @param config
|
|
385
|
+
* @returns masked config
|
|
386
|
+
*/
|
|
387
|
+
const maskConfig = (config) => {
|
|
388
|
+
var _a, _b;
|
|
389
|
+
// We stringify and parse again to make a deep copy
|
|
390
|
+
const configCopy = JSON.parse(JSON.stringify(config));
|
|
391
|
+
const containers = (_a = configCopy.template) === null || _a === void 0 ? void 0 : _a.containers;
|
|
392
|
+
if (!containers) {
|
|
393
|
+
return configCopy;
|
|
394
|
+
}
|
|
395
|
+
for (const container of containers) {
|
|
396
|
+
const env = (_b = container.env) !== null && _b !== void 0 ? _b : [];
|
|
397
|
+
for (const envVar of env) {
|
|
398
|
+
const name = envVar.name;
|
|
399
|
+
const val = envVar.value;
|
|
400
|
+
if (!name || !val) {
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
if (!constants_2.SKIP_MASKING_CLOUDRUN_ENV_VARS.has(name)) {
|
|
404
|
+
envVar.value = (0, utils_1.maskString)(val);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
return configCopy;
|
|
409
|
+
};
|
|
410
|
+
exports.maskConfig = maskConfig;
|
|
411
|
+
/**
|
|
412
|
+
* Summarizes the Cloud Run config as to not flood the terminal
|
|
413
|
+
* @param config
|
|
414
|
+
* @returns a summarized config
|
|
415
|
+
*/
|
|
416
|
+
const summarizeConfig = (config) => {
|
|
417
|
+
var _a;
|
|
418
|
+
const summarizedConfig = {};
|
|
419
|
+
summarizedConfig.name = config.name;
|
|
420
|
+
summarizedConfig.uid = config.uid;
|
|
421
|
+
summarizedConfig.uri = config.uri;
|
|
422
|
+
// Get env vars and image for each containers
|
|
423
|
+
const template = config.template;
|
|
424
|
+
if (template) {
|
|
425
|
+
const summarizedContainers = [];
|
|
426
|
+
const containers = (_a = template.containers) !== null && _a !== void 0 ? _a : [];
|
|
427
|
+
containers.forEach((container) => {
|
|
428
|
+
const summarizedContainer = {};
|
|
429
|
+
summarizedContainer.env = container.env;
|
|
430
|
+
summarizedContainer.image = container.image;
|
|
431
|
+
summarizedContainers.push(summarizedContainer);
|
|
432
|
+
});
|
|
433
|
+
summarizedConfig.containers = summarizedContainers;
|
|
434
|
+
}
|
|
435
|
+
return summarizedConfig;
|
|
436
|
+
};
|
|
437
|
+
exports.summarizeConfig = summarizeConfig;
|
|
438
|
+
/**
|
|
439
|
+
* Gets recent logs
|
|
440
|
+
* @param logClient Logging client
|
|
441
|
+
* @param serviceId
|
|
442
|
+
* @param location
|
|
443
|
+
* @param startMillis start time in milliseconds or undefined if no start time is specified
|
|
444
|
+
* @param endMillis end time in milliseconds or undefined if no end time is specified
|
|
445
|
+
* @param severityFilter if included, adds the string to the filter
|
|
446
|
+
* @returns array of logs as CloudRunLog interfaces
|
|
447
|
+
*/
|
|
448
|
+
const getLogs = (logClient, serviceId, location, startMillis, endMillis, severityFilter) => __awaiter(void 0, void 0, void 0, function* () {
|
|
449
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
450
|
+
const logs = [];
|
|
451
|
+
// Default to the recent logs using MAX_LOG_AGE_MINUTES
|
|
452
|
+
const date = new Date();
|
|
453
|
+
date.setMinutes(date.getMinutes() - MAX_LOG_AGE_MINUTES);
|
|
454
|
+
let startDate = date.toISOString();
|
|
455
|
+
let endDate = new Date().toISOString(); // Current time
|
|
456
|
+
// If startMillis and endMillis are provided, use them to set the date range
|
|
457
|
+
if (startMillis && endMillis) {
|
|
458
|
+
startDate = new Date(startMillis).toISOString();
|
|
459
|
+
endDate = new Date(endMillis).toISOString();
|
|
460
|
+
}
|
|
461
|
+
// Query options
|
|
462
|
+
let filter = `resource.labels.service_name="${serviceId}" AND resource.labels.location="${location}" AND timestamp>="${startDate}" AND timestamp<="${endDate}" AND (textPayload:* OR httpRequest:*)`;
|
|
463
|
+
// We only want to include logs with a textPayload or logs that were an HTTP request.
|
|
464
|
+
// Any other logs are just audit logs which are spammy and don't have any relevant information.
|
|
465
|
+
filter += severityFilter !== null && severityFilter !== void 0 ? severityFilter : '';
|
|
466
|
+
const options = {
|
|
467
|
+
filter,
|
|
468
|
+
orderBy: FILTER_ORDER,
|
|
469
|
+
pageSize: exports.MAX_LOGS,
|
|
470
|
+
};
|
|
471
|
+
const [entries] = yield logClient.getEntries(options);
|
|
472
|
+
for (const entry of entries) {
|
|
473
|
+
let msg = '';
|
|
474
|
+
if (entry.metadata.textPayload) {
|
|
475
|
+
msg = entry.metadata.textPayload;
|
|
476
|
+
}
|
|
477
|
+
if (entry.metadata.httpRequest) {
|
|
478
|
+
const request = entry.metadata.httpRequest;
|
|
479
|
+
const status = (_a = request.status) !== null && _a !== void 0 ? _a : '';
|
|
480
|
+
let ms = 'unknown';
|
|
481
|
+
const latency = request.latency;
|
|
482
|
+
if (latency) {
|
|
483
|
+
ms = (Number(latency.seconds) * 1000 + Math.round(Number(latency.nanos) / 1000000)).toString();
|
|
484
|
+
}
|
|
485
|
+
const bytes = (0, utils_1.formatBytes)(Number(request.responseSize));
|
|
486
|
+
const method = (_b = request.requestMethod) !== null && _b !== void 0 ? _b : '';
|
|
487
|
+
const requestUrl = (_c = request.requestUrl) !== null && _c !== void 0 ? _c : '';
|
|
488
|
+
msg += `${method} ${status}. responseSize: ${bytes}. latency: ${ms} ms. requestUrl: ${requestUrl}`;
|
|
489
|
+
}
|
|
490
|
+
const log = {
|
|
491
|
+
severity: (_e = (_d = entry.metadata.severity) === null || _d === void 0 ? void 0 : _d.toString()) !== null && _e !== void 0 ? _e : '',
|
|
492
|
+
timestamp: (_g = (_f = entry.metadata.timestamp) === null || _f === void 0 ? void 0 : _f.toString()) !== null && _g !== void 0 ? _g : '',
|
|
493
|
+
logName: (_h = entry.metadata.logName) !== null && _h !== void 0 ? _h : '',
|
|
494
|
+
message: `"${msg}"`,
|
|
495
|
+
};
|
|
496
|
+
logs.push(log);
|
|
497
|
+
}
|
|
498
|
+
return logs;
|
|
499
|
+
});
|
|
500
|
+
exports.getLogs = getLogs;
|
|
501
|
+
/**
|
|
502
|
+
* Save logs in a CSV format
|
|
503
|
+
* @param logs array of logs stored as CloudRunLog interfaces
|
|
504
|
+
* @param filePath path to save the CSV file
|
|
505
|
+
*/
|
|
506
|
+
const saveLogsFile = (logs, filePath) => {
|
|
507
|
+
const rows = [['severity', 'timestamp', 'logName', 'message']];
|
|
508
|
+
logs.forEach((log) => {
|
|
509
|
+
const severity = `"${log.severity}"`;
|
|
510
|
+
const timestamp = `"${log.timestamp}"`;
|
|
511
|
+
const logName = `"${log.logName}"`;
|
|
512
|
+
const logMessage = `"${log.message}"`;
|
|
513
|
+
rows.push([severity, timestamp, logName, logMessage]);
|
|
514
|
+
});
|
|
515
|
+
const data = rows.join('\n');
|
|
516
|
+
(0, fs_2.writeFile)(filePath, data);
|
|
517
|
+
};
|
|
518
|
+
exports.saveLogsFile = saveLogsFile;
|
|
519
|
+
/**
|
|
520
|
+
* Gets recent revisions for a cloud-run service
|
|
521
|
+
* @param service
|
|
522
|
+
* @param location
|
|
523
|
+
* @param project
|
|
524
|
+
* @returns a string array of recent revisions and their deployment timestamp
|
|
525
|
+
*/
|
|
526
|
+
const getRecentRevisions = (service, location, project) => __awaiter(void 0, void 0, void 0, function* () {
|
|
527
|
+
var _j;
|
|
528
|
+
const client = new run_1.RevisionsClient();
|
|
529
|
+
const request = {
|
|
530
|
+
parent: client.servicePath(project, location, service),
|
|
531
|
+
};
|
|
532
|
+
// listRevisions() returns a tuple [Revision[], Request, Response],
|
|
533
|
+
// so we index the first element to get the array of revisions
|
|
534
|
+
const revisions = (yield client.listRevisions(request))[0];
|
|
535
|
+
const revisionTimestampStrings = [];
|
|
536
|
+
let counter = 1;
|
|
537
|
+
for (const entry of revisions) {
|
|
538
|
+
const fullName = entry.name;
|
|
539
|
+
const timestamp = entry.createTime;
|
|
540
|
+
if (fullName && timestamp) {
|
|
541
|
+
// Get the revision name
|
|
542
|
+
const nameSplit = fullName.split('/');
|
|
543
|
+
const revisionName = nameSplit[nameSplit.length - 1];
|
|
544
|
+
// Format the timestamp by first converting seconds/nanos to milliseconds, then using `new Date()`
|
|
545
|
+
const milliseconds = Number((_j = timestamp.seconds) !== null && _j !== void 0 ? _j : 0) * 1000;
|
|
546
|
+
const timestampString = new Date(milliseconds).toISOString().replace('T', ' ').replace('Z', '').slice(0, -4); // Chop off the milliseconds, which will always be .000
|
|
547
|
+
revisionTimestampStrings.push(`\`${revisionName}\` Deployed on ${timestampString}`);
|
|
548
|
+
}
|
|
549
|
+
// Stop iterating once we reach MAX_REVISIONS
|
|
550
|
+
counter += 1;
|
|
551
|
+
if (counter > MAX_REVISIONS) {
|
|
552
|
+
break;
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
return revisionTimestampStrings;
|
|
556
|
+
});
|
|
557
|
+
exports.getRecentRevisions = getRecentRevisions;
|
|
558
|
+
/**
|
|
559
|
+
* Generate the insights file
|
|
560
|
+
* @param insightsFilePath path to the insights file
|
|
561
|
+
* @param isDryRun whether or not this is a dry run
|
|
562
|
+
* @param config Cloud run service configuration
|
|
563
|
+
* @param service
|
|
564
|
+
* @param location
|
|
565
|
+
* @param project
|
|
566
|
+
* @param revisions a string array of recent revisions
|
|
567
|
+
*/
|
|
568
|
+
const generateInsightsFile = (insightsFilePath, isDryRun, config, service, location, project, revisions) => {
|
|
569
|
+
var _a, _b, _c, _d, _e, _f;
|
|
570
|
+
const lines = [];
|
|
571
|
+
// Header
|
|
572
|
+
lines.push('# Flare Insights');
|
|
573
|
+
lines.push('\n_Autogenerated file from `cloud-run flare`_ ');
|
|
574
|
+
if (isDryRun) {
|
|
575
|
+
lines.push('_This command was run in dry mode._');
|
|
576
|
+
}
|
|
577
|
+
// Cloud Run Service Configuration
|
|
578
|
+
lines.push('\n## Cloud Run Service Configuration');
|
|
579
|
+
lines.push(`**Service Name**: \`${service}\` `);
|
|
580
|
+
lines.push(`**Location**: \`${location}\` `);
|
|
581
|
+
lines.push(`**Project**: \`${project}\` `);
|
|
582
|
+
const description = config.description;
|
|
583
|
+
if (description && description.length > 0) {
|
|
584
|
+
lines.push(`**Description**: \`${description}\` `);
|
|
585
|
+
}
|
|
586
|
+
lines.push(`**URI**: \`${(_a = config.uri) !== null && _a !== void 0 ? _a : ''}\``);
|
|
587
|
+
// Environment variables
|
|
588
|
+
const containers = (_c = (_b = config.template) === null || _b === void 0 ? void 0 : _b.containers) !== null && _c !== void 0 ? _c : [];
|
|
589
|
+
for (const container of containers) {
|
|
590
|
+
// We want to separate environment variables by container if there are multiple containers
|
|
591
|
+
// We can use the container image to uniquely identify each container
|
|
592
|
+
lines.push(`\n**Environment Variables** (${(_d = container.image) !== null && _d !== void 0 ? _d : 'unknown image'}):`);
|
|
593
|
+
const envVars = new Map();
|
|
594
|
+
for (const envVar of (_e = container.env) !== null && _e !== void 0 ? _e : []) {
|
|
595
|
+
const name = envVar.name;
|
|
596
|
+
const value = envVar.value;
|
|
597
|
+
if (name && value) {
|
|
598
|
+
envVars.set(name, value);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
if (envVars.size === 0) {
|
|
602
|
+
lines.push('- No environment variables found.');
|
|
603
|
+
}
|
|
604
|
+
for (const [key, value] of envVars) {
|
|
605
|
+
lines.push(`- \`${key}\`: \`${value}\``);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
// Labels
|
|
609
|
+
lines.push('\n**Labels**:');
|
|
610
|
+
const labels = (_f = config.labels) !== null && _f !== void 0 ? _f : {};
|
|
611
|
+
const entries = Object.entries(labels);
|
|
612
|
+
if (entries.length === 0) {
|
|
613
|
+
lines.push('- No labels found.');
|
|
614
|
+
}
|
|
615
|
+
for (const [key, value] of entries) {
|
|
616
|
+
lines.push(`- \`${key}\`: \`${value}\``);
|
|
617
|
+
}
|
|
618
|
+
// Recent revisions
|
|
619
|
+
if (revisions.length > 0) {
|
|
620
|
+
lines.push('\n**Recent Revisions**:');
|
|
621
|
+
for (const revision of revisions) {
|
|
622
|
+
lines.push(`- ${revision}`);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
// CLI Insights
|
|
626
|
+
lines.push('\n ## CLI');
|
|
627
|
+
lines.push(`**Run Location**: \`${process_1.default.cwd()}\` `);
|
|
628
|
+
lines.push(`**CLI Version**: \`${version_1.version}\` `);
|
|
629
|
+
const timeString = new Date().toISOString().replace('T', ' ').replace('Z', '') + ' UTC';
|
|
630
|
+
lines.push(`**Timestamp**: \`${timeString}\` `);
|
|
631
|
+
(0, fs_2.writeFile)(insightsFilePath, lines.join('\n'));
|
|
632
|
+
};
|
|
633
|
+
exports.generateInsightsFile = generateInsightsFile;
|
|
634
|
+
//# sourceMappingURL=flare.js.map
|