import { Controller } from 'egg' ; const detector = require ( 'detector' ) ; interface Ibody { res ? : any ; err ? : any ; token ? : string ; behavior : { } ; } export default class ReportController extends Controller { constructor ( ctx ) { super ( ctx ) ; } public VReport = { t : { type : 'string' , required : true , allowEmpty : false } , times : { type : 'number' , required : false } , page : { type : 'string' , required : false } , v : { type : 'string' , required : false } , e : { type : 'string' , required : false } , token : { type : 'string' , required : true , allowEmpty : false } , begin : { type : 'number' , required : false } , sr : { type : 'string' , required : false } , vp : { type : 'string' , required : false } , _v : { type : 'string' , required : false } , o : { type : 'string' , required : false } , uid : { type : 'string' , required : false } , sid : { type : 'string' , required : false } , ct : { type : 'string' , required : false } , ul : { type : 'string' , required : false } , dt : { type : 'string' , required : false } , dl : { type : 'string' , required : false } , dr : { type : 'string' , required : false } , dpr : { type : 'number' , required : false } , de : { type : 'string' , required : false } , st : { type : 'string' , required : false } , msg : { type : 'string' , required : false } , cate : { type : 'string' , required : false } , detail : { type : 'string' , required : false } , file : { type : 'string' , required : false } , line : { type : 'number' , required : false } , col : { type : 'number' , required : false } , dom : { type : 'number' , required : false } , load : { type : 'number' , required : false } , res : { type : 'string' , required : false } , url : { type : 'string' , required : false } , success : { type : 'boolean' , required : false } , time : { type : 'number' , required : false } , code : { type : 'number' , required : false } , healthy : { type : 'number' , required : false } , stay : { type : 'number' , required : false } , errcount : { type : 'number' , required : false } , apisucc : { type : 'number' , required : false } , apifail : { type : 'number' , required : false } , dns : { type : 'number' , required : false } , tcp : { type : 'number' , required : false } , ssl : { type : 'number' , required : false } , ttfb : { type : 'number' , required : false } , trans : { type : 'number' , required : false } , firstbyte : { type : 'number' , required : false } , fpt : { type : 'number' , required : false } , tti : { type : 'number' , required : false } , ready : { type : 'number' , required : false } , bandwidth : { type : 'number' , required : false } , navtype : { type : 'string' , required : false } , fmp : { type : 'number' , required : false } , resTimes : { type : 'string' , required : false } , } ; public toNumberParas = [ 'times' , 'begin' , 'dpr' , 'line' , 'col' , 'dom' , 'load' , 'time' , 'code' , 'healthy' , 'stay' , 'errcount' , 'apisucc' , 'apifail' , 'dns' , 'tcp' , 'ssl' , 'ttfb' , 'trans' , 'firstbyte' , 'fpt' , 'tti' , 'ready' , 'bandwidth' , 'fmp' ] ; /**
     * *******************************************************************************************
     * web用户数据上报保存到kafka
     * *******************************************************************************************
     */ public async create ( ) { const { ctx , service } = this ; const body = await this . adapterBody ( ) ; ctx . validate ( this . VReport , body ) ; const { token } = body ; if ( token ) { const tokenObj = await this . service . project . getProjectByToken ( token ) ; if ( tokenObj && tokenObj . is_use === 1 ) { const { report } = service . web ; await report . save ( body ) ; } } ctx . helper . success ( ) ; } /**
     * *******************************************************************************************
     * 组装上报参数
     * *******************************************************************************************
     */ public async adapterBody ( ) { const { ctx , service } = this ; let body = ctx . request . body ; if ( body && typeof body === 'string' ) { body = JSON . parse ( body ) ; } this . toNumberParas . map ( item => { if ( ctx . query [ item ] ) { ctx . query [ item ] = + ctx . query [ item ] ; } } ) ; const ip = ctx . get ( 'X-Real-IP' ) || ctx . get ( 'X-Forwarded-For' ) || ctx . ip ; const location = await service . web . report . getLocation ( ip ) ; const user_agent = ctx . headers [ 'user-agent' ] ; const device = detector . parse ( user_agent ) ; if ( ctx . query . dr ) { ctx . query . source = ctx . query . dr . split ( '/' ) [ 2 ] . split ( '.' ) [ 1 ] ; } return { ... ctx . query , detector : device , body : body || { } , ... location , ip , pv : 1 , uv : ip , user_agent , '@timestamp' : new Date ( ) } ; } async saveWebReportDataForRedis ( query ) { try { if ( this . app . config . redis_consumption . total_limit_web ) { const length = await this . app . redis . llen ( 'web_repore_datas' ) ; if ( length >= this . app . config . redis_consumption . total_limit_web ) return ; } this . app . redis . lpush ( 'web_repore_datas' , JSON . stringify ( query ) ) ; } catch ( e ) { console . log ( e ) ; } } async saveWebReportDataForMongodb ( ctx ) { ctx . service . web . report . saveWebReportData ( ctx ) ; } }