第3 章数据生成模块
3.1 埋点数据基本格式
Ø 公共字段:基本所有安卓手机都包含的字段
Ø 业务字段:埋点上报的字段,有具体的业务类型
下面就是一个示例,表示业务字段的上传。
下面就是一个示例,表示业务字段的上传。
{
"ap":"xxxxx",//项目数据来源 app pc
"cm": { //公共字段
**"mid": "", // (String)** **设备唯一标识**
**"uid": "", // (String)** **用户标识**
"vc": "1", // (String) versionCode,程序版本号
"vn": "1.0", // (String) versionName,程序版本名
"l": "zh", // (String) language系统语言
**"sr": "", // (String)** **渠道号,应用从哪个渠道来的**。
"os": "7.1.1", // (String) Android系统版本
"ar": "CN", // (String) area区域
**"md": "BBB100-1", // (String) model****手机型号**
**"ba": "blackberry", // (String) brand****手机品牌**
"sv": "V2.2.1", // (String) sdkVersion
"g": "", // (String) gmail
**"hw": "1620x1080", // (String) heightXwidth****,屏幕宽高**
"t": "1506047606608", // (String) 客户端日志产生时的时间
"nw": "WIFI", // (String) 网络模式
"ln": 0, // (double) lng经度
"la": 0 // (double) lat 纬度
},
"et": [ //事件
{
"ett": "1506047605364", //客户端事件产生时间
"en": "display", //事件名称
"kv": { //事件结果,以key-value形式自行定义
"goodsid": "236",
"action": "1",
"extend1": "1",
"place": "2",
"category": "75"
}
}
]
}
示例日志(服务器时间戳 | 日志):
1540934156385|{
"ap": "gmall",
"cm": {
"uid": "1234",
"vc": "2",
"vn": "1.0",
"la": "EN",
"sr": "",
"os": "7.1.1",
"ar": "CN",
"md": "BBB100-1",
"ba": "blackberry",
"sv": "V2.2.1",
"g": "abc@gmail.com",
"hw": "1620x1080",
"t": "1506047606608",
"nw": "WIFI",
"ln": 0
},
"et": [
{
"ett": "1506047605364", //客户端事件产生时间
"en": "display", //事件名称
"kv": { //事件结果,以key-value形式自行定义
"goodsid": "236",
"action": "1",
"extend1": "1",
"place": "2",
"category": "75"
}
},{
"ett": "1552352626835",
"en": "active_background",
"kv": {
"active_source": "1"
}
}
]
}
}
下面是各个埋点日志格式。其中商品点击属于信息流的范畴
3.2 事件日志数据
3.2.1 商品列表页(loading)
事件名称:loading
标签 |
含义 |
action |
动作:开始加载=1,加载成功=2,加载失败=3 |
loading_time |
加载时长:计算下拉开始到接口返回数据的时间,(开始加载报0,加载成功或加载失败才上报时间) |
loading_way |
加载类型:1-读取缓存,2-从接口拉新数据 (加载成功才上报加载类型) |
extend1 |
扩展字段 Extend1
|
extend2 |
扩展字段 Extend2 |
type |
加载类型:自动加载**=1****,用户下拽加载****=2****,底部加载****=3****(底部条触发点击底部提示条****/**点击返回顶部加载)
|
type1 |
加载失败码:把加载失败状态码报回来(报空为加载成功,没有失败) |
3.2.2 商品点击(display)
事件标签:display
标签 |
含义 |
|
action |
动作:曝光商品=1,点击商品=2, |
|
goodsid |
商品ID(服务端下发的ID) |
|
place |
顺序(第几条商品,第一条为0,第二条为1,如此类推) |
|
extend1 |
曝光类型:1 - 首次曝光 2-重复曝光 |
|
category |
分类ID(服务端定义的分类ID) |
|
|
|
|
3.2.3 商品详情页(newsdetail)
事件标签:newsdetail
标签 |
含义 |
|
entry |
页面入口来源:应用首页=1、push=2、详情页相关推荐=3 |
|
action |
动作:开始加载=1,加载成功=2(pv),加载失败=3, 退出页面=4 |
|
goodsid |
商品ID(服务端下发的ID) |
|
show_style |
商品样式:0、无图、1、一张大图、2、两张图、3、三张小图、4、一张小图、5、一张大图两张小图 |
|
news_staytime |
页面停留时长:从商品开始加载时开始计算,到用户关闭页面所用的时间。若中途用跳转到其它页面了,则暂停计时,待回到详情页时恢复计时。或中途划出的时间超过10分钟,则本次计时作废,不上报本次数据。如未加载成功退出,则报空。 |
|
loading_time |
加载时长:计算页面开始加载到接口返回数据的时间 (开始加载报0,加载成功或加载失败才上报时间) |
|
type1 |
加载失败码:把加载失败状态码报回来(报空为加载成功,没有失败) |
|
category |
分类ID(服务端定义的分类ID) |
|
|
|
|
3.2.4 广告(ad)
事件名称:ad
标签 |
含义 |
entry |
入口:商品列表页=1 应用首页=2 商品详情页=3 |
action |
动作: 广告展示=1 广告点击=2 |
contentType |
Type: 1 商品 2 营销活动 |
displayMills |
展示时长 毫秒数 |
itemId |
商品id |
activityId |
营销活动id |
3.2.5 消息通知(notification)
事件标签:notification
标签 |
含义 |
action |
动作:通知产生=1,通知弹出=2,通知点击=3,常驻通知展示(不重复上报,一天之内只报一次)=4 |
type |
通知id:预警通知=1,天气预报(早=2,晚=3),常驻=4 |
ap_time |
客户端弹出时间 |
content |
备用字段 |
3.2.6 用户后台活跃(active_background)
事件标签: active_background
标签 |
含义 |
active_source |
1=upgrade,2=download(下载),3=plugin_upgrade |
3.2.7 评论(comment)
描述:评论表
序号 |
字段名称 |
字段描述 |
字段类型 |
长度 |
允许空 |
缺省值 |
1 |
comment_id |
评论表 |
int |
10,0 |
|
|
2 |
userid |
用户id |
int |
10,0 |
√ |
0 |
3 |
p_comment_id |
父级评论id(为0则是一级评论,不为0则是回复) |
int |
10,0 |
√ |
|
4 |
content |
评论内容 |
string |
1000 |
√ |
|
5 |
addtime |
创建时间 |
string |
|
√ |
|
6 |
other_id |
评论的相关id |
int |
10,0 |
√ |
|
7 |
praise_count |
点赞数量 |
int |
10,0 |
√ |
0 |
8 |
reply_count |
回复数量 |
int |
10,0 |
√ |
0 |
3.2.8 收藏(favorites)
描述:收藏
序号 |
字段名称 |
字段描述 |
字段类型 |
长度 |
允许空 |
缺省值 |
1 |
id |
主键 |
int |
10,0 |
|
|
2 |
course_id |
商品id |
int |
10,0 |
√ |
0 |
3 |
userid |
用户ID |
int |
10,0 |
√ |
0 |
4 |
add_time |
创建时间 |
string |
|
√ |
|
3.2.9 点赞(praise)
描述:所有的点赞表
序号 |
字段名称 |
字段描述 |
字段类型 |
长度 |
允许空 |
缺省值 |
1 |
id |
主键id |
int |
10,0 |
|
|
2 |
userid |
用户id |
int |
10,0 |
√ |
|
3 |
target_id |
点赞的对象id |
int |
10,0 |
√ |
|
4 |
type |
点赞类型 1问答点赞 2问答评论点赞 3 文章点赞数4 评论点赞 |
int |
10,0 |
√ |
|
5 |
add_time |
添加时间 |
string |
|
√ |
|
3.2.10 错误日志
errorBrief |
错误摘要 |
errorDetail |
错误详情 |
3.3 启动日志数据
事件标签: start
标签 |
含义 |
entry |
入口: push=1,widget=2,icon=3,notification=4, lockscreen_widget =5 |
open_ad_type |
开屏广告类型: 开屏原生广告=1, 开屏插屏广告=2 |
action |
状态:成功=1 失败=2 |
loading_time |
加载时长:计算下拉开始到接口返回数据的时间,(开始加载报0,加载成功或加载失败才上报时间) |
detail |
失败码(没有则上报空) |
extend1 |
失败的message(没有则上报空) |
en |
日志类型start |
{
"action":"1",
"ar":"MX",
"ba":"HTC",
"detail":"",
"en":"start",
"entry":"2",
"extend1":"",
"g":"43R2SEQX@gmail.com",
"hw":"640*960",
"l":"en",
"la":"20.4",
"ln":"-99.3",
"loading_time":"2",
"md":"HTC-2",
"mid":"995",
"nw":"4G",
"open_ad_type":"2",
"os":"8.1.2",
"sr":"B",
"sv":"V2.0.6",
"t":"1561472502444",
"uid":"995",
"vc":"10",
"vn":"1.3.4"
}
3.4 数据生成脚本
3.4.1 创建Maven工程
1)创建log-collector
=================================
代码已经创建好了,可以直接使用。点击链接直接下载
https://download.csdn.net/download/liangq740/12787847
Bean 的源码
Main的源码
=======================================
2)创建一个包名:com.atguigu.appclient
3)在com.atguigu.appclient包下创建一个类,AppMain。
4)在pom.xml文件中添加如下内容
<slf4j.version>1.7.20</slf4j.version>
<logback.version>1.0.7</logback.version>
<!--阿里巴巴开源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>
<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
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.atguigu.appclient.AppMain</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
注意:com.atguigu.appclient.AppMain要和自己建的全类名一致。
3.4.2 公共字段Bean
1)创建包名:com.atguigu.bean
2)在com.atguigu.bean包下依次创建如下bean对象
package com.atguigu.bean;
/**
* 公共日志
*/
public class AppBase{
private String mid; // (String) 设备唯一标识
private String uid; // (String) 用户uid
private 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) sdkVersion
private String g; // (String) gmail
private 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;
}
}
3.4.3 启动日志Bean
package com.atguigu.bean;
/**
* 启动日志
*/
public class AppStart extends AppBase {
private String entry;//入口: push=1,widget=2,icon=3,notification=4, lockscreen_widget =5
private String open_ad_type;//开屏广告类型: 开屏原生广告=1, 开屏插屏广告=2
private String action;//状态:成功=1 失败=2
private 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;
}
}
3.4.3 错误日志Bean
package com.atguigu.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;
}
}
3.4.4 事件日志Bean之商品点击
package com.atguigu.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;
}
}
3.4.5 事件日志Bean之商品详情页
package com.atguigu.bean;
/**
* 商品详情
*/
public class AppNewsDetail {
private String entry;//页面入口来源:应用首页=1、push=2、详情页相关推荐=3
private String action;//动作:开始加载=1,加载成功=2(pv),加载失败=3, 退出页面=4
private 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;
}
}
3.4.6 事件日志Bean之商品列表页
package com.atguigu.bean;
/**
* 商品列表
*/
public class AppLoading {
private String action;//动作:开始加载=1,加载成功=2,加载失败=3
private String loading_time;//加载时长:计算下拉开始到接口返回数据的时间,(开始加载报0,加载成功或加载失败才上报时间)
private String loading_way;//加载类型:1-读取缓存,2-从接口拉新数据 (加载成功才上报加载类型)
private String extend1;//扩展字段 Extend1
private String extend2;//扩展字段 Extend2
private 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;
}
}
3.4.7 事件日志Bean之广告
package com.atguigu.bean;
/**
* 广告
*/
public class AppAd {
private String entry;//入口:商品列表页=1 应用首页=2 商品详情页=3
private String action;//动作: 广告展示=1 广告点击=2
private String contentType;//Type: 1 商品 2 营销活动
private String displayMills;//展示时长 毫秒数
private String itemId; //商品id
private String activityId; //营销活动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 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;
}
}
3.4.8 事件日志Bean之消息通知
package com.atguigu.bean;
/**
* 消息通知日志
*/
public class AppNotification {
private String action;//动作:通知产生=1,通知弹出=2,通知点击=3,常驻通知展示(不重复上报,一天之内只报一次)=4
private String type;//通知id:预警通知=1,天气预报(早=2,晚=3),常驻=4
private 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;
}
}
3.4.9 事件日志Bean之用户后台活跃
package com.atguigu.bean;
/**
* 用户后台活跃
*/
public class AppActive_background {
private String active_source;//1=upgrade,2=download(下载),3=plugin_upgrade
public String getActive_source() {
return active_source;
}
public void setActive_source(String active_source) {
this.active_source = active_source;
}
}
3.4.10 事件日志Bean之用户评论
package com.atguigu.bean;
/**
* 评论
*/
public class AppComment {
private int comment_id;//评论表
private int userid;//用户id
private int p_comment_id;//父级评论id(为0则是一级评论,不为0则是回复)
private String content;//评论内容
private String addtime;//创建时间
private int other_id;//评论的相关id
private 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;
}
}
3.4.11 事件日志Bean之用户收藏
package com.atguigu.bean;
/**
* 收藏
*/
public class AppFavorites {
private int id;//主键
private int course_id;//商品id
private int userid;//用户ID
private 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;
}
}
3.4.12 事件日志Bean之用户点赞
package com.atguigu.bean;
/**
* 点赞
*/
public class AppPraise {
private int id; //主键id
private int userid;//用户id
private int target_id;//点赞的对象id
private 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;
}
}
3.4.13 主函数
在AppMain类中添加如下内容:
package com.atguigu.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.atguigu.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();
// 设备id
private static int s_mid = 0;
// 用户id
private static int s_uid = 0;
// 商品id
private static int s_goodsid = 0;
public static void main(String[] args) {
// 参数一:控制发送每条的延时时间,默认是0
Long 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();
//设备id
appBase.setMid(s_mid + "");
s_mid++;
// 用户id
appBase.setUid(s_uid + "");
s_uid++;
// 程序版本号 5,6等
appBase.setVc("" + rand.nextInt(20));
//程序版本名 v1.1.1
appBase.setVn("1." + rand.nextInt(4) + "." + rand.nextInt(10));
// 安卓系统版本
appBase.setOs("8." + rand.nextInt(3) + "." + rand.nextInt(10));
// 语言 es,en,pt
int 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));
// gmail
appBase.setG(getRandomCharAndNumr(8) + "@gmail.com");
// 屏幕宽高 hw
flag = 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,WIFI
flag = 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");
}
// 商品id
String 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));
// 商品id
appNewsDetail.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);
// 扩展字段1
appLoading.setExtend1("");
// 扩展字段2
appLoading.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();
//设备id
appStart.setMid(s_mid + "");
s_mid++;
// 用户id
appStart.setUid(s_uid + "");
s_uid++;
// 程序版本号 5,6等
appStart.setVc("" + rand.nextInt(20));
//程序版本名 v1.1.1
appStart.setVn("1." + rand.nextInt(4) + "." + rand.nextInt(10));
// 安卓系统版本
appStart.setOs("8." + rand.nextInt(3) + "." + rand.nextInt(10));
//设置日志类型
appStart.setEn("start");
// 语言 es,en,pt
int 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));
// gmail
appStart.setG(getRandomCharAndNumr(8) + "@gmail.com");
// 屏幕宽高 hw
flag = 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,WIFI
flag = 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 + "");
// 通知id
flag = 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();
}
}
3.4.14 配置日志打印Logback
Logback主要用于在磁盘和控制台打印日志。
Logback具体使用:
1)在resources文件夹下创建logback.xml文件。
2)在logback.xml文件中填写如下配置
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径 -->
<property name="LOG_HOME" value="/tmp/logs/" />
<!-- 控制台输出 -->
<appender name="STDOUT"
class="ch.qos.logback.core.ConsoleAppender">
<encoder
class="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目录 下 -->
<rollingPolicy
class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名 -->
<FileNamePattern>${LOG_HOME}/app-%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日志文件保留天数 -->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder
class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%msg%n</pattern>
</encoder>
<!--日志文件最大的大小 -->
<triggeringPolicy
class="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>
3.4.15 打包
1)采用Maven对程序打包
2)采用带依赖的jar包。包含了程序运行需要的所有依赖。
3)后续日志生成过程,在安装完Hadoop和Zookeeper之后执行。