[APM] Add ad-hoc profiling to requests (#143169)

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Dario Gieselaar 2022-10-20 13:57:47 +02:00 committed by GitHub
parent eaf4e5ca2e
commit c3db6614f6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 398 additions and 14 deletions

2
.github/CODEOWNERS vendored
View file

@ -143,6 +143,7 @@ x-pack/examples/files_example @elastic/kibana-app-services
/src/core/types/elasticsearch @elastic/apm-ui
/packages/kbn-utility-types/src/dot.ts @dgieselaar
/packages/kbn-utility-types/src/dot_test.ts @dgieselaar
/packages/kbn-adhoc-profiler @elastic/apm-ui
#CC# /src/plugins/apm_oss/ @elastic/apm-ui
#CC# /x-pack/plugins/observability/ @elastic/apm-ui
@ -855,6 +856,7 @@ packages/home/sample_data_card @elastic/shared-ux
packages/home/sample_data_tab @elastic/shared-ux
packages/home/sample_data_types @elastic/shared-ux
packages/kbn-ace @elastic/platform-deployment-management
packages/kbn-adhoc-profiler @elastic/apm-ui
packages/kbn-alerts @elastic/security-solution
packages/kbn-ambient-storybook-types @elastic/kibana-operations
packages/kbn-ambient-ui-types @elastic/kibana-operations

View file

@ -131,6 +131,7 @@
"@hapi/inert": "^6.0.4",
"@hapi/wreck": "^17.1.0",
"@kbn/ace": "link:bazel-bin/packages/kbn-ace",
"@kbn/adhoc-profiler": "link:bazel-bin/packages/kbn-adhoc-profiler",
"@kbn/aiops-components": "link:bazel-bin/x-pack/packages/ml/aiops_components",
"@kbn/aiops-utils": "link:bazel-bin/x-pack/packages/ml/aiops_utils",
"@kbn/alerts": "link:bazel-bin/packages/kbn-alerts",
@ -574,6 +575,7 @@
"peggy": "^1.2.0",
"pluralize": "3.1.0",
"polished": "^3.7.2",
"pprof": "^3.2.0",
"pretty-ms": "6.0.0",
"prop-types": "^15.8.1",
"proxy-from-env": "1.0.0",
@ -858,6 +860,7 @@
"@types/json5": "^0.0.30",
"@types/jsonwebtoken": "^8.5.6",
"@types/kbn__ace": "link:bazel-bin/packages/kbn-ace/npm_module_types",
"@types/kbn__adhoc-profiler": "link:bazel-bin/packages/kbn-adhoc-profiler/npm_module_types",
"@types/kbn__aiops-components": "link:bazel-bin/x-pack/packages/ml/aiops_components/npm_module_types",
"@types/kbn__aiops-utils": "link:bazel-bin/x-pack/packages/ml/aiops_utils/npm_module_types",
"@types/kbn__alerts": "link:bazel-bin/packages/kbn-alerts/npm_module_types",

View file

@ -181,6 +181,7 @@ filegroup(
"//packages/home/sample_data_tab:build",
"//packages/home/sample_data_types:build",
"//packages/kbn-ace:build",
"//packages/kbn-adhoc-profiler:build",
"//packages/kbn-alerts:build",
"//packages/kbn-ambient-storybook-types:build",
"//packages/kbn-ambient-ui-types:build",
@ -529,6 +530,7 @@ filegroup(
"//packages/home/sample_data_card:build_types",
"//packages/home/sample_data_tab:build_types",
"//packages/kbn-ace:build_types",
"//packages/kbn-adhoc-profiler:build_types",
"//packages/kbn-alerts:build_types",
"//packages/kbn-analytics:build_types",
"//packages/kbn-apm-config-loader:build_types",

View file

@ -0,0 +1,128 @@
load("@npm//@bazel/typescript:index.bzl", "ts_config")
load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project")
PKG_DIRNAME = "kbn-adhoc-profiler"
PKG_REQUIRE_NAME = "@kbn/adhoc-profiler"
SOURCE_FILES = glob(
[
"**/*.ts",
],
exclude = [
"**/*.config.js",
"**/*.mock.*",
"**/*.test.*",
"**/*.stories.*",
"**/__snapshots__/**",
"**/integration_tests/**",
"**/mocks/**",
"**/scripts/**",
"**/storybook/**",
"**/test_fixtures/**",
"**/test_helpers/**",
],
)
SRCS = SOURCE_FILES
filegroup(
name = "srcs",
srcs = SRCS,
)
NPM_MODULE_EXTRA_FILES = [
"package.json",
]
# In this array place runtime dependencies, including other packages and NPM packages
# which must be available for this code to run.
#
# To reference other packages use:
# "//repo/relative/path/to/package"
# eg. "//packages/kbn-utils"
#
# To reference a NPM package use:
# "@npm//name-of-package"
# eg. "@npm//lodash"
RUNTIME_DEPS = [
"@npm//pprof",
"@npm//execa"
]
# In this array place dependencies necessary to build the types, which will include the
# :npm_module_types target of other packages and packages from NPM, including @types/*
# packages.
#
# To reference the types for another package use:
# "//repo/relative/path/to/package:npm_module_types"
# eg. "//packages/kbn-utils:npm_module_types"
#
# References to NPM packages work the same as RUNTIME_DEPS
TYPES_DEPS = [
"@npm//@types/node",
"@npm//@types/jest",
"@npm//pprof",
"@npm//execa"
]
jsts_transpiler(
name = "target_node",
srcs = SRCS,
build_pkg_name = package_name(),
)
ts_config(
name = "tsconfig",
src = "tsconfig.json",
deps = [
"//:tsconfig.base.json",
"//:tsconfig.bazel.json",
],
)
ts_project(
name = "tsc_types",
args = ['--pretty'],
srcs = SRCS,
deps = TYPES_DEPS,
declaration = True,
declaration_map = True,
emit_declaration_only = True,
out_dir = "target_types",
tsconfig = ":tsconfig",
)
js_library(
name = PKG_DIRNAME,
srcs = NPM_MODULE_EXTRA_FILES,
deps = RUNTIME_DEPS + [":target_node"],
package_name = PKG_REQUIRE_NAME,
visibility = ["//visibility:public"],
)
pkg_npm(
name = "npm_module",
deps = [":" + PKG_DIRNAME],
)
filegroup(
name = "build",
srcs = [":npm_module"],
visibility = ["//visibility:public"],
)
pkg_npm_types(
name = "npm_module_types",
srcs = SRCS,
deps = [":tsc_types"],
package_name = PKG_REQUIRE_NAME,
tsconfig = ":tsconfig",
visibility = ["//visibility:public"],
)
filegroup(
name = "build_types",
srcs = [":npm_module_types"],
visibility = ["//visibility:public"],
)

View file

@ -0,0 +1,5 @@
# @kbn/adhoc-profiler
This package offers tools for ad hoc profiling. Currently it only exports one method: `inspectCpuProfile`, which will start a CPU profile before executing the callback it is given, and opens the collected profile in a web browser. It assumes that you have `go` and [`pprof`](https://github.com/google/pprof) installed.
Profiles are stored in the user's temporary directory (returned from `os.tmpdir()`).

View file

@ -0,0 +1,9 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
export { inspectCpuProfile } from './inspect_cpu_profile';

View file

@ -0,0 +1,28 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import Fs from 'fs';
import Os from 'os';
import Path from 'path';
import execa from 'execa';
import { pprof } from './require_pprof';
import { withCpuProfile } from './with_cpu_profile';
export function inspectCpuProfile<T>(callback: () => T): T;
export function inspectCpuProfile<T>(callback: () => any) {
return withCpuProfile(callback, (profile) => {
pprof.encode(profile).then((buffer) => {
const filename = Path.join(Os.tmpdir(), Date.now() + '.pb.gz');
Fs.writeFile(filename, buffer, (err) => {
execa('pprof', ['-web', filename]);
});
});
});
}

View file

@ -0,0 +1,13 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
module.exports = {
preset: '@kbn/test/jest_node',
rootDir: '../..',
roots: ['<rootDir>/packages/kbn-adhoc-profiler'],
};

View file

@ -0,0 +1,7 @@
{
"type": "shared-common",
"id": "@kbn/adhoc-profiler",
"owner": "@elastic/apm-ui",
"runtimeDeps": [],
"typeDeps": [],
}

View file

@ -0,0 +1,7 @@
{
"name": "@kbn/adhoc-profiler",
"private": true,
"version": "1.0.0",
"main": "./target_node/index.js",
"license": "SSPL-1.0 OR Elastic License 2.0"
}

View file

@ -0,0 +1,14 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { PProf } from './types';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const pprof = require('pprof') as PProf;
export { pprof };

View file

@ -0,0 +1,18 @@
{
"extends": "../../tsconfig.bazel.json",
"compilerOptions": {
"declaration": true,
"declarationMap": true,
"emitDeclarationOnly": true,
"outDir": "target_types",
"stripInternal": false,
"types": [
"jest",
"node",
"long"
]
},
"include": [
"**/*.ts",
]
}

View file

@ -0,0 +1,13 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import type pprofRuntime from 'pprof';
type PProf = typeof pprofRuntime;
type Profile = ReturnType<ReturnType<PProf['time']['start']>>;
export type { PProf, Profile };

View file

@ -0,0 +1,32 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { isPromise } from 'util/types';
import { pprof } from './require_pprof';
import { Profile } from './types';
export function withCpuProfile<T>(callback: () => T, onProfileDone: (profile: Profile) => void): T;
export function withCpuProfile(callback: () => any, onProfileDone: (profile: Profile) => void) {
const stop = pprof.time.start();
const result = callback();
function collectProfile() {
const profile = stop();
onProfileDone(profile);
}
if (isPromise(result)) {
result.finally(() => {
collectProfile();
});
} else {
collectProfile();
}
return result;
}

View file

@ -5,23 +5,25 @@
* 2.0.
*/
import Boom from '@hapi/boom';
import * as t from 'io-ts';
import { KibanaRequest, RouteRegistrar } from '@kbn/core/server';
import { errors } from '@elastic/elasticsearch';
import agent from 'elastic-apm-node';
import { ServerRouteRepository } from '@kbn/server-route-repository';
import { merge } from 'lodash';
import Boom from '@hapi/boom';
import { RequestHandler } from '@kbn/core-http-server';
import { KibanaRequest, RouteRegistrar } from '@kbn/core/server';
import { jsonRt, mergeRt } from '@kbn/io-ts-utils';
import { InspectResponse } from '@kbn/observability-plugin/typings/common';
import {
decodeRequestParams,
parseEndpoint,
routeValidationObject,
ServerRouteRepository,
} from '@kbn/server-route-repository';
import { jsonRt, mergeRt } from '@kbn/io-ts-utils';
import { InspectResponse } from '@kbn/observability-plugin/typings/common';
import agent from 'elastic-apm-node';
import * as t from 'io-ts';
import { merge } from 'lodash';
import { inspectCpuProfile } from '@kbn/adhoc-profiler';
import { pickKeys } from '../../../common/utils/pick_keys';
import { APMRouteHandlerResources, TelemetryUsageCounter } from '../typings';
import type { ApmPluginRequestHandlerContext } from '../typings';
import { APMRouteHandlerResources, TelemetryUsageCounter } from '../typings';
const inspectRt = t.exact(
t.partial({
@ -64,6 +66,29 @@ export function registerRoutes({
const router = core.setup.http.createRouter();
function wrapRouteHandlerInProfiler(
handler: RequestHandler<
unknown,
unknown,
unknown,
ApmPluginRequestHandlerContext
>
): RequestHandler<
unknown,
{ _profile?: 'inspect' },
unknown,
ApmPluginRequestHandlerContext
> {
return (context, request, response) => {
const { _profile } = request.query;
if (_profile === 'inspect') {
delete request.query._profile;
return inspectCpuProfile(() => handler(context, request, response));
}
return handler(context, request, response);
};
}
routes.forEach((route) => {
const { params, endpoint, options, handler } = route;
@ -80,7 +105,7 @@ export function registerRoutes({
options,
validate: routeValidationObject,
},
async (context, request, response) => {
wrapRouteHandlerInProfiler(async (context, request, response) => {
if (agent.isStarted()) {
agent.addLabels({
plugin: 'apm',
@ -186,7 +211,7 @@ export function registerRoutes({
// cleanup
inspectableEsQueriesMap.delete(request);
}
}
})
);
});
}

View file

@ -2605,6 +2605,10 @@
version "0.0.0"
uid ""
"@kbn/adhoc-profiler@link:bazel-bin/packages/kbn-adhoc-profiler":
version "0.0.0"
uid ""
"@kbn/aiops-components@link:bazel-bin/x-pack/packages/ml/aiops_components":
version "0.0.0"
uid ""
@ -4166,6 +4170,21 @@
resolved "https://registry.yarnpkg.com/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-2.0.1.tgz#c15367178d8bfe4765e6b47b542fe821ce259c7b"
integrity sha512-HP6XvfNIzfoMVfyGjBckjiAOQK9WfX0ywdLubuPMPv+Vqf5fj0uCbgBQYpiqcWZT6cbyyRnTSXDheT1ugvF6UQ==
"@mapbox/node-pre-gyp@^1.0.0":
version "1.0.10"
resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz#8e6735ccebbb1581e5a7e652244cadc8a844d03c"
integrity sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==
dependencies:
detect-libc "^2.0.0"
https-proxy-agent "^5.0.0"
make-dir "^3.1.0"
node-fetch "^2.6.7"
nopt "^5.0.0"
npmlog "^5.0.1"
rimraf "^3.0.2"
semver "^7.3.5"
tar "^6.1.11"
"@mapbox/point-geometry@0.1.0", "@mapbox/point-geometry@^0.1.0", "@mapbox/point-geometry@~0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz#8a83f9335c7860effa2eeeca254332aa0aeed8f2"
@ -6797,6 +6816,10 @@
version "0.0.0"
uid ""
"@types/kbn__adhoc-profiler@link:bazel-bin/packages/kbn-adhoc-profiler/npm_module_types":
version "0.0.0"
uid ""
"@types/kbn__aiops-components@link:bazel-bin/x-pack/packages/ml/aiops_components/npm_module_types":
version "0.0.0"
uid ""
@ -10811,6 +10834,13 @@ binary-search@^1.3.3:
resolved "https://registry.yarnpkg.com/binary-search/-/binary-search-1.3.6.tgz#e32426016a0c5092f0f3598836a1c7da3560565c"
integrity sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA==
bindings@^1.2.1:
version "1.5.0"
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df"
integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==
dependencies:
file-uri-to-path "1.0.0"
bitmap-sdf@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/bitmap-sdf/-/bitmap-sdf-1.0.3.tgz#c99913e5729357a6fd350de34158180c013880b2"
@ -13479,6 +13509,11 @@ delaunator@5:
dependencies:
robust-predicates "^3.0.0"
delay@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/delay/-/delay-5.0.0.tgz#137045ef1b96e5071060dd5be60bf9334436bd1d"
integrity sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
@ -15410,6 +15445,11 @@ file-system-cache@^1.0.5:
fs-extra "^0.30.0"
ramda "^0.21.0"
file-uri-to-path@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
filelist@^1.0.1:
version "1.0.4"
resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5"
@ -15508,6 +15548,11 @@ find-up@^4.0.0, find-up@^4.1.0:
locate-path "^5.0.0"
path-exists "^4.0.0"
findit2@^2.2.3:
version "2.2.3"
resolved "https://registry.yarnpkg.com/findit2/-/findit2-2.2.3.tgz#58a466697df8a6205cdfdbf395536b8bd777a5f6"
integrity sha512-lg/Moejf4qXovVutL0Lz4IsaPoNYMuxt4PA0nGqFxnJ1CTTGGlEO2wKgoDpwknhvZ8k4Q2F+eesgkLbG2Mxfog==
flat-cache@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11"
@ -20832,6 +20877,11 @@ nan@^2.13.2, nan@^2.14.2, nan@^2.15.0:
resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee"
integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==
nan@^2.14.0:
version "2.17.0"
resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb"
integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==
nano-css@^5.2.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/nano-css/-/nano-css-5.2.1.tgz#73b8470fa40b028a134d3393ae36bbb34b9fa332"
@ -21805,7 +21855,7 @@ p-limit@^2.0.0, p-limit@^2.2.0, p-limit@^2.3.0:
dependencies:
p-try "^2.0.0"
p-limit@^3.0.1, p-limit@^3.0.2:
p-limit@^3.0.0, p-limit@^3.0.1, p-limit@^3.0.2:
version "3.1.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
@ -22237,6 +22287,11 @@ pify@^4.0.1:
resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231"
integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==
pify@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-5.0.0.tgz#1f5eca3f5e87ebec28cc6d54a0e4aaf00acc127f"
integrity sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==
pinkie-promise@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa"
@ -22779,6 +22834,22 @@ potpack@^1.0.2:
resolved "https://registry.yarnpkg.com/potpack/-/potpack-1.0.2.tgz#23b99e64eb74f5741ffe7656b5b5c4ddce8dfc14"
integrity sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==
pprof@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/pprof/-/pprof-3.2.0.tgz#5a60638dc51a61128a3d57c74514e8fd99e93722"
integrity sha512-yhORhVWefg94HZgjVa6CDtYSNZJnJzZ82d4pkmrZJxf1/Y29Me/uHYLEVo6KawKKFhQywl5cGbkdnVx9bZoMew==
dependencies:
"@mapbox/node-pre-gyp" "^1.0.0"
bindings "^1.2.1"
delay "^5.0.0"
findit2 "^2.2.3"
nan "^2.14.0"
p-limit "^3.0.0"
pify "^5.0.0"
protobufjs "~6.11.0"
source-map "^0.7.3"
split "^1.0.1"
preact-render-to-string@^5.1.19:
version "5.1.19"
resolved "https://registry.yarnpkg.com/preact-render-to-string/-/preact-render-to-string-5.1.19.tgz#ffae7c3bd1680be5ecf5991d41fe3023b3051e0e"
@ -23059,7 +23130,7 @@ protobufjs@6.8.8:
"@types/node" "^10.1.0"
long "^4.0.0"
protobufjs@^6.11.3:
protobufjs@^6.11.3, protobufjs@~6.11.0:
version "6.11.3"
resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.3.tgz#637a527205a35caa4f3e2a9a4a13ddffe0e7af74"
integrity sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg==
@ -25886,6 +25957,13 @@ split-string@^3.0.1, split-string@^3.0.2:
dependencies:
extend-shallow "^3.0.0"
split@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9"
integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==
dependencies:
through "2"
sprintf-js@~1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
@ -26879,7 +26957,7 @@ through2@~0.4.1:
readable-stream "~1.0.17"
xtend "~2.1.1"
"through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6, through@^2.3.8, through@~2.3.4:
through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6, through@^2.3.8, through@~2.3.4:
version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=