feat: add analytics metric granularity query
Some checks failed
CI / verify (push) Has been cancelled
Some checks failed
CI / verify (push) Has been cancelled
This commit is contained in:
@@ -109,10 +109,10 @@ use crate::{
|
||||
admin_list_profile_invite_codes, admin_list_profile_redeem_codes,
|
||||
admin_list_profile_task_configs, admin_upsert_profile_invite_code,
|
||||
admin_upsert_profile_redeem_code, admin_upsert_profile_task_config,
|
||||
claim_profile_task_reward, create_profile_recharge_order, get_profile_dashboard,
|
||||
get_profile_play_stats, get_profile_recharge_center, get_profile_referral_invite_center,
|
||||
get_profile_task_center, get_profile_wallet_ledger, redeem_profile_referral_invite_code,
|
||||
redeem_profile_reward_code,
|
||||
claim_profile_task_reward, create_profile_recharge_order, get_profile_analytics_metric,
|
||||
get_profile_dashboard, get_profile_play_stats, get_profile_recharge_center,
|
||||
get_profile_referral_invite_center, get_profile_task_center, get_profile_wallet_ledger,
|
||||
redeem_profile_referral_invite_code, redeem_profile_reward_code,
|
||||
},
|
||||
runtime_save::{
|
||||
delete_runtime_snapshot, get_runtime_snapshot, list_profile_save_archives,
|
||||
@@ -1074,6 +1074,13 @@ pub fn build_router(state: AppState) -> Router {
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/profile/analytics/metric",
|
||||
get(get_profile_analytics_metric).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/profile/tasks",
|
||||
get(get_profile_task_center).route_layer(middleware::from_fn_with_state(
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use axum::{
|
||||
Json,
|
||||
extract::{Extension, Path, State},
|
||||
extract::{Extension, Path, Query, State},
|
||||
http::StatusCode,
|
||||
response::Response,
|
||||
};
|
||||
use module_runtime::{
|
||||
PROFILE_RECHARGE_PAYMENT_CHANNEL_MOCK, RuntimeProfileInviteCodeRecord,
|
||||
AnalyticsGranularity, PROFILE_RECHARGE_PAYMENT_CHANNEL_MOCK, RuntimeProfileInviteCodeRecord,
|
||||
RuntimeProfileMembershipBenefitRecord, RuntimeProfileRechargeCenterRecord,
|
||||
RuntimeProfileRechargeOrderRecord, RuntimeProfileRechargeProductRecord,
|
||||
RuntimeProfileRedeemCodeMode, RuntimeProfileRedeemCodeRecord,
|
||||
@@ -15,10 +15,12 @@ use module_runtime::{
|
||||
RuntimeReferralInviteCenterRecord, RuntimeTrackingScopeKind,
|
||||
};
|
||||
use serde_json::{Value, json};
|
||||
use serde::Deserialize;
|
||||
use shared_contracts::runtime::{
|
||||
AdminDisableProfileRedeemCodeRequest, AdminDisableProfileTaskConfigRequest,
|
||||
AdminUpsertProfileInviteCodeRequest, AdminUpsertProfileRedeemCodeRequest,
|
||||
AdminUpsertProfileTaskConfigRequest, ClaimProfileTaskRewardResponse,
|
||||
AdminUpsertProfileTaskConfigRequest, AnalyticsBucketMetricResponse,
|
||||
AnalyticsMetricQueryResponse, ClaimProfileTaskRewardResponse,
|
||||
CreateProfileRechargeOrderRequest, CreateProfileRechargeOrderResponse,
|
||||
PROFILE_TASK_CYCLE_DAILY, PROFILE_TASK_STATUS_CLAIMABLE, PROFILE_TASK_STATUS_CLAIMED,
|
||||
PROFILE_TASK_STATUS_DISABLED, PROFILE_TASK_STATUS_INCOMPLETE,
|
||||
@@ -31,6 +33,8 @@ use shared_contracts::runtime::{
|
||||
PROFILE_WALLET_LEDGER_SOURCE_TYPE_POINTS_RECHARGE,
|
||||
PROFILE_WALLET_LEDGER_SOURCE_TYPE_PUZZLE_AUTHOR_INCENTIVE_CLAIM,
|
||||
PROFILE_WALLET_LEDGER_SOURCE_TYPE_REDEEM_CODE_REWARD,
|
||||
ANALYTICS_GRANULARITY_DAY, ANALYTICS_GRANULARITY_MONTH, ANALYTICS_GRANULARITY_QUARTER,
|
||||
ANALYTICS_GRANULARITY_WEEK, ANALYTICS_GRANULARITY_YEAR,
|
||||
PROFILE_WALLET_LEDGER_SOURCE_TYPE_SNAPSHOT_SYNC, ProfileDashboardSummaryResponse,
|
||||
ProfileInviteCodeAdminListResponse, ProfileInviteCodeAdminResponse,
|
||||
ProfileMembershipBenefitResponse, ProfileMembershipResponse, ProfilePlayStatsResponse,
|
||||
@@ -278,6 +282,51 @@ pub async fn redeem_profile_reward_code(
|
||||
))
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct AnalyticsMetricQueryParams {
|
||||
pub event_key: String,
|
||||
pub scope_kind: String,
|
||||
pub scope_id: String,
|
||||
pub granularity: String,
|
||||
}
|
||||
|
||||
pub async fn get_profile_analytics_metric(
|
||||
State(state): State<AppState>,
|
||||
Extension(request_context): Extension<RequestContext>,
|
||||
Extension(_authenticated): Extension<AuthenticatedAccessToken>,
|
||||
Query(query): Query<AnalyticsMetricQueryParams>,
|
||||
) -> Result<Json<Value>, Response> {
|
||||
let scope_kind = parse_tracking_scope_kind(&query.scope_kind).map_err(|error| {
|
||||
runtime_profile_error_response(
|
||||
&request_context,
|
||||
AppError::from_status(StatusCode::BAD_REQUEST).with_message(error),
|
||||
)
|
||||
})?;
|
||||
let granularity = parse_analytics_granularity(&query.granularity).map_err(|error| {
|
||||
runtime_profile_error_response(
|
||||
&request_context,
|
||||
AppError::from_status(StatusCode::BAD_REQUEST).with_message(error),
|
||||
)
|
||||
})?;
|
||||
|
||||
let record = state
|
||||
.spacetime_client()
|
||||
.query_analytics_metric(query.event_key, scope_kind, query.scope_id, granularity)
|
||||
.await
|
||||
.map_err(|error| {
|
||||
runtime_profile_error_response(
|
||||
&request_context,
|
||||
map_runtime_profile_client_error(error),
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(json_success_body(
|
||||
Some(&request_context),
|
||||
build_analytics_metric_query_response(record),
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn get_profile_task_center(
|
||||
State(state): State<AppState>,
|
||||
Extension(request_context): Extension<RequestContext>,
|
||||
@@ -811,6 +860,23 @@ fn build_profile_task_center_response(
|
||||
}
|
||||
}
|
||||
|
||||
fn build_analytics_metric_query_response(
|
||||
record: module_runtime::AnalyticsMetricQueryResponse,
|
||||
) -> AnalyticsMetricQueryResponse {
|
||||
AnalyticsMetricQueryResponse {
|
||||
buckets: record
|
||||
.buckets
|
||||
.into_iter()
|
||||
.map(|bucket| AnalyticsBucketMetricResponse {
|
||||
bucket_key: bucket.bucket_key,
|
||||
bucket_start_date_key: bucket.bucket_start_date_key,
|
||||
bucket_end_date_key: bucket.bucket_end_date_key,
|
||||
value: bucket.value,
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn build_profile_task_item_response(
|
||||
record: RuntimeProfileTaskItemRecord,
|
||||
) -> ProfileTaskItemResponse {
|
||||
@@ -935,6 +1001,17 @@ fn parse_tracking_scope_kind(raw: &str) -> Result<RuntimeTrackingScopeKind, Stri
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_analytics_granularity(raw: &str) -> Result<AnalyticsGranularity, String> {
|
||||
match raw.trim().to_ascii_lowercase().as_str() {
|
||||
ANALYTICS_GRANULARITY_DAY => Ok(AnalyticsGranularity::Day),
|
||||
ANALYTICS_GRANULARITY_WEEK => Ok(AnalyticsGranularity::Week),
|
||||
ANALYTICS_GRANULARITY_MONTH => Ok(AnalyticsGranularity::Month),
|
||||
ANALYTICS_GRANULARITY_QUARTER => Ok(AnalyticsGranularity::Quarter),
|
||||
ANALYTICS_GRANULARITY_YEAR => Ok(AnalyticsGranularity::Year),
|
||||
_ => Err("统计粒度无效".to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
fn format_profile_task_cycle(cycle: RuntimeProfileTaskCycle) -> &'static str {
|
||||
match cycle {
|
||||
RuntimeProfileTaskCycle::Daily => PROFILE_TASK_CYCLE_DAILY,
|
||||
|
||||
Reference in New Issue
Block a user