mirror of
https://github.com/suitenumerique/meet.git
synced 2026-09-10 01:15:45 +00:00
Compare commits
6 Commits
fix/ack-422
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| e336122cfa | |||
| 172dc70649 | |||
| e0ab7f191f | |||
| 455b315dbb | |||
| 3089b03062 | |||
| 60febb3b57 |
@@ -13,6 +13,12 @@ and this project adheres to
|
|||||||
- 🐛(backend) acknowledge unknown LiveKit webhook events instead of 422
|
- 🐛(backend) acknowledge unknown LiveKit webhook events instead of 422
|
||||||
- 🔒️(backend) enforce display name setting on rename API
|
- 🔒️(backend) enforce display name setting on rename API
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- 📈(frontend) include LiveKit SIDs in the connection analytics event
|
||||||
|
- 🔇(backend) silence expected 401 warnings on /me
|
||||||
|
- 🔇(backend) silence noisy request summary info logs
|
||||||
|
|
||||||
## [1.31.0] - 2026-09-08
|
## [1.31.0] - 2026-09-08
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
"""Logging filters for the core application."""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
|
||||||
|
class SilenceExpected401(logging.Filter):
|
||||||
|
"""Drop the expected 401 from anonymous hits on the /me endpoint.
|
||||||
|
|
||||||
|
The frontend probes `/users/me/` to check authentication; a 401 for
|
||||||
|
anonymous users is normal, not a warning worth logging.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def filter(self, record):
|
||||||
|
"""Return False for a 401 on a silenced path, True otherwise."""
|
||||||
|
if getattr(record, "status_code", None) != 401:
|
||||||
|
return True
|
||||||
|
|
||||||
|
request = getattr(record, "request", None)
|
||||||
|
path = getattr(request, "path", None)
|
||||||
|
if not path:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return path not in settings.LOGGING_SILENCED_401_PATHS
|
||||||
@@ -469,6 +469,9 @@ class Base(Configuration):
|
|||||||
|
|
||||||
# Sentry
|
# Sentry
|
||||||
SENTRY_DSN = values.Value(None, environ_name="SENTRY_DSN")
|
SENTRY_DSN = values.Value(None, environ_name="SENTRY_DSN")
|
||||||
|
SENTRY_TRACES_SAMPLE_RATE = values.FloatValue(
|
||||||
|
0.0, environ_name="SENTRY_TRACES_SAMPLE_RATE", environ_prefix=None
|
||||||
|
)
|
||||||
|
|
||||||
# Easy thumbnails
|
# Easy thumbnails
|
||||||
THUMBNAIL_EXTENSION = "webp"
|
THUMBNAIL_EXTENSION = "webp"
|
||||||
@@ -1110,6 +1113,12 @@ class Base(Configuration):
|
|||||||
environ_prefix=None,
|
environ_prefix=None,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
LOGGING_SILENCED_401_PATHS = values.ListValue(
|
||||||
|
default=["/api/v1.0/users/me/"],
|
||||||
|
environ_name="LOGGING_SILENCED_401_PATHS",
|
||||||
|
environ_prefix=None,
|
||||||
|
)
|
||||||
|
|
||||||
# Logging
|
# Logging
|
||||||
# We want to make it easy to log to console but by default we log production
|
# We want to make it easy to log to console but by default we log production
|
||||||
# to Sentry and don't want to log to console.
|
# to Sentry and don't want to log to console.
|
||||||
@@ -1122,10 +1131,16 @@ class Base(Configuration):
|
|||||||
"style": "{",
|
"style": "{",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"filters": {
|
||||||
|
"silence_expected_401": {
|
||||||
|
"()": "core.logging_filters.SilenceExpected401",
|
||||||
|
},
|
||||||
|
},
|
||||||
"handlers": {
|
"handlers": {
|
||||||
"console": {
|
"console": {
|
||||||
"class": "logging.StreamHandler",
|
"class": "logging.StreamHandler",
|
||||||
"formatter": "simple",
|
"formatter": "simple",
|
||||||
|
"filters": ["silence_expected_401"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
# Override root logger to send it to console
|
# Override root logger to send it to console
|
||||||
@@ -1136,6 +1151,13 @@ class Base(Configuration):
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
"loggers": {
|
"loggers": {
|
||||||
|
"request.summary": {
|
||||||
|
"level": values.Value(
|
||||||
|
"WARNING",
|
||||||
|
environ_name="LOGGING_LEVEL_REQUEST_SUMMARY",
|
||||||
|
environ_prefix="",
|
||||||
|
)
|
||||||
|
},
|
||||||
"core": {
|
"core": {
|
||||||
"handlers": ["console"],
|
"handlers": ["console"],
|
||||||
"level": values.Value(
|
"level": values.Value(
|
||||||
@@ -1211,7 +1233,14 @@ class Base(Configuration):
|
|||||||
dsn=cls.SENTRY_DSN,
|
dsn=cls.SENTRY_DSN,
|
||||||
environment=cls.__name__.lower(), # build, test, development, production
|
environment=cls.__name__.lower(), # build, test, development, production
|
||||||
release=get_release(),
|
release=get_release(),
|
||||||
integrations=[DjangoIntegration()],
|
traces_sample_rate=cls.SENTRY_TRACES_SAMPLE_RATE,
|
||||||
|
integrations=[
|
||||||
|
DjangoIntegration(
|
||||||
|
transaction_style="url",
|
||||||
|
middleware_spans=True,
|
||||||
|
cache_spans=True,
|
||||||
|
)
|
||||||
|
],
|
||||||
)
|
)
|
||||||
sentry_sdk.set_tag("application", "backend")
|
sentry_sdk.set_tag("application", "backend")
|
||||||
|
|
||||||
|
|||||||
@@ -71,20 +71,30 @@ export const ConnectionObserver = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isAnalyticsEnabled) return
|
if (!isAnalyticsEnabled) return
|
||||||
|
|
||||||
const handleConnection = () => {
|
const handleConnection = async () => {
|
||||||
// Preserve original connection timestamp across reconnections to measure
|
// Preserve original connection timestamp across reconnections to measure
|
||||||
// total session duration from first connect to final disconnect.
|
// total session duration from first connect to final disconnect.
|
||||||
if (connectionStartTimeRef.current != null) return
|
if (connectionStartTimeRef.current != null) return
|
||||||
connectionStartTimeRef.current = Date.now()
|
connectionStartTimeRef.current = Date.now()
|
||||||
void captureMediaEvent('connection-event', {})
|
const participantSid = room.localParticipant.sid
|
||||||
|
const roomSid = await room.getSid().catch(() => undefined)
|
||||||
|
void captureMediaEvent('connection-event', {
|
||||||
|
livekit_room_sid: roomSid,
|
||||||
|
livekit_participant_sid: participantSid,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleReconnect = () => {
|
const handleReconnect = () => {
|
||||||
captureEvent('reconnect-event')
|
captureEvent('reconnect-event')
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleReconnected = () => {
|
const handleReconnected = async () => {
|
||||||
captureEvent('reconnected-event')
|
const participantSid = room.localParticipant.sid
|
||||||
|
const roomSid = await room.getSid().catch(() => undefined)
|
||||||
|
captureEvent('reconnected-event', {
|
||||||
|
livekit_room_sid: roomSid,
|
||||||
|
livekit_participant_sid: participantSid,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSignalingConnect = () => {
|
const handleSignalingConnect = () => {
|
||||||
|
|||||||
@@ -480,7 +480,7 @@
|
|||||||
"destination": "Ein neues Dokument wird erstellt auf",
|
"destination": "Ein neues Dokument wird erstellt auf",
|
||||||
"destinationUnknown": "Ein neues Dokument wird erstellt",
|
"destinationUnknown": "Ein neues Dokument wird erstellt",
|
||||||
"language": "Meeting-Sprache:",
|
"language": "Meeting-Sprache:",
|
||||||
"recording": "Auch eine Aufzeichnung starten"
|
"recording": "Auch eine Videoaufzeichnung starten"
|
||||||
},
|
},
|
||||||
"button": {
|
"button": {
|
||||||
"start": "Meeting-Transkription starten",
|
"start": "Meeting-Transkription starten",
|
||||||
|
|||||||
@@ -480,7 +480,7 @@
|
|||||||
"destination": "A new document will be created on",
|
"destination": "A new document will be created on",
|
||||||
"destinationUnknown": "A new document will be created",
|
"destinationUnknown": "A new document will be created",
|
||||||
"language": "Meeting language:",
|
"language": "Meeting language:",
|
||||||
"recording": "Also start a recording"
|
"recording": "Also start a video recording"
|
||||||
},
|
},
|
||||||
"button": {
|
"button": {
|
||||||
"start": "Start transcribing the meeting",
|
"start": "Start transcribing the meeting",
|
||||||
|
|||||||
@@ -479,7 +479,7 @@
|
|||||||
"destination": "Se creará un nuevo documento en",
|
"destination": "Se creará un nuevo documento en",
|
||||||
"destinationUnknown": "Se creará un nuevo documento",
|
"destinationUnknown": "Se creará un nuevo documento",
|
||||||
"language": "Idioma de la reunión:",
|
"language": "Idioma de la reunión:",
|
||||||
"recording": "Iniciar también una grabación"
|
"recording": "Iniciar también una grabación de vídeo"
|
||||||
},
|
},
|
||||||
"button": {
|
"button": {
|
||||||
"start": "Empezar a transcribir la reunión",
|
"start": "Empezar a transcribir la reunión",
|
||||||
|
|||||||
@@ -480,7 +480,7 @@
|
|||||||
"destination": "Un nouveau document sera créé sur",
|
"destination": "Un nouveau document sera créé sur",
|
||||||
"destinationUnknown": "Un nouveau document sera créé",
|
"destinationUnknown": "Un nouveau document sera créé",
|
||||||
"language": "Langue de la réunion :",
|
"language": "Langue de la réunion :",
|
||||||
"recording": "Démarrer aussi un enregistrement"
|
"recording": "Démarrer aussi un enregistrement vidéo"
|
||||||
},
|
},
|
||||||
"button": {
|
"button": {
|
||||||
"start": "Commencer à transcrire la réunion",
|
"start": "Commencer à transcrire la réunion",
|
||||||
|
|||||||
@@ -480,7 +480,7 @@
|
|||||||
"destination": "Er wordt een nieuw document aangemaakt op",
|
"destination": "Er wordt een nieuw document aangemaakt op",
|
||||||
"destinationUnknown": "Een nieuw document wordt aangemaakt",
|
"destinationUnknown": "Een nieuw document wordt aangemaakt",
|
||||||
"language": "Vergadertalen:",
|
"language": "Vergadertalen:",
|
||||||
"recording": "Start ook een opname"
|
"recording": "Start ook een video-opname"
|
||||||
},
|
},
|
||||||
"button": {
|
"button": {
|
||||||
"start": "Begin met het transcriberen van de vergadering",
|
"start": "Begin met het transcriberen van de vergadering",
|
||||||
|
|||||||
Reference in New Issue
Block a user