实战-数据仓库构建(二)
问题导读:
1、如何进行埋点数据处理?
2、事件日志数据如何设计表?
3、如何使用数据生成脚本?
4、如何配置日志打印Logback?
一、数据生成模块
1)埋点数据基本格式
- 公共字段:基本所有安卓手机都包含的字段
- 业务(事件)字段:埋点上报的字段,有具体的业务类型
示例如下
2)示例日志(服务器时间戳 | 日志)如下
注意:事件字段包含多个用户行为数据
3)事件日志数据
【3.1】商品列表页(loading)
事件名称:loading
【3.2】商品点击(display)
事件标签:display
【3.3】商品详情页(newsdetail)
事件名称:newsdetail
【3.4】广告(ad)
事件名称:ad
【3.5】消息通知(notification)
事件名称:notification
【3.7】评论(comment)
事件名称:comment
【3.8】收藏(favorites)
事件名称:favorites
【3.11】启动日志数据
事件标签: start
4)数据生成脚本
【4.1】架构图
【4.2】流程
1)创建Maven工程
2)导入依赖
<!--版本号统一--><properties><slf4j.version>1.7.20</slf4j.version><logback.version>1.0.7</logback.version></properties><dependencies><!--阿里巴巴开源 json 解析框架--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.51</version></dependency><!--日志生成框架--><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-core</artifactId><version>${logback.version}</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>${logback.version}</version></dependency></dependencies><!--编译打包插件--><build><plugins><plugin><artifactId>maven-compiler-plugin</artifactId><version>2.3.2</version><configuration><source>1.8</source><target>1.8</target></configuration></plugin><plugin><artifactId>maven-assembly-plugin </artifactId><configuration><descriptorRefs><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs><archive><manifest><!--主方法全限定名--><mainClass>com.zsy.appclient.AppMain</mainClass></manifest></archive></configuration><executions><execution><id>make-assembly</id><phase>package</phase><goals><goal>single</goal></goals></execution></executions></plugin></plugins></build>
3)编写bean对象
- 用户后台活跃 AppActive_background.java
package com.zsy.bean;
/*** 用户后台活跃*/
public class AppActive_background {private String active_source;//1=upgrade,2=download(下载),3=plugin_upgradepublic String getActive_source() {return active_source;}public void setActive_source(String active_source) {this.active_source = active_source;}
}
广告AppAd.java
package com.zsy.bean;
/*** 广告*/
public class AppAd {private String entry;//入口:商品列表页=1 应用首页=2 商品详情页=3private String action;//动作: 广告展示=1 广告点击=2private String contentType;//Type: 1 商品 2 营销活动private String displayMills;//展示时长 毫秒数private String itemId; //商品idprivate String activityId; //营销活动idpublic String getEntry() {return entry;}public void setEntry(String entry) {this.entry = entry;}public String getAction() {return action;}public void setAction(String action) {this.action = action;}public String getActivityId() {return activityId;}public void setActivityId(String activityId) {this.activityId = activityId;}public String getContentType() {return contentType;}public void setContentType(String contentType) {this.contentType = contentType;}public String getDisplayMills() {return displayMills;}public void setDisplayMills(String displayMills) {this.displayMills = displayMills;}public String getItemId() {return itemId;}public void setItemId(String itemId) {this.itemId = itemId;}
}
公共日志 AppBase.java
package com.zsy.bean;
/*** 公共日志*/
public class AppBase{private String mid; // (String) 设备唯一标识private String uid; // (String) 用户uidprivate String vc; // (String) versionCode,程序版本号private String vn; // (String) versionName,程序版本名private String l; // (String) 系统语言private String sr; // (String) 渠道号,应用从哪个渠道来的。private String os; // (String) Android系统版本private String ar; // (String) 区域private String md; // (String) 手机型号private String ba; // (String) 手机品牌private String sv; // (String) sdkVersionprivate String g; // (String) gmailprivate String hw; // (String) heightXwidth,屏幕宽高private String t; // (String) 客户端日志产生时的时间private String nw; // (String) 网络模式private String ln; // (double) lng经度private String la; // (double) lat 纬度public String getMid() {return mid;}public void setMid(String mid) {this.mid = mid;}public String getUid() {return uid;}public void setUid(String uid) {this.uid = uid;}public String getVc() {return vc;}public void setVc(String vc) {this.vc = vc;}public String getVn() {return vn;}public void setVn(String vn) {this.vn = vn;}public String getL() {return l;}public void setL(String l) {this.l = l;}public String getSr() {return sr;}public void setSr(String sr) {this.sr = sr;}public String getOs() {return os;}public void setOs(String os) {this.os = os;}public String getAr() {return ar;}public void setAr(String ar) {this.ar = ar;}public String getMd() {return md;}public void setMd(String md) {this.md = md;}public String getBa() {return ba;}public void setBa(String ba) {this.ba = ba;}public String getSv() {return sv;}public void setSv(String sv) {this.sv = sv;}public String getG() {return g;}public void setG(String g) {this.g = g;}public String getHw() {return hw;}public void setHw(String hw) {this.hw = hw;}public String getT() {return t;}public void setT(String t) {this.t = t;}public String getNw() {return nw;}public void setNw(String nw) {this.nw = nw;}public String getLn() {return ln;}public void setLn(String ln) {this.ln = ln;}public String getLa() {return la;}public void setLa(String la) {this.la = la;}
}
评论 AppComment.java
package com.zsy.bean;
/*** 评论*/
public class AppComment {private int comment_id;//评论表private int userid;//用户idprivate int p_comment_id;//父级评论id(为0则是一级评论,不为0则是回复)private String content;//评论内容private String addtime;//创建时间private int other_id;//评论的相关idprivate int praise_count;//点赞数量private int reply_count;//回复数量public int getComment_id() {return comment_id;}public void setComment_id(int comment_id) {this.comment_id = comment_id;}public int getUserid() {return userid;}public void setUserid(int userid) {this.userid = userid;}public int getP_comment_id() {return p_comment_id;}public void setP_comment_id(int p_comment_id) {this.p_comment_id = p_comment_id;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}public String getAddtime() {return addtime;}public void setAddtime(String addtime) {this.addtime = addtime;}public int getOther_id() {return other_id;}public void setOther_id(int other_id) {this.other_id = other_id;}public int getPraise_count() {return praise_count;}public void setPraise_count(int praise_count) {this.praise_count = praise_count;}public int getReply_count() {return reply_count;}public void setReply_count(int reply_count) {this.reply_count = reply_count;}
}
商品点击日志 AppDisplay.java
package com.zsy.bean;
/*** 商品点击日志*/
public class AppDisplay {private String action;//动作:曝光商品=1,点击商品=2,private String goodsid;//商品ID(服务端下发的ID)private String place;//顺序(第几条商品,第一条为0,第二条为1,如此类推)private String extend1;//曝光类型:1 - 首次曝光 2-重复曝光(没有使用)private String category;//分类ID(服务端定义的分类ID)public String getAction() {return action;}public void setAction(String action) {this.action = action;}public String getGoodsid() {return goodsid;}public void setGoodsid(String goodsid) {this.goodsid = goodsid;}public String getPlace() {return place;}public void setPlace(String place) {this.place = place;}public String getExtend1() {return extend1;}public void setExtend1(String extend1) {this.extend1 = extend1;}public String getCategory() {return category;}public void setCategory(String category) {this.category = category;}
}
错误日志 AppErrorLog.java
package com.zsy.bean;
/*** 错误日志*/
public class AppErrorLog {private String errorBrief; //错误摘要private String errorDetail; //错误详情public String getErrorBrief() {return errorBrief;}public void setErrorBrief(String errorBrief) {this.errorBrief = errorBrief;}public String getErrorDetail() {return errorDetail;}public void setErrorDetail(String errorDetail) {this.errorDetail = errorDetail;}
}
收藏 AppFavorites.java
package com.zsy.bean;
/*** 收藏*/
public class AppFavorites {private int id;//主键private int course_id;//商品idprivate int userid;//用户IDprivate String add_time;//创建时间public int getId() {return id;}public void setId(int id) {this.id = id;}public int getCourse_id() {return course_id;}public void setCourse_id(int course_id) {this.course_id = course_id;}public int getUserid() {return userid;}public void setUserid(int userid) {this.userid = userid;}public String getAdd_time() {return add_time;}public void setAdd_time(String add_time) {this.add_time = add_time;}
}
商品列表 AppLoading.java
package com.zsy.bean;
/*** 商品列表*/
public class AppLoading {private String action;//动作:开始加载=1,加载成功=2,加载失败=3private String loading_time;//加载时长:计算下拉开始到接口返回数据的时间,(开始加载报0,加载成功或加载失败才上报时间)private String loading_way;//加载类型:1-读取缓存,2-从接口拉新数据 (加载成功才上报加载类型)private String extend1;//扩展字段 Extend1private String extend2;//扩展字段 Extend2private String type;//加载类型:自动加载=1,用户下拽加载=2,底部加载=3(底部条触发点击底部提示条/点击返回顶部加载)private String type1;//加载失败码:把加载失败状态码报回来(报空为加载成功,没有失败)public String getAction() {return action;}public void setAction(String action) {this.action = action;}public String getLoading_time() {return loading_time;}public void setLoading_time(String loading_time) {this.loading_time = loading_time;}public String getLoading_way() {return loading_way;}public void setLoading_way(String loading_way) {this.loading_way = loading_way;}public String getExtend1() {return extend1;}public void setExtend1(String extend1) {this.extend1 = extend1;}public String getExtend2() {return extend2;}public void setExtend2(String extend2) {this.extend2 = extend2;}public String getType() {return type;}public void setType(String type) {this.type = type;}public String getType1() {return type1;}public void setType1(String type1) {this.type1 = type1;}
}
商品详情 AppNewsDetail.java
package com.zsy.bean;
/*** 商品详情*/
public class AppNewsDetail {private String entry;//页面入口来源:应用首页=1、push=2、详情页相关推荐=3private String action;//动作:开始加载=1,加载成功=2(pv),加载失败=3, 退出页面=4private String goodsid;//商品ID(服务端下发的ID)private String showtype;//商品样式:0、无图1、一张大图2、两张图3、三张小图4、一张小图5、一张大图两张小图 来源于详情页相关推荐的商品,上报样式都为0(因为都是左文右图)private String news_staytime;//页面停留时长:从商品开始加载时开始计算,到用户关闭页面所用的时间。若中途用跳转到其它页面了,则暂停计时,待回到详情页时恢复计时。或中途划出的时间超过10分钟,则本次计时作废,不上报本次数据。如未加载成功退出,则报空。private String loading_time;//加载时长:计算页面开始加载到接口返回数据的时间 (开始加载报0,加载成功或加载失败才上报时间)private String type1;//加载失败码:把加载失败状态码报回来(报空为加载成功,没有失败)private String category;//分类ID(服务端定义的分类ID)public String getEntry() {return entry;}public void setEntry(String entry) {this.entry = entry;}public String getAction() {return action;}public void setAction(String action) {this.action = action;}public String getGoodsid() {return goodsid;}public void setGoodsid(String goodsid) {this.goodsid = goodsid;}public String getShowtype() {return showtype;}public void setShowtype(String showtype) {this.showtype = showtype;}public String getNews_staytime() {return news_staytime;}public void setNews_staytime(String news_staytime) {this.news_staytime = news_staytime;}public String getLoading_time() {return loading_time;}public void setLoading_time(String loading_time) {this.loading_time = loading_time;}public String getType1() {return type1;}public void setType1(String type1) {this.type1 = type1;}public String getCategory() {return category;}public void setCategory(String category) {this.category = category;}
}
消息通知日志 AppNotification.java
package com.zsy.bean;
/*** 消息通知日志*/
public class AppNotification {private String action;//动作:通知产生=1,通知弹出=2,通知点击=3,常驻通知展示(不重复上报,一天之内只报一次)=4private String type;//通知id:预警通知=1,天气预报(早=2,晚=3),常驻=4private String ap_time;//客户端弹出时间private String content;//备用字段public String getAction() {return action;}public void setAction(String action) {this.action = action;}public String getType() {return type;}public void setType(String type) {this.type = type;}public String getAp_time() {return ap_time;}public void setAp_time(String ap_time) {this.ap_time = ap_time;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}
}
点赞 AppPraise.java
package com.zsy.bean;
/*** 点赞*/
public class AppPraise {private int id; //主键idprivate int userid;//用户idprivate int target_id;//点赞的对象idprivate int type;//点赞类型 1问答点赞 2问答评论点赞 3 文章点赞数4 评论点赞private String add_time;//添加时间public int getId() {return id;}public void setId(int id) {this.id = id;}public int getUserid() {return userid;}public void setUserid(int userid) {this.userid = userid;}public int getTarget_id() {return target_id;}public void setTarget_id(int target_id) {this.target_id = target_id;}public int getType() {return type;}public void setType(int type) {this.type = type;}public String getAdd_time() {return add_time;}public void setAdd_time(String add_time) {this.add_time = add_time;}
}
启动日志 AppStart.java
package com.zsy.bean;
/*** 启动日志*/
public class AppStart extends AppBase {private String entry;//入口: push=1,widget=2,icon=3,notification=4, lockscreen_widget =5private String open_ad_type;//开屏广告类型: 开屏原生广告=1, 开屏插屏广告=2private String action;//状态:成功=1 失败=2private String loading_time;//加载时长:计算下拉开始到接口返回数据的时间,(开始加载报0,加载成功或加载失败才上报时间)private String detail;//失败码(没有则上报空)private String extend1;//失败的message(没有则上报空)private String en;//启动日志类型标记public String getEntry() {return entry;}public void setEntry(String entry) {this.entry = entry;}public String getOpen_ad_type() {return open_ad_type;}public void setOpen_ad_type(String open_ad_type) {this.open_ad_type = open_ad_type;}public String getAction() {return action;}public void setAction(String action) {this.action = action;}public String getLoading_time() {return loading_time;}public void setLoading_time(String loading_time) {this.loading_time = loading_time;}public String getDetail() {return detail;}public void setDetail(String detail) {this.detail = detail;}public String getExtend1() {return extend1;}public void setExtend1(String extend1) {this.extend1 = extend1;}public String getEn() {return en;}public void setEn(String en) {this.en = en;}
}
4.创建数据生成代码 AppMain.java
package com.zsy.appclient;import java.io.UnsupportedEncodingException;
import java.util.Random;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.zsy.bean.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** 日志行为数据模拟*/
public class AppMain {private final static Logger logger = LoggerFactory.getLogger(AppMain.class);private static Random rand = new Random();// 设备idprivate static int s_mid = 0;// 用户idprivate static int s_uid = 0;// 商品idprivate static int s_goodsid = 0;public static void main(String[] args) {// 参数一:控制发送每条的延时时间,默认是0Long delay = args.length > 0 ? Long.parseLong(args[0]) : 0L;// 参数二:循环遍历次数int loop_len = args.length > 1 ? Integer.parseInt(args[1]) : 1000;// 生成数据generateLog(delay, loop_len);}private static void generateLog(Long delay, int loop_len) {for (int i = 0; i < loop_len; i++) {int flag = rand.nextInt(2);switch (flag) {case (0)://应用启动AppStart appStart = generateStart();String jsonString = JSON.toJSONString(appStart);//控制台打印logger.info(jsonString);break;case (1):JSONObject json = new JSONObject();json.put("ap", "app");json.put("cm", generateComFields());JSONArray eventsArray = new JSONArray();// 事件日志// 商品点击,展示if (rand.nextBoolean()) {eventsArray.add(generateDisplay());json.put("et", eventsArray);}// 商品详情页if (rand.nextBoolean()) {eventsArray.add(generateNewsDetail());json.put("et", eventsArray);}// 商品列表页if (rand.nextBoolean()) {eventsArray.add(generateNewList());json.put("et", eventsArray);}// 广告if (rand.nextBoolean()) {eventsArray.add(generateAd());json.put("et", eventsArray);}// 消息通知if (rand.nextBoolean()) {eventsArray.add(generateNotification());json.put("et", eventsArray);}// 用户后台活跃if (rand.nextBoolean()) {eventsArray.add(generateBackground());json.put("et", eventsArray);}//故障日志if (rand.nextBoolean()) {eventsArray.add(generateError());json.put("et", eventsArray);}// 用户评论if (rand.nextBoolean()) {eventsArray.add(generateComment());json.put("et", eventsArray);}// 用户收藏if (rand.nextBoolean()) {eventsArray.add(generateFavorites());json.put("et", eventsArray);}// 用户点赞if (rand.nextBoolean()) {eventsArray.add(generatePraise());json.put("et", eventsArray);}//时间long millis = System.currentTimeMillis();//控制台打印logger.info(millis + "|" + json.toJSONString());break;}// 延迟try {Thread.sleep(delay);} catch (InterruptedException e) {e.printStackTrace();}}}/*** 公共字段设置*/private static JSONObject generateComFields() {AppBase appBase = new AppBase();//设备idappBase.setMid(s_mid + "");s_mid++;// 用户idappBase.setUid(s_uid + "");s_uid++;// 程序版本号 5,6等appBase.setVc("" + rand.nextInt(20));//程序版本名 v1.1.1appBase.setVn("1." + rand.nextInt(4) + "." + rand.nextInt(10));// 安卓系统版本appBase.setOs("8." + rand.nextInt(3) + "." + rand.nextInt(10));// 语言 es,en,ptint flag = rand.nextInt(3);switch (flag) {case (0):appBase.setL("es");break;case (1):appBase.setL("en");break;case (2):appBase.setL("pt");break;}// 渠道号 从哪个渠道来的appBase.setSr(getRandomChar(1));// 区域flag = rand.nextInt(2);switch (flag) {case 0:appBase.setAr("BR");case 1:appBase.setAr("MX");}// 手机品牌 ba ,手机型号 md,就取2位数字了flag = rand.nextInt(3);switch (flag) {case 0:appBase.setBa("Sumsung");appBase.setMd("sumsung-" + rand.nextInt(20));break;case 1:appBase.setBa("Huawei");appBase.setMd("Huawei-" + rand.nextInt(20));break;case 2:appBase.setBa("HTC");appBase.setMd("HTC-" + rand.nextInt(20));break;}// 嵌入sdk的版本appBase.setSv("V2." + rand.nextInt(10) + "." + rand.nextInt(10));// gmailappBase.setG(getRandomCharAndNumr(8) + "@gmail.com");// 屏幕宽高 hwflag = rand.nextInt(4);switch (flag) {case 0:appBase.setHw("640*960");break;case 1:appBase.setHw("640*1136");break;case 2:appBase.setHw("750*1134");break;case 3:appBase.setHw("1080*1920");break;}// 客户端产生日志时间long millis = System.currentTimeMillis();appBase.setT("" + (millis - rand.nextInt(99999999)));// 手机网络模式 3G,4G,WIFIflag = rand.nextInt(3);switch (flag) {case 0:appBase.setNw("3G");break;case 1:appBase.setNw("4G");break;case 2:appBase.setNw("WIFI");break;}// 拉丁美洲 西经34°46′至西经117°09;北纬32°42′至南纬53°54′// 经度appBase.setLn((-34 - rand.nextInt(83) - rand.nextInt(60) / 10.0) + "");// 纬度appBase.setLa((32 - rand.nextInt(85) - rand.nextInt(60) / 10.0) + "");return (JSONObject) JSON.toJSON(appBase);}/*** 商品展示事件*/private static JSONObject generateDisplay() {AppDisplay appDisplay = new AppDisplay();boolean boolFlag = rand.nextInt(10) < 7;// 动作:曝光商品=1,点击商品=2,if (boolFlag) {appDisplay.setAction("1");} else {appDisplay.setAction("2");}// 商品idString goodsId = s_goodsid + "";s_goodsid++;appDisplay.setGoodsid(goodsId);// 顺序 设置成6条吧int flag = rand.nextInt(6);appDisplay.setPlace("" + flag);// 曝光类型flag = 1 + rand.nextInt(2);appDisplay.setExtend1("" + flag);// 分类flag = 1 + rand.nextInt(100);appDisplay.setCategory("" + flag);JSONObject jsonObject = (JSONObject) JSON.toJSON(appDisplay);return packEventJson("display", jsonObject);}/*** 商品详情页*/private static JSONObject generateNewsDetail() {AppNewsDetail appNewsDetail = new AppNewsDetail();// 页面入口来源int flag = 1 + rand.nextInt(3);appNewsDetail.setEntry(flag + "");// 动作appNewsDetail.setAction("" + (rand.nextInt(4) + 1));// 商品idappNewsDetail.setGoodsid(s_goodsid + "");// 商品来源类型flag = 1 + rand.nextInt(3);appNewsDetail.setShowtype(flag + "");// 商品样式flag = rand.nextInt(6);appNewsDetail.setShowtype("" + flag);// 页面停留时长flag = rand.nextInt(10) * rand.nextInt(7);appNewsDetail.setNews_staytime(flag + "");// 加载时长flag = rand.nextInt(10) * rand.nextInt(7);appNewsDetail.setLoading_time(flag + "");// 加载失败码flag = rand.nextInt(10);switch (flag) {case 1:appNewsDetail.setType1("102");break;case 2:appNewsDetail.setType1("201");break;case 3:appNewsDetail.setType1("325");break;case 4:appNewsDetail.setType1("433");break;case 5:appNewsDetail.setType1("542");break;default:appNewsDetail.setType1("");break;}// 分类flag = 1 + rand.nextInt(100);appNewsDetail.setCategory("" + flag);JSONObject eventJson = (JSONObject) JSON.toJSON(appNewsDetail);return packEventJson("newsdetail", eventJson);}/*** 商品列表*/private static JSONObject generateNewList() {AppLoading appLoading = new AppLoading();// 动作int flag = rand.nextInt(3) + 1;appLoading.setAction(flag + "");// 加载时长flag = rand.nextInt(10) * rand.nextInt(7);appLoading.setLoading_time(flag + "");// 失败码flag = rand.nextInt(10);switch (flag) {case 1:appLoading.setType1("102");break;case 2:appLoading.setType1("201");break;case 3:appLoading.setType1("325");break;case 4:appLoading.setType1("433");break;case 5:appLoading.setType1("542");break;default:appLoading.setType1("");break;}// 页面 加载类型flag = 1 + rand.nextInt(2);appLoading.setLoading_way("" + flag);// 扩展字段1appLoading.setExtend1("");// 扩展字段2appLoading.setExtend2("");// 用户加载类型flag = 1 + rand.nextInt(3);appLoading.setType("" + flag);JSONObject jsonObject = (JSONObject) JSON.toJSON(appLoading);return packEventJson("loading", jsonObject);}/*** 广告相关字段*/private static JSONObject generateAd() {AppAd appAd = new AppAd();// 入口int flag = rand.nextInt(3) + 1;appAd.setEntry(flag + "");// 动作flag = rand.nextInt(5) + 1;appAd.setAction(flag + "");// 内容类型类型flag = rand.nextInt(6) + 1;appAd.setContentType(flag + "");// 展示样式flag = rand.nextInt(120000) + 1000;appAd.setDisplayMills(flag + "");flag = rand.nextInt(1);if (flag == 1) {appAd.setContentType(flag + "");flag = rand.nextInt(6);appAd.setItemId(flag + "");} else {appAd.setContentType(flag + "");flag = rand.nextInt(1) + 1;appAd.setActivityId(flag + "");}JSONObject jsonObject = (JSONObject) JSON.toJSON(appAd);return packEventJson("ad", jsonObject);}/*** 启动日志*/private static AppStart generateStart() {AppStart appStart = new AppStart();//设备idappStart.setMid(s_mid + "");s_mid++;// 用户idappStart.setUid(s_uid + "");s_uid++;// 程序版本号 5,6等appStart.setVc("" + rand.nextInt(20));//程序版本名 v1.1.1appStart.setVn("1." + rand.nextInt(4) + "." + rand.nextInt(10));// 安卓系统版本appStart.setOs("8." + rand.nextInt(3) + "." + rand.nextInt(10));//设置日志类型appStart.setEn("start");// 语言 es,en,ptint flag = rand.nextInt(3);switch (flag) {case (0):appStart.setL("es");break;case (1):appStart.setL("en");break;case (2):appStart.setL("pt");break;}// 渠道号 从哪个渠道来的appStart.setSr(getRandomChar(1));// 区域flag = rand.nextInt(2);switch (flag) {case 0:appStart.setAr("BR");case 1:appStart.setAr("MX");}// 手机品牌 ba ,手机型号 md,就取2位数字了flag = rand.nextInt(3);switch (flag) {case 0:appStart.setBa("Sumsung");appStart.setMd("sumsung-" + rand.nextInt(20));break;case 1:appStart.setBa("Huawei");appStart.setMd("Huawei-" + rand.nextInt(20));break;case 2:appStart.setBa("HTC");appStart.setMd("HTC-" + rand.nextInt(20));break;}// 嵌入sdk的版本appStart.setSv("V2." + rand.nextInt(10) + "." + rand.nextInt(10));// gmailappStart.setG(getRandomCharAndNumr(8) + "@gmail.com");// 屏幕宽高 hwflag = rand.nextInt(4);switch (flag) {case 0:appStart.setHw("640*960");break;case 1:appStart.setHw("640*1136");break;case 2:appStart.setHw("750*1134");break;case 3:appStart.setHw("1080*1920");break;}// 客户端产生日志时间long millis = System.currentTimeMillis();appStart.setT("" + (millis - rand.nextInt(99999999)));// 手机网络模式 3G,4G,WIFIflag = rand.nextInt(3);switch (flag) {case 0:appStart.setNw("3G");break;case 1:appStart.setNw("4G");break;case 2:appStart.setNw("WIFI");break;}// 拉丁美洲 西经34°46′至西经117°09;北纬32°42′至南纬53°54′// 经度appStart.setLn((-34 - rand.nextInt(83) - rand.nextInt(60) / 10.0) + "");// 纬度appStart.setLa((32 - rand.nextInt(85) - rand.nextInt(60) / 10.0) + "");// 入口flag = rand.nextInt(5) + 1;appStart.setEntry(flag + "");// 开屏广告类型flag = rand.nextInt(2) + 1;appStart.setOpen_ad_type(flag + "");// 状态flag = rand.nextInt(10) > 8 ? 2 : 1;appStart.setAction(flag + "");// 加载时长appStart.setLoading_time(rand.nextInt(20) + "");// 失败码flag = rand.nextInt(10);switch (flag) {case 1:appStart.setDetail("102");break;case 2:appStart.setDetail("201");break;case 3:appStart.setDetail("325");break;case 4:appStart.setDetail("433");break;case 5:appStart.setDetail("542");break;default:appStart.setDetail("");break;}// 扩展字段appStart.setExtend1("");return appStart;}/*** 消息通知*/private static JSONObject generateNotification() {AppNotification appNotification = new AppNotification();int flag = rand.nextInt(4) + 1;// 动作appNotification.setAction(flag + "");// 通知idflag = rand.nextInt(4) + 1;appNotification.setType(flag + "");// 客户端弹时间appNotification.setAp_time((System.currentTimeMillis() - rand.nextInt(99999999)) + "");// 备用字段appNotification.setContent("");JSONObject jsonObject = (JSONObject) JSON.toJSON(appNotification);return packEventJson("notification", jsonObject);}/*** 后台活跃*/private static JSONObject generateBackground() {AppActive_background appActive_background = new AppActive_background();// 启动源int flag = rand.nextInt(3) + 1;appActive_background.setActive_source(flag + "");JSONObject jsonObject = (JSONObject) JSON.toJSON(appActive_background);return packEventJson("active_background", jsonObject);}/*** 错误日志数据*/private static JSONObject generateError() {AppErrorLog appErrorLog = new AppErrorLog();String[] errorBriefs = {"at cn.lift.dfdf.web.AbstractBaseController.validInbound(AbstractBaseController.java:72)", "at cn.lift.appIn.control.CommandUtil.getInfo(CommandUtil.java:67)"}; //错误摘要String[] errorDetails = {"java.lang.NullPointerException\\n " + "at cn.lift.appIn.web.AbstractBaseController.validInbound(AbstractBaseController.java:72)\\n " + "at cn.lift.dfdf.web.AbstractBaseController.validInbound", "at cn.lift.dfdfdf.control.CommandUtil.getInfo(CommandUtil.java:67)\\n " + "at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\\n" + " at java.lang.reflect.Method.invoke(Method.java:606)\\n"}; //错误详情//错误摘要appErrorLog.setErrorBrief(errorBriefs[rand.nextInt(errorBriefs.length)]);//错误详情appErrorLog.setErrorDetail(errorDetails[rand.nextInt(errorDetails.length)]);JSONObject jsonObject = (JSONObject) JSON.toJSON(appErrorLog);return packEventJson("error", jsonObject);}/*** 为各个事件类型的公共字段(时间、事件类型、Json数据)拼接*/private static JSONObject packEventJson(String eventName, JSONObject jsonObject) {JSONObject eventJson = new JSONObject();eventJson.put("ett", (System.currentTimeMillis() - rand.nextInt(99999999)) + "");eventJson.put("en", eventName);eventJson.put("kv", jsonObject);return eventJson;}/*** 获取随机字母组合** @param length 字符串长度*/private static String getRandomChar(Integer length) {StringBuilder str = new StringBuilder();Random random = new Random();for (int i = 0; i < length; i++) {// 字符串str.append((char) (65 + random.nextInt(26)));// 取得大写字母}return str.toString();}/*** 获取随机字母数字组合** @param length 字符串长度*/private static String getRandomCharAndNumr(Integer length) {StringBuilder str = new StringBuilder();Random random = new Random();for (int i = 0; i < length; i++) {boolean b = random.nextBoolean();if (b) { // 字符串// int choice = random.nextBoolean() ? 65 : 97; 取得65大写字母还是97小写字母str.append((char) (65 + random.nextInt(26)));// 取得大写字母} else { // 数字str.append(String.valueOf(random.nextInt(10)));}}return str.toString();}/*** 收藏*/private static JSONObject generateFavorites() {AppFavorites favorites = new AppFavorites();favorites.setCourse_id(rand.nextInt(10));favorites.setUserid(rand.nextInt(10));favorites.setAdd_time((System.currentTimeMillis() - rand.nextInt(99999999)) + "");JSONObject jsonObject = (JSONObject) JSON.toJSON(favorites);return packEventJson("favorites", jsonObject);}/*** 点赞*/private static JSONObject generatePraise() {AppPraise praise = new AppPraise();praise.setId(rand.nextInt(10));praise.setUserid(rand.nextInt(10));praise.setTarget_id(rand.nextInt(10));praise.setType(rand.nextInt(4) + 1);praise.setAdd_time((System.currentTimeMillis() - rand.nextInt(99999999)) + "");JSONObject jsonObject = (JSONObject) JSON.toJSON(praise);return packEventJson("praise", jsonObject);}/*** 评论*/private static JSONObject generateComment() {AppComment comment = new AppComment();comment.setComment_id(rand.nextInt(10));comment.setUserid(rand.nextInt(10));comment.setP_comment_id(rand.nextInt(5));comment.setContent(getCONTENT());comment.setAddtime((System.currentTimeMillis() - rand.nextInt(99999999)) + "");comment.setOther_id(rand.nextInt(10));comment.setPraise_count(rand.nextInt(1000));comment.setReply_count(rand.nextInt(200));JSONObject jsonObject = (JSONObject) JSON.toJSON(comment);return packEventJson("comment", jsonObject);}/*** 生成单个汉字*/private static char getRandomChar() {String str = "";int hightPos; //int lowPos;Random random = new Random();//随机生成汉子的两个字节hightPos = (176 + Math.abs(random.nextInt(39)));lowPos = (161 + Math.abs(random.nextInt(93)));byte[] b = new byte[2];b[0] = (Integer.valueOf(hightPos)).byteValue();b[1] = (Integer.valueOf(lowPos)).byteValue();try {str = new String(b, "GBK");} catch (UnsupportedEncodingException e) {e.printStackTrace();System.out.println("错误");}return str.charAt(0);}/*** 拼接成多个汉字*/private static String getCONTENT() {StringBuilder str = new StringBuilder();for (int i = 0; i < rand.nextInt(100); i++) {str.append(getRandomChar());}return str.toString();}
}
5)配置日志打印Logback
简介:Logback主要用于在磁盘和控制台打印日志
使用
- 1)在resource文件夹下创建logback.xml文件
- 2)在logback.xml文件添加如下配置
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false"><!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径 --><property name="LOG_HOME" value="/opt/tmp/logs"/><!-- 控制台输出 --><appender name="STDOUT"class="ch.qos.logback.core.ConsoleAppender"><encoderclass="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!--格式化输出:%d 表示日期,%thread 表示线程名,%-5level:级别从左显示 5 个字符宽度%msg:日志消息,%n 是换行符 --><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern></encoder></appender><!-- 按照每天生成日志文件。存储事件日志 --><appender name="FILE"class="ch.qos.logback.core.rolling.RollingFileAppender"><!-- <File>${LOG_HOME}/app.log</File>设置日志不超过${log.max.size}时的保存路径,注意,如果是 web 项目会保存到 Tomcat 的 bin 目录 下 --><rollingPolicyclass="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!--日志文件输出的文件名 --><FileNamePattern>${LOG_HOME}/app-%d{yyyy-MM-dd}.log</FileNamePattern><!--日志文件保留天数 --><MaxHistory>30</MaxHistory></rollingPolicy><encoderclass="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>%msg%n</pattern></encoder><!--日志文件最大的大小 --><triggeringPolicyclass="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"><MaxFileSize>10MB</MaxFileSize></triggeringPolicy></appender><!--异步打印日志--><appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender"><!-- 不丢失日志.默认的,如果队列的 80%已满,则会丢弃 TRACT、DEBUG、INFO 级别的日志 --><discardingThreshold>0</discardingThreshold><!-- 更改默认的队列的深度,该值会影响性能.默认值为 256 --><queueSize>512</queueSize><!-- 添加附加的 appender,最多只能添加一个 --><appender-ref ref="FILE"/></appender><!-- 日志输出级别 --><root level="INFO"><appender-ref ref="STDOUT"/><appender-ref ref="ASYNC_FILE"/><appender-ref ref="error"/></root>
</configuration>
6.代码整体架构
7.项目打包准备后续放在服务器上运行产生测试数据
实战-数据仓库构建(二)相关推荐
- 实战-数据仓库构建(一)
问题导读: 1.数据仓库的架构是什么样的? 2.如何进行技术选型? 3.系统数据流程如何设计? 4.如何进行服务器选型? 一.数据仓库 数据仓库(Data Warehouse),是为企业所有决策制定过 ...
- 《离线和实时大数据开发实战》(二)大数据平台架构 技术概览
前言 接着上一章 构建大数据开发知识体系图谱,本次继续分享邦中老师的<离线和实时大数据开发实战>读书笔记 .到底什么样的平台才能算是大数据平台呢?带着这个问题,我们开始今天的内容 ( •̀ ...
- [.NET领域驱动设计实战系列]专题二:结合领域驱动设计的面向服务架构来搭建网上书店...
原文:[.NET领域驱动设计实战系列]专题二:结合领域驱动设计的面向服务架构来搭建网上书店 一.前言 在前面专题一中,我已经介绍了我写这系列文章的初衷了.由于dax.net中的DDD框架和Bytear ...
- 大数据培训 | 数据仓库构建方法论和实践
数据仓库的价值 构思一个主题讨论数据仓库的构建方法论,包括数据仓库的价值.选型.构建思路,随着数据规模膨胀和业务复杂度的提升,大型企业需要构建企业级的数据仓库(数据湖)来快速支撑业务的数据化需求,与传 ...
- 视频教程-SEM实战教程(二)-网络营销
SEM实战教程(二) 毕业于中国人民大学,从事网络营销推广多年,网络营销讲师,有丰富的SEM.微博微信营销培训经验,多年的网络营销实战派研究者,操作过医疗集团.出国留学.教育培训等推广项目,现专注SE ...
- Fiddler实战深入研究(二)
Fiddler实战深入研究(二) 阅读目录 Fiddler不能捕获chrome的session的设置 理解数据包统计 请求重定向(AutoResponder) Composer选项卡 Filters选 ...
- Fiddler实战深入研究(二)——模拟返回数值
转自大神:https://www.cnblogs.com/tugenhua0707/p/4637771.html ------------------------------------------- ...
- Fiddler实战深入研究(二)[转载]
Fiddler实战深入研究(二) 阅读目录 Fiddler不能捕获chrome的session的设置 理解数据包统计 请求重定向(AutoResponder) Composer选项卡 Filters选 ...
- 机器学习实战教程(二):决策树基础篇之让我们从相亲说起
机器学习实战教程(二):决策树基础篇之让我们从相亲说起 一.前言 二.决策树 三.决策树的构建的准备工作 1.特征选择 (1)香农熵 (2)编写代码计算经验熵 (3) 信息增益 (4) 编写代码计算信 ...
最新文章
- Scala安装时的坑
- android jar 无法访问r文件,android项目中gen目录不能自动生成R.java的原因
- Java8 Hashtable 源码阅读
- 【渝粤教育】 国家开放大学2020年春季 1373特殊教育概论 参考试题
- 给element的select添加复选框
- 最全python爬虫库安装详解
- ECMAScript 6 里面的私有变量
- c#自定义事件的使用方法
- 飞线5根连接图_手机主板焊盘掉点飞线维修方法
- JavaSE基础:泛型
- python批量获取百度贴吧_python网络爬虫案例:批量爬取百度贴吧页面数据
- Excel文件批量删除指定行或列
- C语言客房管理系统课程设计
- 基于NW实现的前端桌面应用
- 51单片机流水灯现象1
- 【前端】【JavaScript】通过成绩判断等级
- virtualbox虚拟机网络配置实现内网外网互通
- 多种ubuntu引导修复方法
- 托爾斯泰《安娜‧卡列妮娜》的寫作背景
- 温度传感器DS18B20应用