mirror of
https://github.com/vector-im/element-call.git
synced 2026-10-16 23:45:50 +00:00
Show the whole transport in debug UI and logs
A transport may soon carry a LiveKit SFU `url` instead of, or as well as, a `livekit_service_url`, so a service URL alone no longer identifies it. Pass the whole transport to the tiles' debug stats and print it as JSON in log lines instead of picking out the service URL.
This commit is contained in:
@@ -16,30 +16,21 @@ import classNames from "classnames";
|
||||
import { Modal } from "./Modal";
|
||||
import styles from "./RTCConnectionStats.module.css";
|
||||
import mediaViewStyles from "../src/tile/MediaView.module.css";
|
||||
import { type LivekitTransport } from "matrix-js-sdk/lib/matrixrtc";
|
||||
|
||||
interface Props {
|
||||
audio?: RTCInboundRtpStreamStats | RTCOutboundRtpStreamStats;
|
||||
video?: RTCInboundRtpStreamStats | RTCOutboundRtpStreamStats;
|
||||
focusUrl?: string;
|
||||
transport?: LivekitTransport;
|
||||
rtcBackendIdentity?: string;
|
||||
}
|
||||
|
||||
const extractDomain = (url: string): string => {
|
||||
try {
|
||||
const parsedUrl = new URL(url);
|
||||
return parsedUrl.hostname; // Returns "kdk.cpm"
|
||||
} catch (error) {
|
||||
console.error("Invalid URL:", error);
|
||||
return url;
|
||||
}
|
||||
};
|
||||
|
||||
// This is only used in developer mode for debugging purposes, so we don't need full localization
|
||||
export const RTCConnectionStats: FC<Props> = ({
|
||||
audio,
|
||||
video,
|
||||
focusUrl,
|
||||
transport,
|
||||
rtcBackendIdentity,
|
||||
...rest
|
||||
}) => {
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const [modalContents, setModalContents] = useState<
|
||||
@@ -76,10 +67,10 @@ export const RTCConnectionStats: FC<Props> = ({
|
||||
<Text as="span" size="xs" title="rtcBackendIdentity">
|
||||
rtcBackendIdentity:{rtcBackendIdentity}
|
||||
</Text>
|
||||
{focusUrl && (
|
||||
{transport && (
|
||||
<div>
|
||||
<Text as="span" size="xs" title="focusURL">
|
||||
{extractDomain(focusUrl)}
|
||||
<Text as="span" size="xs" title="transport">
|
||||
{JSON.stringify(transport)}
|
||||
</Text>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -635,9 +635,7 @@ export function createCallViewModel$(
|
||||
mediaDevices,
|
||||
muteStates,
|
||||
trackProcessorState$,
|
||||
logger.getChild(
|
||||
"[Publisher " + connection.transport.livekit_service_url + "]",
|
||||
),
|
||||
logger.getChild(`[Publisher ${JSON.stringify(connection.transport)}]`),
|
||||
controlledAudioDevices,
|
||||
);
|
||||
},
|
||||
@@ -829,8 +827,8 @@ export function createCallViewModel$(
|
||||
livekitRoom$: scope.behavior(
|
||||
connection$.pipe(map((c) => c?.livekitRoom)),
|
||||
),
|
||||
focusUrl$: scope.behavior(
|
||||
connection$.pipe(map((c) => c?.transport.livekit_service_url)),
|
||||
transport$: scope.behavior(
|
||||
connection$.pipe(map((c) => c?.transport)),
|
||||
),
|
||||
mediaDevices,
|
||||
pretendToBeDisconnected$: localMembership.reconnecting$,
|
||||
|
||||
@@ -334,7 +334,7 @@ export const createLocalMembership$ = ({
|
||||
),
|
||||
tap((connection) => {
|
||||
logger.info(
|
||||
`Local connection updated: ${connection?.transport?.livekit_service_url}`,
|
||||
`Local connection updated: ${JSON.stringify(connection?.transport)}`,
|
||||
);
|
||||
}),
|
||||
),
|
||||
@@ -406,7 +406,7 @@ export const createLocalMembership$ = ({
|
||||
scope.reconcile(localConnection$, async (connection) => {
|
||||
logger.info(
|
||||
"reconcile based on new localConnection:",
|
||||
connection?.transport.livekit_service_url,
|
||||
JSON.stringify(connection?.transport),
|
||||
);
|
||||
if (connection !== null) {
|
||||
const publisher = createPublisherFactory(connection);
|
||||
|
||||
@@ -45,7 +45,7 @@ export class RtcTransportAutoDiscovery {
|
||||
const backendTransport = await this.tryBackendTransports();
|
||||
if (backendTransport) {
|
||||
this.logger.info(
|
||||
`Found backend transport: ${backendTransport.livekit_service_url}`,
|
||||
`Found backend transport: ${JSON.stringify(backendTransport)}`,
|
||||
);
|
||||
return backendTransport;
|
||||
}
|
||||
@@ -54,7 +54,7 @@ export class RtcTransportAutoDiscovery {
|
||||
const configTransport = this.tryConfigTransport();
|
||||
if (configTransport) {
|
||||
this.logger.info(
|
||||
`Found app config transport: ${configTransport.livekit_service_url}`,
|
||||
`Found app config transport: ${JSON.stringify(configTransport)}`,
|
||||
);
|
||||
return configTransport;
|
||||
}
|
||||
|
||||
@@ -140,10 +140,10 @@ export class Connection {
|
||||
this.existingSFUConfig = opts.existingSFUConfig;
|
||||
this.roomId = opts.roomId;
|
||||
this.logger = logger.getChild(
|
||||
"[Connection " + opts.transport.livekit_service_url + "]",
|
||||
`[Connection ${JSON.stringify(opts.transport)}]`,
|
||||
);
|
||||
this.logger.info(
|
||||
`constructor: ${opts.transport.livekit_service_url} roomId: ${this.roomId} withSfuConfig?: ${opts.existingSFUConfig ? JSON.stringify(opts.existingSFUConfig) : "undefined"}`,
|
||||
`constructor: roomId: ${this.roomId} withSfuConfig?: ${opts.existingSFUConfig ? JSON.stringify(opts.existingSFUConfig) : "undefined"}`,
|
||||
);
|
||||
const { transport, client, scope } = opts;
|
||||
|
||||
@@ -297,9 +297,7 @@ export class Connection {
|
||||
this.existingSFUConfig ??
|
||||
(await this.getSFUConfigForRemoteConnection());
|
||||
this.logger.debug(
|
||||
"Starting Connection to: ",
|
||||
this.transport.livekit_service_url,
|
||||
"jwt: ",
|
||||
"Starting Connection - jwt: ",
|
||||
jwt,
|
||||
"wss: ",
|
||||
url,
|
||||
@@ -400,17 +398,13 @@ export class Connection {
|
||||
* If the connection is already stopped, this is a no-op.
|
||||
*/
|
||||
public async stop(): Promise<void> {
|
||||
this.logger.debug(
|
||||
`stop: disconnecing from lk room ${this.transport.livekit_service_url}`,
|
||||
);
|
||||
this.logger.debug("stop: disconnecing from lk room");
|
||||
if (this.stopped) return;
|
||||
// Mark as stopped before disconnecting so that a connect() aborted by the
|
||||
// disconnect sees the flag and does not report the abort as an error.
|
||||
this.stopped = true;
|
||||
await this.livekitRoom.disconnect();
|
||||
this._state$.next({ state: "stopped" });
|
||||
this.logger.debug(
|
||||
`stop: DONE disconnecing from lk room ${this.transport.livekit_service_url}`,
|
||||
);
|
||||
this.logger.debug("stop: DONE disconnecing from lk room");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,9 +143,9 @@ export function createRemoteMatrixLivekitMembers$({
|
||||
// Log whether the member could be matched to a LiveKit participant,
|
||||
// since a tile shows "waiting for media" for as long as it cannot.
|
||||
participant$.pipe(scope.bind()).subscribe((p) => {
|
||||
const url = data$.value.connection?.transport.livekit_service_url;
|
||||
const transport = data$.value.connection?.transport;
|
||||
logger.info(
|
||||
`[RemoteMatrixLivekitMembers] ${rtcBackendIdentity}: LiveKit participant ${p ? `matched (${p.sid})` : "missing"} on ${url ?? "no connection"}`,
|
||||
`[RemoteMatrixLivekitMembers] ${rtcBackendIdentity}: LiveKit participant ${p ? `matched (${p.sid})` : "missing"} on ${transport ? JSON.stringify(transport) : "no connection"}`,
|
||||
);
|
||||
});
|
||||
// will only get called once per backend identity.
|
||||
|
||||
@@ -40,6 +40,7 @@ import { E2eeType } from "../../e2ee/e2eeType";
|
||||
import { observeInboundRtpStreamStats$ } from "./observeRtpStreamStats";
|
||||
import { type UserMediaViewModel } from "./UserMediaViewModel";
|
||||
import { type ScreenShareViewModel } from "./ScreenShareViewModel";
|
||||
import { type LivekitTransport } from "matrix-js-sdk/lib/matrixrtc";
|
||||
|
||||
// TODO: Encryption status is kinda broken and thus unused right now. Remove?
|
||||
export enum EncryptionStatus {
|
||||
@@ -59,10 +60,10 @@ export interface BaseMemberMediaViewModel extends BaseMediaViewModel {
|
||||
*/
|
||||
video$: Behavior<TrackReference | undefined>;
|
||||
/**
|
||||
* The URL of the LiveKit focus on which this member should be publishing.
|
||||
* Exposed for debugging.
|
||||
* The LiveKit transport on which this member should be publishing. Exposed
|
||||
* for debugging.
|
||||
*/
|
||||
focusUrl$: Behavior<string | undefined>;
|
||||
transport$: Behavior<LivekitTransport | undefined>;
|
||||
/**
|
||||
* Whether there should be a warning that this media is unencrypted.
|
||||
*/
|
||||
@@ -75,7 +76,7 @@ export interface MemberMediaInputs extends BaseMediaViewModel {
|
||||
livekitRoom$: Behavior<LivekitRoom | undefined>;
|
||||
audioSource: AudioSource;
|
||||
videoSource: VideoSource;
|
||||
focusUrl$: Behavior<string | undefined>;
|
||||
transport$: Behavior<LivekitTransport | undefined>;
|
||||
encryptionSystem: EncryptionSystem;
|
||||
}
|
||||
|
||||
@@ -86,7 +87,7 @@ export function createMemberMedia(
|
||||
livekitRoom$,
|
||||
audioSource,
|
||||
videoSource,
|
||||
focusUrl$,
|
||||
transport$,
|
||||
encryptionSystem,
|
||||
...inputs
|
||||
}: MemberMediaInputs,
|
||||
@@ -109,7 +110,7 @@ export function createMemberMedia(
|
||||
return {
|
||||
...createBaseMedia(inputs),
|
||||
video$,
|
||||
focusUrl$,
|
||||
transport$,
|
||||
unencryptedWarning$: scope.behavior(
|
||||
combineLatest(
|
||||
[audio$, video$],
|
||||
|
||||
@@ -51,6 +51,7 @@ import { type RemoteUserMediaViewModel } from "../state/media/RemoteUserMediaVie
|
||||
import { type UserMediaViewModel } from "../state/media/UserMediaViewModel";
|
||||
import { type RingingMediaViewModel } from "../state/media/RingingMediaViewModel";
|
||||
import { RingingStatus } from "./RingingStatus";
|
||||
import { type LivekitTransport } from "matrix-js-sdk/lib/matrixrtc";
|
||||
|
||||
interface TileProps {
|
||||
ref?: Ref<HTMLDivElement>;
|
||||
@@ -103,7 +104,7 @@ interface UserMediaTileProps extends TileProps {
|
||||
playbackMuted: boolean;
|
||||
waitingForMedia?: boolean;
|
||||
primaryButton?: ReactNode;
|
||||
focusUrl: string | undefined;
|
||||
transport: LivekitTransport | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,7 +121,7 @@ const UserMediaTileInner: FC<UserMediaTileProps & { menu: ReactNode }> = ({
|
||||
primaryButton,
|
||||
menu,
|
||||
className,
|
||||
focusUrl,
|
||||
transport,
|
||||
displayName,
|
||||
mxcAvatarUrl,
|
||||
focusable,
|
||||
@@ -214,7 +215,7 @@ const UserMediaTileInner: FC<UserMediaTileProps & { menu: ReactNode }> = ({
|
||||
currentReaction={reaction ?? undefined}
|
||||
raisedHandOnClick={raisedHandOnClick}
|
||||
waitingForMedia={waitingForMedia}
|
||||
focusUrl={focusUrl}
|
||||
transport={transport}
|
||||
setVideoAspectRatio={vm.setVideoAspectRatio}
|
||||
audioStreamStats={audioStreamStats}
|
||||
videoStreamStats={videoStreamStats}
|
||||
@@ -279,7 +280,7 @@ const LocalUserMediaTile: FC<LocalUserMediaTileProps> = ({
|
||||
const mirror = useBehavior(vm.mirror$);
|
||||
const alwaysShow = useBehavior(vm.alwaysShow$);
|
||||
const switchCamera = useBehavior(vm.switchCamera$);
|
||||
const focusUrl = useBehavior(vm.focusUrl$);
|
||||
const transport = useBehavior(vm.transport$);
|
||||
|
||||
const latestAlwaysShow = useLatest(alwaysShow);
|
||||
const onSelectAlwaysShow = useCallback(
|
||||
@@ -334,7 +335,7 @@ const LocalUserMediaTile: FC<LocalUserMediaTileProps> = ({
|
||||
menuStart={menuStart}
|
||||
menuEnd={menuEnd}
|
||||
focusable={focusable}
|
||||
focusUrl={focusUrl}
|
||||
transport={transport}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
@@ -356,7 +357,7 @@ const RemoteUserMediaTile: FC<RemoteUserMediaTileProps> = ({
|
||||
const waitingForMedia = useBehavior(vm.waitingForMedia$);
|
||||
const playbackMuted = useBehavior(vm.playbackMuted$);
|
||||
const playbackVolume = useBehavior(vm.playbackVolume$);
|
||||
const focusUrl = useBehavior(vm.focusUrl$);
|
||||
const transport = useBehavior(vm.transport$);
|
||||
|
||||
const onSelectMute = useCallback(
|
||||
(e: Event) => {
|
||||
@@ -398,7 +399,7 @@ const RemoteUserMediaTile: FC<RemoteUserMediaTileProps> = ({
|
||||
</MenuItem>
|
||||
</>
|
||||
}
|
||||
focusUrl={focusUrl}
|
||||
transport={transport}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -33,6 +33,7 @@ import { ReactionIndicator } from "../reactions/ReactionIndicator";
|
||||
import { RTCConnectionStats } from "../RTCConnectionStats";
|
||||
import videoPlaceholder from "../graphics/video-placeholder.gif";
|
||||
import { autoVideoFit } from "../utils/videoFit";
|
||||
import { type LivekitTransport } from "matrix-js-sdk/lib/matrixrtc";
|
||||
|
||||
interface Props extends ComponentProps<typeof animated.div> {
|
||||
className?: string;
|
||||
@@ -67,9 +68,9 @@ interface Props extends ComponentProps<typeof animated.div> {
|
||||
videoStreamStats?: RTCInboundRtpStreamStats | RTCOutboundRtpStreamStats;
|
||||
rtcBackendIdentity?: string;
|
||||
/**
|
||||
* The focus url, mainly for debugging purposes.
|
||||
* The LiveKit transport, mainly for debugging purposes.
|
||||
*/
|
||||
focusUrl?: string;
|
||||
transport?: LivekitTransport;
|
||||
/**
|
||||
* Called whenever the aspect ratio of the video content becomes known or
|
||||
* otherwise changes.
|
||||
@@ -106,7 +107,7 @@ export const MediaView: FC<Props> = ({
|
||||
audioStreamStats,
|
||||
videoStreamStats,
|
||||
rtcBackendIdentity,
|
||||
focusUrl,
|
||||
transport,
|
||||
setVideoAspectRatio: setTheirVideoAspectRatio,
|
||||
...props
|
||||
}) => {
|
||||
@@ -227,7 +228,7 @@ export const MediaView: FC<Props> = ({
|
||||
<RTCConnectionStats
|
||||
audio={audioStreamStats}
|
||||
video={videoStreamStats}
|
||||
focusUrl={focusUrl}
|
||||
transport={transport}
|
||||
rtcBackendIdentity={rtcBackendIdentity}
|
||||
/>
|
||||
</>
|
||||
|
||||
@@ -54,6 +54,7 @@ import { platform } from "../Platform";
|
||||
import { type RingingMediaViewModel } from "../state/media/RingingMediaViewModel";
|
||||
import { RingingStatus } from "./RingingStatus";
|
||||
import { useRootElement } from "../RootElementContext";
|
||||
import { type LivekitTransport } from "matrix-js-sdk/lib/matrixrtc";
|
||||
|
||||
interface SpotlightItemBaseProps {
|
||||
ref?: Ref<HTMLDivElement>;
|
||||
@@ -74,7 +75,7 @@ interface SpotlightItemBaseProps {
|
||||
interface SpotlightMemberMediaItemBaseProps extends SpotlightItemBaseProps {
|
||||
video: TrackReferenceOrPlaceholder | undefined;
|
||||
unencryptedWarning: boolean;
|
||||
focusUrl: string | undefined;
|
||||
transport: LivekitTransport | undefined;
|
||||
}
|
||||
|
||||
interface SpotlightUserMediaItemBaseProps extends SpotlightMemberMediaItemBaseProps {
|
||||
@@ -177,13 +178,13 @@ const SpotlightMemberMediaItem: FC<SpotlightMemberMediaItemProps> = ({
|
||||
}) => {
|
||||
const video = useBehavior(vm.video$);
|
||||
const unencryptedWarning = useBehavior(vm.unencryptedWarning$);
|
||||
const focusUrl = useBehavior(vm.focusUrl$);
|
||||
const transport = useBehavior(vm.transport$);
|
||||
|
||||
const baseProps: SpotlightMemberMediaItemBaseProps &
|
||||
RefAttributes<HTMLDivElement> = {
|
||||
video: video ?? undefined,
|
||||
unencryptedWarning,
|
||||
focusUrl,
|
||||
transport,
|
||||
...props,
|
||||
};
|
||||
|
||||
|
||||
+3
-3
@@ -358,7 +358,7 @@ export function mockLocalMedia(
|
||||
participant$: constant(localParticipant),
|
||||
encryptionSystem: { kind: E2eeType.PER_PARTICIPANT },
|
||||
livekitRoom$: constant(mockLivekitRoom({ localParticipant })),
|
||||
focusUrl$: constant("https://rtc-example.org"),
|
||||
transport$: constant(exampleTransport),
|
||||
mediaDevices,
|
||||
displayName$: constant(member.rawDisplayName ?? "nodisplayname"),
|
||||
mxcAvatarUrl$: constant(member.getMxcAvatarUrl()),
|
||||
@@ -401,7 +401,7 @@ export function mockRemoteMedia(
|
||||
participant$: constant(participant),
|
||||
encryptionSystem: { kind: E2eeType.PER_PARTICIPANT },
|
||||
livekitRoom$: constant(livekitRoom),
|
||||
focusUrl$: constant("https://rtc-example.org"),
|
||||
transport$: constant(exampleTransport),
|
||||
pretendToBeDisconnected$: constant(false),
|
||||
displayName$: constant(member.rawDisplayName ?? "nodisplayname"),
|
||||
mxcAvatarUrl$: constant(member.getMxcAvatarUrl()),
|
||||
@@ -428,7 +428,7 @@ export function mockRemoteScreenShare(
|
||||
participant$: constant(participant),
|
||||
encryptionSystem: { kind: E2eeType.PER_PARTICIPANT },
|
||||
livekitRoom$: constant(livekitRoom),
|
||||
focusUrl$: constant("https://rtc-example.org"),
|
||||
transport$: constant(exampleTransport),
|
||||
pretendToBeDisconnected$: constant(false),
|
||||
displayName$: constant(member.rawDisplayName ?? "nodisplayname"),
|
||||
mxcAvatarUrl$: constant(member.getMxcAvatarUrl()),
|
||||
|
||||
Reference in New Issue
Block a user