Improve logging #5
| @@ -4,6 +4,7 @@ import { createContext, useEffect, useState } from "react"; | |||||||
| import { MediaContainer } from "./media"; | import { MediaContainer } from "./media"; | ||||||
| import { MinistreamApiClient, StreamInfo } from "./api"; | import { MinistreamApiClient, StreamInfo } from "./api"; | ||||||
| import React from "react"; | import React from "react"; | ||||||
|  | import { Log } from "./log"; | ||||||
|  |  | ||||||
| interface AppProps { | interface AppProps { | ||||||
|     api: MinistreamApiClient |     api: MinistreamApiClient | ||||||
| @@ -33,24 +34,10 @@ export function App({ api }: AppProps) { | |||||||
|         setSelectedStream(item) |         setSelectedStream(item) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const updateStreamList = () => { |  | ||||||
|         api.listStreams().then((list) => { |  | ||||||
|             setStreamList(list) |  | ||||||
|             if (list.length != streamList.length) { |  | ||||||
|                 setStreamList(list) |  | ||||||
|                 return |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if (!list.every((_, idx) => { |  | ||||||
|                 return list[idx].streamKey === streamList[idx].streamKey |  | ||||||
|             })) { |  | ||||||
|                 setStreamList(list) |  | ||||||
|             } |  | ||||||
|         }) |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     const updateTitle = () => { |     const updateTitle = () => { | ||||||
|             api.siteInfo().then((info) => { |         api.siteInfo().then((info) => { | ||||||
|             if (info.siteName != document.title) { |             if (info.siteName != document.title) { | ||||||
|                 setTitle(info.siteName) |                 setTitle(info.siteName) | ||||||
|                 localStorage.setItem(titleKey, info.siteName) |                 localStorage.setItem(titleKey, info.siteName) | ||||||
| @@ -59,12 +46,32 @@ export function App({ api }: AppProps) { | |||||||
|         return |         return | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     setInterval(() => { |  | ||||||
|         updateStreamList() |  | ||||||
|     }, 10000) |  | ||||||
|  |  | ||||||
|     useEffect(() => { |     useEffect(() => { | ||||||
|  |         const updateStreamList = () => { | ||||||
|  |             api.listStreams().then((list) => { | ||||||
|  |                 setStreamList((current) => { | ||||||
|  |                     if (list.length != current.length) { | ||||||
|  |                         Log.Debug("Updated streamList!") | ||||||
|  |                         return list | ||||||
|  |                     } | ||||||
|  |                     if (!list.every((_, idx) => { | ||||||
|  |                         return list[idx].streamKey === current[idx].streamKey | ||||||
|  |                     })) { | ||||||
|  |                         Log.Debug("Updated streamList..") | ||||||
|  |                         return list | ||||||
|  |                     } | ||||||
|  |                     return current | ||||||
|  |                 }) | ||||||
|  |             }) | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |  | ||||||
|         updateStreamList() |         updateStreamList() | ||||||
|  |         const updateInterval = setInterval(() => { | ||||||
|  |             updateStreamList() | ||||||
|  |         }, 10000) | ||||||
|  |         return () => clearInterval(updateInterval) | ||||||
|     }, []) |     }, []) | ||||||
|  |  | ||||||
|     useEffect(() => { |     useEffect(() => { | ||||||
|   | |||||||
							
								
								
									
										61
									
								
								src/js/log.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/js/log.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | |||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | export namespace Log { | ||||||
|  |     var currentLevel: Level = "INFO" | ||||||
|  |  | ||||||
|  |     if (process.env.NODE_ENV !== 'production') {  | ||||||
|  |         currentLevel = "DEBUG" | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     export type Level = "ERROR" | "WARN" | "INFO" | "DEBUG" | ||||||
|  |  | ||||||
|  |     export function setLevel(level: Level) { | ||||||
|  |         currentLevel = level | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     export interface LogArgs { | ||||||
|  |         [key: string]: string | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     export function Error(message: string, extras?: LogArgs) { | ||||||
|  |         doLog("ERROR", message, extras) | ||||||
|  |     } | ||||||
|  |     export function Warn(message: string, extras?: LogArgs) { | ||||||
|  |         doLog("WARN", message, extras) | ||||||
|  |     } | ||||||
|  |     export function Info(message: string, extras?: LogArgs) { | ||||||
|  |         doLog("INFO", message, extras) | ||||||
|  |     } | ||||||
|  |     export function Debug(message: string, extras?: LogArgs) { | ||||||
|  |         doLog("DEBUG", message, extras) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     function doLog(level: Level, message: string, extras?: LogArgs) { | ||||||
|  |         var logLine = `[${level}] ${message}` | ||||||
|  |  | ||||||
|  |         if (extras) { | ||||||
|  |             Object.keys(extras).forEach((key) => { | ||||||
|  |                 logLine = logLine + ` ${key}=${extras[key]}` | ||||||
|  |             }) | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (levelToNumber(level) >= levelToNumber(currentLevel)) { | ||||||
|  |             console.log(logLine) | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     function levelToNumber(level: Level): number { | ||||||
|  |         switch (level) { | ||||||
|  |             case "DEBUG": | ||||||
|  |                 return 0 | ||||||
|  |             case "INFO": | ||||||
|  |                 return 1 | ||||||
|  |             case "ERROR": | ||||||
|  |                 return 2 | ||||||
|  |             case "WARN": | ||||||
|  |                 return 3 | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -2,6 +2,7 @@ import { ComponentProps, useRef, useEffect, useState } from "react" | |||||||
| import { MinistreamApiClient } from "./api" | import { MinistreamApiClient } from "./api" | ||||||
| import { resolve } from "path" | import { resolve } from "path" | ||||||
| import React from "react" | import React from "react" | ||||||
|  | import { Log } from "./log" | ||||||
|  |  | ||||||
| type MediaContainerProps = { | type MediaContainerProps = { | ||||||
|     selectedStream: string | null |     selectedStream: string | null | ||||||
| @@ -16,7 +17,7 @@ export function MediaContainer({ selectedStream, api }: MediaContainerProps) { | |||||||
|  |  | ||||||
|     // if selected stream changed, recreate pc, and set all to not ready. |     // if selected stream changed, recreate pc, and set all to not ready. | ||||||
|     useEffect(() => { |     useEffect(() => { | ||||||
|         console.log("effect: selectedStream") |         Log.Debug("Ran useEffect.", { "because_state": "selectedStream" }) | ||||||
|         setPC(new RTCPeerConnection({ |         setPC(new RTCPeerConnection({ | ||||||
|             iceServers: [{ urls: "stun:stun.l.google.com:19302" }] |             iceServers: [{ urls: "stun:stun.l.google.com:19302" }] | ||||||
|         })) |         })) | ||||||
| @@ -27,7 +28,7 @@ export function MediaContainer({ selectedStream, api }: MediaContainerProps) { | |||||||
|     }, [selectedStream]) |     }, [selectedStream]) | ||||||
|  |  | ||||||
|     useEffect(() => { |     useEffect(() => { | ||||||
|         console.log("effect: pc") |         Log.Debug("Ran useEffect.", { "because_state": "pc" }) | ||||||
|         pc.addTransceiver("video") |         pc.addTransceiver("video") | ||||||
|         pc.addTransceiver("audio") |         pc.addTransceiver("audio") | ||||||
|         pc.ontrack = (event) => { |         pc.ontrack = (event) => { | ||||||
| @@ -38,30 +39,30 @@ export function MediaContainer({ selectedStream, api }: MediaContainerProps) { | |||||||
|  |  | ||||||
|         pc.onicecandidate = (event) => { |         pc.onicecandidate = (event) => { | ||||||
|             if (!event.candidate) { |             if (!event.candidate) { | ||||||
|                 console.log("ICE gathering complete.") |                 Log.Info("ICE gathering complete.") | ||||||
|                 setICEReady(true) |                 setICEReady(true) | ||||||
|             } else { |             } else { | ||||||
|                 console.log("Adding ICE candidate: " + event.candidate) |                 Log.Debug("Adding ICE candidate.", { "candidate": event.candidate.candidate }) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         pc.oniceconnectionstatechange = () => { |         pc.oniceconnectionstatechange = () => { | ||||||
|             console.log("ICE state changed to " + pc.iceConnectionState) |             Log.Info("ICE gathering complete.") | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         pc.createOffer().then((offer) => { |         pc.createOffer().then((offer) => { | ||||||
|             pc.setLocalDescription(offer).then(() => { console.log("Local description set.") }) |             pc.setLocalDescription(offer).then(() => { Log.Debug("Local description set.") }) | ||||||
|         }) |         }) | ||||||
|     }, [pc]) |     }, [pc]) | ||||||
|  |  | ||||||
|     useEffect(() => { |     useEffect(() => { | ||||||
|         console.log("effect: iceReady") |         Log.Debug("Ran useEffect", { "because_state": "iceReady" }) | ||||||
|         if (!iceReady || !selectedStream) { |         if (!iceReady || !selectedStream) { | ||||||
|             return |             return | ||||||
|         } |         } | ||||||
|         const localOfferSdp = pc.localDescription?.sdp |         const localOfferSdp = pc.localDescription?.sdp | ||||||
|         if (!localOfferSdp) { |         if (!localOfferSdp) { | ||||||
|             console.log("Unable to get local description") |             Log.Error("Unable to get local description.") | ||||||
|             return |             return | ||||||
|         } |         } | ||||||
|         const localOffer = new RTCSessionDescription({ type: "offer", sdp: localOfferSdp }) |         const localOffer = new RTCSessionDescription({ type: "offer", sdp: localOfferSdp }) | ||||||
| @@ -73,7 +74,7 @@ export function MediaContainer({ selectedStream, api }: MediaContainerProps) { | |||||||
|     }, [iceReady]) |     }, [iceReady]) | ||||||
|  |  | ||||||
|     useEffect(() => { |     useEffect(() => { | ||||||
|         console.log("effect: remoteReady") |         Log.Debug("Ran useEffect", { "because_state": "remoteReady" }) | ||||||
|         if (!iceReady || !selectedStream || !remoteReady) { |         if (!iceReady || !selectedStream || !remoteReady) { | ||||||
|             return |             return | ||||||
|         } |         } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user