当前位置:   article > 正文

手机app日志分析系统(一)_as如何分析app日志

as如何分析app日志
  1. 一、项目介绍
  2. -------------------------------------------------
  3. 1.App开发商
  4. 每个开发商可以有多个App产品
  5. 2.App软件
  6. 3.数据服务平台提供商
  7. Umeng,
  8. 向App开发商提供服务。提供App使用情况的统计服务。
  9. 4.SDK
  10. 数据服务平台提供商提供给App开发商的软件包。
  11. 内置log上报程序。
  12. 5.用户
  13. 每个使用App的设备。
  14. 6.租户
  15. 购买了数据服务平台提供商服务的App开发商。
  16. 二、项目分析
  17. ------------------------------------------------------
  18. 1.用户
  19. 设备id,唯一性
  20. 2.新增用户
  21. 首次打开应用的用户。
  22. 卸载再安装不是新增
  23. 3.活跃用户
  24. 指定时间段内打开过app的用户即为活跃用户。多次打开算一次。
  25. 4.月活率
  26. 活跃用户 / 截止到当月累计用户总数。
  27. 5.沉默用户
  28. 两天时间没有启动过app的用户就算沉默用户。
  29. 6.版本分布
  30. 计算各版本的新增用户、活跃用户、启动次数。
  31. 7.本周回流用户
  32. 上周没启动,本周启动的用户
  33. 8.连续n周活跃用户
  34. 连续n周,每周至少启动一次。
  35. 9.忠诚用户
  36. 连续5周以上活跃用户
  37. 10.连续活跃用户
  38. 连续2周以上
  39. 11.近期流失用户
  40. 连续n(2<= n <= 4)周没有启动应用的用户。
  41. 12.留存用户
  42. 某段时间内的新增用户,在经过一段时间后,仍然使用app的用户。
  43. 13.用户新鲜度
  44. 每天启动app的新老用户比例
  45. 14.单次使用时长
  46. 每次启动使用的时间长度。
  47. 15.日使用时长
  48. 每天的使用累加值。
  49. 16.启动次数计算标准
  50. 两次之间<30s,算作一次启动.
  51. 三、日志组成
  52. --------------------------------------------------
  53. 1.启动日志
  54. 2.页面访问日志
  55. 3.事件日志
  56. 4.用户使用日志
  57. 5.错误日志
  58. 四、开始项目 -- 初始化web日志收集程序
  59. ----------------------------------------------------
  60. 1.创建新项目UmengProject
  61. 2.创建公共模块app-analyze-common,存放用于跨模块间访问的类。添加maven依赖
  62. a.创建日志类AppLogEntity
  1. package com.test.app.common;
  2. /**
  3. * AppLog实体类
  4. * 内部含有各种日志时间的集合。
  5. */
  6. public class AppLogEntity {
  7. private String appId; //应用唯一标识
  8. private String tenantId; //租户唯一标识,企业用户
  9. private String deviceId; //设备唯一标识
  10. private String appVersion; //版本
  11. private String appChannel; //渠道,安装时就在清单中制定了,appStore等。
  12. private String appPlatform; //平台
  13. private String osType; //操作系统
  14. private String deviceStyle; //机型
  15. private AppStartupLog[] appStartupLogs; //启动相关信息的数组
  16. private AppPageLog[] appPageLogs; //页面跳转相关信息的数组
  17. private AppEventLog[] appEventLogs; //事件相关信息的数组
  18. private AppUsageLog[] appUsageLogs; //app使用情况相关信息的数组
  19. private AppErrorLog[] appErrorLogs; //错误相关信息的数组
  20. /** get / set **/
  21. }
  1. b.抽取共性,创建日志基本父类AppBaseLog
  1. package com.test.app.common;
  2. import java.io.Serializable;
  3. /**
  4. * AppBaseLog
  5. */
  6. public class AppBaseLog implements Serializable {
  7. private Long createdAtMs; //日志创建时间
  8. private String appId; //应用唯一标识
  9. private String tenantId; //租户唯一标识,企业用户
  10. private String deviceId; //设备唯一标识
  11. private String appVersion; //版本
  12. private String appChannel; //渠道,安装时就在清单中制定了,appStore等。
  13. private String appPlatform; //平台
  14. private String osType; //操作系统
  15. private String deviceStyle; //机型
  16. /*省略get set*/
  17. }
  1. c.创建日志具体分类的相关类AppStartupLog等
  2. ===================================================
  1. package com.test.app.common;
  2. /**
  3. * 启动日志
  4. */
  5. public class AppStartupLog extends AppBaseLog {
  6. private String country; //国家,终端不用上报,服务器自动填充该属性
  7. private String province; //省份,终端不用上报,服务器自动填充该属性
  8. private String ipAddress; //ip地址
  9. private String network; //网络
  10. private String carrier; //运营商
  11. private String brand; //品牌
  12. private String deviceStyle; //机型
  13. private String screenSize; //分辨率
  14. private String osType; //操作系统
  15. //省略getset
  16. }
  1. ====================================================================
  1. package com.test.app.common;
  2. /**
  3. * 应用上报的app错误日志相关信息
  4. */
  5. public class AppErrorLog extends AppBaseLog {
  6. private static final long serialVersionUID = 1L;
  7. private String errorBrief; //错误摘要
  8. private String errorDetail; //错误详情
  9. }
  1. =======================================================================
  1. package com.test.app.common;
  2. import java.util.Map;
  3. /**
  4. * 应用上报的事件相关信息
  5. *
  6. */
  7. public class AppEventLog extends AppBaseLog {
  8. private static final long serialVersionUID = 1L;
  9. private String eventId; //事件唯一标识
  10. private Long eventDurationSecs; //事件持续时长
  11. private Map<String,String> paramKeyValueMap; //参数名/值对
  12. }
  1. =========================================================================
  1. package com.test.app.common;
  2. /**
  3. * 应用上报的页面相关信息
  4. *
  5. */
  6. public class AppPageLog extends AppBaseLog {
  7. private static final long serialVersionUID = 1L;
  8. /*
  9. * 一次启动中的页面访问次数(应保证每次启动的所有页面日志在一次上报中,即最后一条上报的页面记录的nextPage为空)
  10. */
  11. private int pageViewCntInSession = 0;
  12. private String pageId; //页面id
  13. private int visitIndex = 0; //访问顺序号,0为第一个页面
  14. private String nextPage; //下一个访问页面,如为空则表示为退出应用的页面
  15. private Long stayDurationSecs = (long) 0; //当前页面停留时长
  16. }
  1. =============================================================================
  1. package com.test.app.common;
  2. /**
  3. * 应用上报的使用时长相关信息
  4. */
  5. public class AppUsageLog extends AppBaseLog {
  6. private static final long serialVersionUID = 1L;
  7. private Long singleUseDurationSecs; //单次使用时长(秒数),指一次启动内应用在前台的持续时长
  8. private Long singleUploadTraffic; //单次使用过程中的上传流量
  9. private Long singleDownloadTraffic; //单次使用过程中的下载流量
  10. }
  1. d.创建util工具包com.test.app.util和属性拷贝工具类PropertiesUtil
  1. package com.test.app.util;
  2. import java.beans.BeanInfo;
  3. import java.beans.IntrospectionException;
  4. import java.beans.Introspector;
  5. import java.beans.PropertyDescriptor;
  6. import java.lang.reflect.Method;
  7. /**
  8. * 通过内省实现属性复制
  9. */
  10. public class PropertiesUtil {
  11. //复制属性
  12. //要将AppLogEntity中的所有相关属性的值赋值给对用的具体log的属性值[因为具体log的属性值是空的]
  13. public static void copyProperties(Object src, Object des)
  14. {
  15. try {
  16. BeanInfo srcInfo = Introspector.getBeanInfo(src.getClass());
  17. //属性描述符
  18. PropertyDescriptor[] sarr = srcInfo.getPropertyDescriptors();
  19. for(PropertyDescriptor p : sarr)
  20. {
  21. Method getter = p.getReadMethod();
  22. Method setter = p.getWriteMethod();
  23. //获取set方法描述符的name
  24. String setName = setter.getName();
  25. //获取set方法的参数类型
  26. Class [] param = setter.getParameterTypes();
  27. try {
  28. //通过get方法描述符,获取src的属性值
  29. Object value = getter.invoke(src);
  30. //通过src set方法描述符找到des的set方法,给des的属性赋值
  31. Method desSettrer = des.getClass().getMethod(setName, param);
  32. desSettrer.invoke(des, value);
  33. } catch (Exception e) {
  34. //出现异常说明des中没有src的属性
  35. continue;
  36. }
  37. }
  38. } catch (Exception e) {
  39. e.printStackTrace();
  40. }
  41. }
  42. }
  1. 3.创建app日志收集web模块app-log-collect-web
  2. a.添加maven依赖
  3. <?xml version="1.0" encoding="UTF-8"?>
  4. <project xmlns="http://maven.apache.org/POM/4.0.0"
  5. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  6. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  7. <modelVersion>4.0.0</modelVersion>
  8. <groupId>com.test</groupId>
  9. <artifactId>app-logs-collect-web</artifactId>
  10. <version>1.0-SNAPSHOT</version>
  11. <dependencies>
  12. <dependency>
  13. <groupId>junit</groupId>
  14. <artifactId>junit</artifactId>
  15. <version>4.11</version>
  16. </dependency>
  17. <dependency>
  18. <groupId>com.fasterxml.jackson.core</groupId>
  19. <artifactId>jackson-core</artifactId>
  20. <version>2.8.8</version>
  21. </dependency>
  22. <dependency>
  23. <groupId>com.fasterxml.jackson.core</groupId>
  24. <artifactId>jackson-databind</artifactId>
  25. <version>2.8.3</version>
  26. </dependency>
  27. <dependency>
  28. <groupId>com.maxmind.db</groupId>
  29. <artifactId>maxmind-db</artifactId>
  30. <version>1.0.0</version>
  31. </dependency>
  32. <dependency>
  33. <groupId>org.springframework</groupId>
  34. <artifactId>spring-webmvc</artifactId>
  35. <version>4.3.5.RELEASE</version>
  36. </dependency>
  37. <dependency>
  38. <groupId>javax.servlet</groupId>
  39. <artifactId>servlet-api</artifactId>
  40. <version>2.5</version>
  41. </dependency>
  42. <dependency>
  43. <groupId>com.test</groupId>
  44. <artifactId>app-analyze-common</artifactId>
  45. <version>1.0-SNAPSHOT</version>
  46. </dependency>
  47. <dependency>
  48. <groupId>com.alibaba</groupId>
  49. <artifactId>fastjson</artifactId>
  50. <version>1.2.24</version>
  51. </dependency>
  52. </dependencies>
  53. </project>
  54. b.添加app-analyze-common模块依赖,共享模块资源
  55. Project-Structure --> dependencies --> 3.Module De...
  56. 别忘记打钩,不然引用不了
  57. c.创建java包
  58. com.test.applogs.collect.web.controller
  59. d.编写WEB-INF/web.xml
  60. <?xml version="1.0" encoding="UTF-8"?>
  61. <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  62. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  63. xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
  64. version="3.1">
  65. <servlet>
  66. <servlet-name>controller</servlet-name>
  67. <servlet-class>org.springframework.web.servlet.DispatcherServlet
  68. </servlet-class>
  69. </servlet>
  70. <servlet-mapping>
  71. <servlet-name>controller</servlet-name>
  72. <url-pattern>/</url-pattern>
  73. </servlet-mapping>
  74. </web-app>
  75. e.创建新文件WEB-INF/controller-servlet.xml
  76. <?xml version="1.0" encoding="UTF-8"?>
  77. <beans xmlns="http://www.springframework.org/schema/beans"
  78. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  79. xmlns:mvc="http://www.springframework.org/schema/mvc"
  80. xmlns:context="http://www.springframework.org/schema/context"
  81. xsi:schemaLocation="http://www.springframework.org/schema/beans
  82. http://www.springframework.org/schema/beans/spring-beans.xsd
  83. http://www.springframework.org/schema/mvc
  84. http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
  85. http://www.springframework.org/schema/context
  86. http://www.springframework.org/schema/context/spring-context-4.3.xsd">
  87. <!-- 配置扫描路径 -->
  88. <context:component-scan
  89. base-package="com.test.applogs.collect.web.controller"/>
  90. <!-- 使用注解驱动 -->
  91. <mvc:annotation-driven/>
  92. <!-- 内部资源视图解析器 -->
  93. <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  94. <property name="prefix" value="/views"/>
  95. <property name="suffix" value=".jsp"/>
  96. </bean>
  97. <!-- 此处乃进行json数据传输的关键,当配置 -->
  98. <bean id="jsonMapping" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
  99. <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
  100. <property name="messageConverters">
  101. <list>
  102. <ref bean="jsonMapping"/>
  103. </list>
  104. </property>
  105. </bean>
  106. </beans>
  107. f.创建日志收集控制器
  1. package com.test.applogs.collect.web.controller;
  2. import com.alibaba.fastjson.JSONObject;
  3. import com.test.app.util.PropertiesUtil;
  4. import com.test.app.common.*;
  5. import com.test.app.common.AppLogEntity;
  6. import com.test.app.common.AppStartupLog;
  7. import org.springframework.stereotype.Controller;
  8. import org.springframework.web.bind.annotation.RequestBody;
  9. import org.springframework.web.bind.annotation.RequestMapping;
  10. import org.springframework.web.bind.annotation.RequestMethod;
  11. import org.springframework.web.bind.annotation.ResponseBody;
  12. import javax.servlet.http.HttpServletRequest;
  13. /**
  14. */
  15. @Controller()
  16. @RequestMapping("/coll")
  17. public class CollectLogController {
  18. /**
  19. * 启动日志收集
  20. */
  21. @RequestMapping(value = "/index", method = RequestMethod.POST)
  22. @ResponseBody
  23. public AppLogEntity collect(@RequestBody AppLogEntity e, HttpServletRequest req) {
  24. System.out.println("=============================");
  25. //server时间
  26. long myTime = System.currentTimeMillis() ;
  27. //客户端时间
  28. long clientTime = Long.parseLong(req.getHeader("clientTime"));
  29. //时间校对
  30. long diff = myTime - clientTime ;
  31. //对e进行处理,将具体日志分类的属性值填充完毕
  32. processLogs(e);
  33. //修正日志时间
  34. verifyTime(e,diff);
  35. String json = JSONObject.toJSONString(e);
  36. System.out.println(json);
  37. return e;
  38. }
  39. /**
  40. * 校对各个具体日志的创建时间(使用服务器时间差diff)
  41. */
  42. private void verifyTime(AppLogEntity e, long diff)
  43. {
  44. //启动修正
  45. //startuplog
  46. for(AppBaseLog log : e.getAppStartupLogs()){
  47. log.setCreatedAtMs(log.getCreatedAtMs() + diff );
  48. }
  49. for(AppBaseLog log : e.getAppUsageLogs()){
  50. log.setCreatedAtMs(log.getCreatedAtMs() + diff );
  51. }
  52. for(AppBaseLog log : e.getAppPageLogs()){
  53. log.setCreatedAtMs(log.getCreatedAtMs() + diff );
  54. }
  55. for(AppBaseLog log : e.getAppEventLogs()){
  56. log.setCreatedAtMs(log.getCreatedAtMs() + diff );
  57. }
  58. for(AppBaseLog log : e.getAppErrorLogs()){
  59. log.setCreatedAtMs(log.getCreatedAtMs() + diff );
  60. }
  61. }
  62. /**
  63. * 将Log的属性分类复制到各个具体的log中
  64. */
  65. private void processLogs(AppLogEntity e){
  66. for(AppStartupLog log : e.getAppStartupLogs()){
  67. PropertiesUtil.copyProperties(e,log);
  68. }
  69. for(AppErrorLog log : e.getAppErrorLogs()){
  70. PropertiesUtil.copyProperties(e,log);
  71. }
  72. for(AppEventLog log : e.getAppEventLogs()){
  73. PropertiesUtil.copyProperties(e,log);
  74. }
  75. for(AppPageLog log : e.getAppPageLogs()){
  76. PropertiesUtil.copyProperties(e,log);
  77. }
  78. for(AppUsageLog log : e.getAppUsageLogs()){
  79. PropertiesUtil.copyProperties(e,log);
  80. }
  81. }
  82. }
  1. g.创建tomcat-server启动程序
  2. Run --> Edit Configurations --> + --> tomcat server --> ...
  3. Project Structure --> Artifacts --> Add All Maven Jars --> ...
  4. [注意!]Project Structure --> Artifacts --> Add Common模块到out class --> 不然依赖的其他模块是加载不到的,同时添加maven依赖的支持
  5. 4.创建app-logs-phone模块,用于模拟手机生成日志
  6. a.添加maven依赖[可以通过maven的手段,达到访问其他模块的内容,比如common模块]
  7. <?xml version="1.0" encoding="UTF-8"?>
  8. <project xmlns="http://maven.apache.org/POM/4.0.0"
  9. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  10. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  11. <modelVersion>4.0.0</modelVersion>
  12. <groupId>com.test</groupId>
  13. <artifactId>app-logs-phone</artifactId>
  14. <version>1.0-SNAPSHOT</version>
  15. <dependencies>
  16. <dependency>
  17. <groupId>com.alibaba</groupId>
  18. <artifactId>fastjson</artifactId>
  19. <version>1.2.24</version>
  20. </dependency>
  21. <dependency>
  22. <groupId>com.test</groupId>
  23. <artifactId>app-analyze-common</artifactId>
  24. <version>1.0-SNAPSHOT</version>
  25. </dependency>
  26. </dependencies>
  27. </project>
  28. b.创建海量日志生成模拟程序
  1. package com.test.app.client;
  2. import com.alibaba.fastjson.JSONObject;
  3. import com.test.app.common.*;
  4. //import com.test.app.util.PropertiesUtil;
  5. import java.io.File;
  6. import java.io.FileWriter;
  7. import java.io.InputStream;
  8. import java.net.HttpURLConnection;
  9. import java.net.URL;
  10. import java.util.HashMap;
  11. import java.util.Map;
  12. import java.util.Random;
  13. /**
  14. * 数据生成程序
  15. */
  16. public class TestGenData {
  17. /**
  18. *
  19. */
  20. private static String url = "http://localhost:8080/coll/index";
  21. private static Random random = new Random();
  22. private static String appId = "sdk34734";
  23. private static String[] tenantIds = {"cake"};
  24. private static String[] deviceIds = initDeviceId();
  25. private static String[] appVersions = {"3.2.1", "3.2.2"};
  26. private static String[] appChannels = {"youmeng1", "youmeng2"};
  27. private static String[] appPlatforms = {"android", "ios"};
  28. private static Long[] createdAtMsS = initCreatedAtMs();
  29. //国家,终端不用上报,服务器自动填充该属性
  30. private static String[] countrys = {"America", "china"};
  31. //省份,终端不用上报,服务器自动填充该属性
  32. private static String[] provinces = {"Washington", "jiangxi", "beijing"};
  33. //网络
  34. private static String[] networks = {"WiFi", "CellNetwork"};
  35. //运营商
  36. private static String[] carriers = {"中国移动", "中国电信", "EE"};
  37. //机型
  38. private static String[] deviceStyles = {"iPhone 6", "iPhone 6 Plus", "红米手机1s"};
  39. //分辨率
  40. private static String[] screenSizes = {"1136*640", "960*640", "480*320"};
  41. //操作系统
  42. private static String[] osTypes = {"8.3", "7.1.1"};
  43. //品牌
  44. private static String[] brands = {"三星", "华为", "Apple", "魅族", "小米", "锤子"};
  45. //事件唯一标识
  46. private static String[] eventIds = {"popMenu", "autoImport", "BookStore"};
  47. //事件持续时长
  48. private static Long[] eventDurationSecsS = {new Long(25), new Long(67), new Long(45)};
  49. static Map<String, String> map1 = new HashMap<String, String>() {
  50. {
  51. put("testparam1key", "testparam1value");
  52. put("testparam2key", "testparam2value");
  53. }
  54. };
  55. static Map<String, String> map2 = new HashMap<String, String>() {
  56. {
  57. put("testparam3key", "testparam3value");
  58. put("testparam4key", "testparam4value");
  59. }
  60. };
  61. private static Map[] paramKeyValueMapsS = {map1, map2};
  62. //单次使用时长(秒数),指一次启动内应用在前台的持续时长
  63. private static Long[] singleUseDurationSecsS = initSingleUseDurationSecs();
  64. private static String[] errorBriefs = {"at cn.lift.dfdf.web.AbstractBaseController.validInbound(AbstractBaseController.java:72)", "at cn.lift.appIn.control.CommandUtil.getInfo(CommandUtil.java:67)"}; //错误摘要
  65. private static 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"}; //错误详情
  66. //页面id
  67. private static String[] pageIds = {"list.html", "main.html", "test.html"};
  68. //访问顺序号,0为第一个页面
  69. private static int[] visitIndexs = {0, 1, 2, 3, 4};
  70. //下一个访问页面,如为空则表示为退出应用的页面
  71. private static String[] nextPages = {"list.html", "main.html", "test.html", null};
  72. //当前页面停留时长
  73. private static Long[] stayDurationSecsS = {new Long(45), new Long(2), new Long(78)};
  74. //启动相关信息的数组
  75. private static AppStartupLog[] appStartupLogs = initAppStartupLogs();
  76. //页面跳转相关信息的数组
  77. private static AppPageLog[] appPageLogs = initAppPageLogs();
  78. //事件相关信息的数组
  79. private static AppEventLog[] appEventLogs = initAppEventLogs();
  80. //app使用情况相关信息的数组
  81. private static AppUsageLog[] appUsageLogs = initAppUsageLogs();
  82. //错误相关信息的数组
  83. private static AppErrorLog[] appErrorLogs = initAppErrorLogs();
  84. private static String[] initDeviceId() {
  85. String base = "device22";
  86. String[] result = new String[100];
  87. for (int i = 0; i < 100; i++) {
  88. result[i] = base + i + "";
  89. }
  90. return result;
  91. }
  92. private static Long[] initCreatedAtMs() {
  93. Long createdAtMs = System.currentTimeMillis();
  94. Long[] result = new Long[11];
  95. for (int i = 0; i < 10; i++) {
  96. result[i] = createdAtMs - (long) (i * 24 * 3600 * 1000);
  97. }
  98. result[10] = createdAtMs;
  99. return result;
  100. }
  101. private static Long[] initSingleUseDurationSecs() {
  102. Random random = new Random();
  103. Long[] result = new Long[200];
  104. for (int i = 1; i < 200; i++) {
  105. result[i] = (long) random.nextInt(200);
  106. }
  107. return result;
  108. }
  109. //启动相关信息的数组
  110. private static AppStartupLog[] initAppStartupLogs() {
  111. AppStartupLog[] result = new AppStartupLog[10];
  112. for (int i = 0; i < 10; i++) {
  113. AppStartupLog appStartupLog = new AppStartupLog();
  114. appStartupLog.setCountry(countrys[random.nextInt(countrys.length)]);
  115. appStartupLog.setProvince(provinces[random.nextInt(provinces.length)]);
  116. appStartupLog.setNetwork(networks[random.nextInt(networks.length)]);
  117. appStartupLog.setCarrier(carriers[random.nextInt(carriers.length)]);
  118. appStartupLog.setDeviceStyle(deviceStyles[random.nextInt(deviceStyles.length)]);
  119. appStartupLog.setScreenSize(screenSizes[random.nextInt(screenSizes.length)]);
  120. appStartupLog.setOsType(osTypes[random.nextInt(osTypes.length)]);
  121. appStartupLog.setBrand(brands[random.nextInt(brands.length)]);
  122. appStartupLog.setCreatedAtMs(createdAtMsS[random.nextInt(createdAtMsS.length)]);
  123. result[i] = appStartupLog;
  124. }
  125. return result;
  126. }
  127. //页面跳转相关信息的数组
  128. private static AppPageLog[] initAppPageLogs() {
  129. AppPageLog[] result = new AppPageLog[10];
  130. for (int i = 0; i < 10; i++) {
  131. AppPageLog appPageLog = new AppPageLog();
  132. String pageId = pageIds[random.nextInt(pageIds.length)];
  133. int visitIndex = visitIndexs[random.nextInt(visitIndexs.length)];
  134. String nextPage = nextPages[random.nextInt(nextPages.length)];
  135. while (pageId.equals(nextPage)) {
  136. nextPage = nextPages[random.nextInt(nextPages.length)];
  137. }
  138. Long stayDurationSecs = stayDurationSecsS[random.nextInt(stayDurationSecsS.length)];
  139. appPageLog.setPageId(pageId);
  140. appPageLog.setStayDurationSecs(stayDurationSecs);
  141. appPageLog.setVisitIndex(visitIndex);
  142. appPageLog.setNextPage(nextPage);
  143. appPageLog.setCreatedAtMs(createdAtMsS[random.nextInt(createdAtMsS.length)]);
  144. result[i] = appPageLog;
  145. }
  146. return result;
  147. }
  148. ;
  149. //事件相关信息的数组
  150. private static AppEventLog[] initAppEventLogs() {
  151. AppEventLog[] result = new AppEventLog[10];
  152. for (int i = 0; i < 10; i++) {
  153. AppEventLog appEventLog = new AppEventLog();
  154. appEventLog.setEventId(eventIds[random.nextInt(eventIds.length)]);
  155. appEventLog.setParamKeyValueMap(paramKeyValueMapsS[random.nextInt(paramKeyValueMapsS.length)]);
  156. appEventLog.setEventDurationSecs(eventDurationSecsS[random.nextInt(eventDurationSecsS.length)]);
  157. appEventLog.setCreatedAtMs(createdAtMsS[random.nextInt(createdAtMsS.length)]);
  158. result[i] = appEventLog;
  159. }
  160. return result;
  161. }
  162. ;
  163. //app使用情况相关信息的数组
  164. private static AppUsageLog[] initAppUsageLogs() {
  165. AppUsageLog[] result = new AppUsageLog[10];
  166. for (int i = 0; i < 10; i++) {
  167. AppUsageLog appUsageLog = new AppUsageLog();
  168. appUsageLog.setSingleUseDurationSecs(singleUseDurationSecsS[random.nextInt(singleUseDurationSecsS.length)]);
  169. appUsageLog.setCreatedAtMs(createdAtMsS[random.nextInt(createdAtMsS.length)]);
  170. result[i] = appUsageLog;
  171. }
  172. return result;
  173. }
  174. ;
  175. //错误相关信息的数组
  176. private static AppErrorLog[] initAppErrorLogs() {
  177. AppErrorLog[] result = new AppErrorLog[10];
  178. for (int i = 0; i < 10; i++) {
  179. AppErrorLog appErrorLog = new AppErrorLog();
  180. appErrorLog.setErrorBrief(errorBriefs[random.nextInt(errorBriefs.length)]);
  181. appErrorLog.setErrorDetail(errorDetails[random.nextInt(errorDetails.length)]);
  182. appErrorLog.setCreatedAtMs(createdAtMsS[random.nextInt(createdAtMsS.length)]);
  183. appErrorLog.setOsType(osTypes[random.nextInt(osTypes.length)]);
  184. appErrorLog.setDeviceStyle(deviceStyles[random.nextInt(deviceStyles.length)]);
  185. result[i] = appErrorLog;
  186. }
  187. return result;
  188. }
  189. private static void httpPost(String urlString, String params) {
  190. URL url;
  191. try {
  192. url = new URL(urlString);
  193. HttpURLConnection conn = (HttpURLConnection) url.openConnection();
  194. conn.setRequestMethod("POST");
  195. conn.setDoOutput(true);
  196. conn.setDoInput(true);
  197. conn.setUseCaches(false);
  198. conn.setInstanceFollowRedirects(true);
  199. conn.setRequestProperty("User-Agent",
  200. "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0");
  201. conn.setRequestProperty("Content-Type", "application/json");
  202. conn.setConnectTimeout(1000 * 5);
  203. conn.connect();
  204. conn.getOutputStream().write(params.getBytes("utf8"));
  205. conn.getOutputStream().flush();
  206. conn.getOutputStream().close();
  207. byte[] buffer = new byte[1024];
  208. StringBuffer sb = new StringBuffer();
  209. InputStream in = conn.getInputStream();
  210. int httpCode = conn.getResponseCode();
  211. System.out.println(in.available());
  212. while (in.read(buffer, 0, 1024) != -1) {
  213. sb.append(new String(buffer));
  214. }
  215. System.out.println("sb:" + sb.toString());
  216. in.close();
  217. System.out.println(httpCode);
  218. } catch (Exception e) {
  219. e.printStackTrace();
  220. }
  221. }
  222. public static void main(String[] args) {
  223. Test1();
  224. }
  225. private static void Test1() {
  226. Random random = new Random();
  227. try {
  228. //发送数据
  229. for (int i = 1; i <= 2000; i++) {
  230. AppLogEntity logEntity = new AppLogEntity();
  231. //渠道
  232. logEntity.setAppChannel(appChannels[random.nextInt(appChannels.length)]);
  233. //appid
  234. logEntity.setAppId(appId);
  235. //platform
  236. logEntity.setAppPlatform(appPlatforms[random.nextInt(appPlatforms.length)]);
  237. logEntity.setAppVersion(appVersions[random.nextInt(appVersions.length)]);
  238. String tenantId = tenantIds[random.nextInt(tenantIds.length)];
  239. if (tenantId != null) {
  240. logEntity.setTenantId(tenantId);
  241. }
  242. logEntity.setTenantId(tenantIds[random.nextInt(tenantIds.length)]);
  243. logEntity.setDeviceId(deviceIds[random.nextInt(deviceIds.length)]);
  244. //模拟startup log集合
  245. logEntity.setAppStartupLogs(new AppStartupLog[]{appStartupLogs[random.nextInt(appStartupLogs.length)]});
  246. logEntity.setAppEventLogs(new AppEventLog[]{appEventLogs[random.nextInt(appEventLogs.length)]});
  247. logEntity.setAppErrorLogs(new AppErrorLog[]{appErrorLogs[random.nextInt(appErrorLogs.length)]});
  248. logEntity.setAppPageLogs(new AppPageLog[]{appPageLogs[random.nextInt(appPageLogs.length)]});
  249. logEntity.setAppUsageLogs(new AppUsageLog[]{appUsageLogs[random.nextInt(appUsageLogs.length)]});
  250. try {
  251. //将对象转换成json string
  252. String json = JSONObject.toJSONString(logEntity);
  253. UploadUtil.upload(json);
  254. Thread.sleep(2000);
  255. } catch (Exception ex) {
  256. System.out.println(ex);
  257. }
  258. }
  259. } catch (Exception ex) {
  260. ex.printStackTrace();
  261. }
  262. }
  263. private static void Test2() {
  264. boolean result = map1.isEmpty();
  265. System.out.println(result);
  266. }
  267. }
  1. c.创建UploadUtil类,模拟日志上传到web
  1. package com.test.app.client;
  2. import java.io.InputStream;
  3. import java.io.OutputStream;
  4. import java.net.HttpURLConnection;
  5. import java.net.URL;
  6. /**
  7. * 模拟手机上报日志程序
  8. */
  9. public class UploadUtil {
  10. /**
  11. * 上传日志
  12. */
  13. public static void upload(String json) throws Exception {
  14. try{
  15. //输入流
  16. InputStream in = ClassLoader.getSystemResourceAsStream("log.json");
  17. URL url = new URL("http://localhost:8080/coll/index");
  18. HttpURLConnection conn = (HttpURLConnection) url.openConnection();
  19. //设置请求方式为post
  20. conn.setRequestMethod("POST");
  21. //时间头用来供server进行时钟校对的
  22. conn.setRequestProperty("clientTime",System.currentTimeMillis() + "");
  23. //允许上传数据
  24. conn.setDoOutput(true);
  25. //设置请求的头信息,设置内容类型
  26. conn.setRequestProperty("Content-Type", "application/json");
  27. //输出流
  28. OutputStream out = conn.getOutputStream();
  29. out.write(json.getBytes());
  30. out.flush();
  31. out.close();
  32. in.close();
  33. int code = conn.getResponseCode();
  34. System.out.println(code);
  35. }
  36. catch (Exception e){
  37. e.printStackTrace();
  38. }
  39. }
  40. }
  1. d.生产环境下特别注意时钟问题
  2. 手机客户端的时间可能不准,所以不能按照客户端提供的时间来算
  3. 所以。服务器端收集文件之后要进行时间校对
  4. 1)client
  5. 发送数据同时,写入clientTime头。
  6. conn.setRequestProperty("clientTime",System.currentTimeMillis() + "");
  7. 2)web server
  8. //server时间
  9. long myTime = System.currentTimeMillis() ;
  10. //客户端时间
  11. long clientTime = Long.parseLong(req.getHeader("clientTime"));
  12. //时间校对
  13. long diff = myTime - clientTime ;
  14. 3)完成Log实体中公共部分属性和Log类中间属性复制。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/300999
推荐阅读
相关标签
  

闽ICP备14008679号