diff --git a/package.json b/package.json index 66d612ed1..021bd4cfc 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,6 @@ "@sentry/node": "^7.24.2", "@sentry/react": "^7.24.2", "@sentry/tracing": "^7.24.2", - "@theo.gravity/datadog-apm": "^3.0.0", "@tippyjs/react": "^4.2.6", "@tommoor/remove-markdown": "^0.3.2", "@types/mermaid": "^9.1.0", @@ -86,8 +85,9 @@ "copy-to-clipboard": "^3.3.3", "core-js": "^3.26.1", "crypto-js": "^4.1.1", - "datadog-metrics": "^0.9.3", + "datadog-metrics": "^0.10.2", "date-fns": "^2.25.0", + "dd-trace": "^3.9.3", "dotenv": "^4.0.0", "email-providers": "^1.13.1", "emoji-regex": "^10.0.0", diff --git a/server/__mocks__/dd-trace.ts b/server/__mocks__/dd-trace.ts new file mode 100644 index 000000000..9d67df805 --- /dev/null +++ b/server/__mocks__/dd-trace.ts @@ -0,0 +1,39 @@ +/* eslint-disable @typescript-eslint/explicit-function-return-type */ +import { Tracer } from "dd-trace"; + +// eslint-disable-next-line @typescript-eslint/no-empty-function +const emptyFn = function () {}; + +const callableHandlers = { + get(_target: T, _prop: P, _receiver: any): T[P] { + const newMock = new Proxy(emptyFn, callableHandlers); + return (newMock as any) as T[P]; + }, + + apply any, A extends Parameters>( + _target: T, + _thisArg: any, + _args: A + ): ReturnType { + const newMock = new Proxy(emptyFn, callableHandlers); + return (newMock as any) as ReturnType; + }, +}; + +const callableMock = new Proxy(emptyFn, callableHandlers); + +type MockTracer = Tracer & { isMock?: boolean }; + +export const mockTracer = new Proxy({} as MockTracer, { + get(_target: Tracer, key: K) { + if (key === "isMock") { + return true; + } + + if (key === "wrap") { + return (_: any, f: any) => f; + } + + return callableMock; + }, +}); diff --git a/server/collaboration/AuthenticationExtension.ts b/server/collaboration/AuthenticationExtension.ts index 474c9b380..cfe6be9a8 100644 --- a/server/collaboration/AuthenticationExtension.ts +++ b/server/collaboration/AuthenticationExtension.ts @@ -1,11 +1,11 @@ import { onAuthenticatePayload, Extension } from "@hocuspocus/server"; -import { APM } from "@server/logging/tracing"; +import { trace } from "@server/logging/tracing"; import Document from "@server/models/Document"; import { can } from "@server/policies"; import { getUserForJWT } from "@server/utils/jwt"; import { AuthenticationError } from "../errors"; -@APM.trace() +@trace() export default class AuthenticationExtension implements Extension { async onAuthenticate({ connection, diff --git a/server/collaboration/PersistenceExtension.ts b/server/collaboration/PersistenceExtension.ts index a0a70f13c..547f72a12 100644 --- a/server/collaboration/PersistenceExtension.ts +++ b/server/collaboration/PersistenceExtension.ts @@ -7,12 +7,12 @@ import { import * as Y from "yjs"; import { sequelize } from "@server/database/sequelize"; import Logger from "@server/logging/Logger"; -import { APM } from "@server/logging/tracing"; +import { trace } from "@server/logging/tracing"; import Document from "@server/models/Document"; import documentCollaborativeUpdater from "../commands/documentCollaborativeUpdater"; import markdownToYDoc from "./utils/markdownToYDoc"; -@APM.trace() +@trace() export default class PersistenceExtension implements Extension { /** * Map of documentId -> userIds that have modified the document since it diff --git a/server/commands/accountProvisioner.ts b/server/commands/accountProvisioner.ts index bc788c8c8..118fe34c4 100644 --- a/server/commands/accountProvisioner.ts +++ b/server/commands/accountProvisioner.ts @@ -5,7 +5,7 @@ import { InvalidAuthenticationError, AuthenticationProviderDisabledError, } from "@server/errors"; -import { APM } from "@server/logging/tracing"; +import { traceFunction } from "@server/logging/tracing"; import { AuthenticationProvider, Collection, Team, User } from "@server/models"; import teamProvisioner from "./teamProvisioner"; import userProvisioner from "./userProvisioner"; @@ -184,6 +184,6 @@ async function accountProvisioner({ } } -export default APM.traceFunction({ +export default traceFunction({ spanName: "accountProvisioner", })(accountProvisioner); diff --git a/server/commands/collectionExporter.ts b/server/commands/collectionExporter.ts index 8c97cff39..80da27e7d 100644 --- a/server/commands/collectionExporter.ts +++ b/server/commands/collectionExporter.ts @@ -4,7 +4,7 @@ import { FileOperationType, FileOperationState, } from "@shared/types"; -import { APM } from "@server/logging/tracing"; +import { traceFunction } from "@server/logging/tracing"; import { Collection, Event, Team, User, FileOperation } from "@server/models"; import { getAWSKeyForFileOp } from "@server/utils/s3"; @@ -71,6 +71,6 @@ async function collectionExporter({ return fileOperation; } -export default APM.traceFunction({ +export default traceFunction({ spanName: "collectionExporter", })(collectionExporter); diff --git a/server/commands/documentImporter.ts b/server/commands/documentImporter.ts index 2283eaffd..97667d61d 100644 --- a/server/commands/documentImporter.ts +++ b/server/commands/documentImporter.ts @@ -7,7 +7,7 @@ import { Transaction } from "sequelize"; import utf8 from "utf8"; import parseTitle from "@shared/utils/parseTitle"; import { DocumentValidation } from "@shared/validations"; -import { APM } from "@server/logging/tracing"; +import { traceFunction } from "@server/logging/tracing"; import { User } from "@server/models"; import dataURItoBuffer from "@server/utils/dataURItoBuffer"; import parseImages from "@server/utils/parseImages"; @@ -229,6 +229,6 @@ async function documentImporter({ }; } -export default APM.traceFunction({ +export default traceFunction({ spanName: "documentImporter", })(documentImporter); diff --git a/server/commands/documentMover.ts b/server/commands/documentMover.ts index 510e16db1..e37c72ff0 100644 --- a/server/commands/documentMover.ts +++ b/server/commands/documentMover.ts @@ -1,7 +1,7 @@ import invariant from "invariant"; import { Transaction } from "sequelize"; import { ValidationError } from "@server/errors"; -import { APM } from "@server/logging/tracing"; +import { traceFunction } from "@server/logging/tracing"; import { User, Document, Collection, Pin, Event } from "@server/models"; import pinDestroyer from "./pinDestroyer"; @@ -203,6 +203,6 @@ async function documentMover({ return result; } -export default APM.traceFunction({ +export default traceFunction({ spanName: "documentMover", })(documentMover); diff --git a/server/commands/teamCreator.ts b/server/commands/teamCreator.ts index 61cde4184..d0668fce6 100644 --- a/server/commands/teamCreator.ts +++ b/server/commands/teamCreator.ts @@ -1,7 +1,7 @@ import { Transaction } from "sequelize"; import slugify from "slugify"; import { RESERVED_SUBDOMAINS } from "@shared/utils/domains"; -import { APM } from "@server/logging/tracing"; +import { traceFunction } from "@server/logging/tracing"; import { Team, Event } from "@server/models"; import { generateAvatarUrl } from "@server/utils/avatars"; @@ -103,6 +103,6 @@ async function findAvailableSubdomain(team: Team, requestedSubdomain: string) { return subdomain; } -export default APM.traceFunction({ +export default traceFunction({ spanName: "teamCreator", })(teamCreator); diff --git a/server/commands/teamPermanentDeleter.ts b/server/commands/teamPermanentDeleter.ts index 83a3d111f..409905b66 100644 --- a/server/commands/teamPermanentDeleter.ts +++ b/server/commands/teamPermanentDeleter.ts @@ -1,7 +1,7 @@ import { Transaction } from "sequelize"; import { sequelize } from "@server/database/sequelize"; import Logger from "@server/logging/Logger"; -import { APM } from "@server/logging/tracing"; +import { traceFunction } from "@server/logging/tracing"; import { ApiKey, Attachment, @@ -198,6 +198,6 @@ async function teamPermanentDeleter(team: Team) { } } -export default APM.traceFunction({ +export default traceFunction({ spanName: "teamPermanentDeleter", })(teamPermanentDeleter); diff --git a/server/commands/teamProvisioner.ts b/server/commands/teamProvisioner.ts index 18526f2ce..53ba1d226 100644 --- a/server/commands/teamProvisioner.ts +++ b/server/commands/teamProvisioner.ts @@ -6,7 +6,7 @@ import { InvalidAuthenticationError, MaximumTeamsError, } from "@server/errors"; -import { APM } from "@server/logging/tracing"; +import { traceFunction } from "@server/logging/tracing"; import { Team, AuthenticationProvider } from "@server/models"; type TeamProvisionerResult = { @@ -125,6 +125,6 @@ async function teamProvisioner({ }; } -export default APM.traceFunction({ +export default traceFunction({ spanName: "teamProvisioner", })(teamProvisioner); diff --git a/server/emails/mailer.tsx b/server/emails/mailer.tsx index 2af50f1c3..c69e22bd3 100644 --- a/server/emails/mailer.tsx +++ b/server/emails/mailer.tsx @@ -2,7 +2,7 @@ import nodemailer, { Transporter } from "nodemailer"; import Oy from "oy-vey"; import env from "@server/env"; import Logger from "@server/logging/Logger"; -import { APM } from "@server/logging/tracing"; +import { trace } from "@server/logging/tracing"; import isCloudHosted from "@server/utils/isCloudHosted"; import { baseStyles } from "./templates/components/EmailLayout"; @@ -22,7 +22,9 @@ type SendMailOptions = { /** * Mailer class to send emails. */ -@APM.trace() +@trace({ + serviceName: "mailer", +}) export class Mailer { transporter: Transporter | undefined; diff --git a/server/env.ts b/server/env.ts index d7e4c115d..ca17f5d2d 100644 --- a/server/env.ts +++ b/server/env.ts @@ -343,6 +343,11 @@ export class Environment { */ public DD_API_KEY = process.env.DD_API_KEY; + /** + * The name of the service to use in DataDog. + */ + public DD_SERVICE = process.env.DD_SERVICE ?? "outline"; + /** * Google OAuth2 client credentials. To enable authentication with Google. */ diff --git a/server/index.ts b/server/index.ts index 9d9f33819..0a861396d 100644 --- a/server/index.ts +++ b/server/index.ts @@ -1,7 +1,7 @@ /* eslint-disable import/order */ import env from "./env"; -import "./logging/tracing"; // must come before importing any instrumented module +import "./logging/tracer"; // must come before importing any instrumented module import http from "http"; import https from "https"; diff --git a/server/logging/Logger.ts b/server/logging/Logger.ts index 16999b3a3..caf37c5dc 100644 --- a/server/logging/Logger.ts +++ b/server/logging/Logger.ts @@ -5,7 +5,7 @@ import winston from "winston"; import env from "@server/env"; import Metrics from "@server/logging/Metrics"; import Sentry from "@server/logging/sentry"; -import * as Tracing from "./tracing"; +import * as Tracing from "./tracer"; const isProduction = env.ENVIRONMENT === "production"; diff --git a/server/logging/Metrics.ts b/server/logging/Metrics.ts index 674bb2b6c..56f2bf6f5 100644 --- a/server/logging/Metrics.ts +++ b/server/logging/Metrics.ts @@ -29,13 +29,8 @@ class Metrics { return; } - const instanceId = process.env.INSTANCE_ID || process.env.HEROKU_DYNO_ID; - - if (!instanceId) { - throw new Error( - "INSTANCE_ID or HEROKU_DYNO_ID must be set when using DataDog" - ); - } + const instanceId = + process.env.INSTANCE_ID || process.env.HEROKU_DYNO_ID || process.pid; return ddMetrics.gauge(key, value, [...tags, `instance:${instanceId}`]); } diff --git a/server/logging/tracer.ts b/server/logging/tracer.ts new file mode 100644 index 000000000..07df3f4be --- /dev/null +++ b/server/logging/tracer.ts @@ -0,0 +1,92 @@ +import tracer, { Span } from "dd-trace"; +import env from "@server/env"; + +type PrivateDatadogContext = { + req: Record & { + _datadog?: { + span?: Span; + }; + }; +}; + +// If the DataDog agent is installed and the DD_API_KEY environment variable is +// in the environment then we can safely attempt to start the DD tracer +if (env.DD_API_KEY) { + tracer.init({ + version: env.VERSION, + service: env.DD_SERVICE, + env: env.ENVIRONMENT, + }); +} + +const getCurrentSpan = (): Span | null => tracer.scope().active(); + +/** + * Add tags to a span to have more context about how and why it was running. + * If added to the root span, tags are searchable and filterable. + * + * @param tags An object with the tags to add to the span + * @param span An optional span object to add the tags to. If none provided,the current span will be used. + */ +export function addTags(tags: Record, span?: Span | null): void { + if (tracer) { + const currentSpan = span || getCurrentSpan(); + + if (!currentSpan) { + return; + } + + currentSpan.addTags(tags); + } +} + +/** + * The root span is an undocumented internal property that DataDog adds to `context.req`. + * The root span is required in order to add searchable tags. + * Unfortunately, there is no API to access the root span directly. + * See: node_modules/dd-trace/src/plugins/util/web.js + * + * @param context A Koa context object + */ +export function getRootSpanFromRequestContext( + context: PrivateDatadogContext +): Span | null { + // eslint-disable-next-line no-undef + return context?.req?._datadog?.span ?? null; +} + +/** + * Change the resource of the active APM span. This method wraps addTags to allow + * safe use in environments where APM is disabled. + * + * @param name The name of the resource + */ +export function setResource(name: string) { + if (tracer) { + addTags({ + "resource.name": `${name}`, + }); + } +} + +/** + * Mark the current active span as an error. This method wraps addTags to allow + * safe use in environments where APM is disabled. + * + * @param error The error to add to the current span + */ +export function setError(error: Error, span?: Span) { + if (tracer) { + addTags( + { + errorMessage: error.message, + "error.type": error.name, + "error.msg": error.message, + "error.stack": error.stack, + }, + span + ); + } +} + +export default tracer; diff --git a/server/logging/tracing.ts b/server/logging/tracing.ts index ac06a9e0a..bbfe62168 100644 --- a/server/logging/tracing.ts +++ b/server/logging/tracing.ts @@ -1,46 +1,212 @@ -import { init, tracer, addTags, markAsError } from "@theo.gravity/datadog-apm"; +// MIT License + +// Copyright (c) 2020 GameChanger Media + +// 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: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// 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. + +import { SpanOptions } from "dd-trace"; +import DDTags from "dd-trace/ext/tags"; import env from "@server/env"; +import tracer, { setError } from "./tracer"; -export * as APM from "@theo.gravity/datadog-apm"; +type DDTag = typeof DDTags[keyof typeof DDTags]; -// If the DataDog agent is installed and the DD_API_KEY environment variable is -// in the environment then we can safely attempt to start the DD tracer -if (env.DD_API_KEY) { - init( - { - version: env.VERSION, - service: process.env.DD_SERVICE || "outline", - }, - { - useMock: env.ENVIRONMENT === "test", +type Tags = { + [tag in DDTag]?: any; +} & { + [key: string]: any; +}; + +interface Constructor { + new (...args: any[]): any; +} + +interface TraceConfig { + className?: string; + methodName?: string; + serviceName?: string; + spanName?: string; + resourceName?: string; + isRoot?: boolean; + /** Cause the span to show up in trace search and analytics */ + makeSearchable?: boolean; + tags?: Tags; +} + +/** + * This decorator will cause an individual function to be traced by the APM. + * + * @param config Optional configuration for the span that will be created for this trace. + */ +export const traceFunction = (config: TraceConfig) => < + F extends (...args: any[]) => any, + P extends Parameters, + R extends ReturnType +>( + target: F +): F => + env.ENVIRONMENT === "test" + ? target + : (function wrapperFn(this: any, ...args: P): R { + const { + className, + methodName = target.name, + spanName = "DEFAULT_SPAN_NAME", + makeSearchable: useAnalytics, + tags, + } = config; + const childOf = config.isRoot + ? undefined + : tracer.scope().active() || undefined; + const resourceName = config.resourceName + ? config.resourceName + : className + ? `${className}.${methodName}` + : methodName; + const spanOptions: SpanOptions = { + childOf, + tags: { + [DDTags.RESOURCE_NAME]: resourceName, + ...tags, + }, + }; + + const span = tracer.startSpan(spanName, spanOptions); + + if (!span) { + return target.call(this, ...args); + } + + if (config.serviceName) { + span.setTag( + DDTags.SERVICE_NAME, + `${env.DD_SERVICE}-${config.serviceName}` + ); + } + + if (useAnalytics) { + span.setTag(DDTags.ANALYTICS, true); + } + + // The callback fn needs to be wrapped in an arrow fn as the activate fn clobbers `this` + return tracer.scope().activate(span, () => { + const output = target.call(this, ...args); + + if (output && typeof output.then === "function") { + output + .catch((error: Error) => { + setError(error, span); + }) + .finally(() => { + span.finish(); + }); + } else { + span.finish(); + } + + return output; + }); + } as F); + +const traceMethod = (config?: TraceConfig) => + function R>( + target: any, + _propertyKey: string, + descriptor: PropertyDescriptor + ): TypedPropertyDescriptor { + const wrappedFn = descriptor.value; + + if (wrappedFn) { + const className = target.name || target.constructor.name; // target.name is needed if the target is the constructor itself + const methodName = wrappedFn.name; + descriptor.value = traceFunction({ ...config, className, methodName })( + wrappedFn + ); } - ); -} -/** - * Change the resource of the active APM span. This method wraps addTags to allow - * safe use in environments where APM is disabled. - * - * @param name The name of the resource - */ -export function setResource(name: string) { - if (tracer) { - addTags({ - "resource.name": `${name}`, + return descriptor; + }; + +const traceClass = (config?: TraceConfig) => + function (constructor: T): void { + const protoKeys = Reflect.ownKeys(constructor.prototype); + protoKeys.forEach((key) => { + if (key === "constructor") { + return; + } + + const descriptor = Object.getOwnPropertyDescriptor( + constructor.prototype, + key + ); + + // eslint-disable-next-line no-undef + if (typeof key === "string" && typeof descriptor?.value === "function") { + Object.defineProperty( + constructor.prototype, + key, + traceMethod(config)(constructor, key, descriptor) + ); + } }); - } -} + + const staticKeys = Reflect.ownKeys(constructor); + staticKeys.forEach((key) => { + const descriptor = Object.getOwnPropertyDescriptor(constructor, key); + + // eslint-disable-next-line no-undef + if (typeof key === "string" && typeof descriptor?.value === "function") { + Object.defineProperty( + constructor, + key, + traceMethod(config)(constructor, key, descriptor) + ); + } + }); + }; /** - * Mark the current active span as an error. This method wraps addTags to allow - * safe use in environments where APM is disabled. + * This decorator will cause the methods of a class, or an individual method, to be traced by the APM. * - * @param error The error to add + * @param config Optional configuration for the span that will be created for this trace. */ -export function setError(error: Error) { - if (tracer) { - markAsError(error); +// Going to rely on inferrence do its thing for this function +// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types +export function trace(config?: TraceConfig) { + function traceDecorator(target: Constructor): void; + function traceDecorator( + target: Record, + propertyKey: string | symbol, + descriptor: TypedPropertyDescriptor + ): void; + function traceDecorator( + a: Constructor | Record, + b?: any, + c?: any + ): void { + if (typeof a === "function") { + // Need to cast as there is no safe runtime way to check if a function is a constructor + traceClass(config)(a as Constructor); + } else { + traceMethod(config)(a, b, c); + } } -} -export default tracer; + return traceDecorator; +} diff --git a/server/middlewares/authentication.ts b/server/middlewares/authentication.ts index 002ee80b6..b0d577853 100644 --- a/server/middlewares/authentication.ts +++ b/server/middlewares/authentication.ts @@ -1,6 +1,9 @@ import { Next } from "koa"; import Logger from "@server/logging/Logger"; -import tracer, { APM } from "@server/logging/tracing"; +import tracer, { + addTags, + getRootSpanFromRequestContext, +} from "@server/logging/tracer"; import { User, Team, ApiKey } from "@server/models"; import { getUserForJWT } from "@server/utils/jwt"; import { @@ -130,13 +133,13 @@ export default function auth(options: AuthenticationOptions = {}) { ctx.state.user = user; if (tracer) { - APM.addTags( + addTags( { "request.userId": user.id, "request.teamId": user.teamId, "request.authType": ctx.state.authType, }, - APM.getRootSpanFromRequestContext(ctx) + getRootSpanFromRequestContext(ctx) ); } } diff --git a/server/models/helpers/DocumentHelper.tsx b/server/models/helpers/DocumentHelper.tsx index 2ba545434..658f5d87f 100644 --- a/server/models/helpers/DocumentHelper.tsx +++ b/server/models/helpers/DocumentHelper.tsx @@ -23,7 +23,7 @@ import { isRTL } from "@shared/utils/rtl"; import unescape from "@shared/utils/unescape"; import { parser, schema } from "@server/editor"; import Logger from "@server/logging/Logger"; -import { APM } from "@server/logging/tracing"; +import { trace } from "@server/logging/tracing"; import type Document from "@server/models/Document"; import type Revision from "@server/models/Revision"; import User from "@server/models/User"; @@ -43,7 +43,7 @@ type HTMLOptions = { signedUrls?: boolean; }; -@APM.trace() +@trace() export default class DocumentHelper { /** * Returns the document as a Prosemirror Node. This method uses the diff --git a/server/presenters/document.ts b/server/presenters/document.ts index 26bedf161..2ba77ebb4 100644 --- a/server/presenters/document.ts +++ b/server/presenters/document.ts @@ -1,4 +1,4 @@ -import { APM } from "@server/logging/tracing"; +import { traceFunction } from "@server/logging/tracing"; import { Document } from "@server/models"; import DocumentHelper from "@server/models/helpers/DocumentHelper"; import presentUser from "./user"; @@ -63,6 +63,6 @@ async function present( return data; } -export default APM.traceFunction({ +export default traceFunction({ spanName: "presentDocument", })(present); diff --git a/server/presenters/policy.ts b/server/presenters/policy.ts index 47faa40f6..2d8b5c83b 100644 --- a/server/presenters/policy.ts +++ b/server/presenters/policy.ts @@ -1,4 +1,4 @@ -import { APM } from "@server/logging/tracing"; +import { traceFunction } from "@server/logging/tracing"; import { User } from "@server/models"; type Policy = { @@ -16,6 +16,6 @@ function present(user: User, objects: Record[]): Policy[] { })); } -export default APM.traceFunction({ +export default traceFunction({ spanName: "presentPolicy", })(present); diff --git a/server/presenters/slackAttachment.ts b/server/presenters/slackAttachment.ts index 303866887..cd182f4f9 100644 --- a/server/presenters/slackAttachment.ts +++ b/server/presenters/slackAttachment.ts @@ -1,4 +1,4 @@ -import { APM } from "@server/logging/tracing"; +import { traceFunction } from "@server/logging/tracing"; import { Document, Collection, Team } from "@server/models"; type Action = { @@ -33,6 +33,6 @@ function present( }; } -export default APM.traceFunction({ +export default traceFunction({ spanName: "presentSlackAttachment", })(present); diff --git a/server/services/websockets.ts b/server/services/websockets.ts index 69abca7f9..6643c9f00 100644 --- a/server/services/websockets.ts +++ b/server/services/websockets.ts @@ -6,8 +6,8 @@ import IO from "socket.io"; import { createAdapter } from "socket.io-redis"; import Logger from "@server/logging/Logger"; import Metrics from "@server/logging/Metrics"; -import * as Tracing from "@server/logging/tracing"; -import { APM } from "@server/logging/tracing"; +import * as Tracing from "@server/logging/tracer"; +import { traceFunction } from "@server/logging/tracing"; import { Document, Collection, View, User } from "@server/models"; import { can } from "@server/policies"; import { getUserForJWT } from "@server/utils/jwt"; @@ -131,7 +131,7 @@ export default function init( // Handle events from event queue that should be sent to the clients down ws const websockets = new WebsocketsProcessor(); websocketQueue.process( - APM.traceFunction({ + traceFunction({ serviceName: "websockets", spanName: "process", isRoot: true, diff --git a/server/services/worker.ts b/server/services/worker.ts index 5c0018556..71588f9a5 100644 --- a/server/services/worker.ts +++ b/server/services/worker.ts @@ -1,6 +1,6 @@ import Logger from "@server/logging/Logger"; -import * as Tracing from "@server/logging/tracing"; -import { APM } from "@server/logging/tracing"; +import { setResource } from "@server/logging/tracer"; +import { traceFunction } from "@server/logging/tracing"; import { globalEventQueue, processorEventQueue, @@ -13,7 +13,7 @@ import tasks from "../queues/tasks"; export default function init() { // This queue processes the global event bus globalEventQueue.process( - APM.traceFunction({ + traceFunction({ serviceName: "worker", spanName: "process", isRoot: true, @@ -21,7 +21,7 @@ export default function init() { const event = job.data; let err; - Tracing.setResource(`Event.${event.name}`); + setResource(`Event.${event.name}`); Logger.info("worker", `Processing ${event.name}`, { name: event.name, @@ -71,7 +71,7 @@ export default function init() { // Jobs for individual processors are processed here. Only applicable events // as unapplicable events were filtered in the global event queue above. processorEventQueue.process( - APM.traceFunction({ + traceFunction({ serviceName: "worker", spanName: "process", isRoot: true, @@ -79,7 +79,7 @@ export default function init() { const { event, name } = job.data; const ProcessorClass = processors[name]; - Tracing.setResource(`Processor.${name}`); + setResource(`Processor.${name}`); if (!ProcessorClass) { throw new Error( @@ -107,7 +107,7 @@ export default function init() { // Jobs for async tasks are processed here. taskQueue.process( - APM.traceFunction({ + traceFunction({ serviceName: "worker", spanName: "process", isRoot: true, @@ -115,7 +115,7 @@ export default function init() { const { name, props } = job.data; const TaskClass = tasks[name]; - Tracing.setResource(`Task.${name}`); + setResource(`Task.${name}`); if (!TaskClass) { throw new Error( diff --git a/yarn.lock b/yarn.lock index b95b3cf96..2000740f5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1151,36 +1151,63 @@ enabled "2.0.x" kuler "^2.0.0" -"@datadog/native-appsec@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-1.2.1.tgz#f9d4003b470608018c1f697e2d401202a3084632" - integrity sha512-jF+k7xhBmJIYYLtjvhCey08RBbItTG7O2zcSCDGFffhvCvo3ZOoou+IKtAm9z+U7hOoeOmD+Xg+h29xj/BB9MA== +"@datadog/datadog-api-client@^1.3.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@datadog/datadog-api-client/-/datadog-api-client-1.6.0.tgz#c09caa7e34ddaa346ba56c04c0e43bb288c501bd" + integrity sha512-+iYaZt/yb7Unv4zIsh2WSdQU15cwsBTKrtpU4Z1wG90G2LFabqhWzARx/4qQ2Wms07hjUkA2rLTffd0+vGgyGA== dependencies: - detect-libc "^1.0.3" - minimist "^1.2.6" - tar "^6.1.11" + "@types/buffer-from" "^1.1.0" + "@types/node" "*" + "@types/pako" "^1.0.3" + btoa "^1.2.1" + buffer-from "^1.1.2" + cross-fetch "^3.1.5" + durations "^3.4.2" + es6-promise "^4.2.4" + form-data "^3.0.0" + loglevel "^1.7.1" + pako "^2.0.4" + url-parse "^1.4.3" -"@datadog/native-metrics@^1.4.3": - version "1.4.3" - resolved "https://registry.yarnpkg.com/@datadog/native-metrics/-/native-metrics-1.4.3.tgz#30b62bdf227f3a193ca0ab06728a3ad9ccd70f1c" - integrity sha512-EUOoTbCWEAqCp3Cswe3JR3DkK6GUaBQIz7sLPNdy1RDu6Zc39HNCXEDo5RL3Hexo87gDkOq+pRifLkxjwrf7gQ== +"@datadog/native-appsec@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@datadog/native-appsec/-/native-appsec-2.0.0.tgz#ad65ba19bfd68e6b6c6cf64bb8ef55d099af8edc" + integrity sha512-XHARZ6MVgbnfOUO6/F3ZoZ7poXHJCNYFlgcyS2Xetuk9ITA5bfcooX2B2F7tReVB+RLJ+j8bsm0t55SyF04KDw== dependencies: node-gyp-build "^3.9.0" -"@datadog/pprof@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-1.0.2.tgz#835b2e8596738348a5ba81e5e399cdf3bc85bd35" - integrity sha512-AMTK55W3Aa2QX2X8mN9SQfDGw3HvwIK9Or8pXQFss+kjtH5pCkO9oqE5838MeXgRh9BR8HWrjAQE3Ji7FRCK2g== +"@datadog/native-iast-rewriter@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@datadog/native-iast-rewriter/-/native-iast-rewriter-1.0.0.tgz#02bf338055cdcd3c5b3e8d528afe6d967985cf11" + integrity sha512-DGN4cQd30mUaAB349gKeoDTt7acviBERnNYlyk8G+PlobuomTSEohJri5Jo4X+/5oRJPJngGX2VBq7YwMHiing== + dependencies: + node-gyp-build "^4.5.0" + +"@datadog/native-iast-taint-tracking@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@datadog/native-iast-taint-tracking/-/native-iast-taint-tracking-1.0.0.tgz#d875cf0a3ef3907c27311386f85b3f3a9d99431b" + integrity sha512-fS7XoRE5T4JQ7UzWjNT/wZQhS6nmLDwt12IDcSBZfRRJ2VyFth5GvOlQtCPa6Q0k7WMIrt9UXIl/v807cVq1SQ== + dependencies: + node-gyp-build "^3.9.0" + +"@datadog/native-metrics@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@datadog/native-metrics/-/native-metrics-1.5.0.tgz#e71b6b6d65f4bd58dfdffab2737890e8eef34584" + integrity sha512-K63XMDx74RLhOpM8I9GGZR9ft0CNNB/RkjYPLHcVGvVnBR47zmWE2KFa7Yrtzjbk73+88PXI4nzqLyR3PJsaIQ== + dependencies: + node-gyp-build "^3.9.0" + +"@datadog/pprof@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@datadog/pprof/-/pprof-1.1.1.tgz#17e86035140523ac3a96f3662e5dd29822042d61" + integrity sha512-5lYXUpikQhrJwzODtJ7aFM0oKmPccISnTCecuWhjxIj4/7UJv0DamkLak634bgEW+kiChgkKFDapHSesuXRDXQ== dependencies: delay "^5.0.0" findit2 "^2.2.3" - nan "^2.16.0" node-gyp-build "^3.9.0" p-limit "^3.1.0" pify "^5.0.0" protobufjs "^7.0.0" - rimraf "^3.0.2" - semver "^7.3.5" source-map "^0.7.3" split "^1.0.1" @@ -2582,13 +2609,6 @@ magic-string "^0.25.0" string.prototype.matchall "^4.0.6" -"@theo.gravity/datadog-apm@^3.0.0": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@theo.gravity/datadog-apm/-/datadog-apm-3.0.1.tgz#25a1e1aa40a72a121871a939e340208c9ad19138" - integrity sha512-jzPKRWaVIjvbMaM1b7N5kQG8y9c7NrCkesAtlSpqhnXlyHjODOXVWdLi36H0NAr+xg9+oZ+Cja6NukJc2wGRWg== - dependencies: - dd-trace "^2.12.1" - "@tippyjs/react@^4.2.6": version "4.2.6" resolved "https://registry.yarnpkg.com/@tippyjs/react/-/react-4.2.6.tgz#971677a599bf663f20bb1c60a62b9555b749cc71" @@ -2674,6 +2694,13 @@ resolved "https://registry.yarnpkg.com/@types/body-scroll-lock/-/body-scroll-lock-3.1.0.tgz#435f6abf682bf58640e1c2ee5978320b891970e7" integrity sha512-3owAC4iJub5WPqRhxd8INarF2bWeQq1yQHBgYhN0XLBJMpd5ED10RrJ3aKiAwlTyL5wK7RkBD4SZUQz2AAAMdA== +"@types/buffer-from@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@types/buffer-from/-/buffer-from-1.1.0.tgz#fed6287e90fe524dc2b412e0fbc2222c1889c21f" + integrity sha512-BLFpLBcN+RPKUsFxqRkMiwqTOOdi+TrKr5OpLJ9qCnUdSxS6S80+QRX/mIhfR66u0Ykc4QTkReaejOM2ILh+9Q== + dependencies: + "@types/node" "*" + "@types/cheerio@*": version "0.22.30" resolved "https://registry.yarnpkg.com/@types/cheerio/-/cheerio-0.22.30.tgz#6c1ded70d20d890337f0f5144be2c5e9ce0936e6" @@ -3105,7 +3132,7 @@ "@types/node" "*" form-data "^3.0.0" -"@types/node@*", "@types/node@18.0.6", "@types/node@>=10.0.0", "@types/node@>=12", "@types/node@>=13.7.0": +"@types/node@*", "@types/node@18.0.6", "@types/node@>=10.0.0", "@types/node@>=13.7.0": version "18.0.6" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.0.6.tgz#0ba49ac517ad69abe7a1508bc9b3a5483df9d5d7" integrity sha512-/xUq6H2aQm261exT6iZTMifUySEt4GR5KX8eYyY+C4MSNPqSh9oNIP7tz2GLKTlFaiBbgZNxffoR3CVRG+cljw== @@ -3129,6 +3156,11 @@ resolved "https://registry.yarnpkg.com/@types/orderedmap/-/orderedmap-1.0.0.tgz#807455a192bba52cbbb4517044bc82bdbfa8c596" integrity sha512-dxKo80TqYx3YtBipHwA/SdFmMMyLCnP+5mkEqN0eMjcTBzHkiiX0ES118DsjDBjvD+zeSsSU9jULTZ+frog+Gw== +"@types/pako@^1.0.3": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@types/pako/-/pako-1.0.4.tgz#b4262aef92680a9331fcdb8420c69cf3dd98d3f3" + integrity sha512-Z+5bJSm28EXBSUJEgx29ioWeEEHUh6TiMkZHDhLwjc9wVFH+ressbkmX6waUZc5R3Gobn4Qu5llGxaoflZ+yhA== + "@types/parse-json@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" @@ -4632,11 +4664,6 @@ big.js@^5.2.2: resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== -bignumber.js@^9.0.0: - version "9.0.1" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5" - integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA== - binary-extensions@^1.0.0: version "1.13.1" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" @@ -4846,6 +4873,11 @@ bser@2.1.1: dependencies: node-int64 "^0.4.0" +btoa@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/btoa/-/btoa-1.2.1.tgz#01a9909f8b2c93f6bf680ba26131eb30f7fa3d73" + integrity sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g== + buffer-equal-constant-time@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" @@ -4861,7 +4893,7 @@ buffer-equal@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe" integrity sha1-WWFrSYME1Var1GaWayLu2j7KX74= -buffer-from@^1.0.0: +buffer-from@^1.0.0, buffer-from@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== @@ -5743,7 +5775,7 @@ cron-parser@^4.2.1: dependencies: luxon "^3.0.1" -cross-fetch@3.1.5, cross-fetch@^3.0.4: +cross-fetch@3.1.5, cross-fetch@^3.0.4, cross-fetch@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== @@ -6208,29 +6240,30 @@ data-urls@^3.0.1, data-urls@^3.0.2: whatwg-mimetype "^3.0.0" whatwg-url "^11.0.0" -datadog-metrics@^0.9.3: - version "0.9.3" - resolved "https://registry.yarnpkg.com/datadog-metrics/-/datadog-metrics-0.9.3.tgz#e62d92b9619129805802d82111c8bcc4439fc859" - integrity sha512-BVsBX2t+4yA3tHs7DnB5H01cHVNiGJ/bHA8y6JppJDyXG7s2DLm6JaozPGpgsgVGd42Is1CHRG/yMDQpt877Xg== +datadog-metrics@^0.10.2: + version "0.10.2" + resolved "https://registry.yarnpkg.com/datadog-metrics/-/datadog-metrics-0.10.2.tgz#aece2c45874f0d8b7640ef93937f859517c535ed" + integrity sha512-GP1zqzTJz0hjxbpD3LRutrKi9keGqnfq9O7z8tNgFaKGwuqSKH5cpwW7vvh6K8N43QJRFLyXACVmnv/aqEvylA== dependencies: - debug "3.1.0" - dogapi "2.8.4" + "@datadog/datadog-api-client" "^1.3.0" + debug "^4.1.0" date-fns@^2.25.0, date-fns@^2.28.0, date-fns@^2.29.1: version "2.29.2" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.2.tgz#0d4b3d0f3dff0f920820a070920f0d9662c51931" integrity sha512-0VNbwmWJDS/G3ySwFSJA3ayhbURMTJLtwM2DTxf9CWondCnh6DTNlO9JgRSq6ibf4eD0lfMJNBxUdEAHHix+bA== -dd-trace@^2.12.1: - version "2.18.0" - resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-2.18.0.tgz#04638b4aec21b5d62dcbd06c3beab52abd2cb84f" - integrity sha512-1UVo3knRHA39/X5/qgBKjPmfjss7bSJcZAESk3g4FA9jmTh8NbozfWDbvk+nBXJI20Fcgc+Jamf0I9w5KAceRg== +dd-trace@^3.9.3: + version "3.9.3" + resolved "https://registry.yarnpkg.com/dd-trace/-/dd-trace-3.9.3.tgz#99c44a30a172fb7f91f75e18ff7f7001df54854b" + integrity sha512-30F9AoYozo9v3I6ycmDJl22XLbLapo2SmirAJh6ULjQ8q/Gb9yP1vf57bnFlTWjtdFgxxeBxVY/ksnTRzZcsew== dependencies: - "@datadog/native-appsec" "^1.2.1" - "@datadog/native-metrics" "^1.4.3" - "@datadog/pprof" "^1.0.2" + "@datadog/native-appsec" "2.0.0" + "@datadog/native-iast-rewriter" "1.0.0" + "@datadog/native-iast-taint-tracking" "1.0.0" + "@datadog/native-metrics" "^1.5.0" + "@datadog/pprof" "^1.1.1" "@datadog/sketches-js" "^2.1.0" - "@types/node" ">=12" crypto-randomuuid "^1.0.0" diagnostics_channel "^1.1.0" ignore "^5.2.0" @@ -6248,6 +6281,7 @@ dd-trace@^2.12.1: module-details-from-path "^1.0.3" opentracing ">=0.12.1" path-to-regexp "^0.1.2" + protobufjs "^7.1.2" retry "^0.10.1" semver "^5.5.0" @@ -6256,13 +6290,6 @@ de-indent@^1.0.2: resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" integrity sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0= -debug@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" @@ -6309,11 +6336,6 @@ deep-equal@~1.0.1: resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU= -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -6424,11 +6446,6 @@ destroy@^1.0.4: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= -detect-libc@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== - detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" @@ -6520,17 +6537,6 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" -dogapi@2.8.4: - version "2.8.4" - resolved "https://registry.yarnpkg.com/dogapi/-/dogapi-2.8.4.tgz#ada64f20c6acdea206b9fd9e70df0c96241b6621" - integrity sha512-065fsvu5dB0o4+ENtLjZILvXMClDNH/yA9H6L8nsdcNiz9l0Hzpn7aQaCOPYXxqyzq4CRPOdwkFXUjDOXfRGbg== - dependencies: - extend "^3.0.2" - json-bigint "^1.0.0" - lodash "^4.17.21" - minimist "^1.2.5" - rc "^1.2.8" - dom-converter@^0.2: version "0.2.0" resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" @@ -6713,6 +6719,11 @@ duplexify@^3.4.2, duplexify@^3.6.0: readable-stream "^2.0.0" stream-shift "^1.0.0" +durations@^3.4.2: + version "3.4.2" + resolved "https://registry.yarnpkg.com/durations/-/durations-3.4.2.tgz#1de230454373cccfecab927de0bebae2295301db" + integrity sha512-V/lf7y33dGaypZZetVI1eu7BmvkbC4dItq12OElLRpKuaU5JxQstV2zHwLv8P7cNbQ+KL1WD80zMCTx5dNC4dg== + eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" @@ -7063,6 +7074,11 @@ es6-iterator@^2.0.3: es5-ext "^0.10.35" es6-symbol "^3.1.1" +es6-promise@^4.2.4: + version "4.2.8" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" + integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== + es6-symbol@^3.1.1, es6-symbol@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" @@ -7511,7 +7527,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: assign-symbols "^1.0.0" is-extendable "^1.0.1" -extend@^3.0.0, extend@^3.0.2: +extend@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== @@ -8829,7 +8845,7 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -ini@^1.3.4, ini@~1.3.0: +ini@^1.3.4: version "1.3.7" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84" integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ== @@ -9950,13 +9966,6 @@ jsesc@~0.5.0: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= -json-bigint@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-bigint/-/json-bigint-1.0.0.tgz#ae547823ac0cad8398667f8cd9ef4730f5b01ff1" - integrity sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ== - dependencies: - bignumber.js "^9.0.0" - json-loader@0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d" @@ -10628,6 +10637,11 @@ logform@^2.2.0: ms "^2.1.1" triple-beam "^1.3.0" +loglevel@^1.7.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.8.1.tgz#5c621f83d5b48c54ae93b6156353f555963377b4" + integrity sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg== + long@^5.0.0: version "5.2.0" resolved "https://registry.yarnpkg.com/long/-/long-5.2.0.tgz#2696dadf4b4da2ce3f6f6b89186085d94d52fd61" @@ -11171,7 +11185,7 @@ mz@^2.4.0: object-assign "^4.0.1" thenify-all "^1.0.0" -nan@^2.12.1, nan@^2.16.0: +nan@^2.12.1: version "2.17.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb" integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ== @@ -11268,6 +11282,11 @@ node-gyp-build@^3.9.0: resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-3.9.0.tgz#53a350187dd4d5276750da21605d1cb681d09e25" integrity sha512-zLcTg6P4AbcHPq465ZMFNXx7XpKKJh+7kkN699NiQWisR2uWYOWNWqRHAmbnmKiL4e9aLSlmy5U7rEMUXV59+A== +node-gyp-build@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.5.0.tgz#7a64eefa0b21112f89f58379da128ac177f20e40" + integrity sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg== + node-htmldiff@^0.9.4: version "0.9.4" resolved "https://registry.yarnpkg.com/node-htmldiff/-/node-htmldiff-0.9.4.tgz#d8fec52fbe736780afff28d2c8476ec106520887" @@ -11699,6 +11718,11 @@ pako@^1.0.5, pako@~1.0.2, pako@~1.0.5: resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== +pako@^2.0.4: + version "2.1.0" + resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86" + integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug== + parallel-transform@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" @@ -12449,7 +12473,7 @@ proto-list@~1.2.1: resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= -protobufjs@^7.0.0: +protobufjs@^7.0.0, protobufjs@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.1.2.tgz#a0cf6aeaf82f5625bffcf5a38b7cd2a7de05890c" integrity sha512-4ZPTPkXCdel3+L81yw3dG6+Kq3umdWKh7Dc7GW/CpNk4SX3hK58iPCWeCyhVTDrbkNeKrYNZ7EojM5WDaEWTLQ== @@ -12682,16 +12706,6 @@ raw-loader@^0.5.1: resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-0.5.1.tgz#0c3d0beaed8a01c966d9787bf778281252a979aa" integrity sha1-DD0L6u2KAclm2Xh793goElKpeao= -rc@^1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - react-avatar-editor@^13.0.0: version "13.0.0" resolved "https://registry.yarnpkg.com/react-avatar-editor/-/react-avatar-editor-13.0.0.tgz#55013625ee9ae715c1fe2dc553b8079994d8a5f2" @@ -14342,11 +14356,6 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - style-data@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/style-data/-/style-data-2.0.0.tgz#1cea7cf3b7658170b1addfbc7ee1036185318c06" @@ -14519,7 +14528,7 @@ tapable@^2.0.0, tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== -tar@^6.0.2, tar@^6.1.11: +tar@^6.0.2: version "6.1.11" resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== @@ -15164,7 +15173,7 @@ url-loader@^4.1.1: mime-types "^2.1.27" schema-utils "^3.0.0" -url-parse@^1.5.3: +url-parse@^1.4.3, url-parse@^1.5.3: version "1.5.10" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==