基于Hive的手机应用信息统计分析系统
项目概要
需求
手机应用日志
定期离线分析手机应用新增用户、活跃用户、沉默用户、启动次数、版本分布和留存用户等业务指标。
工作流程
- 手机APP启动时,上报启动日志、错误日志、页面日志、事件日志、使用时长日志等信息到日志收集服务器。
- 日志收集服务器将收集到的日志信息发送给kafka。
- Flume分别消费kafka中的5种主题信息,并把数据存储到HDFS上。
- 通过crontab任务调度定时把HDFS中的信息拷贝到Hive数据仓库中。
- 核心业务操作采用Hive查询。
一般先flume再kafka或者只有kafka
一般数据开发就负责2到5或6(展示),即数据收集和处理或加上展示。
具体实现
公共模板、手机端日志生成模块、日志收集web模块、flume拦截器、hive自定义函数
日志
public class AppBaseLog implements Serializable
日志基类包含日志创建时间、应用ID、租户企业ID、设备ID(手机用户ID)、应用版本、应用下载渠道、操作系统及其版本、机型等信息。
其他日志继承自基类,错误日志类、事件日志类、页面日志类、启动日志类、使用时长日志类、地理信息类。
还有一个AppLogEntity类,里面包含了这些上述日志的数组,手机应用每次发送的日志信息就是使用这个类。
手机客户端
一个模拟日志生成的类。
数据收集模板
WebController类,将收集到的日志信息发送给Kafka。
一个手机用户发送一份AppLogEntity对象数据,里面包含了各种日志类型的数据。将这些数据分别转化为Json格式,然后通过Kafka的ProducerRecord发送到Kafka集群。
总体流程
Tomcat运行web程序,generateData类不断向端口发送日志信息。web类的controller层将数据发送到kafka集群。搭建Flume管道,从Kafka集群中拉取数据到HDFS。
编写Hive脚本,通过crondtab实现每隔一段时间从HDFS上导入数据到Hive。
Hive UDF类
根据输入的时间信息:
返回当天的起始时间;
返回本周的起始时间;
返回本月的起始时间;
根据输入的时间和时间格式化信息:返回按照格式化要求显示的信息。
新建一个DateUtil类,里面有输入时间获取相应起始时间的函数。
新建一个DayBegin类,继承UDF类,重写并重载各种evaluate方法。实现的方法包括无参返回当天的零点;偏移量参数返回当天加偏移量的那一天的零点;指定日期加偏移量返回该天的起始时间;根据String计算某天的起始时间;string时间 + offset;string时间 + 指定时间格式;string时间 + 指定时间格式 + 偏移。
按DayBegin类的思路,再实现周、月的类。
还有一个FormatTimeUDF类,增加根据long时间 + string指定时间格式 返回string时间;根据string时间 + string指定时间格式 返回string时间;根据long时间 +string指定时间格式 + 辅助参数 返回周内第一天的string时间。
public class FormatTimeUDF extends UDF {
// 根据输入的时间毫秒值(long类型)和格式化要求,返回String类型时间
public String evaluate(long ms,String fmt) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat(fmt) ;
Date d = new Date();
d.setTime(ms);
return sdf.format(d) ;
}
// 根据输入的时间毫秒值(String类型)和格式化要求,返回String类型时间
public String evaluate(String ms,String fmt) throws ParseException {
SimpleDateFormat sdf = new SimpleDateFormat(fmt) ;
Date d = new Date();
d.setTime(Long.parseLong(ms));
return sdf.format(d) ;
}
// 根据输入的时间毫秒值(long类型)、格式化要求,和区分周的任意值,返回String类型时间
public String evaluate(long ms ,String fmt , int week) throws ParseException {
Date d = new Date();
d.setTime(ms);
//周内第一天
Date firstDay = DateUtil.getWeekBeginTime(d) ;
SimpleDateFormat sdf = new SimpleDateFormat(fmt) ;
return sdf.format(firstDay) ;
}
添加函数:将jar包放到hive/lib,修改hive-site,在hiveclient上注册函数(一个类一个函数)
HIVE查询
主要包括:新增用户、活跃用户、沉默用户、留存用户(上周没,这周有;这两周没,之前有;本周留存)、新鲜度
新增用户
createdatms为日志创建时间
# 判断今天的新增用户
select count(*)
from (
select min(createdatms) mintime
from ext_startup_logs
where appid = 'sdk34734'
group by deviceid
having mintime >= getdaybegin()
)t;
# 昨天就是 mintime >= getdaybegin(-1) and mintime < getdaybegin()
活跃用户
# 日活跃用户
select count(distinct deviceid)
from ext_startup_logs
where appid = 'sdk34734' and createdatms >= getdaybegin() and createdatms < getdaybegin(1);
# 优化,根据时间分区表去查询,避免全表扫描。ym和day在load数据时已经设定好的分区名
where ym = formattime(getdaybegin(),'yyyyMM') and day = formattime(getdaybegin(),'dd') and appid = 'sdk34734';
# 一周内每日的日活跃数。formattime得到每日的开始。
select formattime(createdatms,'yyyy/MM/dd') day ,count(distinct deviceid)
from ext_startup_logs
where concat(ym, day) >= formattime(getdaybegin(-6), "yyyyMMdd")
and appid = 'sdk34734'
group by formattime(createdatms,'yyyy/MM/dd');
# 一次查询出过去的5周,每周的周活跃数。formattime的0参数是为了得出当日对应的周开始
select formattime(createdatms,'yyyy/MM/dd',0) week ,count(distinct deviceid)
from ext_startup_logs
where appid = 'sdk34734'
and createdatms >= getweekbegin(-6) and createdatms < getweekbegin(-1)
group by formattime(createdatms,'yyyy/MM/dd',0);
# 过去5周,包含本周的每周周活跃数
where concat(ym,day) >= formattime(getweekbegin(-4),'yyyyMMdd') and appid ='sdk34734'
# 一次查询出过去的三个月内的月活跃数
select formattime(createdatms,'yyyy/MM',0) month ,count(distinct deviceid)
from ext_startup_logs
where appid = 'sdk34734'
and createdatms >= getmonthbegin(-2) and createdatms < getmonthbegin(-1)
group by formattime(createdatms,'yyyy/MM',0);
# 包含本月
where ym >= formattime(getmonthbegin(-2),'yyyyMM') and appid ='sdk34734'
# 连续三周活跃用户
select deviceid , count(distinct(formattime(createdatms,'yyyyMMdd',0))) c
from ext_startup_logs
where concat(ym,day) >= formattime(getweekbegin(-2),'yyyyMMdd') and appid = 'sdk34734'
group by deviceid
having c = 3;
沉默用户
条件:只有一条日志;安装2天内不算
select count(*)
from (
select deviceid, count(createdate) c
from ext_startup_logs
where concat(ym, day) < formattime(getdaybegin(-2), 'yyyyMMdd') and appid = 'sdk34734'
group by deviceid
having c = 1;
);
留存用户
# 本周回流,即上周没启动过,本周启动了
select distinct s.deviceid
from ext_startup_logs s
where appid = 'sdk34734' and concat(ym,day) >= formattime(getweekbegin(),'yyyyMMdd') and deviceid not in (
select distinct t.deviceid
from ext_startup_logs t
where t.appid = 'sdk34734'
and concat(t.ym,t.day) >= formattime(getweekbegin(-1),'yyyyMMdd')
and concat(t.ym,t.day) < formattime(getweekbegin(),'yyyyMMdd')
);
# 连续2周没有启动的用户,之前启动过
select distinct s.deviceid
from ext_startup_logs s
where concat(ym,day) < formattime(getweekbegin(-1),'yyyyMMdd')
and appid='sdk34734'
and s.deviceid not in (
select distinct(t.deviceid)
from ext_startup_logs t
where concat(t.ym,t.day) >= formattime(getweekbegin(-1),'yyyyMMdd')
and t.appid='sdk34734'
);
# 留存用户。本周留存指上周新增,且本周活跃。
select distinct s.deviceid
from ext_startup_logs s
where concat(ym,day) >= formattime(getweekbegin(),'yyyyMMdd')
and s.appid = 'sdk34734'
and s.deviceid in (
select tt.deviceid , min(tt.createdatms) mintime
from ext_startup_logs tt
where tt.appid = 'sdk34734'
group by tt.deviceid
having mintime >= getweekbegin(-2)
and mintime < getweekbegin(-1)
);
新鲜度分析
# 新鲜度分析,某段时间的新增用户数/某段时间的活跃的用户数
# 今天新增
select count(*)
from(
select min(createdatms) mintime
from ext_startup_logs
where appid = 'sdk34734'
group by deviceid
having mintime >= getdaybegin()
)t;
# 今天活跃
select count(distinct deviceid)
from ext_startup_logs
where concat(ym, day) = formattime(getdaybegin, "yyyyMMdd");
and appid = 'sdk34734'
基于Hive的手机应用信息统计分析系统的更多相关文章
- 《Spring_Four》第三次作业——基于Jsoup的大学生考试信息展示系统的原型设计与开发
<Spring_Four团队>第三次团队项目——基于Jsoup的大学生考试信息展示系统的原型设计与开发 一.实验目的与要求 (1)掌握软件原型开发技术: (2)学习使用软件原型开发工具:本 ...
- SDC信息统计分析系统ETL工具的研究与实现[专业:计算机应用技术]
SDC信息统计分析系统ETL工具的研究与实现[专业:计算机应用技术] http://www.docin.com/p-265530271.html
- 《Spring_Four》第二次作业 基于Jsoup的大学生考试信息展示系统开题报告
一.项目概述 该项目拟采用Jsoup对大学生三大考试(考研.考公务员.考教师资格证)进行消息搜集,研发完成一款轻量级的信息展示APP,本项目主要的创新点在于可以搜集大量的考试信息,对其进行一个展示,而 ...
- 基于Python的渗透测试信息收集系统的设计和实现
信息收集系统的设计和实现 渗透测试是保卫网络安全的一种有效且必要的技术手段,而渗透测试的本质就是信息收集,信息搜集整理可为后续的情报跟进提供强大的保证,目标资产信息搜集的广度,决定渗透过程的复杂程度, ...
- 基于JSP开发手机销售购物商城系统
开发环境: Windows操作系统开发工具:Eclipse+Jdk+Tomcat+MySQL数据库 运行效果图: 源码及原文链接:https://javadao.xyz/forum.php?mod=v ...
- 基于hive的日志分析系统
转自 http://www.cppblog.com/koson/archive/2010/07/19/120773.html hive 简介 hive 是一个基于 ...
- 基于HBase的手机数据备份系统 .
基于HBase实现的手机数据备份系统,实现了手机关键信息的备份,如短信.联系人等. 包括服务器端(Server)和客户端(Client) Server运行环境:Hadoop+HBase+Tomcat ...
- 基于JSP+Servlet开发手机销售购物商城系统(前台+后台)源码
基于JSP+Servlet开发手机销售购物商城系统(前台+后台) 开发环境: Windows操作系统 开发工具:Eclipse/MyEclipse+Jdk+Tomcat+MySQL数据库 运行效果图: ...
- AppUtils【获取手机的信息和应用版本号、安装apk】
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 一个获取设备的系统版本号.设备的型号.应用版本号code值.应用版本号name值.包名.是否更新.安装apk的工具类. 其实这个工具 ...
随机推荐
- 并查集(Union Find)的基本实现
概念 并查集是一种树形的数据结构,用来处理一些不交集的合并及查询问题.主要有两个操作: find:确定元素属于哪一个子集. union:将两个子集合并成同一个集合. 所以并查集能够解决网络中节点的连通 ...
- 动态生成java、动态编译、动态加载
我曾经见过一个“规则引擎”,是在应用系统web界面直接编写java代码,然后保存后,规则即生效,我一直很是奇怪,这是如何实现的呢?实际这就好像jsp,被中间件动态的编译成java文件,有被动态的编译成 ...
- 个人Linux(ubuntu)使用记录——远程访问linux
说明:记录自己的linux使用过程,并不打算把它当作一个教程,仅仅只是记录下自己使用过程中的一些命令,配置等东西,这样方便自己查阅,也就不用到处去网上搜索了,所以文章毫无章法可言,甚至会记录得很乱. ...
- 四角递推(CF Working out,动态规划递推)
题目:假如有A,B两个人,在一个m*n的矩阵,然后A在(1,1),B在(m,1),A要走到(m,n),B要走到(1,n),两人走的过程中可以捡起格子上的数字,而且两人速度不一样,可以同时到一个点(哪怕 ...
- UVA - 1619 Feel Good(扫描法)
题目: 思路: 预处理出a[i]在哪个范围区间内是最小的,然后直接遍历a数组求答案就可以了. 这个预处理的技巧巧妙的用了之前的处理结果.(大佬tql) 代码: #include <bits/st ...
- Linux下“任务管理器”
也不知道linux叫不叫任务管理器. Ctrl+Alt+T打开终端,输入top,就会出现一堆东西. 如果有个东西未响应了,就可以输入k+这个进程的pid就可以杀死它. https://blog.csd ...
- Linux:DHCP服务配置
DHCP服务程序能够使局域网内的主机自动且动态的获取IP地址.子网掩码.网关地址以及DNS服务器地址等信息. 说明:先安装DHCP服务 yum install dhcp -y ...
- Code128条形码如何计算其宽度?如何得出其校验位?
原文链接 Code128条形码是一个非常高密的字母数字条码,能够存储需要的编码数据,它可以编码所有128个ASCII码字符,它使用最少的空间. 在Code128符号体系中,每个数据字符编码都是由11个 ...
- axios在实际项目中的使用介绍
1.axios本身就封装了各种数据请求的方法 执行 GET 请求 // 为给定 ID 的 user 创建请求 axios.get('/user?ID=12345') .then(function (r ...
- 关于Scrum 实战故事录播的感悟升级
昨晚与几位自组织的伙伴进行了<Scrum 实战> 第17 章 <富有成效的每日站会>录播Sprint 不断的优化和精进的感悟. 首先,D兄给予了如下的建议: 1. 将段落 分得 ...