feat(analytics): persona logging upgrade and Sentry system config
Add client-logging SDK, expanded event taxonomy, API observability, admin domain events UI, and move SENTRY_DSN to HQ system settings with @sentry/node bootstrap after config preload. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
import { createUserTracker, getSessionId } from '@dukang/client-logging';
|
||||
import { API_BASE, CLIENT_APP, getToken } from './api';
|
||||
|
||||
const tracker = createUserTracker({
|
||||
apiBase: API_BASE,
|
||||
clientApp: CLIENT_APP,
|
||||
getToken,
|
||||
});
|
||||
|
||||
export { getSessionId };
|
||||
|
||||
export function track(eventName: string, params?: Record<string, unknown>) {
|
||||
tracker.track(eventName, params);
|
||||
}
|
||||
|
||||
export function trackPageView(eventName: string, params?: Record<string, unknown>) {
|
||||
tracker.trackPageView(eventName, params);
|
||||
}
|
||||
|
||||
export function initUserAnalytics() {
|
||||
tracker.trackSessionStart();
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { trackPageView } from './analytics';
|
||||
|
||||
export function usePageView(eventName: string, params?: Record<string, unknown>) {
|
||||
const fired = useRef(false);
|
||||
useEffect(() => {
|
||||
if (fired.current) return;
|
||||
fired.current = true;
|
||||
trackPageView(eventName, params);
|
||||
}, [eventName, params]);
|
||||
}
|
||||
@@ -33,6 +33,7 @@ import {
|
||||
DEFAULT_SHARE_TITLE,
|
||||
toWeappShareMessage,
|
||||
} from '../../lib/wechat-share';
|
||||
import { trackPageView } from '../../lib/analytics';
|
||||
type Product = {
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -79,6 +80,10 @@ export default function HomePage() {
|
||||
const scrollLockTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
const lastScrollSyncAtRef = useRef(0);
|
||||
|
||||
useEffect(() => {
|
||||
trackPageView('home_view', { pagePath: '/pages/home/index', cityCode });
|
||||
}, [cityCode]);
|
||||
|
||||
const loadMiniHome = useCallback(() => {
|
||||
return request<{ miniHome?: MiniHomeConfig }>('/common/client-config')
|
||||
.then((cfg) => {
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
DEFAULT_SHARE_TITLE,
|
||||
toWeappShareMessage,
|
||||
} from '../../lib/wechat-share';
|
||||
import { usePageView } from '../../lib/usePageView';
|
||||
|
||||
const isWeapp = process.env.TARO_ENV === 'weapp';
|
||||
|
||||
@@ -74,6 +75,7 @@ function fullReceiverAddress(order: OrderDetail) {
|
||||
export default function OrderDetailPage() {
|
||||
const router = useRouter();
|
||||
const orderId = router.params.id ?? '';
|
||||
usePageView('order_detail_view', orderId ? { orderId } : undefined);
|
||||
const [order, setOrder] = useState<OrderDetail | null>(null);
|
||||
const [confirming, setConfirming] = useState(false);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import PageShell from '../../components/PageShell';
|
||||
import SubPageHeader from '../../components/SubPageHeader';
|
||||
import { request, toast } from '../../lib/api';
|
||||
import { buildPayUrl } from '../../lib/checkout-nav';
|
||||
import { usePageView } from '../../lib/usePageView';
|
||||
|
||||
import { ORDER_STATUS_LABELS } from '@dukang/shared-types';
|
||||
|
||||
@@ -54,6 +55,7 @@ type OrderRow = {
|
||||
export default function OrdersPage() {
|
||||
const router = useRouter();
|
||||
const [tab, setTab] = useState(() => normalizeOrdersTab(router.params.tab as string));
|
||||
usePageView('order_list_view', { tab });
|
||||
const [orders, setOrders] = useState<OrderRow[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import {
|
||||
toWeappShareMessage,
|
||||
} from '../../lib/wechat-share';
|
||||
import iconHome from '../../assets/tabbar/home.png';
|
||||
import { usePageView } from '../../lib/usePageView';
|
||||
|
||||
type Product = ProductImageSource & {
|
||||
id: string;
|
||||
@@ -50,6 +51,10 @@ type Product = ProductImageSource & {
|
||||
export default function ProductDetailPage() {
|
||||
const router = useRouter();
|
||||
const productId = router.params.id ?? '';
|
||||
usePageView(
|
||||
'product_detail_view',
|
||||
productId ? { refType: 'PRODUCT', refId: productId, productId } : undefined,
|
||||
);
|
||||
const [product, setProduct] = useState<Product | null>(null);
|
||||
const [headerSolid, setHeaderSolid] = useState(false);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user