commit
e870188be3
17 changed files with 1009 additions and 31 deletions
18
config/otel_dev/README.md
Normal file
18
config/otel_dev/README.md
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
# OpenTelemetry Collector for development
|
||||||
|
|
||||||
|
This directory contains a docker compose file that starts a jaeger all-in-one instance
|
||||||
|
with an in-memory database, along with a standalone OpenTelemetry collector that forwards
|
||||||
|
traces into the jaeger. Jaeger has a built-in OpenTelemetry collector, but it can't be
|
||||||
|
configured to send CORS headers so can't be used from a browser. This sets the config on
|
||||||
|
the collector to send CORS headers.
|
||||||
|
|
||||||
|
This also adds an nginx to add CORS headers to the jaeger query endpoint, such that it can
|
||||||
|
be used from webapps like stalk (https://deniz.co/stalk/). The CORS enabled endpoint is
|
||||||
|
exposed on port 16687. To use stalk, you should simply be able to navigate to it and add
|
||||||
|
http://127.0.0.1:16687/api as a data source.
|
||||||
|
|
||||||
|
(Yes, we could enable the OTLP collector in jaeger all-in-one and passed this through
|
||||||
|
the nginx to enable CORS too, rather than running a separate collector. There's no reason
|
||||||
|
it's done this way other than that I'd already set up the separate collector.)
|
||||||
|
|
||||||
|
Running `docker compose up` in this directory should be all you need.
|
||||||
41
config/otel_dev/collector-gateway.yaml
Normal file
41
config/otel_dev/collector-gateway.yaml
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
receivers:
|
||||||
|
otlp:
|
||||||
|
protocols:
|
||||||
|
http:
|
||||||
|
endpoint: 0.0.0.0:4318
|
||||||
|
cors:
|
||||||
|
allowed_origins:
|
||||||
|
# This can't be '*' because opentelemetry-js uses sendBeacon which always operates
|
||||||
|
# in 'withCredentials' mode, which browsers don't allow with an allow-origin of '*'
|
||||||
|
#- "https://pr976--element-call.netlify.app"
|
||||||
|
- "https://*"
|
||||||
|
allowed_headers:
|
||||||
|
- "*"
|
||||||
|
processors:
|
||||||
|
batch:
|
||||||
|
timeout: 1s
|
||||||
|
resource:
|
||||||
|
attributes:
|
||||||
|
- key: test.key
|
||||||
|
value: "test-value"
|
||||||
|
action: insert
|
||||||
|
exporters:
|
||||||
|
logging:
|
||||||
|
loglevel: info
|
||||||
|
jaeger:
|
||||||
|
endpoint: jaeger-all-in-one:14250
|
||||||
|
tls:
|
||||||
|
insecure: true
|
||||||
|
extensions:
|
||||||
|
health_check:
|
||||||
|
pprof:
|
||||||
|
endpoint: :1888
|
||||||
|
zpages:
|
||||||
|
endpoint: :55679
|
||||||
|
service:
|
||||||
|
extensions: [pprof, zpages, health_check]
|
||||||
|
pipelines:
|
||||||
|
traces:
|
||||||
|
receivers: [otlp]
|
||||||
|
processors: [batch, resource]
|
||||||
|
exporters: [logging, jaeger]
|
||||||
29
config/otel_dev/docker-compose.yaml
Normal file
29
config/otel_dev/docker-compose.yaml
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
version: "2"
|
||||||
|
services:
|
||||||
|
# Jaeger
|
||||||
|
jaeger-all-in-one:
|
||||||
|
image: jaegertracing/all-in-one:latest
|
||||||
|
ports:
|
||||||
|
- "16686:16686"
|
||||||
|
- "14268"
|
||||||
|
- "14250"
|
||||||
|
# Collector
|
||||||
|
collector-gateway:
|
||||||
|
image: otel/opentelemetry-collector:latest
|
||||||
|
volumes:
|
||||||
|
- ./collector-gateway.yaml:/etc/collector-gateway.yaml
|
||||||
|
command: ["--config=/etc/collector-gateway.yaml"]
|
||||||
|
ports:
|
||||||
|
- "1888:1888" # pprof extension
|
||||||
|
- "13133:13133" # health_check extension
|
||||||
|
- "4317:4317" # OTLP gRPC receiver
|
||||||
|
- "4318:4318" # OTLP HTTP receiver
|
||||||
|
- "55670:55679" # zpages extension
|
||||||
|
depends_on:
|
||||||
|
- jaeger-all-in-one
|
||||||
|
nginx:
|
||||||
|
image: nginxinc/nginx-unprivileged:latest
|
||||||
|
volumes:
|
||||||
|
- ./nginx_otel.conf:/etc/nginx/conf.d/default.conf:ro
|
||||||
|
ports:
|
||||||
|
- "16687:8080"
|
||||||
16
config/otel_dev/nginx_otel.conf
Normal file
16
config/otel_dev/nginx_otel.conf
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
server {
|
||||||
|
listen 8080;
|
||||||
|
server_name localhost;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://jaeger-all-in-one:16686/;
|
||||||
|
add_header Access-Control-Allow-Origin *;
|
||||||
|
|
||||||
|
if ($request_method = OPTIONS) {
|
||||||
|
add_header Access-Control-Allow-Origin *;
|
||||||
|
add_header Content-Type text/plain;
|
||||||
|
add_header Content-Length 0;
|
||||||
|
return 204;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -19,6 +19,13 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@juggle/resize-observer": "^3.3.1",
|
"@juggle/resize-observer": "^3.3.1",
|
||||||
"@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.14.tgz",
|
"@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.14.tgz",
|
||||||
|
"@opentelemetry/api": "^1.4.0",
|
||||||
|
"@opentelemetry/context-zone": "^1.9.1",
|
||||||
|
"@opentelemetry/exporter-jaeger": "^1.9.1",
|
||||||
|
"@opentelemetry/exporter-trace-otlp-http": "^0.35.1",
|
||||||
|
"@opentelemetry/instrumentation-document-load": "^0.31.1",
|
||||||
|
"@opentelemetry/instrumentation-user-interaction": "^0.32.1",
|
||||||
|
"@opentelemetry/sdk-trace-web": "^1.9.1",
|
||||||
"@react-aria/button": "^3.3.4",
|
"@react-aria/button": "^3.3.4",
|
||||||
"@react-aria/dialog": "^3.1.4",
|
"@react-aria/dialog": "^3.1.4",
|
||||||
"@react-aria/focus": "^3.5.0",
|
"@react-aria/focus": "^3.5.0",
|
||||||
|
|
@ -46,7 +53,7 @@
|
||||||
"i18next-browser-languagedetector": "^6.1.8",
|
"i18next-browser-languagedetector": "^6.1.8",
|
||||||
"i18next-http-backend": "^1.4.4",
|
"i18next-http-backend": "^1.4.4",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#da03c3b529576a8fcde6f2c9a171fa6cca012830",
|
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#042f2ed76c501c10dde98a31732fd92d862e2187",
|
||||||
"matrix-widget-api": "^1.3.1",
|
"matrix-widget-api": "^1.3.1",
|
||||||
"mermaid": "^8.13.8",
|
"mermaid": "^8.13.8",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
|
|
|
||||||
73
src/analytics/OtelPosthogExporter.ts
Normal file
73
src/analytics/OtelPosthogExporter.ts
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
Copyright 2023 New Vector Ltd
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { SpanExporter, ReadableSpan } from "@opentelemetry/sdk-trace-base";
|
||||||
|
import { ExportResult, ExportResultCode } from "@opentelemetry/core";
|
||||||
|
|
||||||
|
import { PosthogAnalytics } from "./PosthogAnalytics";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is implementation of {@link SpanExporter} that sends spans
|
||||||
|
* to Posthog
|
||||||
|
*/
|
||||||
|
export class PosthogSpanExporter implements SpanExporter {
|
||||||
|
/**
|
||||||
|
* Export spans.
|
||||||
|
* @param spans
|
||||||
|
* @param resultCallback
|
||||||
|
*/
|
||||||
|
async export(
|
||||||
|
spans: ReadableSpan[],
|
||||||
|
resultCallback: (result: ExportResult) => void
|
||||||
|
): Promise<void> {
|
||||||
|
console.log("POSTHOGEXPORTER", spans);
|
||||||
|
for (const span of spans) {
|
||||||
|
const sendInstantly = [
|
||||||
|
"otel_callEnded",
|
||||||
|
"otel_otherSentInstantlyEventName",
|
||||||
|
].includes(span.name);
|
||||||
|
|
||||||
|
for (const spanEvent of span.events) {
|
||||||
|
await PosthogAnalytics.instance.trackFromSpan(
|
||||||
|
{
|
||||||
|
eventName: spanEvent.name,
|
||||||
|
...spanEvent.attributes,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
send_instantly: sendInstantly,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await PosthogAnalytics.instance.trackFromSpan(
|
||||||
|
{ eventName: span.name, ...span.attributes },
|
||||||
|
{
|
||||||
|
send_instantly: sendInstantly,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
resultCallback({ code: ExportResultCode.SUCCESS });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Shutdown the exporter.
|
||||||
|
*/
|
||||||
|
shutdown(): Promise<void> {
|
||||||
|
console.log("POSTHOGEXPORTER shutdown of otelPosthogExporter");
|
||||||
|
return new Promise<void>((resolve, _reject) => {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -385,6 +385,22 @@ export class PosthogAnalytics {
|
||||||
this.capture(eventName, properties, options);
|
this.capture(eventName, properties, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async trackFromSpan(
|
||||||
|
{ eventName, ...properties },
|
||||||
|
options?: CaptureOptions
|
||||||
|
): Promise<void> {
|
||||||
|
if (this.identificationPromise) {
|
||||||
|
// only make calls to posthog after the identificaion is done
|
||||||
|
await this.identificationPromise;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
this.anonymity == Anonymity.Disabled ||
|
||||||
|
this.anonymity == Anonymity.Anonymous
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
this.capture(eventName, properties, options);
|
||||||
|
}
|
||||||
|
|
||||||
public startListeningToSettingsChanges(): void {
|
public startListeningToSettingsChanges(): void {
|
||||||
// Listen to account data changes from sync so we can observe changes to relevant flags and update.
|
// Listen to account data changes from sync so we can observe changes to relevant flags and update.
|
||||||
// This is called -
|
// This is called -
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,14 @@ export interface ConfigOptions {
|
||||||
submit_url: string;
|
submit_url: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the URL to send opentelemetry data to. If unset, opentelemetry will
|
||||||
|
* be disabled.
|
||||||
|
*/
|
||||||
|
opentelemetry?: {
|
||||||
|
collector_url: string;
|
||||||
|
};
|
||||||
|
|
||||||
// Describes the default homeserver to use. The same format as Element Web
|
// Describes the default homeserver to use. The same format as Element Web
|
||||||
// (without identity servers as we don't use them).
|
// (without identity servers as we don't use them).
|
||||||
default_server_config?: {
|
default_server_config?: {
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import * as Sentry from "@sentry/react";
|
||||||
|
|
||||||
import { getUrlParams } from "./UrlParams";
|
import { getUrlParams } from "./UrlParams";
|
||||||
import { Config } from "./config/Config";
|
import { Config } from "./config/Config";
|
||||||
|
import { ElementCallOpenTelemetry } from "./otel/otel";
|
||||||
|
|
||||||
enum LoadState {
|
enum LoadState {
|
||||||
None,
|
None,
|
||||||
|
|
@ -35,6 +36,7 @@ class DependencyLoadStates {
|
||||||
// olm: LoadState = LoadState.None;
|
// olm: LoadState = LoadState.None;
|
||||||
config: LoadState = LoadState.None;
|
config: LoadState = LoadState.None;
|
||||||
sentry: LoadState = LoadState.None;
|
sentry: LoadState = LoadState.None;
|
||||||
|
openTelemetry: LoadState = LoadState.None;
|
||||||
|
|
||||||
allDepsAreLoaded() {
|
allDepsAreLoaded() {
|
||||||
return !Object.values(this).some((s) => s !== LoadState.Loaded);
|
return !Object.values(this).some((s) => s !== LoadState.Loaded);
|
||||||
|
|
@ -209,6 +211,15 @@ export class Initializer {
|
||||||
this.loadStates.sentry = LoadState.Loaded;
|
this.loadStates.sentry = LoadState.Loaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OpenTelemetry (also only after config loaded)
|
||||||
|
if (
|
||||||
|
this.loadStates.openTelemetry === LoadState.None &&
|
||||||
|
this.loadStates.config === LoadState.Loaded
|
||||||
|
) {
|
||||||
|
ElementCallOpenTelemetry.globalInit();
|
||||||
|
this.loadStates.openTelemetry = LoadState.Loaded;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.loadStates.allDepsAreLoaded()) {
|
if (this.loadStates.allDepsAreLoaded()) {
|
||||||
// resolve if there is no dependency that is not loaded
|
// resolve if there is no dependency that is not loaded
|
||||||
resolve();
|
resolve();
|
||||||
|
|
|
||||||
301
src/otel/OTelGroupCallMembership.ts
Normal file
301
src/otel/OTelGroupCallMembership.ts
Normal file
|
|
@ -0,0 +1,301 @@
|
||||||
|
/*
|
||||||
|
Copyright 2023 New Vector Ltd
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import opentelemetry, { Span, Attributes, Context } from "@opentelemetry/api";
|
||||||
|
import {
|
||||||
|
GroupCall,
|
||||||
|
MatrixClient,
|
||||||
|
MatrixEvent,
|
||||||
|
RoomMember,
|
||||||
|
} from "matrix-js-sdk";
|
||||||
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
import {
|
||||||
|
CallError,
|
||||||
|
CallState,
|
||||||
|
MatrixCall,
|
||||||
|
VoipEvent,
|
||||||
|
} from "matrix-js-sdk/src/webrtc/call";
|
||||||
|
import {
|
||||||
|
CallsByUserAndDevice,
|
||||||
|
GroupCallError,
|
||||||
|
GroupCallEvent,
|
||||||
|
} from "matrix-js-sdk/src/webrtc/groupCall";
|
||||||
|
|
||||||
|
import { ElementCallOpenTelemetry } from "./otel";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flattens out an object into a single layer with components
|
||||||
|
* of the key separated by dots
|
||||||
|
*/
|
||||||
|
function flattenVoipEvent(event: VoipEvent): Attributes {
|
||||||
|
const flatObject = {};
|
||||||
|
|
||||||
|
flattenVoipEventRecursive(
|
||||||
|
event as unknown as Record<string, unknown>, // XXX Types
|
||||||
|
flatObject,
|
||||||
|
"matrix.event.",
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
|
return flatObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
function flattenVoipEventRecursive(
|
||||||
|
obj: Record<string, unknown>,
|
||||||
|
flatObject: Record<string, unknown>,
|
||||||
|
prefix: string,
|
||||||
|
depth: number
|
||||||
|
) {
|
||||||
|
if (depth > 10)
|
||||||
|
throw new Error(
|
||||||
|
"Depth limit exceeded: aborting VoipEvent recursion. Prefix is " + prefix
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const [k, v] of Object.entries(obj)) {
|
||||||
|
if (["string", "number"].includes(typeof v)) {
|
||||||
|
flatObject[prefix + k] = v;
|
||||||
|
} else if (typeof v === "object") {
|
||||||
|
flattenVoipEventRecursive(
|
||||||
|
v as Record<string, unknown>,
|
||||||
|
flatObject,
|
||||||
|
prefix + k + ".",
|
||||||
|
depth + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CallTrackingInfo {
|
||||||
|
userId: string;
|
||||||
|
deviceId: string;
|
||||||
|
call: MatrixCall;
|
||||||
|
span: Span;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represent the span of time which we intend to be joined to a group call
|
||||||
|
*/
|
||||||
|
export class OTelGroupCallMembership {
|
||||||
|
private callMembershipSpan?: Span;
|
||||||
|
private groupCallContext?: Context;
|
||||||
|
private myUserId: string;
|
||||||
|
private myDeviceId: string;
|
||||||
|
private myMember: RoomMember;
|
||||||
|
private callsByCallId = new Map<string, CallTrackingInfo>();
|
||||||
|
|
||||||
|
constructor(private groupCall: GroupCall, client: MatrixClient) {
|
||||||
|
this.myUserId = client.getUserId();
|
||||||
|
this.myDeviceId = client.getDeviceId();
|
||||||
|
this.myMember = groupCall.room.getMember(client.getUserId());
|
||||||
|
|
||||||
|
this.groupCall.on(GroupCallEvent.CallsChanged, this.onCallsChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
this.groupCall.removeListener(
|
||||||
|
GroupCallEvent.CallsChanged,
|
||||||
|
this.onCallsChanged
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public onJoinCall() {
|
||||||
|
// Create the main span that tracks the time we intend to be in the call
|
||||||
|
this.callMembershipSpan =
|
||||||
|
ElementCallOpenTelemetry.instance.tracer.startSpan(
|
||||||
|
"matrix.groupCallMembership"
|
||||||
|
);
|
||||||
|
this.callMembershipSpan.setAttribute(
|
||||||
|
"matrix.confId",
|
||||||
|
this.groupCall.groupCallId
|
||||||
|
);
|
||||||
|
this.callMembershipSpan.setAttribute("matrix.userId", this.myUserId);
|
||||||
|
this.callMembershipSpan.setAttribute("matrix.deviceId", this.myDeviceId);
|
||||||
|
this.callMembershipSpan.setAttribute(
|
||||||
|
"matrix.displayName",
|
||||||
|
this.myMember.name
|
||||||
|
);
|
||||||
|
|
||||||
|
this.groupCallContext = opentelemetry.trace.setSpan(
|
||||||
|
opentelemetry.context.active(),
|
||||||
|
this.callMembershipSpan
|
||||||
|
);
|
||||||
|
|
||||||
|
this.callMembershipSpan?.addEvent("matrix.joinCall");
|
||||||
|
}
|
||||||
|
|
||||||
|
public onLeaveCall() {
|
||||||
|
this.callMembershipSpan?.addEvent("matrix.leaveCall");
|
||||||
|
|
||||||
|
// and end the main span to indicate we've left
|
||||||
|
if (this.callMembershipSpan) this.callMembershipSpan.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
public onUpdateRoomState(event: MatrixEvent) {
|
||||||
|
if (
|
||||||
|
!event ||
|
||||||
|
(!event.getType().startsWith("m.call") &&
|
||||||
|
!event.getType().startsWith("org.matrix.msc3401.call"))
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.callMembershipSpan?.addEvent(
|
||||||
|
`matrix.roomStateEvent_${event.getType()}`,
|
||||||
|
flattenVoipEvent(event.getContent())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public onCallsChanged = (calls: CallsByUserAndDevice) => {
|
||||||
|
for (const [userId, userCalls] of calls.entries()) {
|
||||||
|
for (const [deviceId, call] of userCalls.entries()) {
|
||||||
|
if (!this.callsByCallId.has(call.callId)) {
|
||||||
|
const span = ElementCallOpenTelemetry.instance.tracer.startSpan(
|
||||||
|
`matrix.call`,
|
||||||
|
undefined,
|
||||||
|
this.groupCallContext
|
||||||
|
);
|
||||||
|
// XXX: anonymity
|
||||||
|
span.setAttribute("matrix.call.target.userId", userId);
|
||||||
|
span.setAttribute("matrix.call.target.deviceId", deviceId);
|
||||||
|
this.callsByCallId.set(call.callId, {
|
||||||
|
userId,
|
||||||
|
deviceId,
|
||||||
|
call,
|
||||||
|
span,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const callTrackingInfo of this.callsByCallId.values()) {
|
||||||
|
const userCalls = calls.get(callTrackingInfo.userId);
|
||||||
|
if (!userCalls || !userCalls.has(callTrackingInfo.deviceId)) {
|
||||||
|
callTrackingInfo.span.end();
|
||||||
|
this.callsByCallId.delete(callTrackingInfo.call.callId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public onCallStateChange(call: MatrixCall, newState: CallState) {
|
||||||
|
const callTrackingInfo = this.callsByCallId.get(call.callId);
|
||||||
|
if (!callTrackingInfo) {
|
||||||
|
logger.error(`Got call state change for unknown call ID ${call.callId}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
callTrackingInfo.span.addEvent("matrix.call.stateChange", {
|
||||||
|
state: newState,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public onSendEvent(call: MatrixCall, event: VoipEvent) {
|
||||||
|
const eventType = event.eventType as string;
|
||||||
|
if (!eventType.startsWith("m.call")) return;
|
||||||
|
|
||||||
|
if (event.type === "toDevice") {
|
||||||
|
this.callMembershipSpan?.addEvent(
|
||||||
|
`matrix.sendToDeviceEvent_${event.eventType}`,
|
||||||
|
flattenVoipEvent(event)
|
||||||
|
);
|
||||||
|
} else if (event.type === "sendEvent") {
|
||||||
|
this.callMembershipSpan?.addEvent(
|
||||||
|
`matrix.sendToRoomEvent_${event.eventType}`,
|
||||||
|
flattenVoipEvent(event)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public onReceivedVoipEvent(event: MatrixEvent) {
|
||||||
|
// These come straight from CallEventHandler so don't have
|
||||||
|
// a call already associated (in principle we could receive
|
||||||
|
// events for calls we don't know about).
|
||||||
|
const callId = event.getContent().call_id;
|
||||||
|
if (!callId) {
|
||||||
|
this.callMembershipSpan?.addEvent("matrix.receive_voip_event_no_callid", {
|
||||||
|
"sender.userId": event.getSender(),
|
||||||
|
});
|
||||||
|
logger.error("Received call event with no call ID!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const call = this.callsByCallId.get(callId);
|
||||||
|
if (!call) {
|
||||||
|
this.callMembershipSpan?.addEvent(
|
||||||
|
"matrix.receive_voip_event_unknown_callid",
|
||||||
|
{
|
||||||
|
"sender.userId": event.getSender(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
logger.error("Received call event for unknown call ID " + callId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
call.span.addEvent("matrix.receive_voip_event", {
|
||||||
|
"sender.userId": event.getSender(),
|
||||||
|
...flattenVoipEvent(event.getContent()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public onToggleMicrophoneMuted(newValue: boolean) {
|
||||||
|
this.callMembershipSpan?.addEvent("matrix.toggleMicMuted", {
|
||||||
|
"matrix.microphone.muted": newValue,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public onSetMicrophoneMuted(setMuted: boolean) {
|
||||||
|
this.callMembershipSpan?.addEvent("matrix.setMicMuted", {
|
||||||
|
"matrix.microphone.muted": setMuted,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public onToggleLocalVideoMuted(newValue: boolean) {
|
||||||
|
this.callMembershipSpan?.addEvent("matrix.toggleVidMuted", {
|
||||||
|
"matrix.video.muted": newValue,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public onSetLocalVideoMuted(setMuted: boolean) {
|
||||||
|
this.callMembershipSpan?.addEvent("matrix.setVidMuted", {
|
||||||
|
"matrix.video.muted": setMuted,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public onToggleScreensharing(newValue: boolean) {
|
||||||
|
this.callMembershipSpan?.addEvent("matrix.setVidMuted", {
|
||||||
|
"matrix.screensharing.enabled": newValue,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public onCallError(error: CallError, call: MatrixCall) {
|
||||||
|
const callTrackingInfo = this.callsByCallId.get(call.callId);
|
||||||
|
if (!callTrackingInfo) {
|
||||||
|
logger.error(`Got error for unknown call ID ${call.callId}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
callTrackingInfo.span.recordException(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
public onGroupCallError(error: GroupCallError) {
|
||||||
|
this.callMembershipSpan?.recordException(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
public onUndecryptableToDevice(event: MatrixEvent) {
|
||||||
|
this.callMembershipSpan?.addEvent("matrix.toDevice.undecryptable", {
|
||||||
|
"sender.userId": event.getSender(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
104
src/otel/otel.ts
Normal file
104
src/otel/otel.ts
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
Copyright 2023 New Vector Ltd
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
ConsoleSpanExporter,
|
||||||
|
SimpleSpanProcessor,
|
||||||
|
} from "@opentelemetry/sdk-trace-base";
|
||||||
|
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
|
||||||
|
import { WebTracerProvider } from "@opentelemetry/sdk-trace-web";
|
||||||
|
import opentelemetry, { Tracer } from "@opentelemetry/api";
|
||||||
|
import { Resource } from "@opentelemetry/resources";
|
||||||
|
import { SemanticResourceAttributes } from "@opentelemetry/semantic-conventions";
|
||||||
|
import { logger } from "@sentry/utils";
|
||||||
|
|
||||||
|
import { PosthogSpanExporter } from "../analytics/OtelPosthogExporter";
|
||||||
|
import { Anonymity } from "../analytics/PosthogAnalytics";
|
||||||
|
import { Config } from "../config/Config";
|
||||||
|
import { getSetting, settingsBus } from "../settings/useSetting";
|
||||||
|
|
||||||
|
const SERVICE_NAME = "element-call";
|
||||||
|
|
||||||
|
let sharedInstance: ElementCallOpenTelemetry;
|
||||||
|
|
||||||
|
export class ElementCallOpenTelemetry {
|
||||||
|
private _provider: WebTracerProvider;
|
||||||
|
private _tracer: Tracer;
|
||||||
|
private _anonymity: Anonymity;
|
||||||
|
|
||||||
|
static globalInit(): void {
|
||||||
|
settingsBus.on("opt-in-analytics", recheckOTelEnabledStatus);
|
||||||
|
recheckOTelEnabledStatus(getSetting("opt-in-analytics", false));
|
||||||
|
}
|
||||||
|
|
||||||
|
static get instance(): ElementCallOpenTelemetry {
|
||||||
|
return sharedInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(collectorUrl: string) {
|
||||||
|
const otlpExporter = new OTLPTraceExporter({
|
||||||
|
url: collectorUrl,
|
||||||
|
});
|
||||||
|
const consoleExporter = new ConsoleSpanExporter();
|
||||||
|
const posthogExporter = new PosthogSpanExporter();
|
||||||
|
|
||||||
|
// This is how we can make Jaeger show a reaonsable service in the dropdown on the left.
|
||||||
|
const providerConfig = {
|
||||||
|
resource: new Resource({
|
||||||
|
[SemanticResourceAttributes.SERVICE_NAME]: SERVICE_NAME,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
this._provider = new WebTracerProvider(providerConfig);
|
||||||
|
|
||||||
|
this._provider.addSpanProcessor(new SimpleSpanProcessor(otlpExporter));
|
||||||
|
this._provider.addSpanProcessor(new SimpleSpanProcessor(posthogExporter));
|
||||||
|
this._provider.addSpanProcessor(new SimpleSpanProcessor(consoleExporter));
|
||||||
|
opentelemetry.trace.setGlobalTracerProvider(this._provider);
|
||||||
|
|
||||||
|
this._tracer = opentelemetry.trace.getTracer(
|
||||||
|
// This is not the serviceName shown in jaeger
|
||||||
|
"my-element-call-otl-tracer"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public get tracer(): Tracer {
|
||||||
|
return this._tracer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get provider(): WebTracerProvider {
|
||||||
|
return this._provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get anonymity(): Anonymity {
|
||||||
|
return this._anonymity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function recheckOTelEnabledStatus(optInAnalayticsEnabled: boolean): void {
|
||||||
|
const shouldEnable =
|
||||||
|
optInAnalayticsEnabled &&
|
||||||
|
Boolean(Config.get().opentelemetry?.collector_url);
|
||||||
|
|
||||||
|
if (shouldEnable && !sharedInstance) {
|
||||||
|
logger.info("Starting OpenTelemetry debug reporting");
|
||||||
|
sharedInstance = new ElementCallOpenTelemetry(
|
||||||
|
Config.get().opentelemetry?.collector_url
|
||||||
|
);
|
||||||
|
} else if (!shouldEnable && sharedInstance) {
|
||||||
|
logger.info("Stopping OpenTelemetry debug reporting");
|
||||||
|
sharedInstance = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -28,14 +28,25 @@ import ReactJson, { CollapsedFieldProps } from "react-json-view";
|
||||||
import mermaid from "mermaid";
|
import mermaid from "mermaid";
|
||||||
import { Item } from "@react-stately/collections";
|
import { Item } from "@react-stately/collections";
|
||||||
import { MatrixEvent, IContent } from "matrix-js-sdk/src/models/event";
|
import { MatrixEvent, IContent } from "matrix-js-sdk/src/models/event";
|
||||||
import { GroupCall } from "matrix-js-sdk/src/webrtc/groupCall";
|
import {
|
||||||
|
GroupCall,
|
||||||
|
GroupCallError,
|
||||||
|
GroupCallEvent,
|
||||||
|
} from "matrix-js-sdk/src/webrtc/groupCall";
|
||||||
import { ClientEvent, MatrixClient } from "matrix-js-sdk/src/client";
|
import { ClientEvent, MatrixClient } from "matrix-js-sdk/src/client";
|
||||||
import { RoomStateEvent } from "matrix-js-sdk/src/models/room-state";
|
import { RoomStateEvent } from "matrix-js-sdk/src/models/room-state";
|
||||||
import { CallEvent, VoipEvent } from "matrix-js-sdk/src/webrtc/call";
|
import {
|
||||||
|
CallEvent,
|
||||||
|
CallState,
|
||||||
|
CallError,
|
||||||
|
MatrixCall,
|
||||||
|
VoipEvent,
|
||||||
|
} from "matrix-js-sdk/src/webrtc/call";
|
||||||
|
|
||||||
import styles from "./GroupCallInspector.module.css";
|
import styles from "./GroupCallInspector.module.css";
|
||||||
import { SelectInput } from "../input/SelectInput";
|
import { SelectInput } from "../input/SelectInput";
|
||||||
import { PosthogAnalytics } from "../analytics/PosthogAnalytics";
|
import { PosthogAnalytics } from "../analytics/PosthogAnalytics";
|
||||||
|
import { OTelGroupCallMembership } from "../otel/OTelGroupCallMembership";
|
||||||
|
|
||||||
interface InspectorContextState {
|
interface InspectorContextState {
|
||||||
eventsByUserId?: { [userId: string]: SequenceDiagramMatrixEvent[] };
|
eventsByUserId?: { [userId: string]: SequenceDiagramMatrixEvent[] };
|
||||||
|
|
@ -353,7 +364,7 @@ function reducer(
|
||||||
function useGroupCallState(
|
function useGroupCallState(
|
||||||
client: MatrixClient,
|
client: MatrixClient,
|
||||||
groupCall: GroupCall,
|
groupCall: GroupCall,
|
||||||
showPollCallStats: boolean
|
otelGroupCallMembership: OTelGroupCallMembership
|
||||||
): InspectorContextState {
|
): InspectorContextState {
|
||||||
const [state, dispatch] = useReducer(reducer, {
|
const [state, dispatch] = useReducer(reducer, {
|
||||||
localUserId: client.getUserId(),
|
localUserId: client.getUserId(),
|
||||||
|
|
@ -381,28 +392,55 @@ function useGroupCallState(
|
||||||
callStateEvent,
|
callStateEvent,
|
||||||
memberStateEvents,
|
memberStateEvents,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
otelGroupCallMembership?.onUpdateRoomState(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onReceivedVoipEvent(event: MatrixEvent) {
|
function onReceivedVoipEvent(event: MatrixEvent) {
|
||||||
dispatch({ type: ClientEvent.ReceivedVoipEvent, event });
|
dispatch({ type: ClientEvent.ReceivedVoipEvent, event });
|
||||||
|
|
||||||
|
otelGroupCallMembership?.onReceivedVoipEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSendVoipEvent(event: VoipEvent) {
|
function onSendVoipEvent(event: VoipEvent, call: MatrixCall) {
|
||||||
dispatch({ type: CallEvent.SendVoipEvent, rawEvent: event });
|
dispatch({ type: CallEvent.SendVoipEvent, rawEvent: event });
|
||||||
|
|
||||||
|
otelGroupCallMembership?.onSendEvent(call, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onCallStateChange(
|
||||||
|
newState: CallState,
|
||||||
|
_: CallState,
|
||||||
|
call: MatrixCall
|
||||||
|
) {
|
||||||
|
otelGroupCallMembership?.onCallStateChange(call, newState);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onCallError(error: CallError, call: MatrixCall) {
|
||||||
|
otelGroupCallMembership.onCallError(error, call);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onGroupCallError(error: GroupCallError) {
|
||||||
|
otelGroupCallMembership.onGroupCallError(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onUndecryptableToDevice(event: MatrixEvent) {
|
function onUndecryptableToDevice(event: MatrixEvent) {
|
||||||
dispatch({ type: ClientEvent.ReceivedVoipEvent, event });
|
dispatch({ type: ClientEvent.ReceivedVoipEvent, event });
|
||||||
|
|
||||||
Sentry.captureMessage("Undecryptable to-device Event");
|
Sentry.captureMessage("Undecryptable to-device Event");
|
||||||
|
// probably unnecessary if it's now captured via otel?
|
||||||
PosthogAnalytics.instance.eventUndecryptableToDevice.track(
|
PosthogAnalytics.instance.eventUndecryptableToDevice.track(
|
||||||
groupCall.groupCallId
|
groupCall.groupCallId
|
||||||
);
|
);
|
||||||
|
|
||||||
|
otelGroupCallMembership.onUndecryptableToDevice(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
client.on(RoomStateEvent.Events, onUpdateRoomState);
|
client.on(RoomStateEvent.Events, onUpdateRoomState);
|
||||||
//groupCall.on("calls_changed", onCallsChanged);
|
|
||||||
groupCall.on(CallEvent.SendVoipEvent, onSendVoipEvent);
|
groupCall.on(CallEvent.SendVoipEvent, onSendVoipEvent);
|
||||||
|
groupCall.on(CallEvent.State, onCallStateChange);
|
||||||
|
groupCall.on(CallEvent.Error, onCallError);
|
||||||
|
groupCall.on(GroupCallEvent.Error, onGroupCallError);
|
||||||
//client.on("state", onCallsChanged);
|
//client.on("state", onCallsChanged);
|
||||||
//client.on("hangup", onCallHangup);
|
//client.on("hangup", onCallHangup);
|
||||||
client.on(ClientEvent.ReceivedVoipEvent, onReceivedVoipEvent);
|
client.on(ClientEvent.ReceivedVoipEvent, onReceivedVoipEvent);
|
||||||
|
|
@ -412,8 +450,10 @@ function useGroupCallState(
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
client.removeListener(RoomStateEvent.Events, onUpdateRoomState);
|
client.removeListener(RoomStateEvent.Events, onUpdateRoomState);
|
||||||
//groupCall.removeListener("calls_changed", onCallsChanged);
|
|
||||||
groupCall.removeListener(CallEvent.SendVoipEvent, onSendVoipEvent);
|
groupCall.removeListener(CallEvent.SendVoipEvent, onSendVoipEvent);
|
||||||
|
groupCall.removeListener(CallEvent.State, onCallStateChange);
|
||||||
|
groupCall.removeListener(CallEvent.Error, onCallError);
|
||||||
|
groupCall.removeListener(GroupCallEvent.Error, onGroupCallError);
|
||||||
//client.removeListener("state", onCallsChanged);
|
//client.removeListener("state", onCallsChanged);
|
||||||
//client.removeListener("hangup", onCallHangup);
|
//client.removeListener("hangup", onCallHangup);
|
||||||
client.removeListener(ClientEvent.ReceivedVoipEvent, onReceivedVoipEvent);
|
client.removeListener(ClientEvent.ReceivedVoipEvent, onReceivedVoipEvent);
|
||||||
|
|
@ -422,7 +462,7 @@ function useGroupCallState(
|
||||||
onUndecryptableToDevice
|
onUndecryptableToDevice
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
}, [client, groupCall]);
|
}, [client, groupCall, otelGroupCallMembership]);
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
@ -430,17 +470,19 @@ function useGroupCallState(
|
||||||
interface GroupCallInspectorProps {
|
interface GroupCallInspectorProps {
|
||||||
client: MatrixClient;
|
client: MatrixClient;
|
||||||
groupCall: GroupCall;
|
groupCall: GroupCall;
|
||||||
|
otelGroupCallMembership: OTelGroupCallMembership;
|
||||||
show: boolean;
|
show: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function GroupCallInspector({
|
export function GroupCallInspector({
|
||||||
client,
|
client,
|
||||||
groupCall,
|
groupCall,
|
||||||
|
otelGroupCallMembership,
|
||||||
show,
|
show,
|
||||||
}: GroupCallInspectorProps) {
|
}: GroupCallInspectorProps) {
|
||||||
const [currentTab, setCurrentTab] = useState("sequence-diagrams");
|
const [currentTab, setCurrentTab] = useState("sequence-diagrams");
|
||||||
const [selectedUserId, setSelectedUserId] = useState<string>();
|
const [selectedUserId, setSelectedUserId] = useState<string>();
|
||||||
const state = useGroupCallState(client, groupCall, show);
|
const state = useGroupCallState(client, groupCall, otelGroupCallMembership);
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const [_, setState] = useContext(InspectorContext);
|
const [_, setState] = useContext(InspectorContext);
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,8 @@ export function GroupCallView({
|
||||||
screenshareFeeds,
|
screenshareFeeds,
|
||||||
participants,
|
participants,
|
||||||
unencryptedEventsFromUsers,
|
unencryptedEventsFromUsers,
|
||||||
} = useGroupCall(groupCall);
|
otelGroupCallMembership,
|
||||||
|
} = useGroupCall(groupCall, client);
|
||||||
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { setAudioInput, setVideoInput } = useMediaHandler();
|
const { setAudioInput, setVideoInput } = useMediaHandler();
|
||||||
|
|
@ -143,7 +144,6 @@ export function GroupCallView({
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await groupCall.enter();
|
await groupCall.enter();
|
||||||
|
|
||||||
PosthogAnalytics.instance.eventCallEnded.cacheStartCall(new Date());
|
PosthogAnalytics.instance.eventCallEnded.cacheStartCall(new Date());
|
||||||
PosthogAnalytics.instance.eventCallStarted.track(groupCall.groupCallId);
|
PosthogAnalytics.instance.eventCallStarted.track(groupCall.groupCallId);
|
||||||
|
|
||||||
|
|
@ -238,6 +238,7 @@ export function GroupCallView({
|
||||||
onLeave={onLeave}
|
onLeave={onLeave}
|
||||||
isEmbedded={isEmbedded}
|
isEmbedded={isEmbedded}
|
||||||
hideHeader={hideHeader}
|
hideHeader={hideHeader}
|
||||||
|
otelGroupCallMembership={otelGroupCallMembership}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -262,6 +263,7 @@ export function GroupCallView({
|
||||||
roomIdOrAlias={roomIdOrAlias}
|
roomIdOrAlias={roomIdOrAlias}
|
||||||
unencryptedEventsFromUsers={unencryptedEventsFromUsers}
|
unencryptedEventsFromUsers={unencryptedEventsFromUsers}
|
||||||
hideHeader={hideHeader}
|
hideHeader={hideHeader}
|
||||||
|
otelGroupCallMembership={otelGroupCallMembership}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,7 @@ import { TileDescriptor } from "../video-grid/TileDescriptor";
|
||||||
import { AudioSink } from "../video-grid/AudioSink";
|
import { AudioSink } from "../video-grid/AudioSink";
|
||||||
import { useCallViewKeyboardShortcuts } from "../useCallViewKeyboardShortcuts";
|
import { useCallViewKeyboardShortcuts } from "../useCallViewKeyboardShortcuts";
|
||||||
import { NewVideoGrid } from "../video-grid/NewVideoGrid";
|
import { NewVideoGrid } from "../video-grid/NewVideoGrid";
|
||||||
|
import { OTelGroupCallMembership } from "../otel/OTelGroupCallMembership";
|
||||||
|
|
||||||
const canScreenshare = "getDisplayMedia" in (navigator.mediaDevices ?? {});
|
const canScreenshare = "getDisplayMedia" in (navigator.mediaDevices ?? {});
|
||||||
// There is currently a bug in Safari our our code with cloning and sending MediaStreams
|
// There is currently a bug in Safari our our code with cloning and sending MediaStreams
|
||||||
|
|
@ -100,6 +101,7 @@ interface Props {
|
||||||
roomIdOrAlias: string;
|
roomIdOrAlias: string;
|
||||||
unencryptedEventsFromUsers: Set<string>;
|
unencryptedEventsFromUsers: Set<string>;
|
||||||
hideHeader: boolean;
|
hideHeader: boolean;
|
||||||
|
otelGroupCallMembership: OTelGroupCallMembership;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function InCallView({
|
export function InCallView({
|
||||||
|
|
@ -122,6 +124,7 @@ export function InCallView({
|
||||||
roomIdOrAlias,
|
roomIdOrAlias,
|
||||||
unencryptedEventsFromUsers,
|
unencryptedEventsFromUsers,
|
||||||
hideHeader,
|
hideHeader,
|
||||||
|
otelGroupCallMembership,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
usePreventScroll();
|
usePreventScroll();
|
||||||
|
|
@ -440,6 +443,7 @@ export function InCallView({
|
||||||
<GroupCallInspector
|
<GroupCallInspector
|
||||||
client={client}
|
client={client}
|
||||||
groupCall={groupCall}
|
groupCall={groupCall}
|
||||||
|
otelGroupCallMembership={otelGroupCallMembership}
|
||||||
show={showInspector}
|
show={showInspector}
|
||||||
/>
|
/>
|
||||||
{rageshakeRequestModalState.isOpen && (
|
{rageshakeRequestModalState.isOpen && (
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ import { GroupCallInspector } from "./GroupCallInspector";
|
||||||
import { OverflowMenu } from "./OverflowMenu";
|
import { OverflowMenu } from "./OverflowMenu";
|
||||||
import { Size } from "../Avatar";
|
import { Size } from "../Avatar";
|
||||||
import { ParticipantInfo } from "./useGroupCall";
|
import { ParticipantInfo } from "./useGroupCall";
|
||||||
|
import { OTelGroupCallMembership } from "../otel/OTelGroupCallMembership";
|
||||||
|
|
||||||
function getPromptText(
|
function getPromptText(
|
||||||
networkWaiting: boolean,
|
networkWaiting: boolean,
|
||||||
|
|
@ -106,6 +107,7 @@ interface Props {
|
||||||
onLeave: () => void;
|
onLeave: () => void;
|
||||||
isEmbedded: boolean;
|
isEmbedded: boolean;
|
||||||
hideHeader: boolean;
|
hideHeader: boolean;
|
||||||
|
otelGroupCallMembership: OTelGroupCallMembership;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PTTCallView: React.FC<Props> = ({
|
export const PTTCallView: React.FC<Props> = ({
|
||||||
|
|
@ -119,6 +121,7 @@ export const PTTCallView: React.FC<Props> = ({
|
||||||
onLeave,
|
onLeave,
|
||||||
isEmbedded,
|
isEmbedded,
|
||||||
hideHeader,
|
hideHeader,
|
||||||
|
otelGroupCallMembership,
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { modalState: inviteModalState, modalProps: inviteModalProps } =
|
const { modalState: inviteModalState, modalProps: inviteModalProps } =
|
||||||
|
|
@ -192,6 +195,7 @@ export const PTTCallView: React.FC<Props> = ({
|
||||||
<GroupCallInspector
|
<GroupCallInspector
|
||||||
client={client}
|
client={client}
|
||||||
groupCall={groupCall}
|
groupCall={groupCall}
|
||||||
|
otelGroupCallMembership={otelGroupCallMembership}
|
||||||
// Never shown in PTT mode, but must be present to collect call state
|
// Never shown in PTT mode, but must be present to collect call state
|
||||||
// https://github.com/vector-im/element-call/issues/328
|
// https://github.com/vector-im/element-call/issues/328
|
||||||
show={false}
|
show={false}
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,14 @@ import { CallFeed, CallFeedEvent } from "matrix-js-sdk/src/webrtc/callFeed";
|
||||||
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { IWidgetApiRequest } from "matrix-widget-api";
|
import { IWidgetApiRequest } from "matrix-widget-api";
|
||||||
|
import { MatrixClient } from "matrix-js-sdk";
|
||||||
|
|
||||||
import { usePageUnload } from "./usePageUnload";
|
import { usePageUnload } from "./usePageUnload";
|
||||||
import { PosthogAnalytics } from "../analytics/PosthogAnalytics";
|
import { PosthogAnalytics } from "../analytics/PosthogAnalytics";
|
||||||
import { TranslatedError, translatedError } from "../TranslatedError";
|
import { TranslatedError, translatedError } from "../TranslatedError";
|
||||||
import { ElementWidgetActions, ScreenshareStartData, widget } from "../widget";
|
import { ElementWidgetActions, ScreenshareStartData, widget } from "../widget";
|
||||||
|
import { OTelGroupCallMembership } from "../otel/OTelGroupCallMembership";
|
||||||
|
import { ElementCallOpenTelemetry } from "../otel/otel";
|
||||||
|
|
||||||
export enum ConnectionState {
|
export enum ConnectionState {
|
||||||
EstablishingCall = "establishing call", // call hasn't been established yet
|
EstablishingCall = "establishing call", // call hasn't been established yet
|
||||||
|
|
@ -66,6 +69,7 @@ export interface UseGroupCallReturnType {
|
||||||
participants: Map<RoomMember, Map<string, ParticipantInfo>>;
|
participants: Map<RoomMember, Map<string, ParticipantInfo>>;
|
||||||
hasLocalParticipant: boolean;
|
hasLocalParticipant: boolean;
|
||||||
unencryptedEventsFromUsers: Set<string>;
|
unencryptedEventsFromUsers: Set<string>;
|
||||||
|
otelGroupCallMembership: OTelGroupCallMembership;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
|
|
@ -84,6 +88,13 @@ interface State {
|
||||||
hasLocalParticipant: boolean;
|
hasLocalParticipant: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is a bit of a hack, but we keep the opentelemetry tracker object at the file
|
||||||
|
// level so that it doesn't pop in & out of existence as react mounts & unmounts
|
||||||
|
// components. The right solution is probably for this to live in the js-sdk and have
|
||||||
|
// the same lifetime as groupcalls themselves.
|
||||||
|
let groupCallOTelMembership: OTelGroupCallMembership;
|
||||||
|
let groupCallOTelMembershipGroupCallId: string;
|
||||||
|
|
||||||
function getParticipants(
|
function getParticipants(
|
||||||
groupCall: GroupCall
|
groupCall: GroupCall
|
||||||
): Map<RoomMember, Map<string, ParticipantInfo>> {
|
): Map<RoomMember, Map<string, ParticipantInfo>> {
|
||||||
|
|
@ -124,7 +135,10 @@ function getParticipants(
|
||||||
return participants;
|
return participants;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useGroupCall(groupCall: GroupCall): UseGroupCallReturnType {
|
export function useGroupCall(
|
||||||
|
groupCall: GroupCall,
|
||||||
|
client: MatrixClient
|
||||||
|
): UseGroupCallReturnType {
|
||||||
const [
|
const [
|
||||||
{
|
{
|
||||||
state,
|
state,
|
||||||
|
|
@ -158,6 +172,19 @@ export function useGroupCall(groupCall: GroupCall): UseGroupCallReturnType {
|
||||||
hasLocalParticipant: false,
|
hasLocalParticipant: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (groupCallOTelMembershipGroupCallId !== groupCall.groupCallId) {
|
||||||
|
if (groupCallOTelMembership) groupCallOTelMembership.dispose();
|
||||||
|
|
||||||
|
// If the user disables analytics, this will stay around until they leave the call
|
||||||
|
// so analytics will be disabled once they leave.
|
||||||
|
if (ElementCallOpenTelemetry.instance) {
|
||||||
|
groupCallOTelMembership = new OTelGroupCallMembership(groupCall, client);
|
||||||
|
groupCallOTelMembershipGroupCallId = groupCall.groupCallId;
|
||||||
|
} else {
|
||||||
|
groupCallOTelMembership = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const [unencryptedEventsFromUsers, addUnencryptedEventUser] = useReducer(
|
const [unencryptedEventsFromUsers, addUnencryptedEventUser] = useReducer(
|
||||||
(state: Set<string>, newVal: string) => {
|
(state: Set<string>, newVal: string) => {
|
||||||
return new Set(state).add(newVal);
|
return new Set(state).add(newVal);
|
||||||
|
|
@ -175,6 +202,11 @@ export function useGroupCall(groupCall: GroupCall): UseGroupCallReturnType {
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const leaveCall = useCallback(() => {
|
||||||
|
groupCallOTelMembership?.onLeaveCall();
|
||||||
|
groupCall.leave();
|
||||||
|
}, [groupCall]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// disable the media action keys, otherwise audio elements get paused when
|
// disable the media action keys, otherwise audio elements get paused when
|
||||||
// the user presses media keys or unplugs headphones, etc.
|
// the user presses media keys or unplugs headphones, etc.
|
||||||
|
|
@ -367,12 +399,12 @@ export function useGroupCall(groupCall: GroupCall): UseGroupCallReturnType {
|
||||||
onParticipantsChanged
|
onParticipantsChanged
|
||||||
);
|
);
|
||||||
groupCall.removeListener(GroupCallEvent.Error, onError);
|
groupCall.removeListener(GroupCallEvent.Error, onError);
|
||||||
groupCall.leave();
|
leaveCall();
|
||||||
};
|
};
|
||||||
}, [groupCall, updateState]);
|
}, [groupCall, updateState, leaveCall]);
|
||||||
|
|
||||||
usePageUnload(() => {
|
usePageUnload(() => {
|
||||||
groupCall.leave();
|
leaveCall();
|
||||||
});
|
});
|
||||||
|
|
||||||
const initLocalCallFeed = useCallback(
|
const initLocalCallFeed = useCallback(
|
||||||
|
|
@ -391,17 +423,21 @@ export function useGroupCall(groupCall: GroupCall): UseGroupCallReturnType {
|
||||||
PosthogAnalytics.instance.eventCallEnded.cacheStartCall(new Date());
|
PosthogAnalytics.instance.eventCallEnded.cacheStartCall(new Date());
|
||||||
PosthogAnalytics.instance.eventCallStarted.track(groupCall.groupCallId);
|
PosthogAnalytics.instance.eventCallStarted.track(groupCall.groupCallId);
|
||||||
|
|
||||||
|
// This must be called before we start trying to join the call, as we need to
|
||||||
|
// have started tracking by the time calls start getting created.
|
||||||
|
groupCallOTelMembership?.onJoinCall();
|
||||||
|
|
||||||
groupCall.enter().catch((error) => {
|
groupCall.enter().catch((error) => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
updateState({ error });
|
updateState({ error });
|
||||||
});
|
});
|
||||||
}, [groupCall, updateState]);
|
}, [groupCall, updateState]);
|
||||||
|
|
||||||
const leave = useCallback(() => groupCall.leave(), [groupCall]);
|
|
||||||
|
|
||||||
const toggleLocalVideoMuted = useCallback(() => {
|
const toggleLocalVideoMuted = useCallback(() => {
|
||||||
const toggleToMute = !groupCall.isLocalVideoMuted();
|
const toggleToMute = !groupCall.isLocalVideoMuted();
|
||||||
groupCall.setLocalVideoMuted(toggleToMute);
|
groupCall.setLocalVideoMuted(toggleToMute);
|
||||||
|
groupCallOTelMembership?.onToggleLocalVideoMuted(toggleToMute);
|
||||||
|
// TODO: These explict posthog calls should be unnecessary now with the posthog otel exporter?
|
||||||
PosthogAnalytics.instance.eventMuteCamera.track(
|
PosthogAnalytics.instance.eventMuteCamera.track(
|
||||||
toggleToMute,
|
toggleToMute,
|
||||||
groupCall.groupCallId
|
groupCall.groupCallId
|
||||||
|
|
@ -411,6 +447,7 @@ export function useGroupCall(groupCall: GroupCall): UseGroupCallReturnType {
|
||||||
const setMicrophoneMuted = useCallback(
|
const setMicrophoneMuted = useCallback(
|
||||||
(setMuted) => {
|
(setMuted) => {
|
||||||
groupCall.setMicrophoneMuted(setMuted);
|
groupCall.setMicrophoneMuted(setMuted);
|
||||||
|
groupCallOTelMembership?.onSetMicrophoneMuted(setMuted);
|
||||||
PosthogAnalytics.instance.eventMuteMicrophone.track(
|
PosthogAnalytics.instance.eventMuteMicrophone.track(
|
||||||
setMuted,
|
setMuted,
|
||||||
groupCall.groupCallId
|
groupCall.groupCallId
|
||||||
|
|
@ -421,10 +458,13 @@ export function useGroupCall(groupCall: GroupCall): UseGroupCallReturnType {
|
||||||
|
|
||||||
const toggleMicrophoneMuted = useCallback(() => {
|
const toggleMicrophoneMuted = useCallback(() => {
|
||||||
const toggleToMute = !groupCall.isMicrophoneMuted();
|
const toggleToMute = !groupCall.isMicrophoneMuted();
|
||||||
|
groupCallOTelMembership?.onToggleMicrophoneMuted(toggleToMute);
|
||||||
setMicrophoneMuted(toggleToMute);
|
setMicrophoneMuted(toggleToMute);
|
||||||
}, [groupCall, setMicrophoneMuted]);
|
}, [groupCall, setMicrophoneMuted]);
|
||||||
|
|
||||||
const toggleScreensharing = useCallback(async () => {
|
const toggleScreensharing = useCallback(async () => {
|
||||||
|
groupCallOTelMembership?.onToggleScreensharing(!groupCall.isScreensharing);
|
||||||
|
|
||||||
if (!groupCall.isScreensharing()) {
|
if (!groupCall.isScreensharing()) {
|
||||||
// toggling on
|
// toggling on
|
||||||
updateState({ requestingScreenshare: true });
|
updateState({ requestingScreenshare: true });
|
||||||
|
|
@ -525,7 +565,7 @@ export function useGroupCall(groupCall: GroupCall): UseGroupCallReturnType {
|
||||||
error,
|
error,
|
||||||
initLocalCallFeed,
|
initLocalCallFeed,
|
||||||
enter,
|
enter,
|
||||||
leave,
|
leave: leaveCall,
|
||||||
toggleLocalVideoMuted,
|
toggleLocalVideoMuted,
|
||||||
toggleMicrophoneMuted,
|
toggleMicrophoneMuted,
|
||||||
toggleScreensharing,
|
toggleScreensharing,
|
||||||
|
|
@ -537,5 +577,6 @@ export function useGroupCall(groupCall: GroupCall): UseGroupCallReturnType {
|
||||||
participants,
|
participants,
|
||||||
hasLocalParticipant,
|
hasLocalParticipant,
|
||||||
unencryptedEventsFromUsers,
|
unencryptedEventsFromUsers,
|
||||||
|
otelGroupCallMembership: groupCallOTelMembership,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
287
yarn.lock
287
yarn.lock
|
|
@ -1910,6 +1910,138 @@
|
||||||
mkdirp "^1.0.4"
|
mkdirp "^1.0.4"
|
||||||
rimraf "^3.0.2"
|
rimraf "^3.0.2"
|
||||||
|
|
||||||
|
"@opentelemetry/api@^1.4.0":
|
||||||
|
version "1.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.4.0.tgz#2c91791a9ba6ca0a0f4aaac5e45d58df13639ac8"
|
||||||
|
integrity sha512-IgMK9i3sFGNUqPMbjABm0G26g0QCKCUBfglhQ7rQq6WcxbKfEHRcmwsoER4hZcuYqJgkYn2OeuoJIv7Jsftp7g==
|
||||||
|
|
||||||
|
"@opentelemetry/context-zone-peer-dep@1.9.1":
|
||||||
|
version "1.9.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@opentelemetry/context-zone-peer-dep/-/context-zone-peer-dep-1.9.1.tgz#634b1a25eebc68484d3568865ee5a2321b6b020d"
|
||||||
|
integrity sha512-4qaNi2noNMlT3DhOzXN4qKDiyZFjowj2vnfdtcAHZUwpIP0MQlpE3JYCr+2w7zKGJDfEOp2hg2A9Dkn8TqvzSw==
|
||||||
|
|
||||||
|
"@opentelemetry/context-zone@^1.9.1":
|
||||||
|
version "1.9.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@opentelemetry/context-zone/-/context-zone-1.9.1.tgz#1f1c48fb491283ab32320b3d95e542a3a3e86035"
|
||||||
|
integrity sha512-Kx2n9ftRokgHUAI6CIxsNepCsEP/fggDBH3GT27GdZkqgPYZqBn+nlTS23dB6etjWcSRd0piJnT3OIEnaxyIGA==
|
||||||
|
dependencies:
|
||||||
|
"@opentelemetry/context-zone-peer-dep" "1.9.1"
|
||||||
|
zone.js "^0.11.0"
|
||||||
|
|
||||||
|
"@opentelemetry/core@1.9.1", "@opentelemetry/core@^1.8.0":
|
||||||
|
version "1.9.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.9.1.tgz#e343337e1a7bf30e9a6aef3ef659b9b76379762a"
|
||||||
|
integrity sha512-6/qon6tw2I8ZaJnHAQUUn4BqhTbTNRS0WP8/bA0ynaX+Uzp/DDbd0NS0Cq6TMlh8+mrlsyqDE7mO50nmv2Yvlg==
|
||||||
|
dependencies:
|
||||||
|
"@opentelemetry/semantic-conventions" "1.9.1"
|
||||||
|
|
||||||
|
"@opentelemetry/exporter-jaeger@^1.9.1":
|
||||||
|
version "1.9.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-jaeger/-/exporter-jaeger-1.9.1.tgz#941d39c2d425021c734354bbc280a4ae19f95aad"
|
||||||
|
integrity sha512-6F10NMOtBT3HdxpT0IwYf1BX8RzZB7SpqHTvZsB2vzUvxVAyoLX8+cuo6Ke9sHS9YMqoTA3rER5x9kC6NOxEMQ==
|
||||||
|
dependencies:
|
||||||
|
"@opentelemetry/core" "1.9.1"
|
||||||
|
"@opentelemetry/sdk-trace-base" "1.9.1"
|
||||||
|
"@opentelemetry/semantic-conventions" "1.9.1"
|
||||||
|
jaeger-client "^3.15.0"
|
||||||
|
|
||||||
|
"@opentelemetry/exporter-trace-otlp-http@^0.35.1":
|
||||||
|
version "0.35.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.35.1.tgz#9bf988f91fb145b29a051bce8ff5ef85029ca575"
|
||||||
|
integrity sha512-EJgAsrvscKsqb/GzF1zS74vM+Z/aQRhrFE7hs/1GK1M9bLixaVyMGwg2pxz1wdYdjxS1mqpHMhXU+VvMvFCw1w==
|
||||||
|
dependencies:
|
||||||
|
"@opentelemetry/core" "1.9.1"
|
||||||
|
"@opentelemetry/otlp-exporter-base" "0.35.1"
|
||||||
|
"@opentelemetry/otlp-transformer" "0.35.1"
|
||||||
|
"@opentelemetry/resources" "1.9.1"
|
||||||
|
"@opentelemetry/sdk-trace-base" "1.9.1"
|
||||||
|
|
||||||
|
"@opentelemetry/instrumentation-document-load@^0.31.1":
|
||||||
|
version "0.31.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-document-load/-/instrumentation-document-load-0.31.1.tgz#a535a5d1d71706701d3ff560a700b9dd03e4fb59"
|
||||||
|
integrity sha512-Ej4EB3m7GXzj4o8zF73amcnqXroN6/QdURjDAOgxN27zvvurR84larzGD7PjqgzzdtV+T7e/0BK07M0I2eA8PQ==
|
||||||
|
dependencies:
|
||||||
|
"@opentelemetry/core" "^1.8.0"
|
||||||
|
"@opentelemetry/instrumentation" "^0.35.1"
|
||||||
|
"@opentelemetry/sdk-trace-base" "^1.0.0"
|
||||||
|
"@opentelemetry/sdk-trace-web" "^1.8.0"
|
||||||
|
"@opentelemetry/semantic-conventions" "^1.0.0"
|
||||||
|
|
||||||
|
"@opentelemetry/instrumentation-user-interaction@^0.32.1":
|
||||||
|
version "0.32.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-user-interaction/-/instrumentation-user-interaction-0.32.1.tgz#654c0352c2f7d5bb6cc21f07f9ec56f18f2cc854"
|
||||||
|
integrity sha512-27we7cENzEtO2oCRiEkYG4cFe1v94ybeLvM+5jqNDkZF7UY0GlctCW+jvqf569Z3Gs7yHrakO2sZf4EMEfTFWg==
|
||||||
|
dependencies:
|
||||||
|
"@opentelemetry/core" "^1.8.0"
|
||||||
|
"@opentelemetry/instrumentation" "^0.35.1"
|
||||||
|
"@opentelemetry/sdk-trace-web" "^1.8.0"
|
||||||
|
|
||||||
|
"@opentelemetry/instrumentation@^0.35.1":
|
||||||
|
version "0.35.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.35.1.tgz#065bdbc4771137347e648eb4c6c6de6e9e97e4d1"
|
||||||
|
integrity sha512-EZsvXqxenbRTSNsft6LDcrT4pjAiyZOx3rkDNeqKpwZZe6GmZtsXaZZKuDkJtz9fTjOGjDHjZj9/h80Ya9iIJw==
|
||||||
|
dependencies:
|
||||||
|
require-in-the-middle "^5.0.3"
|
||||||
|
semver "^7.3.2"
|
||||||
|
shimmer "^1.2.1"
|
||||||
|
|
||||||
|
"@opentelemetry/otlp-exporter-base@0.35.1":
|
||||||
|
version "0.35.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.35.1.tgz#535166608d5d36e6c959b2857d01245ee3a916b1"
|
||||||
|
integrity sha512-Sc0buJIs8CfUeQCL/12vDDjBREgsqHdjboBa/kPQDgMf008OBJSM02Ijj6T1TH+QVHl/VHBBEVJF+FTf0EH9Vg==
|
||||||
|
dependencies:
|
||||||
|
"@opentelemetry/core" "1.9.1"
|
||||||
|
|
||||||
|
"@opentelemetry/otlp-transformer@0.35.1":
|
||||||
|
version "0.35.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-transformer/-/otlp-transformer-0.35.1.tgz#d4333b71324b83dbb1b0b3a4cfd769b3e214c6f9"
|
||||||
|
integrity sha512-c0HXcJ49MKoWSaA49J8PXlVx48CeEFpL0odP6KBkVT+Bw6kAe8JlI3mIezyN05VCDJGtS2I5E6WEsE+DJL1t9A==
|
||||||
|
dependencies:
|
||||||
|
"@opentelemetry/core" "1.9.1"
|
||||||
|
"@opentelemetry/resources" "1.9.1"
|
||||||
|
"@opentelemetry/sdk-metrics" "1.9.1"
|
||||||
|
"@opentelemetry/sdk-trace-base" "1.9.1"
|
||||||
|
|
||||||
|
"@opentelemetry/resources@1.9.1":
|
||||||
|
version "1.9.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.9.1.tgz#5ad3d80ba968a3a0e56498ce4bc82a6a01f2682f"
|
||||||
|
integrity sha512-VqBGbnAfubI+l+yrtYxeLyOoL358JK57btPMJDd3TCOV3mV5TNBmzvOfmesM4NeTyXuGJByd3XvOHvFezLn3rQ==
|
||||||
|
dependencies:
|
||||||
|
"@opentelemetry/core" "1.9.1"
|
||||||
|
"@opentelemetry/semantic-conventions" "1.9.1"
|
||||||
|
|
||||||
|
"@opentelemetry/sdk-metrics@1.9.1":
|
||||||
|
version "1.9.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-metrics/-/sdk-metrics-1.9.1.tgz#babc162a81df9884c16b1e67c2dd26ab478f3080"
|
||||||
|
integrity sha512-AyhKDcA8NuV7o1+9KvzRMxNbATJ8AcrutKilJ6hWSo9R5utnzxgffV4y+Hp4mJn84iXxkv+CBb99GOJ2A5OMzA==
|
||||||
|
dependencies:
|
||||||
|
"@opentelemetry/core" "1.9.1"
|
||||||
|
"@opentelemetry/resources" "1.9.1"
|
||||||
|
lodash.merge "4.6.2"
|
||||||
|
|
||||||
|
"@opentelemetry/sdk-trace-base@1.9.1", "@opentelemetry/sdk-trace-base@^1.0.0":
|
||||||
|
version "1.9.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.9.1.tgz#c349491b432a7e0ae7316f0b48b2d454d79d2b84"
|
||||||
|
integrity sha512-Y9gC5M1efhDLYHeeo2MWcDDMmR40z6QpqcWnPCm4Dmh+RHAMf4dnEBBntIe1dDpor686kyU6JV1D29ih1lZpsQ==
|
||||||
|
dependencies:
|
||||||
|
"@opentelemetry/core" "1.9.1"
|
||||||
|
"@opentelemetry/resources" "1.9.1"
|
||||||
|
"@opentelemetry/semantic-conventions" "1.9.1"
|
||||||
|
|
||||||
|
"@opentelemetry/sdk-trace-web@^1.8.0", "@opentelemetry/sdk-trace-web@^1.9.1":
|
||||||
|
version "1.9.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-web/-/sdk-trace-web-1.9.1.tgz#9734c62dfb554336779c0eb4f78bb622d8bde988"
|
||||||
|
integrity sha512-VCnr8IYW1GYonGF8M3nDqUGFjf2jcL3nlhnNyF3PKGw6OI7xNCBR+65IgW5Va7QhDP0D01jRVJ9oNuTshrVewA==
|
||||||
|
dependencies:
|
||||||
|
"@opentelemetry/core" "1.9.1"
|
||||||
|
"@opentelemetry/sdk-trace-base" "1.9.1"
|
||||||
|
"@opentelemetry/semantic-conventions" "1.9.1"
|
||||||
|
|
||||||
|
"@opentelemetry/semantic-conventions@1.9.1", "@opentelemetry/semantic-conventions@^1.0.0":
|
||||||
|
version "1.9.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.9.1.tgz#ad3367684a57879392513479e0a436cb2ac46dad"
|
||||||
|
integrity sha512-oPQdbFDmZvjXk5ZDoBGXG8B4tSB/qW5vQunJWQMFUBp7Xe8O1ByPANueJ+Jzg58esEBegyyxZ7LRmfJr7kFcFg==
|
||||||
|
|
||||||
"@pmmmwh/react-refresh-webpack-plugin@^0.5.3":
|
"@pmmmwh/react-refresh-webpack-plugin@^0.5.3":
|
||||||
version "0.5.7"
|
version "0.5.7"
|
||||||
resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.7.tgz#58f8217ba70069cc6a73f5d7e05e85b458c150e2"
|
resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.7.tgz#58f8217ba70069cc6a73f5d7e05e85b458c150e2"
|
||||||
|
|
@ -4164,6 +4296,11 @@ ansi-align@^3.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
string-width "^4.1.0"
|
string-width "^4.1.0"
|
||||||
|
|
||||||
|
ansi-color@^0.2.1:
|
||||||
|
version "0.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ansi-color/-/ansi-color-0.2.1.tgz#3e75c037475217544ed763a8db5709fa9ae5bf9a"
|
||||||
|
integrity sha512-bF6xLaZBLpOQzgYUtYEhJx090nPSZk1BQ/q2oyBK9aMMcJHzx9uXGCjI2Y+LebsN4Jwoykr0V9whbPiogdyHoQ==
|
||||||
|
|
||||||
ansi-colors@^3.0.0:
|
ansi-colors@^3.0.0:
|
||||||
version "3.2.4"
|
version "3.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf"
|
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf"
|
||||||
|
|
@ -4985,6 +5122,16 @@ buffer@^5.5.0:
|
||||||
base64-js "^1.3.1"
|
base64-js "^1.3.1"
|
||||||
ieee754 "^1.1.13"
|
ieee754 "^1.1.13"
|
||||||
|
|
||||||
|
bufrw@^1.3.0:
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/bufrw/-/bufrw-1.3.0.tgz#28d6cfdaf34300376836310f5c31d57eeb40c8fa"
|
||||||
|
integrity sha512-jzQnSbdJqhIltU9O5KUiTtljP9ccw2u5ix59McQy4pV2xGhVLhRZIndY8GIrgh5HjXa6+QJ9AQhOd2QWQizJFQ==
|
||||||
|
dependencies:
|
||||||
|
ansi-color "^0.2.1"
|
||||||
|
error "^7.0.0"
|
||||||
|
hexer "^1.5.0"
|
||||||
|
xtend "^4.0.0"
|
||||||
|
|
||||||
builtin-status-codes@^3.0.0:
|
builtin-status-codes@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
|
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
|
||||||
|
|
@ -5132,15 +5279,10 @@ camelcase@^6.2.0:
|
||||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
|
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
|
||||||
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
|
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
|
||||||
|
|
||||||
caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001335, caniuse-lite@^1.0.30001359:
|
caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001335, caniuse-lite@^1.0.30001359, caniuse-lite@^1.0.30001400:
|
||||||
version "1.0.30001363"
|
version "1.0.30001460"
|
||||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001363.tgz#26bec2d606924ba318235944e1193304ea7c4f15"
|
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001460.tgz"
|
||||||
integrity sha512-HpQhpzTGGPVMnCjIomjt+jvyUu8vNFo3TaDiZ/RcoTrlOq/5+tC8zHdsbgFB6MxmaY+jCpsH09aD80Bb4Ow3Sg==
|
integrity sha512-Bud7abqjvEjipUkpLs4D7gR0l8hBYBHoa+tGtKJHvT2AYzLp1z7EmVkUT4ERpVUfca8S2HGIVs883D8pUH1ZzQ==
|
||||||
|
|
||||||
caniuse-lite@^1.0.30001400:
|
|
||||||
version "1.0.30001425"
|
|
||||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001425.tgz#52917791a453eb3265143d2cd08d80629e82c735"
|
|
||||||
integrity sha512-/pzFv0OmNG6W0ym80P3NtapU0QEiDS3VuYAZMGoLLqiC7f6FJFe1MjpQDREGApeenD9wloeytmVDj+JLXPC6qw==
|
|
||||||
|
|
||||||
case-sensitive-paths-webpack-plugin@^2.3.0:
|
case-sensitive-paths-webpack-plugin@^2.3.0:
|
||||||
version "2.4.0"
|
version "2.4.0"
|
||||||
|
|
@ -6901,6 +7043,21 @@ error-stack-parser@^2.0.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
stackframe "^1.3.4"
|
stackframe "^1.3.4"
|
||||||
|
|
||||||
|
error@7.0.2:
|
||||||
|
version "7.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/error/-/error-7.0.2.tgz#a5f75fff4d9926126ddac0ea5dc38e689153cb02"
|
||||||
|
integrity sha512-UtVv4l5MhijsYUxPJo4390gzfZvAnTHreNnDjnTZaKIiZ/SemXxAhBkYSKtWa5RtBXbLP8tMgn/n0RUa/H7jXw==
|
||||||
|
dependencies:
|
||||||
|
string-template "~0.2.1"
|
||||||
|
xtend "~4.0.0"
|
||||||
|
|
||||||
|
error@^7.0.0:
|
||||||
|
version "7.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/error/-/error-7.2.1.tgz#eab21a4689b5f684fc83da84a0e390de82d94894"
|
||||||
|
integrity sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA==
|
||||||
|
dependencies:
|
||||||
|
string-template "~0.2.1"
|
||||||
|
|
||||||
es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5, es-abstract@^1.20.1:
|
es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5, es-abstract@^1.20.1:
|
||||||
version "1.20.1"
|
version "1.20.1"
|
||||||
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814"
|
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814"
|
||||||
|
|
@ -8581,6 +8738,16 @@ heimdalljs@^0.2.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
rsvp "~3.2.1"
|
rsvp "~3.2.1"
|
||||||
|
|
||||||
|
hexer@^1.5.0:
|
||||||
|
version "1.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/hexer/-/hexer-1.5.0.tgz#b86ce808598e8a9d1892c571f3cedd86fc9f0653"
|
||||||
|
integrity sha512-dyrPC8KzBzUJ19QTIo1gXNqIISRXQ0NwteW6OeQHRN4ZuZeHkdODfj0zHBdOlHbRY8GqbqK57C9oWSvQZizFsg==
|
||||||
|
dependencies:
|
||||||
|
ansi-color "^0.2.1"
|
||||||
|
minimist "^1.1.0"
|
||||||
|
process "^0.10.0"
|
||||||
|
xtend "^4.0.0"
|
||||||
|
|
||||||
highlight.js@^10.4.1, highlight.js@~10.7.0:
|
highlight.js@^10.4.1, highlight.js@~10.7.0:
|
||||||
version "10.7.3"
|
version "10.7.3"
|
||||||
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531"
|
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531"
|
||||||
|
|
@ -9468,6 +9635,17 @@ iterate-value@^1.0.2:
|
||||||
es-get-iterator "^1.0.2"
|
es-get-iterator "^1.0.2"
|
||||||
iterate-iterator "^1.0.1"
|
iterate-iterator "^1.0.1"
|
||||||
|
|
||||||
|
jaeger-client@^3.15.0:
|
||||||
|
version "3.19.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/jaeger-client/-/jaeger-client-3.19.0.tgz#9b5bd818ebd24e818616ee0f5cffe1722a53ae6e"
|
||||||
|
integrity sha512-M0c7cKHmdyEUtjemnJyx/y9uX16XHocL46yQvyqDlPdvAcwPDbHrIbKjQdBqtiE4apQ/9dmr+ZLJYYPGnurgpw==
|
||||||
|
dependencies:
|
||||||
|
node-int64 "^0.4.0"
|
||||||
|
opentracing "^0.14.4"
|
||||||
|
thriftrw "^3.5.0"
|
||||||
|
uuid "^8.3.2"
|
||||||
|
xorshift "^1.1.1"
|
||||||
|
|
||||||
jest-changed-files@^29.2.0:
|
jest-changed-files@^29.2.0:
|
||||||
version "29.2.0"
|
version "29.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.2.0.tgz#b6598daa9803ea6a4dce7968e20ab380ddbee289"
|
resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.2.0.tgz#b6598daa9803ea6a4dce7968e20ab380ddbee289"
|
||||||
|
|
@ -10211,7 +10389,7 @@ lodash.flow@^3.3.0:
|
||||||
resolved "https://registry.yarnpkg.com/lodash.flow/-/lodash.flow-3.5.0.tgz#87bf40292b8cf83e4e8ce1a3ae4209e20071675a"
|
resolved "https://registry.yarnpkg.com/lodash.flow/-/lodash.flow-3.5.0.tgz#87bf40292b8cf83e4e8ce1a3ae4209e20071675a"
|
||||||
integrity sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw==
|
integrity sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw==
|
||||||
|
|
||||||
lodash.merge@^4.6.2:
|
lodash.merge@4.6.2, lodash.merge@^4.6.2:
|
||||||
version "4.6.2"
|
version "4.6.2"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
||||||
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
|
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
|
||||||
|
|
@ -10239,6 +10417,11 @@ loglevel@^1.7.1:
|
||||||
resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.8.0.tgz#e7ec73a57e1e7b419cb6c6ac06bf050b67356114"
|
resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.8.0.tgz#e7ec73a57e1e7b419cb6c6ac06bf050b67356114"
|
||||||
integrity sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==
|
integrity sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==
|
||||||
|
|
||||||
|
long@^2.4.0:
|
||||||
|
version "2.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/long/-/long-2.4.0.tgz#9fa180bb1d9500cdc29c4156766a1995e1f4524f"
|
||||||
|
integrity sha512-ijUtjmO/n2A5PaosNG9ZGDsQ3vxJg7ZW8vsY8Kp0f2yIZWhSJvjmegV7t+9RPQKxKrvj8yKGehhS+po14hPLGQ==
|
||||||
|
|
||||||
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
|
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||||
|
|
@ -10362,9 +10545,9 @@ matrix-events-sdk@0.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/matrix-events-sdk/-/matrix-events-sdk-0.0.1.tgz#c8c38911e2cb29023b0bbac8d6f32e0de2c957dd"
|
resolved "https://registry.yarnpkg.com/matrix-events-sdk/-/matrix-events-sdk-0.0.1.tgz#c8c38911e2cb29023b0bbac8d6f32e0de2c957dd"
|
||||||
integrity sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA==
|
integrity sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA==
|
||||||
|
|
||||||
"matrix-js-sdk@github:matrix-org/matrix-js-sdk#da03c3b529576a8fcde6f2c9a171fa6cca012830":
|
"matrix-js-sdk@github:matrix-org/matrix-js-sdk#042f2ed76c501c10dde98a31732fd92d862e2187":
|
||||||
version "24.0.0"
|
version "24.0.0"
|
||||||
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/da03c3b529576a8fcde6f2c9a171fa6cca012830"
|
resolved "https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/042f2ed76c501c10dde98a31732fd92d862e2187"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.12.5"
|
"@babel/runtime" "^7.12.5"
|
||||||
"@matrix-org/matrix-sdk-crypto-js" "^0.1.0-alpha.5"
|
"@matrix-org/matrix-sdk-crypto-js" "^0.1.0-alpha.5"
|
||||||
|
|
@ -10387,6 +10570,14 @@ matrix-widget-api@^1.3.1:
|
||||||
"@types/events" "^3.0.0"
|
"@types/events" "^3.0.0"
|
||||||
events "^3.2.0"
|
events "^3.2.0"
|
||||||
|
|
||||||
|
matrix-widget-api@^1.3.1:
|
||||||
|
version "1.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/matrix-widget-api/-/matrix-widget-api-1.3.1.tgz#e38f404c76bb15c113909505c1c1a5b4d781c2f5"
|
||||||
|
integrity sha512-+rN6vGvnXm+fn0uq9r2KWSL/aPtehD6ObC50jYmUcEfgo8CUpf9eUurmjbRlwZkWq3XHXFuKQBUCI9UzqWg37Q==
|
||||||
|
dependencies:
|
||||||
|
"@types/events" "^3.0.0"
|
||||||
|
events "^3.2.0"
|
||||||
|
|
||||||
md5.js@^1.3.4:
|
md5.js@^1.3.4:
|
||||||
version "1.3.5"
|
version "1.3.5"
|
||||||
resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
|
resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
|
||||||
|
|
@ -10619,6 +10810,11 @@ minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
brace-expansion "^1.1.7"
|
brace-expansion "^1.1.7"
|
||||||
|
|
||||||
|
minimist@^1.1.0:
|
||||||
|
version "1.2.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
|
||||||
|
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
|
||||||
|
|
||||||
minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6:
|
minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6:
|
||||||
version "1.2.6"
|
version "1.2.6"
|
||||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
||||||
|
|
@ -10701,6 +10897,11 @@ mktemp@~0.4.0:
|
||||||
resolved "https://registry.yarnpkg.com/mktemp/-/mktemp-0.4.0.tgz#6d0515611c8a8c84e484aa2000129b98e981ff0b"
|
resolved "https://registry.yarnpkg.com/mktemp/-/mktemp-0.4.0.tgz#6d0515611c8a8c84e484aa2000129b98e981ff0b"
|
||||||
integrity sha512-IXnMcJ6ZyTuhRmJSjzvHSRhlVPiN9Jwc6e59V0bEJ0ba6OBeX2L0E+mRN1QseeOF4mM+F1Rit6Nh7o+rl2Yn/A==
|
integrity sha512-IXnMcJ6ZyTuhRmJSjzvHSRhlVPiN9Jwc6e59V0bEJ0ba6OBeX2L0E+mRN1QseeOF4mM+F1Rit6Nh7o+rl2Yn/A==
|
||||||
|
|
||||||
|
module-details-from-path@^1.0.3:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b"
|
||||||
|
integrity sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==
|
||||||
|
|
||||||
moment-mini@^2.24.0:
|
moment-mini@^2.24.0:
|
||||||
version "2.24.0"
|
version "2.24.0"
|
||||||
resolved "https://registry.yarnpkg.com/moment-mini/-/moment-mini-2.24.0.tgz#fa68d98f7fe93ae65bf1262f6abb5fb6983d8d18"
|
resolved "https://registry.yarnpkg.com/moment-mini/-/moment-mini-2.24.0.tgz#fa68d98f7fe93ae65bf1262f6abb5fb6983d8d18"
|
||||||
|
|
@ -11083,6 +11284,11 @@ open@^8.4.0:
|
||||||
is-docker "^2.1.1"
|
is-docker "^2.1.1"
|
||||||
is-wsl "^2.2.0"
|
is-wsl "^2.2.0"
|
||||||
|
|
||||||
|
opentracing@^0.14.4:
|
||||||
|
version "0.14.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/opentracing/-/opentracing-0.14.7.tgz#25d472bd0296dc0b64d7b94cbc995219031428f5"
|
||||||
|
integrity sha512-vz9iS7MJ5+Bp1URw8Khvdyw1H/hGvzHWlKQ7eRrQojSCDL1/SrWfrY9QebLw97n2deyRtzHRC3MkQfVNUCo91Q==
|
||||||
|
|
||||||
optionator@^0.8.1:
|
optionator@^0.8.1:
|
||||||
version "0.8.3"
|
version "0.8.3"
|
||||||
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
|
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
|
||||||
|
|
@ -11940,6 +12146,11 @@ process-nextick-args@^2.0.0, process-nextick-args@~2.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
||||||
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
|
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
|
||||||
|
|
||||||
|
process@^0.10.0:
|
||||||
|
version "0.10.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/process/-/process-0.10.1.tgz#842457cc51cfed72dc775afeeafb8c6034372725"
|
||||||
|
integrity sha512-dyIett8dgGIZ/TXKUzeYExt7WA6ldDzys9vTDU/cCA9L17Ypme+KzS+NjQCjpn9xsvi/shbMC+yP/BcFMBz0NA==
|
||||||
|
|
||||||
process@^0.11.10:
|
process@^0.11.10:
|
||||||
version "0.11.10"
|
version "0.11.10"
|
||||||
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
|
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
|
||||||
|
|
@ -12670,6 +12881,15 @@ require-directory@^2.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
|
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
|
||||||
integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
|
integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
|
||||||
|
|
||||||
|
require-in-the-middle@^5.0.3:
|
||||||
|
version "5.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/require-in-the-middle/-/require-in-the-middle-5.2.0.tgz#4b71e3cc7f59977100af9beb76bf2d056a5a6de2"
|
||||||
|
integrity sha512-efCx3b+0Z69/LGJmm9Yvi4cqEdxnoGnxYxGxBghkkTTFeXRtTCmmhO0AnAfHz59k957uTSuy8WaHqOs8wbYUWg==
|
||||||
|
dependencies:
|
||||||
|
debug "^4.1.1"
|
||||||
|
module-details-from-path "^1.0.3"
|
||||||
|
resolve "^1.22.1"
|
||||||
|
|
||||||
requires-port@^1.0.0:
|
requires-port@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
|
||||||
|
|
@ -12714,7 +12934,7 @@ resolve.exports@^1.1.0:
|
||||||
resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9"
|
resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9"
|
||||||
integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==
|
integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==
|
||||||
|
|
||||||
resolve@^1.1.6, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.3.2:
|
resolve@^1.1.6, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.0, resolve@^1.22.1, resolve@^1.3.2:
|
||||||
version "1.22.1"
|
version "1.22.1"
|
||||||
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
|
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
|
||||||
integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
|
integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
|
||||||
|
|
@ -13067,6 +13287,11 @@ shelljs@0.8.4:
|
||||||
interpret "^1.0.0"
|
interpret "^1.0.0"
|
||||||
rechoir "^0.6.2"
|
rechoir "^0.6.2"
|
||||||
|
|
||||||
|
shimmer@^1.2.1:
|
||||||
|
version "1.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337"
|
||||||
|
integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==
|
||||||
|
|
||||||
side-channel@^1.0.3, side-channel@^1.0.4:
|
side-channel@^1.0.3, side-channel@^1.0.4:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
|
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
|
||||||
|
|
@ -13356,6 +13581,11 @@ string-length@^4.0.1:
|
||||||
char-regex "^1.0.2"
|
char-regex "^1.0.2"
|
||||||
strip-ansi "^6.0.0"
|
strip-ansi "^6.0.0"
|
||||||
|
|
||||||
|
string-template@~0.2.1:
|
||||||
|
version "0.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/string-template/-/string-template-0.2.1.tgz#42932e598a352d01fc22ec3367d9d84eec6c9add"
|
||||||
|
integrity sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw==
|
||||||
|
|
||||||
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
|
"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
|
||||||
version "4.2.3"
|
version "4.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||||
|
|
@ -13677,6 +13907,15 @@ text-table@^0.2.0:
|
||||||
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
|
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
|
||||||
integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
|
integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
|
||||||
|
|
||||||
|
thriftrw@^3.5.0:
|
||||||
|
version "3.12.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/thriftrw/-/thriftrw-3.12.0.tgz#30857847755e7f036b2e0a79d11c9f55075539d9"
|
||||||
|
integrity sha512-4YZvR4DPEI41n4Opwr4jmrLGG4hndxr7387kzRFIIzxHQjarPusH4lGXrugvgb7TtPrfZVTpZCVe44/xUxowEw==
|
||||||
|
dependencies:
|
||||||
|
bufrw "^1.3.0"
|
||||||
|
error "7.0.2"
|
||||||
|
long "^2.4.0"
|
||||||
|
|
||||||
through2-filter@^3.0.0:
|
through2-filter@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-3.0.0.tgz#700e786df2367c2c88cd8aa5be4cf9c1e7831254"
|
resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-3.0.0.tgz#700e786df2367c2c88cd8aa5be4cf9c1e7831254"
|
||||||
|
|
@ -13866,6 +14105,11 @@ tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0:
|
||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
|
||||||
integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
|
integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
|
||||||
|
|
||||||
|
tslib@^2.3.0:
|
||||||
|
version "2.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf"
|
||||||
|
integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==
|
||||||
|
|
||||||
tsutils@^3.21.0:
|
tsutils@^3.21.0:
|
||||||
version "3.21.0"
|
version "3.21.0"
|
||||||
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
|
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
|
||||||
|
|
@ -14315,6 +14559,11 @@ uuid@^3.3.2:
|
||||||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
|
||||||
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
|
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
|
||||||
|
|
||||||
|
uuid@^8.3.2:
|
||||||
|
version "8.3.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
|
||||||
|
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
||||||
|
|
||||||
v8-compile-cache@^2.0.3:
|
v8-compile-cache@^2.0.3:
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
|
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
|
||||||
|
|
@ -14833,6 +15082,11 @@ xmlchars@^2.2.0:
|
||||||
resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
|
resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
|
||||||
integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
|
integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
|
||||||
|
|
||||||
|
xorshift@^1.1.1:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/xorshift/-/xorshift-1.2.0.tgz#30a4cdd8e9f8d09d959ed2a88c42a09c660e8148"
|
||||||
|
integrity sha512-iYgNnGyeeJ4t6U11NpA/QiKy+PXn5Aa3Azg5qkwIFz1tBLllQrjjsk9yzD7IAK0naNU4JxdeDgqW9ov4u/hc4g==
|
||||||
|
|
||||||
xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1:
|
xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1:
|
||||||
version "4.0.2"
|
version "4.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||||
|
|
@ -14904,6 +15158,13 @@ yocto-queue@^0.1.0:
|
||||||
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
||||||
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
||||||
|
|
||||||
|
zone.js@^0.11.0:
|
||||||
|
version "0.11.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.11.8.tgz#40dea9adc1ad007b5effb2bfed17f350f1f46a21"
|
||||||
|
integrity sha512-82bctBg2hKcEJ21humWIkXRlLBBmrc3nN7DFh5LGGhcyycO2S7FN8NmdvlcKaGFDNVL4/9kFLmwmInTavdJERA==
|
||||||
|
dependencies:
|
||||||
|
tslib "^2.3.0"
|
||||||
|
|
||||||
zwitch@^1.0.0:
|
zwitch@^1.0.0:
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920"
|
resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue