feat(observability): add structured application logging

Emit correlated JSON logs from the API and FunASR services, propagate request IDs to the client, and configure bounded opt-in Docker logging.

Document the host-wide Grafana/Loki query workflow and keep observability deployment ownership outside the application repository.
This commit is contained in:
2026-07-22 13:52:40 +08:00
parent a63e9a1705
commit a875fe9f63
30 changed files with 1261 additions and 817 deletions

View File

@@ -1,4 +1,10 @@
import { getApiErrorMessage, getProfileDefaults, updateProfileDefaults } from '../../utils/api'
import {
copyApiRequestId,
getApiErrorMessage,
getApiRequestId,
getProfileDefaults,
updateProfileDefaults
} from '../../utils/api'
import type { StudentProfileDefaults } from '../../utils/types'
const grades = ['初一', '初二', '初三']
@@ -30,7 +36,8 @@ Page({
maximumDuration,
loading: false,
saving: false,
errorMessage: ''
errorMessage: '',
errorRequestId: ''
},
onShow() {
@@ -38,7 +45,7 @@ Page({
},
async loadDefaults(showSuccess = false) {
this.setData({ loading: true, errorMessage: '' })
this.setData({ loading: true, errorMessage: '', errorRequestId: '' })
try {
const defaults = await getProfileDefaults()
this.setData({
@@ -49,7 +56,7 @@ Page({
})
if (showSuccess) wx.showToast({ title: '预设已刷新', icon: 'success' })
} catch (error) {
this.setData({ errorMessage: getApiErrorMessage(error) })
this.setData({ errorMessage: getApiErrorMessage(error), errorRequestId: getApiRequestId(error) })
} finally {
this.setData({ loading: false })
}
@@ -59,6 +66,10 @@ Page({
void this.loadDefaults(true)
},
copyRequestId() {
copyApiRequestId(this.data.errorRequestId)
},
onGradeChange(event: PickerEvent) {
this.setData({ 'defaults.grade': grades[Number(event.detail.value)] })
},