Improve logging #5

Merged
torjus merged 2 commits from better-logging into master 2023-12-06 01:57:58 +00:00
3 changed files with 96 additions and 27 deletions

View File

@ -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
View 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
}
}
}

View File

@ -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
} }