├── README.md ├── img ├── jiagoutu.png ├── login.png ├── qingxiafter.png ├── qingxibefore.png └── result.png ├── web_analytics ├── .classpath ├── .project ├── .settings │ ├── .jsdtscope │ ├── org.eclipse.core.resources.prefs │ ├── org.eclipse.jdt.core.prefs │ ├── org.eclipse.m2e.core.prefs │ ├── org.eclipse.wst.common.component │ ├── org.eclipse.wst.common.project.facet.core.xml │ ├── org.eclipse.wst.jsdt.ui.superType.container │ ├── org.eclipse.wst.jsdt.ui.superType.name │ └── org.eclipse.wst.validation.prefs ├── pom.xml ├── src │ └── main │ │ ├── java │ │ └── com │ │ │ └── moon │ │ │ ├── controller │ │ │ └── AdminAction.java │ │ │ ├── dao │ │ │ ├── AdminDao.java │ │ │ ├── BaseDao.java │ │ │ └── ResultDao.java │ │ │ ├── model │ │ │ ├── Admin.java │ │ │ └── WebLog.java │ │ │ └── util │ │ │ ├── EncodingFilter.java │ │ │ └── GlobalData.java │ │ ├── resources │ │ ├── conf │ │ │ └── struts-admin.xml │ │ ├── log4j.properties │ │ ├── messageResource_zh_CN.properties │ │ └── struts.xml │ │ └── webapp │ │ ├── WEB-INF │ │ └── web.xml │ │ ├── css │ │ ├── bootstrap.min.css │ │ ├── clndr.css │ │ ├── custom.css │ │ ├── font-awesome.css │ │ ├── jqvmap.css │ │ ├── lines.css │ │ ├── style.css │ │ └── style1.css │ │ ├── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.svg │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ ├── fontawesome-webfont.woff2 │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ │ ├── images │ │ ├── Thumbs.db │ │ ├── adm.png │ │ ├── arrow-left.png │ │ ├── arrow-right.png │ │ ├── avtar.png │ │ ├── bg.jpg │ │ ├── bg1.jpg │ │ ├── close.png │ │ ├── cloud.png │ │ ├── key.png │ │ ├── logo.png │ │ └── pass.png │ │ ├── index.jsp │ │ ├── js │ │ ├── Chart.js │ │ ├── bootstrap.min.js │ │ ├── clndr.js │ │ ├── custom.js │ │ ├── d3.v3.js │ │ ├── jquery.min.js │ │ ├── jquery.vmap.js │ │ ├── jquery.vmap.sampledata.js │ │ ├── jquery.vmap.world.js │ │ ├── metisMenu.min.js │ │ ├── moment-2.2.1.js │ │ ├── rickshaw.js │ │ ├── site.js │ │ └── underscore-min.js │ │ ├── login.jsp │ │ └── tablecloth │ │ ├── index.html │ │ └── tablecloth │ │ ├── _notes │ │ └── dwsync.xml │ │ ├── tablecloth.css │ │ ├── tablecloth.js │ │ └── tr_back.gif └── target │ ├── classes │ ├── com │ │ └── moon │ │ │ ├── controller │ │ │ └── AdminAction.class │ │ │ ├── dao │ │ │ ├── AdminDao.class │ │ │ ├── BaseDao.class │ │ │ └── ResultDao.class │ │ │ ├── model │ │ │ ├── Admin.class │ │ │ └── WebLog.class │ │ │ └── util │ │ │ ├── EncodingFilter.class │ │ │ └── GlobalData.class │ ├── conf │ │ └── struts-admin.xml │ ├── log4j.properties │ ├── messageResource_zh_CN.properties │ └── struts.xml │ └── m2e-wtp │ └── web-resources │ └── META-INF │ ├── MANIFEST.MF │ └── maven │ └── om.weblog.zw │ └── web_analytics │ ├── pom.properties │ └── pom.xml └── weblog ├── .classpath ├── .project ├── .settings ├── org.eclipse.core.resources.prefs ├── org.eclipse.jdt.core.prefs └── org.eclipse.m2e.core.prefs ├── cleaned.jar ├── pom.xml ├── src ├── main │ └── java │ │ ├── com │ │ └── weblog │ │ │ ├── mr │ │ │ └── LogCleaner.java │ │ │ ├── parser │ │ │ └── LogParser.java │ │ │ └── shell │ │ │ ├── weblog_common.sh │ │ │ ├── weblog_daily.sh │ │ │ └── weblog_init.sh │ │ └── org │ │ └── apache │ │ └── hadoop │ │ └── fs │ │ └── FileUtil.java └── test │ └── java │ └── com │ └── weblog │ └── AppTest.java └── target ├── classes ├── com │ └── weblog │ │ ├── mr │ │ ├── LogCleaner$MyMapper.class │ │ ├── LogCleaner$MyReducer.class │ │ └── LogCleaner.class │ │ ├── parser │ │ └── LogParser.class │ │ └── shell │ │ ├── weblog_common.sh │ │ ├── weblog_daily.sh │ │ └── weblog_init.sh └── org │ └── apache │ └── hadoop │ └── fs │ ├── FileUtil$CygPathCommand.class │ └── FileUtil.class └── test-classes └── com └── weblog └── AppTest.class /README.md: -------------------------------------------------------------------------------- 1 | # weblog 2 | 基于Hadoop的Web日志分析,包括日志的清洗、日志的统计分析、统计结果的导出、指标数据的Web展示 3 | 4 | ## 主要分析、统计的指标数据 5 | 6 | **浏览量PV**:页面浏览量PV(Page View),是指用户浏览页面的总和,一个独立用户每打开一个页面就被记录一次。网站总流量,可以考核用户对网站的兴趣,就像收视率对电视剧一样。但是对于网站运营者说,更重要的是,每个栏目下的总浏览量。 7 | 8 | **访客数UV**(包括新访客数、新访客比例):访客数(UV)即唯一访客数,一天之内网站的独立访客数(以Cookie为依据),一天内同一访客多次访问网站只计算1 个访客。在统计工具中,我们经常可以看到,独立访客和IP数的数据是不一样的,独立访客都多于IP数。那是因为,同一个IP地址下,可能有很多台电脑一同使用,这种情况,相信都很常见。还有一种情况就是同一台电脑上,用户清空了缓存,使用360等工具,将cookie删除,这样一段时间后,用户再使用该电脑,进入网站,这样访问数UV也被重新加一。对于网站统计来说,关于访客数需要注意的另一个指标就是新访客数,新访客数据可以衡量网站通过推广活动所获得的用户数量。新访客对于总访客数的比值,可以看到网站吸引新鲜血液的能力以及如何保留旧有用户。 9 | 10 | **IP数**:一天之内,访问网站的不同独立IP 个数总和。其中同一IP无论访问了几个页面,独立IP 数均为1。这是我们最熟悉的一个概念,无论同一个IP上有多少电脑,或者其他用户,从某种程度上来说,独立IP的多少,是衡量网站推广活动好坏最直接的数据。 11 | 12 | **跳出率**:只浏览了一个页面便离开了网站的访问次数占总的访问次数的百分比,即只浏览了一个页面的访问次数/全部的访问次数汇总。跳出率是非常重要的访客黏性指标,它显示了访客对网站的兴趣程度:跳出率越低说明流量质量越好,访客对网站的内容越感兴趣,这些访客越可能是网站的有效用户、忠实用户。该指标也可以衡量网络营销的效果,指出有多少访客被网络营销吸引到宣传产品页或网站上之后,又流失掉了。比如,网站在某媒体上打广告推广,分析从这个推广来源进入的访客指标,其跳出率可以反映出选择这个媒体是否合适,广告语的撰写是否优秀,以及网站入口页的设计是否用户体验良好。 13 | 14 | ## 系统架构设计 15 | 16 | 日志是由业务系统产生的,我们可以设置web服务器每天产生一个新的目录,目录下面会产生多个日志文件。设置系统定时器CRON,夜间在0点后,向HDFS导入昨天的日志文件。完成导入后,设置系统定时器,启动MapReduce程序,提取并经过Hive计算统计指标。完成计算后,设置系统定时器,从HDFS导出统计指标数据到MySQL数据库,然后通过web系统将KPI指标直观显示出来,供分析决策使用。 17 | 18 | 架构图: 19 | 20 | ![jiagoutu](img/jiagoutu.png) 21 | 22 | ## 数据库表结构 23 | 24 | Web展示层主要负责的是数据的展现,将最终统计的结果直观的显示出来。其相对简单,主要包括两个模块:用户登录和结果展现。数据库表的设计如下: 25 | 26 | Admin用户登录表: 27 | 28 | |字段名|类型|备注|字段描述| 29 | |----|---|---|---| 30 | |userId|int|主键|用户ID| 31 | |userName|varchar||用户名| 32 | |passWord|varchar||登录密码| 33 | 34 | 35 | 36 | 指标统计结果表: 37 | 38 | |字段名|类型|备注|字段描述| 39 | |----|---|---|---| 40 | |logdate|varchar|主键|日志数据的日期| 41 | |pv|int||统计的PV结果| 42 | |reguser|int||统计的UV结果| 43 | |ip|int||统计的IP结果| 44 | |jumper|int||统计的跳出数结果| 45 | 46 | ## Web日志数据分析流程 47 | 48 | 基于Hadoop的Web系统的实现针对分布式开发坏境搭建、数据的清洗、数据的统计、数据的存储和数据展现具体的开发流程如下: 49 | 50 | (1)分布式集群环境的搭建,模拟hadoop的分布式环境,进行程序的开发,这样我们的程序可以直接部署到真实的物理机器上。 51 | 52 | (2)把日志数据上传到HDFS中进行处理。如果是日志服务器数据较小、压力较小,可以直接使用shell命令把数据上传到HDFS中;如果是日志服务器数据较大、压力较大,使用NFS在另一台服务器上上传数据;如果日志服务器非常多、数据量大,使用flume进行数据处理。 53 | 54 | 日志是在晚上12点左右产生完毕的,假设我们凌晨或者1点去处理昨天的数据。我们需要把日志文件,上传到HDFS里/web_logs目录。使用shell命令把数据从linux磁盘上传到HDFS中,后面清洗的MapReduce程序的数据从HDFS读取。下面是具体的操作: 55 | 在HDFS中创建目录,命令如下:$HADOOP_HOME/bin/hadoop fs –mkdir /web_log。然后写一个shell脚本,叫做upload_to_hdfs.sh,内容大体如下: 56 | 57 | ``` 58 | yesterday=`date --date='1 days ago' +%Y_%m_%d` 59 | ``` 60 | 61 | 获得昨天的时间并对时间进行格式化。 62 | 63 | ``` 64 | hadoop fs -put access_${yesterday}.log /web_log 65 | 66 | ``` 67 | 68 | 把脚本upload_to_hdfs.sh配置到crontab中,执行命令crontab -e, 写法如下: 69 | 70 | ``` 71 | * 1 * * * c 72 | ``` 73 | 74 | 前5列表示是时间,第一列表示分钟,第二列表示小时,第三列表示日,第四列表示月,第五列表示周。我们希望晚上到1点的时候,自动执行upload_to_hdfs.sh脚本。通过这个脚本就可以每天自动将数据上传到HDFS中。上传之后我们就可以对数据进行清洗。 75 | 76 | (3)使用MapReduce对HDFS中的原始数据进行清洗。 77 | 78 | 使用MapReduce对数据进行清洗,把原始数据处理清洗后,放到HDFS的/weblog _cleaned目录下,每天产生一个子目录。将数据清洗项目代码打成jar包,并将其上传至Linux服务器指定目录下,将自动执行清理的MapReduce程序加入脚本中,于每天1点将日志文件上传到HDFS后,执行数据清洗程序对已存入HDFS的日志文件进行过滤,并将过滤后的数据存入weblog_cleaned目录下。 79 | 80 | 清洗之前的数据: 81 | 82 | ![qingxibefore](img/qingxibefore.png) 83 | 84 | 清洗之后的数据: 85 | 86 | ![qingxiafter](img/qingxiafter.png) 87 | 88 | (4)使用Hive对清洗后的数据进行统计分析。 89 | 90 | 数据清洗后的结果,是我们接下来要统计的原始数据,我们使用Hive对清洗后的数据进行分区,建立一个外部分区表。清洗后的数据放在HDFS中,每天产生一个子目录。分区主要是因为每天产生一个文件夹非常方便,使用分区每次只需要指定日期就可以,不用对所有目录进行全表扫描。下面针对不同的指标进行统计,过程主要如下: 91 | 92 | 建立一个外部分区表,脚本如下: 93 | 94 | ``` 95 | CREATE EXTERNAL TABLE weblog(ip string, atime string, url string) PARTITIONED BY (logdate string) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LOCATION '/weblog_cleaned'; 96 | ``` 97 | 98 | 增加分区,脚本如下: 99 | 100 | ``` 101 | ALTER TABLE weblog ADD PARTITION(logdate='${yesterday}') LOCATION '/weblog_cleaned/${yesterday}'; 102 | ``` 103 | 把代码增加到upload_to_hdfs.sh中,内容如下: 104 | 105 | ``` 106 | hive -e "ALTER TABLE weblog ADD PARTITION(logdate='${yesterday}') LOCATION '/weblog _cleaned/${yesterday}';" 107 | ``` 108 | 109 | **统计每日的pv**:意味着统计总共的行数。页面浏览量即为PV(Page View),是指所有用户浏览页面的总和,一个独立用户每打开一个页面就被记录1 次。这里,我们只需要统计日志中的记录个数即可,代码如下: 110 | 111 | ``` 112 | CREATE TABLE weblog_pv_${yesterday} AS SELECT COUNT(1) AS PV FROM weblog WHERE logdate='${yesterday}'; 113 | ``` 114 | **统计每日的注册用户数**:该论坛的用户注册页面为member.php,而当用户点击注册时请求的又是member.php?mod=register的url。因此,这里我们只需要统计出日志中访问的URL是member.php?mod=register的即可,代码如下: 115 | 116 | ``` 117 | CREATE TABLE weblog_reguser_${yesterday} AS SELECT COUNT(1) AS REGUSER FROM weblog WHERE logdate='${yesterday}' AND INSTR(url,'member.php?mod=register')>0; 118 | ``` 119 | 120 | **统计每日的独立ip**:一天之内,访问网站的不同独立 IP 个数加和。其中同一IP无论访问了几个页面,独立IP 数均为1。因此,这里我们只需要统计日志中处理的独立IP数即可,在SQL中我们可以通过DISTINCT关键字,在HQL中也是通过这个关键字,代码如下: 121 | 122 | ``` 123 | CREATE TABLE weblog_ip_${yesterday} AS SELECT COUNT(DISTINCT ip) AS IP FROM weblog WHERE logdate='${yesterday}'; 124 | ``` 125 | **统计每日的跳出用户**:只浏览了一个页面便离开了网站的访问次数,即只浏览了一个页面便不再访问的访问次数。这里,我们可以通过用户的IP进行分组,如果分组后的记录数只有一条,那么即为跳出用户,代码如下: 126 | 127 | ``` 128 | CREATE TABLE weblog_jumper_${yesterday} AS SELECT COUNT(1) AS jumper FROM (SELECT COUNT(ip) AS times FROM weblog WHERE logdate='${yesterday}' GROUP BY ip HAVING times=1) e; 129 | ``` 130 | 把每天统计的数据放入一张表,为了方便通过Sqoop统一导出到MySQL,这里我们借助一张汇总表将刚刚统计到的结果整合起来,通过表连接结合: 131 | 132 | ``` 133 | CREATE TABLE weblog_${yesterday} AS SELECT '${yesterday}', a.pv, b.reguser, c.ip, d.jumper FROM weblog_pv_${yesterday} a JOIN weblog_reguser_${yesterday} b ON 1=1 JOIN weblog_ip_${yesterday} c ON 1=1 JOIN weblog_jumper_${yesterday} d ON 1=1 ; 134 | ``` 135 | 136 | 注意:因为mysql 不允许远程连接,如何让其远程连接: 授权所有权限在目标表上给root用户(任何地方的root),密码是admin。 137 | 138 | ``` 139 | grant all on hive.* to 'root'@'%' identified by 'admin'; 140 | flush privileges; 141 | ``` 142 | (5)使用Sqoop把Hive产生的统计结果导出到mysql中。 143 | 144 | 我们统计完后其结果主要存储在某张Hive表里,为了我们后边Web层的展示,我们需要使用Sqoop工具将Hive里的数据导入到MySQL关系型数据库里。将Hive里的数据导入到mysql里,主要是给应用系统提供数据。下面是导入数据的命令操作: 145 | 146 | ``` 147 | sqoop export --connect jdbc:mysql://hadoop:3306/hmbbs --username root --password admin --table weblog_logs_stat --fields-terminated-by '\001' --export-dir '/hive/weblog_${yesterday}' 148 | ``` 149 | 150 | 将统计后的数据导入mysql中之后,要drop掉 Hive里统计使用的历史表,drop掉以后不用的表,减少存储的压力。 151 | delete hive tables 152 | 153 | ``` 154 | hive -e "drop table weblog_${yesterday};" 155 | 156 | ``` 157 | 158 | (6)使用Struts2框架技术开发Web展示界面。 159 | 160 | 该系统前端主要使用jquery和bootstrap技术,使页面看起来更加美观;后端采用的是Struts2框架结合JDBC技术进行开发。Web系统展示主要包括两个方面:用户登录和统计展示效果如下: 161 | 162 | 登陆界面: 163 | 164 | ![login](img/login.png) 165 | 166 | 167 | 统计结果展示页面: 168 | 169 | ![result](img/result.png) 170 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /img/jiagoutu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/img/jiagoutu.png -------------------------------------------------------------------------------- /img/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/img/login.png -------------------------------------------------------------------------------- /img/qingxiafter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/img/qingxiafter.png -------------------------------------------------------------------------------- /img/qingxibefore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/img/qingxibefore.png -------------------------------------------------------------------------------- /img/result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/img/result.png -------------------------------------------------------------------------------- /web_analytics/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /web_analytics/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | web_analytics 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.wst.jsdt.core.javascriptValidator 10 | 11 | 12 | 13 | 14 | org.eclipse.jdt.core.javabuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.wst.common.project.facet.core.builder 20 | 21 | 22 | 23 | 24 | org.eclipse.m2e.core.maven2Builder 25 | 26 | 27 | 28 | 29 | org.eclipse.wst.validation.validationbuilder 30 | 31 | 32 | 33 | 34 | 35 | org.eclipse.jem.workbench.JavaEMFNature 36 | org.eclipse.wst.common.modulecore.ModuleCoreNature 37 | org.eclipse.jdt.core.javanature 38 | org.eclipse.m2e.core.maven2Nature 39 | org.eclipse.wst.common.project.facet.core.nature 40 | org.eclipse.wst.jsdt.core.jsNature 41 | 42 | 43 | -------------------------------------------------------------------------------- /web_analytics/.settings/.jsdtscope: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /web_analytics/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/main/webapp/login.jsp=UTF-8 3 | encoding/=UTF-8 4 | -------------------------------------------------------------------------------- /web_analytics/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 4 | org.eclipse.jdt.core.compiler.compliance=1.7 5 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 6 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 7 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 8 | org.eclipse.jdt.core.compiler.source=1.7 9 | -------------------------------------------------------------------------------- /web_analytics/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /web_analytics/.settings/org.eclipse.wst.common.component: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /web_analytics/.settings/org.eclipse.wst.common.project.facet.core.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /web_analytics/.settings/org.eclipse.wst.jsdt.ui.superType.container: -------------------------------------------------------------------------------- 1 | org.eclipse.wst.jsdt.launching.baseBrowserLibrary -------------------------------------------------------------------------------- /web_analytics/.settings/org.eclipse.wst.jsdt.ui.superType.name: -------------------------------------------------------------------------------- 1 | Window -------------------------------------------------------------------------------- /web_analytics/.settings/org.eclipse.wst.validation.prefs: -------------------------------------------------------------------------------- 1 | disabled=06target 2 | eclipse.preferences.version=1 3 | -------------------------------------------------------------------------------- /web_analytics/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com 5 | web_analytics 6 | war 7 | 0.0.1-SNAPSHOT 8 | web_analytics Maven Webapp 9 | http://maven.apache.org 10 | 11 | 12 | 13 | 14 | 5.3.1 15 | 16 | 3.2.4 17 | 18 | 1.6.6 19 | 1.2.9 20 | 21 | 22 | 23 | 24 | 25 | 26 | org.springframework 27 | spring-core 28 | ${spring.version} 29 | 30 | 31 | 32 | org.springframework 33 | spring-web 34 | ${spring.version} 35 | 36 | 37 | 38 | org.springframework 39 | spring-oxm 40 | ${spring.version} 41 | 42 | 43 | 44 | org.springframework 45 | spring-tx 46 | ${spring.version} 47 | 48 | 49 | 50 | org.springframework 51 | spring-jdbc 52 | ${spring.version} 53 | 54 | 55 | 56 | org.springframework 57 | spring-webmvc 58 | ${spring.version} 59 | 60 | 61 | 62 | org.springframework 63 | spring-aop 64 | ${spring.version} 65 | 66 | 67 | 68 | org.springframework 69 | spring-context-support 70 | ${spring.version} 71 | 72 | 73 | 74 | org.springframework 75 | spring-aop 76 | ${spring.version} 77 | 78 | 79 | 80 | org.springframework 81 | spring-test 82 | ${spring.version} 83 | 84 | 85 | 86 | 87 | 88 | org.mybatis 89 | mybatis 90 | ${mybatis.version} 91 | 92 | 93 | 94 | org.mybatis 95 | mybatis-spring 96 | 1.2.2 97 | 98 | 99 | 100 | mysql 101 | mysql-connector-java 102 | 8.0.16 103 | 104 | 105 | 106 | junit 107 | junit 108 | 4.13.1 109 | test 110 | 111 | 112 | 113 | com.alibaba 114 | druid 115 | 1.0.2 116 | 117 | 118 | 119 | 120 | org.codehaus.jackson 121 | jackson-mapper-asl 122 | 1.9.13 123 | 124 | 125 | 126 | 127 | 128 | log4j 129 | log4j 130 | ${log4j.version} 131 | 132 | 133 | org.slf4j 134 | slf4j-api 135 | ${slf4j.version} 136 | 137 | 138 | org.slf4j 139 | slf4j-log4j12 140 | ${slf4j.version} 141 | 142 | 143 | 144 | org.apache.struts 145 | struts2-core 146 | 2.3.34 147 | 148 | 149 | jstl 150 | jstl 151 | 1.2 152 | 153 | 154 | javax.servlet 155 | javax.servlet-api 156 | 3.0.1 157 | 158 | 159 | 160 | 161 | 162 | web_analytics 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /web_analytics/src/main/java/com/moon/controller/AdminAction.java: -------------------------------------------------------------------------------- 1 | package com.moon.controller; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | import javax.servlet.http.HttpServletRequest; 6 | import javax.servlet.http.HttpSession; 7 | import org.apache.struts2.ServletActionContext; 8 | import com.moon.dao.AdminDao; 9 | import com.moon.dao.ResultDao; 10 | import com.moon.model.Admin; 11 | import com.moon.model.WebLog; 12 | import com.moon.util.GlobalData; 13 | import com.opensymphony.xwork2.ActionContext; 14 | import com.opensymphony.xwork2.ActionSupport; 15 | import com.opensymphony.xwork2.ModelDriven; 16 | /** 17 | * Created by wei on 2016/5/4 18 | * 用户相关操作 19 | * */ 20 | 21 | public class AdminAction extends ActionSupport implements ModelDriven{ 22 | 23 | Admin admin = new Admin(); 24 | ResultDao result = new ResultDao(); 25 | List list = result.findResult(); 26 | 27 | //登陆功能的实现 28 | public String login() throws Exception { 29 | AdminDao gd = new AdminDao(); 30 | Admin g = gd.login(admin); 31 | 32 | if(null == g){ 33 | return GlobalData.REDO; 34 | } 35 | ActionContext ict = ActionContext.getContext(); 36 | ict.put("result", list); 37 | 38 | 39 | //session 设置 40 | Map session = ActionContext.getContext().getSession(); 41 | session.put(GlobalData.SessionGuesst,admin); 42 | 43 | return "index"; 44 | } 45 | 46 | //管理员登出 47 | 48 | public String logout() throws Exception { 49 | 50 | HttpServletRequest request = ServletActionContext.getRequest(); 51 | HttpSession session = request.getSession(); 52 | session.invalidate(); 53 | return GlobalData.REDO; 54 | } 55 | 56 | 57 | //修改管理员密码 58 | public String update() throws Exception { 59 | AdminDao gd = new AdminDao(); 60 | gd.update(admin); 61 | 62 | return SUCCESS; 63 | } 64 | 65 | public Admin getModel() { 66 | if(this.admin == null){ 67 | this.admin = new Admin(); 68 | } 69 | return this.admin; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /web_analytics/src/main/java/com/moon/dao/AdminDao.java: -------------------------------------------------------------------------------- 1 | package com.moon.dao; 2 | 3 | import java.util.SortedMap; 4 | import javax.servlet.jsp.jstl.sql.Result; 5 | import com.moon.model.Admin; 6 | import com.moon.util.GlobalData; 7 | 8 | /** 9 | * Created by wei on 2016/5/4 10 | * 11 | * */ 12 | public class AdminDao extends BaseDao { 13 | //管理员登陆 14 | public Admin login(Admin admin) { 15 | String sql = "SELECT userId ,userName, passWord FROM admin " + 16 | "WHERE userName=? and passWord=?"; 17 | String args[] = {admin.getUserName(),admin.getPassWord()}; 18 | Result r = query(sql, args); 19 | if(r==null||r.getRowCount()==0){ 20 | return null; 21 | }else{ 22 | SortedMap sm = r.getRows()[0]; 23 | Admin ad = r2o(sm); 24 | return ad; 25 | } 26 | 27 | } 28 | 29 | //管理员密码的修改 30 | public void update(Admin admin) { 31 | String sql =" UPDATE `admin`.`dbo.t_admin` SET `userPw`=?"; 32 | String args[] = {admin.getAgain_pwd()}; 33 | update(sql, args); 34 | } 35 | 36 | 37 | private Admin r2o(SortedMap sm) { 38 | if(sm==null||sm.size()==0){ 39 | return null; 40 | } 41 | 42 | Admin admin = new Admin(); 43 | admin.setUserName(GlobalData.toString(sm, "userName")); 44 | admin.setPassWord(GlobalData.toString(sm, "passWord")); 45 | 46 | return admin ; 47 | 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /web_analytics/src/main/java/com/moon/dao/BaseDao.java: -------------------------------------------------------------------------------- 1 | package com.moon.dao; 2 | 3 | import java.sql.Connection; 4 | import java.sql.DriverManager; 5 | import java.sql.PreparedStatement; 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | import java.sql.Statement; 9 | import java.util.SortedMap; 10 | import javax.servlet.jsp.jstl.sql.Result; 11 | import javax.servlet.jsp.jstl.sql.ResultSupport; 12 | 13 | /** 14 | * Created by wei on 2016/5/4 15 | * 基础DAO 16 | * */ 17 | 18 | public class BaseDao { 19 | //驱动程序的名称和数据库一一对应,强记 20 | private static final String DRIVERNAME = "com.mysql.jdbc.Driver"; 21 | private static String user = "root"; 22 | private static String password = "admin"; 23 | private static String url = "jdbc:mysql://192.168.56.100:3306/weblog"; 24 | 25 | public Connection conn = null; 26 | public Statement stmt = null; 27 | public ResultSet rs = null; 28 | 29 | //安装驱动程序,静态代码块,自动调用一次且仅一次时机,类的任何方法调用 以前 30 | static { 31 | try { 32 | Class.forName(DRIVERNAME); 33 | System.err.println("加载驱动成功"); 34 | } catch (ClassNotFoundException e) { 35 | 36 | System.err.println("加载失败" + e.getMessage()); 37 | } 38 | 39 | } 40 | 41 | public Connection buildConnection() { 42 | Connection connection = null; 43 | try { 44 | connection = DriverManager.getConnection(url, user, password); 45 | } catch (SQLException e) { 46 | 47 | System.out.println("建立连接失败" + e.getMessage()); 48 | } 49 | return connection; 50 | 51 | } 52 | 53 | public int update(String sql) { 54 | int i = -1; 55 | Connection connection = null; 56 | Statement statement = null; 57 | try { 58 | 59 | connection = buildConnection(); 60 | statement = connection.createStatement(); 61 | i = statement.executeUpdate(sql); 62 | } catch (SQLException e) { 63 | System.out.println("执行失败" + e.getMessage()); 64 | System.out.println("执行失败" + sql); 65 | } finally { 66 | try { 67 | connection.close(); 68 | } catch (SQLException e) { 69 | 70 | e.printStackTrace(); 71 | } 72 | } 73 | return i; 74 | } 75 | 76 | /** 77 | * 执行sql语句,实现对数据的增删改,返回影响记录的行数,-1代表执行失败,0代表执行成功,但是未影响数据库;n代表影响数据库的行数 78 | * 79 | * @param sql 80 | * 被执行的一般sql 81 | * @return i 返回影响记录的行数-1,0代表执行成功,但是未影响数据库;n代表影响数据库的行数 82 | * */ 83 | 84 | public int update(String sql, String[] args) { 85 | int i = -1; 86 | Connection connection = null; 87 | PreparedStatement statement = null; 88 | try { 89 | 90 | connection = buildConnection(); 91 | statement = connection.prepareStatement(sql); 92 | // 判断sql语句是否存在占位符 93 | if ((args == null) || (args.length == 0)) { 94 | // do nothing 95 | } else { // 为占位符传参 96 | for (int j = 0; j < args.length; j++) { 97 | // 为占位符传值 98 | // 数组from 0 占位符from 1 99 | statement.setString(j + 1, args[j]); 100 | } 101 | } 102 | i = statement.executeUpdate(); 103 | } catch (SQLException e) { 104 | System.out.println("执行失败" + e.getMessage()); 105 | System.out.println("执行失败" + sql); 106 | } finally { 107 | try { 108 | connection.close(); 109 | } catch (SQLException e) { 110 | // TODO Auto-generated catch block 111 | e.printStackTrace(); 112 | } 113 | } 114 | return i; 115 | } 116 | 117 | /** 118 | * 通用的查询方法,查询结果保存在ResultSet对象中 119 | * 120 | * @param sql 121 | * @param args 122 | * @return Result 123 | * 124 | * */ 125 | public Result query(String sql, String[] args) { 126 | // 定义Result 对象用于封装结果集对象 127 | Result r = null; 128 | Connection connection = null; 129 | PreparedStatement preparedStatement = null; 130 | ResultSet resultSet = null; 131 | 132 | // 建立与数据库的链接 133 | connection = buildConnection(); 134 | // 构建preparestatement 对象,执行带有占位符的sql语句 135 | try { 136 | preparedStatement = connection.prepareStatement(sql); 137 | // 为占位符赋值 138 | if (args == null || args.length == 0) { 139 | 140 | } else { 141 | for (int i = 0; i < args.length; i++) { 142 | preparedStatement.setString(i + 1, args[i]); 143 | } 144 | } 145 | // 执行sql,获得resultset对象 146 | resultSet = preparedStatement.executeQuery(); 147 | // resultset-->result 148 | r = ResultSupport.toResult(resultSet); 149 | 150 | } catch (SQLException e) { 151 | System.out.println("查询失败" + e.getMessage()); 152 | System.out.println("查询失败" + sql); 153 | } finally { 154 | // 回收资源 155 | try { 156 | resultSet.close(); 157 | preparedStatement.close(); 158 | connection.close(); 159 | } catch (SQLException e) { 160 | // TODO Auto-generated catch block 161 | e.printStackTrace(); 162 | } 163 | 164 | } 165 | // 返回执行结果,如果执行失败,返回null 166 | return r; 167 | 168 | } 169 | 170 | // public ResultSet executeQuery(String sql_1) { 171 | // try { 172 | // conn = buildConnection(); 173 | // stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, 174 | // ResultSet.CONCUR_READ_ONLY); 175 | // rs = stmt.executeQuery(sql_1); 176 | // } catch (SQLException ex) { 177 | // System.err.println(ex.getMessage()); 178 | // } 179 | // return rs; 180 | // } 181 | 182 | public int executeUpdate(String sql) { 183 | int result = 0; 184 | try { 185 | conn = buildConnection(); // 调用buildConnection()方法构造Connection对象的一个实例conn 186 | stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, 187 | ResultSet.CONCUR_READ_ONLY); 188 | result = stmt.executeUpdate(sql); // 执行更新操作 189 | } catch (SQLException ex) { 190 | result = 0; 191 | } 192 | return result; 193 | } 194 | 195 | public static void main(String[] args) { 196 | String sql = "SELECT userId ,userName, passWord FROM admin " + 197 | "WHERE userName=? and passWord= ?"; 198 | String ss [] = {"admin","zhangwei"}; 199 | BaseDao db = new BaseDao(); 200 | Result r = db.query(sql, ss); 201 | SortedMap[] sms = r.getRows(); 202 | for(int i=0;i findResult(){ 15 | String sql = "select * from weblog_logs_stat"; 16 | Result rs = super.query(sql, null); 17 | List list = r2o(rs); 18 | 19 | return list; 20 | } 21 | 22 | private List r2o(Result r){ 23 | 24 | if(r==null||r.getRowCount()==0){ 25 | return null; 26 | } 27 | 28 | SortedMap[] sm = r.getRows(); 29 | List list = new ArrayList(); 30 | for(SortedMap sms : sm){ 31 | WebLog log = r2o(sms); 32 | list.add(log); 33 | } 34 | return list; 35 | } 36 | 37 | private WebLog r2o(SortedMap sms){ 38 | WebLog log = new WebLog(); 39 | log.setLogdate(sms.get("logdate").toString()); 40 | log.setIp(new Integer(sms.get("ip").toString())); 41 | log.setPv(new Integer(sms.get("pv").toString())); 42 | log.setReguser(new Integer(sms.get("reguser").toString())); 43 | log.setJumper(new Integer(sms.get("jumper").toString())); 44 | return log; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /web_analytics/src/main/java/com/moon/model/Admin.java: -------------------------------------------------------------------------------- 1 | package com.moon.model; 2 | 3 | public class Admin { 4 | private int userId; 5 | private String userName; 6 | private String passWord; 7 | private String again_pwd; 8 | 9 | public int getUserId() { 10 | return userId; 11 | } 12 | public void setUserId(int userId) { 13 | this.userId = userId; 14 | } 15 | public String getUserName() { 16 | return userName; 17 | } 18 | public void setUserName(String userName) { 19 | this.userName = userName; 20 | } 21 | public String getPassWord() { 22 | return passWord; 23 | } 24 | public void setPassWord(String passWord) { 25 | this.passWord = passWord; 26 | } 27 | public String getAgain_pwd() { 28 | return again_pwd; 29 | } 30 | public void setAgain_pwd(String again_pwd) { 31 | this.again_pwd = again_pwd; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /web_analytics/src/main/java/com/moon/model/WebLog.java: -------------------------------------------------------------------------------- 1 | package com.moon.model; 2 | 3 | public class WebLog { 4 | 5 | private String logdate; 6 | private int pv; 7 | private int reguser; 8 | private int ip; 9 | private int jumper; 10 | 11 | public String getLogdate() { 12 | return logdate; 13 | } 14 | public void setLogdate(String logdate) { 15 | this.logdate = logdate; 16 | } 17 | public int getPv() { 18 | return pv; 19 | } 20 | public void setPv(int pv) { 21 | this.pv = pv; 22 | } 23 | public int getReguser() { 24 | return reguser; 25 | } 26 | public void setReguser(int reguser) { 27 | this.reguser = reguser; 28 | } 29 | public int getIp() { 30 | return ip; 31 | } 32 | public void setIp(int ip) { 33 | this.ip = ip; 34 | } 35 | public int getJumper() { 36 | return jumper; 37 | } 38 | public void setJumper(int jumper) { 39 | this.jumper = jumper; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /web_analytics/src/main/java/com/moon/util/EncodingFilter.java: -------------------------------------------------------------------------------- 1 | package com.moon.util; 2 | 3 | import java.io.IOException; 4 | import javax.servlet.Filter; 5 | import javax.servlet.FilterChain; 6 | import javax.servlet.FilterConfig; 7 | import javax.servlet.ServletException; 8 | import javax.servlet.ServletRequest; 9 | import javax.servlet.ServletResponse; 10 | /** 11 | * Created by wei on 2016/5/4 12 | * 编码过滤器 13 | * */ 14 | public class EncodingFilter implements Filter { 15 | 16 | public void init(FilterConfig filterConfig) throws ServletException { 17 | 18 | } 19 | 20 | public void doFilter(ServletRequest request, ServletResponse response, 21 | FilterChain chain) throws IOException, ServletException { 22 | request.setCharacterEncoding("UTF-8"); 23 | response.setCharacterEncoding("UTF-8"); 24 | chain.doFilter(request, response); 25 | 26 | } 27 | 28 | public void destroy() { 29 | // TODO Auto-generated method stub 30 | 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /web_analytics/src/main/java/com/moon/util/GlobalData.java: -------------------------------------------------------------------------------- 1 | package com.moon.util; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Date; 5 | import java.util.List; 6 | import java.util.SortedMap; 7 | 8 | /** 9 | *Created by wei on 2016/5/4 10 | * 11 | * */ 12 | public class GlobalData { 13 | 14 | public static final String SessionUser="user"; 15 | public static final String LIST = "list"; 16 | public static final String SINGLE = "single"; 17 | public static final String REDO = "redo"; 18 | public static final Object SessionGuesst = "admin"; 19 | 20 | public static int toInt( SortedMap sm, String key ) 21 | { 22 | int i = -1; 23 | if (sm==null || sm.size()==0|| (! sm.containsKey(key))) { 24 | 25 | }else 26 | { 27 | Object o = sm.get(key); 28 | if (o!=null) { 29 | 30 | i = (Integer)o; 31 | } 32 | } 33 | return i; 34 | } 35 | 36 | 37 | 38 | public static Date toDate( SortedMap sm, String key ) 39 | { 40 | Date date = null; 41 | if (sm==null || sm.size()==0|| (! sm.containsKey(key))) { 42 | 43 | }else 44 | { 45 | Object o = sm.get(key); 46 | if (o!=null) { 47 | date = (Date)o; 48 | } 49 | } 50 | return date; 51 | } 52 | 53 | public static long toLong( SortedMap sm, String key ) 54 | { 55 | long l = -1; 56 | if (sm==null || sm.size()==0|| (! sm.containsKey(key))) { 57 | 58 | }else 59 | { 60 | Object o = sm.get(key); 61 | if (o!=null) { 62 | //Cannot cast from Object to int 63 | l = Long.valueOf(0); 64 | } 65 | } 66 | return l; 67 | } 68 | public static String toString( SortedMap sm, String key ) 69 | { 70 | String s = null; 71 | if (sm==null || sm.size()==0|| (! sm.containsKey(key))) { 72 | 73 | }else 74 | { 75 | Object o = sm.get(key); 76 | if (o!=null) { 77 | s = o.toString(); 78 | } 79 | } 80 | return s; 81 | } 82 | 83 | 84 | public static List toList( SortedMap sm, String key ) 85 | { 86 | List s = new ArrayList(); 87 | if (sm==null || sm.size()==0|| (! sm.containsKey(key))) { 88 | 89 | }else 90 | { 91 | String o = (String) sm.get(key); 92 | 93 | if (o!=null) { 94 | 95 | s.add(o); 96 | } 97 | } 98 | return s; 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /web_analytics/src/main/resources/conf/struts-admin.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 10 | 11 | 12 | 13 | index.jsp 14 | login.jsp 15 | change_pwd_success.jsp 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /web_analytics/src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Log4J Settings for log4j 1.2.x (via jakarta-commons-logging) 3 | # 4 | # The five logging levels used by Log are (in order): 5 | # 6 | # 1. DEBUG (the least serious) 7 | # 2. INFO 8 | # 3. WARN 9 | # 4. ERROR 10 | # 5. FATAL (the most serious) 11 | 12 | 13 | # Set root logger level to WARN and append to stdout 14 | log4j.rootLogger=INFO, stdout 15 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 16 | log4j.appender.stdout.Target=System.out 17 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 18 | 19 | # Pattern to output the caller's file name and line number. 20 | log4j.appender.stdout.layout.ConversionPattern=%d %5p (%c:%L) - %m%n 21 | 22 | # Print only messages of level ERROR or above in the package noModule. 23 | log4j.logger.noModule=FATAL 24 | 25 | log4j.logger.com.opensymphony.xwork2=DEBUG 26 | log4j.logger.org.apache.struts2=DEBUG 27 | -------------------------------------------------------------------------------- /web_analytics/src/main/resources/messageResource_zh_CN.properties: -------------------------------------------------------------------------------- 1 | struts.messages.error.content.type.not.allowed=/u4E0A/u4F20/u7C7B/u578B/u9519/u8BEF 2 | struts.messages.error.file.too.large=/u4E0A/u4F20/u6587/u4EF6/u592A/u5927 -------------------------------------------------------------------------------- /web_analytics/src/main/resources/struts.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | /error.jsp 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Struts Blank 5 | 6 | com.moon.util.EncodingFilter 7 | com.moon.util.EncodingFilter 8 | 9 | 10 | com.moon.util.EncodingFilter 11 | /* 12 | 13 | 14 | struts2 15 | org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter 16 | 17 | 18 | 19 | struts2 20 | /* 21 | 22 | 23 | 24 | login.jsp 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/css/clndr.css: -------------------------------------------------------------------------------- 1 | .cal1{ 2 | background: #fff; 3 | margin-bottom: 1em; 4 | min-height: 392px; 5 | } 6 | .noselect { 7 | -webkit-user-select: none; 8 | /* Chrome/Safari */ 9 | -moz-user-select: none; 10 | /* Firefox */ 11 | -ms-user-select: none; 12 | /* IE10+ */ 13 | } 14 | .cal1 .clndr .clndr-controls { 15 | position: relative; 16 | color: #FFF; 17 | font-size: 1em; 18 | font-weight:400; 19 | text-transform: uppercase; 20 | padding:30px 20px; 21 | text-align: center; 22 | background-color:rgb(6, 217, 149); 23 | } 24 | .cal1 .clndr .clndr-controls .month { 25 | text-align:center; 26 | } 27 | .cal1 .clndr .clndr-controls .clndr-control-button .clndr-next-button { 28 | position:absolute; 29 | right:20px; 30 | top:25px; 31 | width:30px; 32 | height:30px; 33 | text-indent: -4000px; 34 | background: url(../images/arrow-right.png) no-repeat 0px; 35 | cursor: pointer; 36 | -webkit-user-select: none; 37 | /* Chrome/Safari */ 38 | -moz-user-select: none; 39 | /* Firefox */ 40 | -ms-user-select: none; 41 | /* IE10+ */ 42 | } 43 | .cal1 .clndr .clndr-controls .clndr-control-button .clndr-next-button.inactive:hover { 44 | cursor: default; 45 | } 46 | .cal1 .clndr .clndr-controls .clndr-control-button .clndr-previous-button { 47 | position:absolute; 48 | left:20px; 49 | top:25px; 50 | width:30px; 51 | height:30px; 52 | text-indent: -4000px; 53 | background: url(../images/arrow-left.png) no-repeat 0px; 54 | cursor: pointer; 55 | -webkit-user-select: none; 56 | /* Chrome/Safari */ 57 | -moz-user-select: none; 58 | /* Firefox */ 59 | -ms-user-select: none; 60 | /* IE10+ */ 61 | } 62 | .cal1 .clndr .clndr-controls .clndr-control-button .clndr-previous-button.inactive:hover { 63 | cursor: default; 64 | } 65 | .cal1 .clndr .clndr-table { 66 | table-layout: fixed; 67 | width:90%; 68 | margin:0 auto; 69 | } 70 | .cal1 .clndr .clndr-table .header-days { 71 | font-size:1em; 72 | font-weight:500; 73 | } 74 | .cal1 .clndr .clndr-table .header-days .header-day { 75 | vertical-align: middle; 76 | text-align: center; 77 | color:rgb(6, 217, 149); 78 | } 79 | .cal1 .clndr .clndr-table tr { 80 | height:45px; 81 | } 82 | .cal1 .clndr .clndr-table tr td { 83 | vertical-align: top; 84 | } 85 | .cal1 .clndr .clndr-table tr .day { 86 | width: 100%; 87 | height: inherit; 88 | color: #A6A6A6; 89 | vertical-align: middle; 90 | cursor: pointer; 91 | -webkit-transition: all 0.3s ease-in-out; 92 | -moz-transition: all 0.3s ease-in-out; 93 | -o-transition: all 0.3s ease-in-out; 94 | transition: all 0.3s ease-in-out; 95 | font-weight: 700; 96 | } 97 | .cal1 .clndr .clndr-table tr .day.today { 98 | background:rgb(6, 217, 149); 99 | color: #FFF; 100 | position:relative; 101 | } 102 | .cal1 .clndr .clndr-table tr .day.today:after { 103 | content: ''; 104 | position: absolute; 105 | left: 14px; 106 | bottom: -6px; 107 | border-left: 6px solid rgba(0, 0, 0, 0); 108 | border-right: 6px solid rgba(0, 0, 0, 0); 109 | border-top: 6px solid rgb(6, 217, 149); 110 | } 111 | .cal1 .clndr .clndr-table tr .day.today:hover { 112 | color: #FFF; 113 | background:rgb(2, 208, 142); 114 | } 115 | .cal1 .clndr .clndr-table tr .day:hover{ 116 | color: #FFF; 117 | background:rgb(2, 199, 135); 118 | } 119 | .cal1 .clndr .clndr-table tr .day.today.event { 120 | background:rgb(6, 217, 149); 121 | color:#FFF; 122 | } 123 | .day.today.event:hover{ 124 | background:#096e9a; 125 | color:#FFF; 126 | } 127 | .cal1 .clndr .clndr-table tr .day .day-contents { 128 | box-sizing: border-box; 129 | font-size:0.8em; 130 | text-align:center; 131 | cursor:pointer; 132 | } 133 | .cal1 .clndr .clndr-table tr .empty, 134 | .cal1 .clndr .clndr-table tr .adjacent-month { 135 | width: 100%; 136 | height: inherit; 137 | color: #989898; 138 | font-weight: 300; 139 | } 140 | @media all and (max-width:1024px){ 141 | .cal1 .clndr .clndr-table tr .day.today:after{ 142 | left:20px; 143 | } 144 | .cal1 .clndr .clndr-controls { 145 | font-size: 0.85em; 146 | padding: 20px 10px; 147 | } 148 | .cal1 .clndr .clndr-controls .clndr-control-button .clndr-previous-button { 149 | left: 10px; 150 | top: 14px; 151 | } 152 | .cal1 .clndr .clndr-controls .clndr-control-button .clndr-next-button { 153 | right: 10px; 154 | top: 14px; 155 | } 156 | .cal1 .clndr .clndr-table .header-days { 157 | font-size: 12px; 158 | } 159 | .cal1 .clndr .clndr-table tr { 160 | height: 35px; 161 | font-size: 12px; 162 | } 163 | .cal1 { 164 | min-height: 280px; 165 | } 166 | } 167 | @media all and (max-width:800px){ 168 | .cal1 .clndr .clndr-table tr .day.today:after{ 169 | left:13px; 170 | } 171 | } 172 | @media all and (max-width:640px){ 173 | .cal1 .clndr .clndr-table tr{ 174 | height:35px; 175 | } 176 | .cal1 .clndr .clndr-table tr .day.today:after{ 177 | left:10px; 178 | } 179 | } 180 | @media all and (max-width:480px){ 181 | .cal1 .clndr .clndr-table tr .day.today:after{ 182 | left:24px; 183 | } 184 | } 185 | @media all and (max-width:320px) { 186 | .cal1 .clndr .clndr-table tr { 187 | height: 35px; 188 | } 189 | .cal1 .clndr .clndr-table tr .day.today:after{ 190 | left:15px; 191 | } 192 | } -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/css/custom.css: -------------------------------------------------------------------------------- 1 | #wrapper { 2 | width: 100%; 3 | } 4 | #page-wrapper { 5 | /*--padding: 0 15px;--*/ 6 | min-height: 568px; 7 | background-color: #fff; 8 | } 9 | 10 | @media(min-width:768px) { 11 | #page-wrapper { 12 | position: inherit; 13 | margin: 0 0 0 250px; 14 | /*--padding: 0 30px;--*/ 15 | border-left: 1px solid #e7e7e7; 16 | } 17 | } 18 | 19 | .navbar-top-links { 20 | margin-right: 0; 21 | } 22 | 23 | .navbar-top-links li { 24 | display: inline-block; 25 | } 26 | 27 | .navbar-top-links li:last-child { 28 | margin-right: 15px; 29 | } 30 | 31 | .navbar-top-links li a { 32 | padding: 15px; 33 | min-height: 50px; 34 | } 35 | 36 | .navbar-top-links .dropdown-menu li { 37 | display: block; 38 | } 39 | 40 | .navbar-top-links .dropdown-menu li:last-child { 41 | margin-right: 0; 42 | } 43 | 44 | .navbar-top-links .dropdown-menu li a { 45 | padding: 3px 20px; 46 | min-height: 0; 47 | } 48 | 49 | .navbar-top-links .dropdown-menu li a div { 50 | white-space: normal; 51 | } 52 | 53 | .navbar-top-links .dropdown-messages, 54 | .navbar-top-links .dropdown-tasks, 55 | .navbar-top-links .dropdown-alerts { 56 | width: 310px; 57 | min-width: 0; 58 | } 59 | .navbar-top-links .dropdown-messages { 60 | margin-left: 5px; 61 | } 62 | .navbar-top-links .dropdown-tasks { 63 | margin-left: -59px; 64 | } 65 | 66 | .navbar-top-links .dropdown-alerts { 67 | margin-left: -123px; 68 | } 69 | 70 | .navbar-top-links .dropdown-user { 71 | right: 0; 72 | left: auto; 73 | } 74 | 75 | .sidebar .sidebar-nav.navbar-collapse { 76 | padding-right: 0; 77 | padding-left: 0; 78 | } 79 | 80 | .sidebar .sidebar-search { 81 | padding: 15px; 82 | } 83 | .sidebar .arrow { 84 | float: right; 85 | } 86 | 87 | .sidebar .fa.arrow:before { 88 | content: "\f104"; 89 | } 90 | 91 | .sidebar .active>a>.fa.arrow:before { 92 | content: "\f107"; 93 | } 94 | 95 | .sidebar .nav-second-level li, 96 | .sidebar .nav-third-level li { 97 | border-bottom: 0!important; 98 | } 99 | 100 | .sidebar .nav-second-level li a { 101 | padding-left: 37px; 102 | } 103 | 104 | .sidebar .nav-third-level li a { 105 | padding-left: 52px; 106 | } 107 | 108 | @media(min-width:768px) { 109 | .sidebar { 110 | z-index: 1; 111 | position: absolute; 112 | width: 250px; 113 | margin-top: 51px; 114 | } 115 | 116 | .navbar-top-links .dropdown-messages, 117 | .navbar-top-links .dropdown-tasks, 118 | .navbar-top-links .dropdown-alerts { 119 | margin-left: auto; 120 | } 121 | } 122 | 123 | -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/css/font-awesome.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | /* FONT PATH 6 | * -------------------------- */ 7 | @font-face { 8 | font-family: 'FontAwesome'; 9 | src: url('../fonts/fontawesome-webfont.eot?v=4.0.3'); 10 | src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.0.3') format('embedded-opentype'), 11 | url('../fonts/fontawesome-webfont.woff?v=4.0.3') format('woff'), 12 | url('../fonts/fontawesome-webfont.ttf?v=4.0.3') format('truetype'), 13 | url('../fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular') format('svg'); 14 | font-weight: normal; 15 | font-style: normal; 16 | } 17 | .box1 { 18 | display: inline-block; 19 | width: 15%; 20 | padding:5px .5em; 21 | background:rgba(238, 238, 238, 0.26); 22 | margin: .5em 1% .5em 0; 23 | text-align: left; 24 | -moz-box-sizing: border-box; 25 | -webkit-box-sizing: border-box; 26 | box-sizing: border-box; 27 | font-size:13px; 28 | } 29 | .fontawesome-icon-list a i { 30 | margin-right:10px; 31 | font-size:25px; 32 | color:#757575; 33 | } 34 | .margin-top{ 35 | margin-top:20px; 36 | } 37 | .fa { 38 | display: inline-block; 39 | font-family: FontAwesome; 40 | font-style: normal; 41 | font-weight: normal; 42 | line-height: 1; 43 | -webkit-font-smoothing: antialiased; 44 | -moz-osx-font-smoothing: grayscale; 45 | } 46 | /* makes the font 33% larger relative to the icon container */ 47 | .fa-lg { 48 | font-size: 1.3333333333333333em; 49 | line-height: 0.75em; 50 | vertical-align: -15%; 51 | } 52 | .fa-2x { 53 | font-size: 2em; 54 | } 55 | .fa-3x { 56 | font-size: 3em; 57 | } 58 | .fa-4x { 59 | font-size: 4em; 60 | } 61 | .fa-5x { 62 | font-size: 5em; 63 | } 64 | .fa-fw { 65 | width: 1.2857142857142858em; 66 | text-align: center; 67 | } 68 | .fa-ul { 69 | padding-left: 0; 70 | margin-left: 2.142857142857143em; 71 | list-style-type: none; 72 | } 73 | .fa-ul > li { 74 | position: relative; 75 | } 76 | .fa-li { 77 | position: absolute; 78 | left: -2.142857142857143em; 79 | width: 2.142857142857143em; 80 | top: 0.14285714285714285em; 81 | text-align: center; 82 | } 83 | .fa-li.fa-lg { 84 | left: -1.8571428571428572em; 85 | } 86 | .fa-border { 87 | padding: .2em .25em .15em; 88 | border: solid 0.08em #eeeeee; 89 | border-radius: .1em; 90 | } 91 | .pull-right { 92 | float: right; 93 | } 94 | .pull-left { 95 | float: left; 96 | } 97 | .fa.pull-left { 98 | margin-right: .3em; 99 | } 100 | .fa.pull-right { 101 | margin-left: .3em; 102 | } 103 | .fa-spin { 104 | -webkit-animation: spin 2s infinite linear; 105 | -moz-animation: spin 2s infinite linear; 106 | -o-animation: spin 2s infinite linear; 107 | animation: spin 2s infinite linear; 108 | } 109 | @-moz-keyframes spin { 110 | 0% { 111 | -moz-transform: rotate(0deg); 112 | } 113 | 100% { 114 | -moz-transform: rotate(359deg); 115 | } 116 | } 117 | @-webkit-keyframes spin { 118 | 0% { 119 | -webkit-transform: rotate(0deg); 120 | } 121 | 100% { 122 | -webkit-transform: rotate(359deg); 123 | } 124 | } 125 | @-o-keyframes spin { 126 | 0% { 127 | -o-transform: rotate(0deg); 128 | } 129 | 100% { 130 | -o-transform: rotate(359deg); 131 | } 132 | } 133 | @-ms-keyframes spin { 134 | 0% { 135 | -ms-transform: rotate(0deg); 136 | } 137 | 100% { 138 | -ms-transform: rotate(359deg); 139 | } 140 | } 141 | @keyframes spin { 142 | 0% { 143 | transform: rotate(0deg); 144 | } 145 | 100% { 146 | transform: rotate(359deg); 147 | } 148 | } 149 | .fa-rotate-90 { 150 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); 151 | -webkit-transform: rotate(90deg); 152 | -moz-transform: rotate(90deg); 153 | -ms-transform: rotate(90deg); 154 | -o-transform: rotate(90deg); 155 | transform: rotate(90deg); 156 | } 157 | .fa-rotate-180 { 158 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); 159 | -webkit-transform: rotate(180deg); 160 | -moz-transform: rotate(180deg); 161 | -ms-transform: rotate(180deg); 162 | -o-transform: rotate(180deg); 163 | transform: rotate(180deg); 164 | } 165 | .fa-rotate-270 { 166 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); 167 | -webkit-transform: rotate(270deg); 168 | -moz-transform: rotate(270deg); 169 | -ms-transform: rotate(270deg); 170 | -o-transform: rotate(270deg); 171 | transform: rotate(270deg); 172 | } 173 | .fa-flip-horizontal { 174 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1); 175 | -webkit-transform: scale(-1, 1); 176 | -moz-transform: scale(-1, 1); 177 | -ms-transform: scale(-1, 1); 178 | -o-transform: scale(-1, 1); 179 | transform: scale(-1, 1); 180 | } 181 | .fa-flip-vertical { 182 | filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1); 183 | -webkit-transform: scale(1, -1); 184 | -moz-transform: scale(1, -1); 185 | -ms-transform: scale(1, -1); 186 | -o-transform: scale(1, -1); 187 | transform: scale(1, -1); 188 | } 189 | .fa-stack { 190 | position: relative; 191 | display: inline-block; 192 | width: 2em; 193 | height: 2em; 194 | line-height: 2em; 195 | vertical-align: middle; 196 | } 197 | .fa-stack-1x, 198 | .fa-stack-2x { 199 | position: absolute; 200 | left: 0; 201 | width: 100%; 202 | text-align: center; 203 | } 204 | .fa-stack-1x { 205 | line-height: inherit; 206 | } 207 | .fa-stack-2x { 208 | font-size: 2em; 209 | } 210 | .fa-inverse { 211 | color: #ffffff; 212 | } 213 | /* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen 214 | readers do not read off random characters that represent icons */ 215 | .fa-glass:before { 216 | content: "\f000"; 217 | } 218 | .fa-music:before { 219 | content: "\f001"; 220 | } 221 | .fa-search:before { 222 | content: "\f002"; 223 | } 224 | .fa-envelope-o:before { 225 | content: "\f003"; 226 | } 227 | .fa-heart:before { 228 | content: "\f004"; 229 | } 230 | .fa-star:before { 231 | content: "\f005"; 232 | } 233 | .fa-star-o:before { 234 | content: "\f006"; 235 | } 236 | .fa-user:before { 237 | content: "\f007"; 238 | } 239 | .fa-film:before { 240 | content: "\f008"; 241 | } 242 | .fa-th-large:before { 243 | content: "\f009"; 244 | } 245 | .fa-th:before { 246 | content: "\f00a"; 247 | } 248 | .fa-th-list:before { 249 | content: "\f00b"; 250 | } 251 | .fa-check:before { 252 | content: "\f00c"; 253 | } 254 | .fa-times:before { 255 | content: "\f00d"; 256 | } 257 | .fa-search-plus:before { 258 | content: "\f00e"; 259 | } 260 | .fa-search-minus:before { 261 | content: "\f010"; 262 | } 263 | .fa-power-off:before { 264 | content: "\f011"; 265 | } 266 | .fa-signal:before { 267 | content: "\f012"; 268 | } 269 | .fa-gear:before, 270 | .fa-cog:before { 271 | content: "\f013"; 272 | } 273 | .fa-trash-o:before { 274 | content: "\f014"; 275 | } 276 | .fa-home:before { 277 | content: "\f015"; 278 | } 279 | .fa-file-o:before { 280 | content: "\f016"; 281 | } 282 | .fa-clock-o:before { 283 | content: "\f017"; 284 | } 285 | .fa-road:before { 286 | content: "\f018"; 287 | } 288 | .fa-download:before { 289 | content: "\f019"; 290 | } 291 | .fa-arrow-circle-o-down:before { 292 | content: "\f01a"; 293 | } 294 | .fa-arrow-circle-o-up:before { 295 | content: "\f01b"; 296 | } 297 | .fa-inbox:before { 298 | content: "\f01c"; 299 | } 300 | .fa-play-circle-o:before { 301 | content: "\f01d"; 302 | } 303 | .fa-rotate-right:before, 304 | .fa-repeat:before { 305 | content: "\f01e"; 306 | } 307 | .fa-refresh:before { 308 | content: "\f021"; 309 | } 310 | .fa-list-alt:before { 311 | content: "\f022"; 312 | } 313 | .fa-lock:before { 314 | content: "\f023"; 315 | } 316 | .fa-flag:before { 317 | content: "\f024"; 318 | } 319 | .fa-headphones:before { 320 | content: "\f025"; 321 | } 322 | .fa-volume-off:before { 323 | content: "\f026"; 324 | } 325 | .fa-volume-down:before { 326 | content: "\f027"; 327 | } 328 | .fa-volume-up:before { 329 | content: "\f028"; 330 | } 331 | .fa-qrcode:before { 332 | content: "\f029"; 333 | } 334 | .fa-barcode:before { 335 | content: "\f02a"; 336 | } 337 | .fa-tag:before { 338 | content: "\f02b"; 339 | } 340 | .fa-tags:before { 341 | content: "\f02c"; 342 | } 343 | .fa-book:before { 344 | content: "\f02d"; 345 | } 346 | .fa-bookmark:before { 347 | content: "\f02e"; 348 | } 349 | .fa-print:before { 350 | content: "\f02f"; 351 | } 352 | .fa-camera:before { 353 | content: "\f030"; 354 | } 355 | .fa-font:before { 356 | content: "\f031"; 357 | } 358 | .fa-bold:before { 359 | content: "\f032"; 360 | } 361 | .fa-italic:before { 362 | content: "\f033"; 363 | } 364 | .fa-text-height:before { 365 | content: "\f034"; 366 | } 367 | .fa-text-width:before { 368 | content: "\f035"; 369 | } 370 | .fa-align-left:before { 371 | content: "\f036"; 372 | } 373 | .fa-align-center:before { 374 | content: "\f037"; 375 | } 376 | .fa-align-right:before { 377 | content: "\f038"; 378 | } 379 | .fa-align-justify:before { 380 | content: "\f039"; 381 | } 382 | .fa-list:before { 383 | content: "\f03a"; 384 | } 385 | .fa-dedent:before, 386 | .fa-outdent:before { 387 | content: "\f03b"; 388 | } 389 | .fa-indent:before { 390 | content: "\f03c"; 391 | } 392 | .fa-video-camera:before { 393 | content: "\f03d"; 394 | } 395 | .fa-picture-o:before { 396 | content: "\f03e"; 397 | } 398 | .fa-pencil:before { 399 | content: "\f040"; 400 | } 401 | .fa-map-marker:before { 402 | content: "\f041"; 403 | } 404 | .fa-adjust:before { 405 | content: "\f042"; 406 | } 407 | .fa-tint:before { 408 | content: "\f043"; 409 | } 410 | .fa-edit:before, 411 | .fa-pencil-square-o:before { 412 | content: "\f044"; 413 | } 414 | .fa-share-square-o:before { 415 | content: "\f045"; 416 | } 417 | .fa-check-square-o:before { 418 | content: "\f046"; 419 | } 420 | .fa-arrows:before { 421 | content: "\f047"; 422 | } 423 | .fa-step-backward:before { 424 | content: "\f048"; 425 | } 426 | .fa-fast-backward:before { 427 | content: "\f049"; 428 | } 429 | .fa-backward:before { 430 | content: "\f04a"; 431 | } 432 | .fa-play:before { 433 | content: "\f04b"; 434 | } 435 | .fa-pause:before { 436 | content: "\f04c"; 437 | } 438 | .fa-stop:before { 439 | content: "\f04d"; 440 | } 441 | .fa-forward:before { 442 | content: "\f04e"; 443 | } 444 | .fa-fast-forward:before { 445 | content: "\f050"; 446 | } 447 | .fa-step-forward:before { 448 | content: "\f051"; 449 | } 450 | .fa-eject:before { 451 | content: "\f052"; 452 | } 453 | .fa-chevron-left:before { 454 | content: "\f053"; 455 | } 456 | .fa-chevron-right:before { 457 | content: "\f054"; 458 | } 459 | .fa-plus-circle:before { 460 | content: "\f055"; 461 | } 462 | .fa-minus-circle:before { 463 | content: "\f056"; 464 | } 465 | .fa-times-circle:before { 466 | content: "\f057"; 467 | } 468 | .fa-check-circle:before { 469 | content: "\f058"; 470 | } 471 | .fa-question-circle:before { 472 | content: "\f059"; 473 | } 474 | .fa-info-circle:before { 475 | content: "\f05a"; 476 | } 477 | .fa-crosshairs:before { 478 | content: "\f05b"; 479 | } 480 | .fa-times-circle-o:before { 481 | content: "\f05c"; 482 | } 483 | .fa-check-circle-o:before { 484 | content: "\f05d"; 485 | } 486 | .fa-ban:before { 487 | content: "\f05e"; 488 | } 489 | .fa-arrow-left:before { 490 | content: "\f060"; 491 | } 492 | .fa-arrow-right:before { 493 | content: "\f061"; 494 | } 495 | .fa-arrow-up:before { 496 | content: "\f062"; 497 | } 498 | .fa-arrow-down:before { 499 | content: "\f063"; 500 | } 501 | .fa-mail-forward:before, 502 | .fa-share:before { 503 | content: "\f064"; 504 | } 505 | .fa-expand:before { 506 | content: "\f065"; 507 | } 508 | .fa-compress:before { 509 | content: "\f066"; 510 | } 511 | .fa-plus:before { 512 | content: "\f067"; 513 | } 514 | .fa-minus:before { 515 | content: "\f068"; 516 | } 517 | .fa-asterisk:before { 518 | content: "\f069"; 519 | } 520 | .fa-exclamation-circle:before { 521 | content: "\f06a"; 522 | } 523 | .fa-gift:before { 524 | content: "\f06b"; 525 | } 526 | .fa-leaf:before { 527 | content: "\f06c"; 528 | } 529 | .fa-fire:before { 530 | content: "\f06d"; 531 | } 532 | .fa-eye:before { 533 | content: "\f06e"; 534 | } 535 | .fa-eye-slash:before { 536 | content: "\f070"; 537 | } 538 | .fa-warning:before, 539 | .fa-exclamation-triangle:before { 540 | content: "\f071"; 541 | } 542 | .fa-plane:before { 543 | content: "\f072"; 544 | } 545 | .fa-calendar:before { 546 | content: "\f073"; 547 | } 548 | .fa-random:before { 549 | content: "\f074"; 550 | } 551 | .fa-comment:before { 552 | content: "\f075"; 553 | } 554 | .fa-magnet:before { 555 | content: "\f076"; 556 | } 557 | .fa-chevron-up:before { 558 | content: "\f077"; 559 | } 560 | .fa-chevron-down:before { 561 | content: "\f078"; 562 | } 563 | .fa-retweet:before { 564 | content: "\f079"; 565 | } 566 | .fa-shopping-cart:before { 567 | content: "\f07a"; 568 | } 569 | .fa-folder:before { 570 | content: "\f07b"; 571 | } 572 | .fa-folder-open:before { 573 | content: "\f07c"; 574 | } 575 | .fa-arrows-v:before { 576 | content: "\f07d"; 577 | } 578 | .fa-arrows-h:before { 579 | content: "\f07e"; 580 | } 581 | .fa-bar-chart-o:before { 582 | content: "\f080"; 583 | } 584 | .fa-twitter-square:before { 585 | content: "\f081"; 586 | } 587 | .fa-facebook-square:before { 588 | content: "\f082"; 589 | } 590 | .fa-camera-retro:before { 591 | content: "\f083"; 592 | } 593 | .fa-key:before { 594 | content: "\f084"; 595 | } 596 | .fa-gears:before, 597 | .fa-cogs:before { 598 | content: "\f085"; 599 | } 600 | .fa-comments:before { 601 | content: "\f086"; 602 | } 603 | .fa-thumbs-o-up:before { 604 | content: "\f087"; 605 | } 606 | .fa-thumbs-o-down:before { 607 | content: "\f088"; 608 | } 609 | .fa-star-half:before { 610 | content: "\f089"; 611 | } 612 | .fa-heart-o:before { 613 | content: "\f08a"; 614 | } 615 | .fa-sign-out:before { 616 | content: "\f08b"; 617 | } 618 | .fa-linkedin-square:before { 619 | content: "\f08c"; 620 | } 621 | .fa-thumb-tack:before { 622 | content: "\f08d"; 623 | } 624 | .fa-external-link:before { 625 | content: "\f08e"; 626 | } 627 | .fa-sign-in:before { 628 | content: "\f090"; 629 | } 630 | .fa-trophy:before { 631 | content: "\f091"; 632 | } 633 | .fa-github-square:before { 634 | content: "\f092"; 635 | } 636 | .fa-upload:before { 637 | content: "\f093"; 638 | } 639 | .fa-lemon-o:before { 640 | content: "\f094"; 641 | } 642 | .fa-phone:before { 643 | content: "\f095"; 644 | } 645 | .fa-square-o:before { 646 | content: "\f096"; 647 | } 648 | .fa-bookmark-o:before { 649 | content: "\f097"; 650 | } 651 | .fa-phone-square:before { 652 | content: "\f098"; 653 | } 654 | .fa-twitter:before { 655 | content: "\f099"; 656 | } 657 | .fa-facebook:before { 658 | content: "\f09a"; 659 | } 660 | .fa-github:before { 661 | content: "\f09b"; 662 | } 663 | .fa-unlock:before { 664 | content: "\f09c"; 665 | } 666 | .fa-credit-card:before { 667 | content: "\f09d"; 668 | } 669 | .fa-rss:before { 670 | content: "\f09e"; 671 | } 672 | .fa-hdd-o:before { 673 | content: "\f0a0"; 674 | } 675 | .fa-bullhorn:before { 676 | content: "\f0a1"; 677 | } 678 | .fa-bell:before { 679 | content: "\f0f3"; 680 | } 681 | .fa-certificate:before { 682 | content: "\f0a3"; 683 | } 684 | .fa-hand-o-right:before { 685 | content: "\f0a4"; 686 | } 687 | .fa-hand-o-left:before { 688 | content: "\f0a5"; 689 | } 690 | .fa-hand-o-up:before { 691 | content: "\f0a6"; 692 | } 693 | .fa-hand-o-down:before { 694 | content: "\f0a7"; 695 | } 696 | .fa-arrow-circle-left:before { 697 | content: "\f0a8"; 698 | } 699 | .fa-arrow-circle-right:before { 700 | content: "\f0a9"; 701 | } 702 | .fa-arrow-circle-up:before { 703 | content: "\f0aa"; 704 | } 705 | .fa-arrow-circle-down:before { 706 | content: "\f0ab"; 707 | } 708 | .fa-globe:before { 709 | content: "\f0ac"; 710 | } 711 | .fa-wrench:before { 712 | content: "\f0ad"; 713 | } 714 | .fa-tasks:before { 715 | content: "\f0ae"; 716 | } 717 | .fa-filter:before { 718 | content: "\f0b0"; 719 | } 720 | .fa-briefcase:before { 721 | content: "\f0b1"; 722 | } 723 | .fa-arrows-alt:before { 724 | content: "\f0b2"; 725 | } 726 | .fa-group:before, 727 | .fa-users:before { 728 | content: "\f0c0"; 729 | } 730 | .fa-chain:before, 731 | .fa-link:before { 732 | content: "\f0c1"; 733 | } 734 | .fa-cloud:before { 735 | content: "\f0c2"; 736 | } 737 | .fa-flask:before { 738 | content: "\f0c3"; 739 | } 740 | .fa-cut:before, 741 | .fa-scissors:before { 742 | content: "\f0c4"; 743 | } 744 | .fa-copy:before, 745 | .fa-files-o:before { 746 | content: "\f0c5"; 747 | } 748 | .fa-paperclip:before { 749 | content: "\f0c6"; 750 | } 751 | .fa-save:before, 752 | .fa-floppy-o:before { 753 | content: "\f0c7"; 754 | } 755 | .fa-square:before { 756 | content: "\f0c8"; 757 | } 758 | .fa-bars:before { 759 | content: "\f0c9"; 760 | } 761 | .fa-list-ul:before { 762 | content: "\f0ca"; 763 | } 764 | .fa-list-ol:before { 765 | content: "\f0cb"; 766 | } 767 | .fa-strikethrough:before { 768 | content: "\f0cc"; 769 | } 770 | .fa-underline:before { 771 | content: "\f0cd"; 772 | } 773 | .fa-table:before { 774 | content: "\f0ce"; 775 | } 776 | .fa-magic:before { 777 | content: "\f0d0"; 778 | } 779 | .fa-truck:before { 780 | content: "\f0d1"; 781 | } 782 | .fa-pinterest:before { 783 | content: "\f0d2"; 784 | } 785 | .fa-pinterest-square:before { 786 | content: "\f0d3"; 787 | } 788 | .fa-google-plus-square:before { 789 | content: "\f0d4"; 790 | } 791 | .fa-google-plus:before { 792 | content: "\f0d5"; 793 | } 794 | .fa-money:before { 795 | content: "\f0d6"; 796 | } 797 | .fa-caret-down:before { 798 | content: "\f0d7"; 799 | } 800 | .fa-caret-up:before { 801 | content: "\f0d8"; 802 | } 803 | .fa-caret-left:before { 804 | content: "\f0d9"; 805 | } 806 | .fa-caret-right:before { 807 | content: "\f0da"; 808 | } 809 | .fa-columns:before { 810 | content: "\f0db"; 811 | } 812 | .fa-unsorted:before, 813 | .fa-sort:before { 814 | content: "\f0dc"; 815 | } 816 | .fa-sort-down:before, 817 | .fa-sort-asc:before { 818 | content: "\f0dd"; 819 | } 820 | .fa-sort-up:before, 821 | .fa-sort-desc:before { 822 | content: "\f0de"; 823 | } 824 | .fa-envelope:before { 825 | content: "\f0e0"; 826 | } 827 | .fa-linkedin:before { 828 | content: "\f0e1"; 829 | } 830 | .fa-rotate-left:before, 831 | .fa-undo:before { 832 | content: "\f0e2"; 833 | } 834 | .fa-legal:before, 835 | .fa-gavel:before { 836 | content: "\f0e3"; 837 | } 838 | .fa-dashboard:before, 839 | .fa-tachometer:before { 840 | content: "\f0e4"; 841 | } 842 | .fa-comment-o:before { 843 | content: "\f0e5"; 844 | } 845 | .fa-comments-o:before { 846 | content: "\f0e6"; 847 | } 848 | .fa-flash:before, 849 | .fa-bolt:before { 850 | content: "\f0e7"; 851 | } 852 | .fa-sitemap:before { 853 | content: "\f0e8"; 854 | } 855 | .fa-umbrella:before { 856 | content: "\f0e9"; 857 | } 858 | .fa-paste:before, 859 | .fa-clipboard:before { 860 | content: "\f0ea"; 861 | } 862 | .fa-lightbulb-o:before { 863 | content: "\f0eb"; 864 | } 865 | .fa-exchange:before { 866 | content: "\f0ec"; 867 | } 868 | .fa-cloud-download:before { 869 | content: "\f0ed"; 870 | } 871 | .fa-cloud-upload:before { 872 | content: "\f0ee"; 873 | } 874 | .fa-user-md:before { 875 | content: "\f0f0"; 876 | } 877 | .fa-stethoscope:before { 878 | content: "\f0f1"; 879 | } 880 | .fa-suitcase:before { 881 | content: "\f0f2"; 882 | } 883 | .fa-bell-o:before { 884 | content: "\f0a2"; 885 | } 886 | .fa-coffee:before { 887 | content: "\f0f4"; 888 | } 889 | .fa-cutlery:before { 890 | content: "\f0f5"; 891 | } 892 | .fa-file-text-o:before { 893 | content: "\f0f6"; 894 | } 895 | .fa-building-o:before { 896 | content: "\f0f7"; 897 | } 898 | .fa-hospital-o:before { 899 | content: "\f0f8"; 900 | } 901 | .fa-ambulance:before { 902 | content: "\f0f9"; 903 | } 904 | .fa-medkit:before { 905 | content: "\f0fa"; 906 | } 907 | .fa-fighter-jet:before { 908 | content: "\f0fb"; 909 | } 910 | .fa-beer:before { 911 | content: "\f0fc"; 912 | } 913 | .fa-h-square:before { 914 | content: "\f0fd"; 915 | } 916 | .fa-plus-square:before { 917 | content: "\f0fe"; 918 | } 919 | .fa-angle-double-left:before { 920 | content: "\f100"; 921 | } 922 | .fa-angle-double-right:before { 923 | content: "\f101"; 924 | } 925 | .fa-angle-double-up:before { 926 | content: "\f102"; 927 | } 928 | .fa-angle-double-down:before { 929 | content: "\f103"; 930 | } 931 | .fa-angle-left:before { 932 | content: "\f104"; 933 | } 934 | .fa-angle-right:before { 935 | content: "\f105"; 936 | } 937 | .fa-angle-up:before { 938 | content: "\f106"; 939 | } 940 | .fa-angle-down:before { 941 | content: "\f107"; 942 | } 943 | .fa-desktop:before { 944 | content: "\f108"; 945 | } 946 | .fa-laptop:before { 947 | content: "\f109"; 948 | } 949 | .fa-tablet:before { 950 | content: "\f10a"; 951 | } 952 | .fa-mobile-phone:before, 953 | .fa-mobile:before { 954 | content: "\f10b"; 955 | } 956 | .fa-circle-o:before { 957 | content: "\f10c"; 958 | } 959 | .fa-quote-left:before { 960 | content: "\f10d"; 961 | } 962 | .fa-quote-right:before { 963 | content: "\f10e"; 964 | } 965 | .fa-spinner:before { 966 | content: "\f110"; 967 | } 968 | .fa-circle:before { 969 | content: "\f111"; 970 | } 971 | .fa-mail-reply:before, 972 | .fa-reply:before { 973 | content: "\f112"; 974 | } 975 | .fa-github-alt:before { 976 | content: "\f113"; 977 | } 978 | .fa-folder-o:before { 979 | content: "\f114"; 980 | } 981 | .fa-folder-open-o:before { 982 | content: "\f115"; 983 | } 984 | .fa-smile-o:before { 985 | content: "\f118"; 986 | } 987 | .fa-frown-o:before { 988 | content: "\f119"; 989 | } 990 | .fa-meh-o:before { 991 | content: "\f11a"; 992 | } 993 | .fa-gamepad:before { 994 | content: "\f11b"; 995 | } 996 | .fa-keyboard-o:before { 997 | content: "\f11c"; 998 | } 999 | .fa-flag-o:before { 1000 | content: "\f11d"; 1001 | } 1002 | .fa-flag-checkered:before { 1003 | content: "\f11e"; 1004 | } 1005 | .fa-terminal:before { 1006 | content: "\f120"; 1007 | } 1008 | .fa-code:before { 1009 | content: "\f121"; 1010 | } 1011 | .fa-reply-all:before { 1012 | content: "\f122"; 1013 | } 1014 | .fa-mail-reply-all:before { 1015 | content: "\f122"; 1016 | } 1017 | .fa-star-half-empty:before, 1018 | .fa-star-half-full:before, 1019 | .fa-star-half-o:before { 1020 | content: "\f123"; 1021 | } 1022 | .fa-location-arrow:before { 1023 | content: "\f124"; 1024 | } 1025 | .fa-crop:before { 1026 | content: "\f125"; 1027 | } 1028 | .fa-code-fork:before { 1029 | content: "\f126"; 1030 | } 1031 | .fa-unlink:before, 1032 | .fa-chain-broken:before { 1033 | content: "\f127"; 1034 | } 1035 | .fa-question:before { 1036 | content: "\f128"; 1037 | } 1038 | .fa-info:before { 1039 | content: "\f129"; 1040 | } 1041 | .fa-exclamation:before { 1042 | content: "\f12a"; 1043 | } 1044 | .fa-superscript:before { 1045 | content: "\f12b"; 1046 | } 1047 | .fa-subscript:before { 1048 | content: "\f12c"; 1049 | } 1050 | .fa-eraser:before { 1051 | content: "\f12d"; 1052 | } 1053 | .fa-puzzle-piece:before { 1054 | content: "\f12e"; 1055 | } 1056 | .fa-microphone:before { 1057 | content: "\f130"; 1058 | } 1059 | .fa-microphone-slash:before { 1060 | content: "\f131"; 1061 | } 1062 | .fa-shield:before { 1063 | content: "\f132"; 1064 | } 1065 | .fa-calendar-o:before { 1066 | content: "\f133"; 1067 | } 1068 | .fa-fire-extinguisher:before { 1069 | content: "\f134"; 1070 | } 1071 | .fa-rocket:before { 1072 | content: "\f135"; 1073 | } 1074 | .fa-maxcdn:before { 1075 | content: "\f136"; 1076 | } 1077 | .fa-chevron-circle-left:before { 1078 | content: "\f137"; 1079 | } 1080 | .fa-chevron-circle-right:before { 1081 | content: "\f138"; 1082 | } 1083 | .fa-chevron-circle-up:before { 1084 | content: "\f139"; 1085 | } 1086 | .fa-chevron-circle-down:before { 1087 | content: "\f13a"; 1088 | } 1089 | .fa-html5:before { 1090 | content: "\f13b"; 1091 | } 1092 | .fa-css3:before { 1093 | content: "\f13c"; 1094 | } 1095 | .fa-anchor:before { 1096 | content: "\f13d"; 1097 | } 1098 | .fa-unlock-alt:before { 1099 | content: "\f13e"; 1100 | } 1101 | .fa-bullseye:before { 1102 | content: "\f140"; 1103 | } 1104 | .fa-ellipsis-h:before { 1105 | content: "\f141"; 1106 | } 1107 | .fa-ellipsis-v:before { 1108 | content: "\f142"; 1109 | } 1110 | .fa-rss-square:before { 1111 | content: "\f143"; 1112 | } 1113 | .fa-play-circle:before { 1114 | content: "\f144"; 1115 | } 1116 | .fa-ticket:before { 1117 | content: "\f145"; 1118 | } 1119 | .fa-minus-square:before { 1120 | content: "\f146"; 1121 | } 1122 | .fa-minus-square-o:before { 1123 | content: "\f147"; 1124 | } 1125 | .fa-level-up:before { 1126 | content: "\f148"; 1127 | } 1128 | .fa-level-down:before { 1129 | content: "\f149"; 1130 | } 1131 | .fa-check-square:before { 1132 | content: "\f14a"; 1133 | } 1134 | .fa-pencil-square:before { 1135 | content: "\f14b"; 1136 | } 1137 | .fa-external-link-square:before { 1138 | content: "\f14c"; 1139 | } 1140 | .fa-share-square:before { 1141 | content: "\f14d"; 1142 | } 1143 | .fa-compass:before { 1144 | content: "\f14e"; 1145 | } 1146 | .fa-toggle-down:before, 1147 | .fa-caret-square-o-down:before { 1148 | content: "\f150"; 1149 | } 1150 | .fa-toggle-up:before, 1151 | .fa-caret-square-o-up:before { 1152 | content: "\f151"; 1153 | } 1154 | .fa-toggle-right:before, 1155 | .fa-caret-square-o-right:before { 1156 | content: "\f152"; 1157 | } 1158 | .fa-euro:before, 1159 | .fa-eur:before { 1160 | content: "\f153"; 1161 | } 1162 | .fa-gbp:before { 1163 | content: "\f154"; 1164 | } 1165 | .fa-dollar:before, 1166 | .fa-usd:before { 1167 | content: "\f155"; 1168 | } 1169 | .fa-rupee:before, 1170 | .fa-inr:before { 1171 | content: "\f156"; 1172 | } 1173 | .fa-cny:before, 1174 | .fa-rmb:before, 1175 | .fa-yen:before, 1176 | .fa-jpy:before { 1177 | content: "\f157"; 1178 | } 1179 | .fa-ruble:before, 1180 | .fa-rouble:before, 1181 | .fa-rub:before { 1182 | content: "\f158"; 1183 | } 1184 | .fa-won:before, 1185 | .fa-krw:before { 1186 | content: "\f159"; 1187 | } 1188 | .fa-bitcoin:before, 1189 | .fa-btc:before { 1190 | content: "\f15a"; 1191 | } 1192 | .fa-file:before { 1193 | content: "\f15b"; 1194 | } 1195 | .fa-file-text:before { 1196 | content: "\f15c"; 1197 | } 1198 | .fa-sort-alpha-asc:before { 1199 | content: "\f15d"; 1200 | } 1201 | .fa-sort-alpha-desc:before { 1202 | content: "\f15e"; 1203 | } 1204 | .fa-sort-amount-asc:before { 1205 | content: "\f160"; 1206 | } 1207 | .fa-sort-amount-desc:before { 1208 | content: "\f161"; 1209 | } 1210 | .fa-sort-numeric-asc:before { 1211 | content: "\f162"; 1212 | } 1213 | .fa-sort-numeric-desc:before { 1214 | content: "\f163"; 1215 | } 1216 | .fa-thumbs-up:before { 1217 | content: "\f164"; 1218 | } 1219 | .fa-thumbs-down:before { 1220 | content: "\f165"; 1221 | } 1222 | .fa-youtube-square:before { 1223 | content: "\f166"; 1224 | } 1225 | .fa-youtube:before { 1226 | content: "\f167"; 1227 | } 1228 | .fa-xing:before { 1229 | content: "\f168"; 1230 | } 1231 | .fa-xing-square:before { 1232 | content: "\f169"; 1233 | } 1234 | .fa-youtube-play:before { 1235 | content: "\f16a"; 1236 | } 1237 | .fa-dropbox:before { 1238 | content: "\f16b"; 1239 | } 1240 | .fa-stack-overflow:before { 1241 | content: "\f16c"; 1242 | } 1243 | .fa-instagram:before { 1244 | content: "\f16d"; 1245 | } 1246 | .fa-flickr:before { 1247 | content: "\f16e"; 1248 | } 1249 | .fa-adn:before { 1250 | content: "\f170"; 1251 | } 1252 | .fa-bitbucket:before { 1253 | content: "\f171"; 1254 | } 1255 | .fa-bitbucket-square:before { 1256 | content: "\f172"; 1257 | } 1258 | .fa-tumblr:before { 1259 | content: "\f173"; 1260 | } 1261 | .fa-tumblr-square:before { 1262 | content: "\f174"; 1263 | } 1264 | .fa-long-arrow-down:before { 1265 | content: "\f175"; 1266 | } 1267 | .fa-long-arrow-up:before { 1268 | content: "\f176"; 1269 | } 1270 | .fa-long-arrow-left:before { 1271 | content: "\f177"; 1272 | } 1273 | .fa-long-arrow-right:before { 1274 | content: "\f178"; 1275 | } 1276 | .fa-apple:before { 1277 | content: "\f179"; 1278 | } 1279 | .fa-windows:before { 1280 | content: "\f17a"; 1281 | } 1282 | .fa-android:before { 1283 | content: "\f17b"; 1284 | } 1285 | .fa-linux:before { 1286 | content: "\f17c"; 1287 | } 1288 | .fa-dribbble:before { 1289 | content: "\f17d"; 1290 | } 1291 | .fa-skype:before { 1292 | content: "\f17e"; 1293 | } 1294 | .fa-foursquare:before { 1295 | content: "\f180"; 1296 | } 1297 | .fa-trello:before { 1298 | content: "\f181"; 1299 | } 1300 | .fa-female:before { 1301 | content: "\f182"; 1302 | } 1303 | .fa-male:before { 1304 | content: "\f183"; 1305 | } 1306 | .fa-gittip:before { 1307 | content: "\f184"; 1308 | } 1309 | .fa-sun-o:before { 1310 | content: "\f185"; 1311 | } 1312 | .fa-moon-o:before { 1313 | content: "\f186"; 1314 | } 1315 | .fa-archive:before { 1316 | content: "\f187"; 1317 | } 1318 | .fa-bug:before { 1319 | content: "\f188"; 1320 | } 1321 | .fa-vk:before { 1322 | content: "\f189"; 1323 | } 1324 | .fa-weibo:before { 1325 | content: "\f18a"; 1326 | } 1327 | .fa-renren:before { 1328 | content: "\f18b"; 1329 | } 1330 | .fa-pagelines:before { 1331 | content: "\f18c"; 1332 | } 1333 | .fa-stack-exchange:before { 1334 | content: "\f18d"; 1335 | } 1336 | .fa-arrow-circle-o-right:before { 1337 | content: "\f18e"; 1338 | } 1339 | .fa-arrow-circle-o-left:before { 1340 | content: "\f190"; 1341 | } 1342 | .fa-toggle-left:before, 1343 | .fa-caret-square-o-left:before { 1344 | content: "\f191"; 1345 | } 1346 | .fa-dot-circle-o:before { 1347 | content: "\f192"; 1348 | } 1349 | .fa-wheelchair:before { 1350 | content: "\f193"; 1351 | } 1352 | .fa-vimeo-square:before { 1353 | content: "\f194"; 1354 | } 1355 | .fa-turkish-lira:before, 1356 | .fa-try:before { 1357 | content: "\f195"; 1358 | } 1359 | .fa-plus-square-o:before { 1360 | content: "\f196"; 1361 | } 1362 | -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/css/jqvmap.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * jQVMap Version 1.0 3 | * 4 | * http://jqvmap.com 5 | * 6 | * Copyright 2012, Peter Schmalfeldt 7 | * Licensed under the MIT license. 8 | * 9 | * Fork Me @ https://github.com/manifestinteractive/jqvmap 10 | */ 11 | .jqvmap-label 12 | { 13 | position: absolute; 14 | display: none; 15 | -webkit-border-radius: 3px; 16 | -moz-border-radius: 3px; 17 | border-radius: 3px; 18 | background: #292929; 19 | color: white; 20 | font-family: sans-serif, Verdana; 21 | font-size: smaller; 22 | padding: 3px; 23 | } 24 | .jqvmap-zoomin, .jqvmap-zoomout 25 | { 26 | position: absolute; 27 | left: 10px; 28 | -webkit-border-radius: 3px; 29 | -moz-border-radius: 3px; 30 | border-radius: 3px; 31 | background: #000000; 32 | padding: 1px; 33 | color: white; 34 | width: 10px; 35 | height: 10px; 36 | cursor: pointer; 37 | line-height: 9px; 38 | text-align: center; 39 | } 40 | .jqvmap-zoomin 41 | { 42 | top: 10px; 43 | } 44 | .jqvmap-zoomout 45 | { 46 | top: 30px; 47 | } 48 | .jqvmap-region 49 | { 50 | cursor: pointer; 51 | } 52 | .jqvmap-ajax_response 53 | { 54 | width: 100%; 55 | height: 500px; 56 | } -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/css/lines.css: -------------------------------------------------------------------------------- 1 | 2 | .rickshaw_graph .detail { 3 | pointer-events: none; 4 | position: absolute; 5 | top: 0; 6 | z-index: 2; 7 | background: rgba(0, 0, 0, 0.1); 8 | bottom: 0; 9 | width: 1px; 10 | transition: opacity 0.25s linear; 11 | -moz-transition: opacity 0.25s linear; 12 | -o-transition: opacity 0.25s linear; 13 | -webkit-transition: opacity 0.25s linear; 14 | } 15 | .rickshaw_graph .detail.inactive { 16 | opacity: 0; 17 | } 18 | .rickshaw_graph .detail .item.active { 19 | opacity: 1; 20 | } 21 | .rickshaw_graph .detail .x_label { 22 | font-family: Arial, sans-serif; 23 | border-radius: 3px; 24 | padding: 6px; 25 | opacity: 0.5; 26 | border: 1px solid #e0e0e0; 27 | font-size: 12px; 28 | position: absolute; 29 | background: white; 30 | white-space: nowrap; 31 | } 32 | .rickshaw_graph .detail .x_label.left { 33 | left: 0; 34 | } 35 | .rickshaw_graph .detail .x_label.right { 36 | right: 0; 37 | } 38 | .rickshaw_graph .detail .item { 39 | position: absolute; 40 | z-index: 2; 41 | border-radius: 3px; 42 | 43 | font-size: 12px; 44 | font-family: Arial, sans-serif; 45 | opacity: 0; 46 | background: rgba(0, 0, 0, 0.4); 47 | color: white; 48 | border: 1px solid rgba(0, 0, 0, 0.4); 49 | margin-left: 1em; 50 | margin-right: 1em; 51 | margin-top: -1em; 52 | white-space: nowrap; 53 | } 54 | .rickshaw_graph .detail .item.left { 55 | left: 0; 56 | } 57 | .rickshaw_graph .detail .item.right { 58 | right: 0; 59 | } 60 | .rickshaw_graph .detail .item.active { 61 | opacity: 1; 62 | background: rgba(0, 0, 0, 0.8); 63 | } 64 | .rickshaw_graph .detail .item:after { 65 | position: absolute; 66 | display: block; 67 | width: 0; 68 | height: 0; 69 | 70 | content: ""; 71 | 72 | border: 5px solid transparent; 73 | } 74 | .rickshaw_graph .detail .item.left:after { 75 | top: 1em; 76 | left: -5px; 77 | margin-top: -5px; 78 | border-right-color: rgba(0, 0, 0, 0.8); 79 | border-left-width: 0; 80 | } 81 | .rickshaw_graph .detail .item.right:after { 82 | top: 1em; 83 | right: -5px; 84 | margin-top: -5px; 85 | border-left-color: rgba(0, 0, 0, 0.8); 86 | border-right-width: 0; 87 | } 88 | .rickshaw_graph .detail .dot { 89 | width: 4px; 90 | height: 4px; 91 | margin-left: -3px; 92 | margin-top: -3.5px; 93 | border-radius: 5px; 94 | position: absolute; 95 | box-shadow: 0 0 2px rgba(0, 0, 0, 0.6); 96 | box-sizing: content-box; 97 | -moz-box-sizing: content-box; 98 | background: white; 99 | border-width: 2px; 100 | border-style: solid; 101 | display: none; 102 | background-clip: padding-box; 103 | } 104 | .rickshaw_graph .detail .dot.active { 105 | display: block; 106 | } 107 | /* graph */ 108 | #chart { 109 | width: 649px !important; 110 | height: 400px !important; 111 | background-color: #fff; 112 | } 113 | .rickshaw_graph { 114 | position: relative; 115 | } 116 | .rickshaw_graph svg { 117 | display: block; 118 | overflow: hidden; 119 | } 120 | @media (max-width:1366px){ 121 | #chart { 122 | width:533px !important; 123 | } 124 | } 125 | @media (max-width:1280px){ 126 | #chart { 127 | width:483px !important; 128 | } 129 | canvas#doughnut, canvas#line, canvas#polarArea, #bar, #pie, #radar { 130 | width: 308px !important; 131 | height: 220px !important; 132 | } 133 | } 134 | @media (max-width:1024px){ 135 | #chart { 136 | width:360px !important; 137 | height:300px !important; 138 | } 139 | } 140 | @media (max-width:768px){ 141 | #chart { 142 | width:468px !important; 143 | height: 300px !important; 144 | } 145 | } 146 | @media (max-width:736px){ 147 | #chart { 148 | width:685px !important; 149 | height: 300px !important; 150 | } 151 | } 152 | @media (max-width:640px){ 153 | #chart { 154 | width:580px !important; 155 | height:250px !important; 156 | } 157 | } 158 | @media (max-width:540px){ 159 | #chart { 160 | width:464px !important; 161 | height:250px !important; 162 | } 163 | } 164 | @media (max-width:480px){ 165 | #chart { 166 | width:447px !important; 167 | height:250px !important; 168 | } 169 | } 170 | @media (max-width:320px){ 171 | #chart { 172 | width:298px !important; 173 | height:250px !important; 174 | } 175 | .copy { 176 | padding: 10px; 177 | } 178 | .copy p{ 179 | font-size:13px; 180 | } 181 | .btn-group-lg>.btn, .btn-lg { 182 | padding: 6px 7px; 183 | font-size: 16px; 184 | } 185 | .label { 186 | font-size: 56%; 187 | } 188 | .pagination-lg>li>a, .pagination-lg>li>span { 189 | padding: 8px 13px; 190 | font-size: 15px; 191 | } 192 | .nav>li>a { 193 | padding: 7px 8px; 194 | } 195 | .modal-dialog { 196 | width: 245px !important; 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/css/style.css: -------------------------------------------------------------------------------- 1 | 2 | /* reset */ 3 | html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,dl,dt,dd,ol,nav ul,nav li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline;} 4 | article, aside, details, figcaption, figure,footer, header, hgroup, menu, nav, section {display: block;} 5 | ol,ul{list-style:none;margin:0px;padding:0px;} 6 | blockquote,q{quotes:none;} 7 | blockquote:before,blockquote:after,q:before,q:after{content:'';content:none;} 8 | table{border-collapse:collapse;border-spacing:0;} 9 | /* start editing from here */ 10 | a{text-decoration:none;} 11 | .txt-rt{text-align:right;}/* text align right */ 12 | .txt-lt{text-align:left;}/* text align left */ 13 | .txt-center{text-align:center;}/* text align center */ 14 | .float-rt{float:right;}/* float right */ 15 | .float-lt{float:left;}/* float left */ 16 | .clear{clear:both;}/* clear float */ 17 | .pos-relative{position:relative;}/* Position Relative */ 18 | .pos-absolute{position:absolute;}/* Position Absolute */ 19 | .vertical-base{ vertical-align:baseline;}/* vertical align baseline */ 20 | .vertical-top{ vertical-align:top;}/* vertical align top */ 21 | nav.vertical ul li{ display:block;}/* vertical menu */ 22 | nav.horizontal ul li{ display: inline-block;}/* horizontal menu */ 23 | img{max-width:100%;} 24 | /*end reset*/ 25 | /****-----start-body----****/ 26 | body{ 27 | background: url(../images/bg1.jpg) no-repeat 0px 0px; 28 | font-family: 'Open Sans', sans-serif; 29 | background-size:cover; 30 | -webkit-background-size:cover; 31 | -moz-background-size:cover; 32 | -o-background-size:cover; 33 | min-height:1050px; 34 | } 35 | .wrap{ 36 | margin: 0 auto; 37 | width: 80%; 38 | } 39 | body a,form li,input[type="submit"],input[type="text"],.sixth-login input[type="submit"],.third-login input[type="submit"]{ 40 | transition: 0.1s all; 41 | -webkit-transition: 0.1s all; 42 | -moz-transition: 0.1s all; 43 | -o-transition: 0.1s all; 44 | } 45 | /*--close--*/ 46 | .close{ 47 | background: url('../images/close.png') no-repeat 0px 0px; 48 | cursor: pointer; 49 | width: 20px; 50 | height: 20px; 51 | position: absolute; 52 | left: 20px; 53 | top: 20px; 54 | -webkit-transition: color 0.2s ease-in-out; 55 | -moz-transition: color 0.2s ease-in-out; 56 | -o-transition: color 0.2s ease-in-out; 57 | transition: color 0.2s ease-in-out; 58 | } 59 | /*--/close--*/ 60 | h1 { 61 | font-family: 'Exo 2', sans-serif; 62 | text-align: center; 63 | padding-top: 4em; 64 | font-weight: 400; 65 | color: #2B2B36; 66 | font-size: 2em; 67 | } 68 | .login-form { 69 | background: #2b2b36; 70 | position: relative; 71 | width: 30%; 72 | margin: 3% auto 0 auto; 73 | text-align: center; 74 | border-radius: 15px; 75 | -webkit-border-radius: 15px; 76 | -moz-border-radius: 15px; 77 | -o-border-radius: 15px; 78 | } 79 | .head img { 80 | width: 100%; 81 | } 82 | .avtar img { 83 | margin: 2em 0 0; 84 | } 85 | .head-info { 86 | padding: 5px 0; 87 | text-align: center; 88 | font-weight: 600; 89 | font-size: 2em; 90 | color: #fff; 91 | background: #23232e; 92 | height: 50px; 93 | border-top-left-radius: 10px; 94 | -webkit-border-top-left-radius: 10px; 95 | -moz-border-top-left-radius: 10px; 96 | -o-border-top-left-radius: 10px; 97 | border-top-right-radius: 10px; 98 | -webkit-border-top-right-radius: 10px; 99 | -moz-border-top-right-radius: 10px; 100 | -o-border-top-right-radius: 10p 101 | } 102 | input[type="text"] { 103 | width: 70%; 104 | padding: 1em 2em 1em 3em; 105 | color: #9199aa; 106 | font-size: 18px; 107 | outline: none; 108 | background: url(../images/adm.png) no-repeat 10px 15px; 109 | border: none; 110 | font-weight: 100; 111 | border-bottom: 1px solid#484856; 112 | margin-top: 2em; 113 | } 114 | input[type="password"]{ 115 | width: 70%; 116 | padding: 1em 2em 1em 3em; 117 | color: #dd3e3e; 118 | font-size: 18px; 119 | outline: none; 120 | background: url(../images/key.png) no-repeat 10px 23px; 121 | border: none; 122 | font-weight: 100; 123 | border-bottom: 1px solid#484856; 124 | margin-bottom: 3em; 125 | } 126 | .key { 127 | background: url(../images/pass.png) no-repeat 447px 17px; 128 | } 129 | input[type="submit"]{ 130 | font-size: 30px; 131 | color: #fff; 132 | outline: none; 133 | border: none; 134 | background: #3ea751; 135 | width: 100%; 136 | padding: 18px 0; 137 | border-bottom-left-radius: 15px; 138 | -webkit-border-bottom-left-radius: 15px; 139 | -moz-border-bottom-left-radius: 15px; 140 | -o-border-bottom-left-radius: 15px; 141 | border-bottom-right-radius: 15px; 142 | -webkit-border-bottom-right-radius: 15px; 143 | -moz-border-bottom-right-radius: 15px; 144 | -o-border-bottom-right-radius: 15px; 145 | cursor: pointer; 146 | } 147 | input[type="submit"]:hover { 148 | background: #ff2775; 149 | border-bottom-left-radius: 15px; 150 | -webkit-border-bottom-left-radius: 15px; 151 | -moz-border-bottom-left-radius: 15px; 152 | -o-border-bottom-left-radius: 15px; 153 | border-bottom-right-radius: 15px; 154 | -webkit-border-bottom-right-radius: 15px; 155 | -moz-border-bottom-right-radius: 15px; 156 | -o-border-bottom-right-radius: 15px; 157 | transition: 1s all; 158 | -webkit-transition: 1s all; 159 | -moz-transition: 1s all; 160 | -o-transition: 1s all; 161 | } 162 | label.lbl-1 { 163 | background: #6756ea; 164 | width: 20px; 165 | height: 20px; 166 | display: block; 167 | float: right; 168 | border-radius: 50%; 169 | margin: 16px 10px 0px 0px; 170 | } 171 | label.lbl-2 { 172 | background: #ea569a; 173 | width: 20px; 174 | height: 20px; 175 | display: block; 176 | float: right; 177 | border-radius: 50%; 178 | margin: 16px 10px 0px 0px; 179 | } 180 | label.lbl-3 { 181 | background: #f1c85f; 182 | width: 20px; 183 | height: 20px; 184 | display: block; 185 | float: right; 186 | border-radius: 50%; 187 | margin: 16px 10px 0px 0px; 188 | } 189 | /*--copyrights--*/ 190 | .copy-rights{ 191 | text-align: center; 192 | margin-top: 8em; 193 | } 194 | .copy-rights p{ 195 | color:#FFF; 196 | font-size: 1em; 197 | line-height:1.8em; 198 | } 199 | .copy-rights p a{ 200 | color:#ff2a75; 201 | -webkit-transition: all 0.3s ease-out; 202 | -moz-transition: all 0.3s ease-out; 203 | -ms-transition: all 0.3s ease-out; 204 | -o-transition: all 0.3s ease-out; 205 | transition: all 0.3s ease-out; 206 | text-decoration:none; 207 | } 208 | .copy-rights p a:hover{ 209 | color:#3faa53; 210 | text-decoration:none; 211 | transition: 0.1s all; 212 | -webkit-transition: 0.1s all; 213 | -moz-transition: 0.1s all; 214 | -o-transition: 0.1s all; 215 | } 216 | /*--/copyrights--*/ 217 | /*--start-responsive-design--*/ 218 | @media (max-width:1440px){ 219 | .key { 220 | background: url(../images/pass.png) no-repeat 376px 17px; 221 | } 222 | 223 | body { 224 | min-height: 811px; 225 | } 226 | } 227 | @media (max-width:1366px){ 228 | .key { 229 | background: url(../images/pass.png) no-repeat 358px 19px; 230 | } 231 | .copy-rights { 232 | margin-top: 3em; 233 | } 234 | body { 235 | min-height: 768px; 236 | } 237 | } 238 | @media (max-width:1280px){ 239 | .key { 240 | background: url(../images/pass.png) no-repeat 336px 18px; 241 | } 242 | body { 243 | min-height: 711px; 244 | } 245 | .copy-rights { 246 | margin-top: 0.5em; 247 | } 248 | } 249 | @media (max-width:1024px){ 250 | .login-form { 251 | width: 37%; 252 | } 253 | .key { 254 | background: url(../images/pass.png) no-repeat 339px 18px; 255 | } 256 | .copy-rights { 257 | margin-top: 3em; 258 | } 259 | h1 { 260 | padding-top: 2em; 261 | } 262 | body { 263 | min-height: 675px; 264 | } 265 | } 266 | @media (max-width:768px){ 267 | .login-form { 268 | width: 50%; 269 | margin: 12% auto 0 auto; 270 | } 271 | .key { 272 | background: url(../images/pass.png) no-repeat 342px 18px; 273 | } 274 | body { 275 | min-height: 929px; 276 | } 277 | } 278 | @media (max-width:640px){ 279 | .login-form { 280 | width: 60%; 281 | margin: 20% auto 0 auto; 282 | } 283 | .key { 284 | background: url(../images/pass.png) no-repeat 342px 19px; 285 | } 286 | } 287 | @media (max-width:480px){ 288 | .login-form { 289 | width: 80%; 290 | } 291 | } 292 | @media (max-width:320px){ 293 | h1 { 294 | padding-top: 1em; 295 | font-size: 1.5em; 296 | } 297 | .login-form { 298 | width: 90%; 299 | margin: 10% auto 0 auto; 300 | } 301 | input[type="text"] { 302 | width: 62%; 303 | padding: 1.2em 2em .5em 2.5em; 304 | font-size: 17px; 305 | margin-top: .5em; 306 | } 307 | input[type="password"] { 308 | width: 62%; 309 | padding: 1.2em 2em .5em 2.5em; 310 | font-size: 17px; 311 | margin-top: .5em; 312 | margin-bottom: 2em; 313 | background: url(../images/key.png) no-repeat 8px 23px; 314 | } 315 | .key { 316 | background: url(../images/pass.png) no-repeat 235px 27px; 317 | } 318 | .avtar img { 319 | margin: 1.1em 0 0; 320 | } 321 | .head-info { 322 | height: 35px; 323 | } 324 | label.lbl-1 { 325 | margin: 8px 10px 0px 0px; 326 | } 327 | label.lbl-2 { 328 | margin: 8px 10px 0px 0px; 329 | } 330 | label.lbl-3 { 331 | margin: 8px 10px 0px 0px; 332 | } 333 | .close { 334 | left: 16px; 335 | top: 13px; 336 | } 337 | .copy-rights { 338 | margin-top: 2em; 339 | } 340 | body { 341 | min-height: 504px; 342 | } 343 | input[type="submit"] { 344 | font-size: 28px; 345 | padding: 10px 0; 346 | } 347 | } 348 | /*--end-responsive-design--*/ -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/web_analytics/src/main/webapp/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/web_analytics/src/main/webapp/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/web_analytics/src/main/webapp/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/web_analytics/src/main/webapp/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/web_analytics/src/main/webapp/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/web_analytics/src/main/webapp/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/web_analytics/src/main/webapp/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/web_analytics/src/main/webapp/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/web_analytics/src/main/webapp/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/images/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/web_analytics/src/main/webapp/images/Thumbs.db -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/images/adm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/web_analytics/src/main/webapp/images/adm.png -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/images/arrow-left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/web_analytics/src/main/webapp/images/arrow-left.png -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/images/arrow-right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/web_analytics/src/main/webapp/images/arrow-right.png -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/images/avtar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/web_analytics/src/main/webapp/images/avtar.png -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/images/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/web_analytics/src/main/webapp/images/bg.jpg -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/images/bg1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/web_analytics/src/main/webapp/images/bg1.jpg -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/images/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/web_analytics/src/main/webapp/images/close.png -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/images/cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/web_analytics/src/main/webapp/images/cloud.png -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/images/key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/web_analytics/src/main/webapp/images/key.png -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/web_analytics/src/main/webapp/images/logo.png -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/images/pass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/web_analytics/src/main/webapp/images/pass.png -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/index.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 | <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> 3 | <% 4 | request.setCharacterEncoding("UTF-8"); 5 | response.setCharacterEncoding("UTF-8"); 6 | %> 7 | 8 | 9 | 10 | 11 | Welcome 12 | 13 | 15 | 16 | 70 | 71 | 72 |
73 | 77 |

基于hadoop的web日志分析平台

78 |
79 |

web日志 KPI分析结果列表

80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 |
logdatepvreguseripjumper

没有数据

${rs.logdate}${rs.pv}${rs.reguser}${rs.ip}${rs.jumper}
110 |
111 |
112 | 113 | -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/js/custom.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | $('#side-menu').metisMenu(); 4 | 5 | }); 6 | 7 | //Loads the correct sidebar on window load, 8 | //collapses the sidebar on window resize. 9 | // Sets the min-height of #page-wrapper to window size 10 | $(function() { 11 | $(window).bind("load resize", function() { 12 | topOffset = 50; 13 | width = (this.window.innerWidth > 0) ? this.window.innerWidth : this.screen.width; 14 | if (width < 768) { 15 | $('div.navbar-collapse').addClass('collapse'); 16 | topOffset = 100; // 2-row-menu 17 | } else { 18 | $('div.navbar-collapse').removeClass('collapse'); 19 | } 20 | 21 | height = ((this.window.innerHeight > 0) ? this.window.innerHeight : this.screen.height) - 1; 22 | height = height - topOffset; 23 | if (height < 1) height = 1; 24 | if (height > topOffset) { 25 | $("#page-wrapper").css("min-height", (height) + "px"); 26 | } 27 | }); 28 | 29 | var url = window.location; 30 | var element = $('ul.nav a').filter(function() { 31 | return this.href == url || url.href.indexOf(this.href) == 0; 32 | }).addClass('active').parent().parent().addClass('in').parent(); 33 | if (element.is('li')) { 34 | element.addClass('active'); 35 | } 36 | }); 37 | -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/js/jquery.vmap.sampledata.js: -------------------------------------------------------------------------------- 1 | var sample_data = {"af":"16.63","al":"11.58","dz":"158.97","ao":"85.81","ag":"1.1","ar":"351.02","am":"8.83","au":"1219.72","at":"366.26","az":"52.17","bs":"7.54","bh":"21.73","bd":"105.4","bb":"3.96","by":"52.89","be":"461.33","bz":"1.43","bj":"6.49","bt":"1.4","bo":"19.18","ba":"16.2","bw":"12.5","br":"2023.53","bn":"11.96","bg":"44.84","bf":"8.67","bi":"1.47","kh":"11.36","cm":"21.88","ca":"1563.66","cv":"1.57","cf":"2.11","td":"7.59","cl":"199.18","cn":"5745.13","co":"283.11","km":"0.56","cd":"12.6","cg":"11.88","cr":"35.02","ci":"22.38","hr":"59.92","cy":"22.75","cz":"195.23","dk":"304.56","dj":"1.14","dm":"0.38","do":"50.87","ec":"61.49","eg":"216.83","sv":"21.8","gq":"14.55","er":"2.25","ee":"19.22","et":"30.94","fj":"3.15","fi":"231.98","fr":"2555.44","ga":"12.56","gm":"1.04","ge":"11.23","de":"3305.9","gh":"18.06","gr":"305.01","gd":"0.65","gt":"40.77","gn":"4.34","gw":"0.83","gy":"2.2","ht":"6.5","hn":"15.34","hk":"226.49","hu":"132.28","is":"12.77","in":"1430.02","id":"695.06","ir":"337.9","iq":"84.14","ie":"204.14","il":"201.25","it":"2036.69","jm":"13.74","jp":"5390.9","jo":"27.13","kz":"129.76","ke":"32.42","ki":"0.15","kr":"986.26","undefined":"5.73","kw":"117.32","kg":"4.44","la":"6.34","lv":"23.39","lb":"39.15","ls":"1.8","lr":"0.98","ly":"77.91","lt":"35.73","lu":"52.43","mk":"9.58","mg":"8.33","mw":"5.04","my":"218.95","mv":"1.43","ml":"9.08","mt":"7.8","mr":"3.49","mu":"9.43","mx":"1004.04","md":"5.36","mn":"5.81","me":"3.88","ma":"91.7","mz":"10.21","mm":"35.65","na":"11.45","np":"15.11","nl":"770.31","nz":"138","ni":"6.38","ne":"5.6","ng":"206.66","no":"413.51","om":"53.78","pk":"174.79","pa":"27.2","pg":"8.81","py":"17.17","pe":"153.55","ph":"189.06","pl":"438.88","pt":"223.7","qa":"126.52","ro":"158.39","ru":"1476.91","rw":"5.69","ws":"0.55","st":"0.19","sa":"434.44","sn":"12.66","rs":"38.92","sc":"0.92","sl":"1.9","sg":"217.38","sk":"86.26","si":"46.44","sb":"0.67","za":"354.41","es":"1374.78","lk":"48.24","kn":"0.56","lc":"1","vc":"0.58","sd":"65.93","sr":"3.3","sz":"3.17","se":"444.59","ch":"522.44","sy":"59.63","tw":"426.98","tj":"5.58","tz":"22.43","th":"312.61","tl":"0.62","tg":"3.07","to":"0.3","tt":"21.2","tn":"43.86","tr":"729.05","tm":0,"ug":"17.12","ua":"136.56","ae":"239.65","gb":"2258.57","us":"14624.18","uy":"40.71","uz":"37.72","vu":"0.72","ve":"285.21","vn":"101.99","ye":"30.02","zm":"15.69","zw":"5.57"}; -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/js/metisMenu.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * metismenu - v1.1.3 3 | * Easy menu jQuery plugin for Twitter Bootstrap 3 4 | * https://github.com/onokumus/metisMenu 5 | * 6 | * Made by Osman Nuri Okumus 7 | * Under MIT License 8 | */ 9 | !function(a,b,c){function d(b,c){this.element=a(b),this.settings=a.extend({},f,c),this._defaults=f,this._name=e,this.init()}var e="metisMenu",f={toggle:!0,doubleTapToGo:!1};d.prototype={init:function(){var b=this.element,d=this.settings.toggle,f=this;this.isIE()<=9?(b.find("li.active").has("ul").children("ul").collapse("show"),b.find("li").not(".active").has("ul").children("ul").collapse("hide")):(b.find("li.active").has("ul").children("ul").addClass("collapse in"),b.find("li").not(".active").has("ul").children("ul").addClass("collapse")),f.settings.doubleTapToGo&&b.find("li.active").has("ul").children("a").addClass("doubleTapToGo"),b.find("li").has("ul").children("a").on("click."+e,function(b){return b.preventDefault(),f.settings.doubleTapToGo&&f.doubleTapToGo(a(this))&&"#"!==a(this).attr("href")&&""!==a(this).attr("href")?(b.stopPropagation(),void(c.location=a(this).attr("href"))):(a(this).parent("li").toggleClass("active").children("ul").collapse("toggle"),void(d&&a(this).parent("li").siblings().removeClass("active").children("ul.in").collapse("hide")))})},isIE:function(){for(var a,b=3,d=c.createElement("div"),e=d.getElementsByTagName("i");d.innerHTML="",e[0];)return b>4?b:a},doubleTapToGo:function(a){var b=this.element;return a.hasClass("doubleTapToGo")?(a.removeClass("doubleTapToGo"),!0):a.parent().children("ul").length?(b.find(".doubleTapToGo").removeClass("doubleTapToGo"),a.addClass("doubleTapToGo"),!1):void 0},remove:function(){this.element.off("."+e),this.element.removeData(e)}},a.fn[e]=function(b){return this.each(function(){var c=a(this);c.data(e)&&c.data(e).remove(),c.data(e,new d(this,b))}),this}}(jQuery,window,document); -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/js/site.js: -------------------------------------------------------------------------------- 1 | // call this from the developer console and you can control both instances 2 | var calendars = {}; 3 | 4 | $(document).ready( function() { 5 | 6 | // assuming you've got the appropriate language files, 7 | // clndr will respect whatever moment's language is set to. 8 | // moment.lang('ru'); 9 | 10 | // here's some magic to make sure the dates are happening this month. 11 | var thisMonth = moment().format('YYYY-MM'); 12 | 13 | var eventArray = [ 14 | { startDate: thisMonth + '-10', endDate: thisMonth + '-14', title: 'Multi-Day Event' }, 15 | { startDate: thisMonth + '-21', endDate: thisMonth + '-23', title: 'Another Multi-Day Event' } 16 | ]; 17 | 18 | // the order of the click handlers is predictable. 19 | // direct click action callbacks come first: click, nextMonth, previousMonth, nextYear, previousYear, or today. 20 | // then onMonthChange (if the month changed). 21 | // finally onYearChange (if the year changed). 22 | 23 | calendars.clndr1 = $('.cal1').clndr({ 24 | events: eventArray, 25 | // constraints: { 26 | // startDate: '2013-11-01', 27 | // endDate: '2013-11-15' 28 | // }, 29 | clickEvents: { 30 | click: function(target) { 31 | console.log(target); 32 | if($(target.element).hasClass('inactive')) { 33 | console.log('not a valid datepicker date.'); 34 | } else { 35 | console.log('VALID datepicker date.'); 36 | } 37 | }, 38 | nextMonth: function() { 39 | console.log('next month.'); 40 | }, 41 | previousMonth: function() { 42 | console.log('previous month.'); 43 | }, 44 | onMonthChange: function() { 45 | console.log('month changed.'); 46 | }, 47 | nextYear: function() { 48 | console.log('next year.'); 49 | }, 50 | previousYear: function() { 51 | console.log('previous year.'); 52 | }, 53 | onYearChange: function() { 54 | console.log('year changed.'); 55 | } 56 | }, 57 | multiDayEvents: { 58 | startDate: 'startDate', 59 | endDate: 'endDate' 60 | }, 61 | showAdjacentMonths: true, 62 | adjacentDaysChangeMonth: false 63 | }); 64 | 65 | // calendars.clndr2 = $('.cal2').clndr({ 66 | // template: $('#template-calendar').html(), 67 | // events: eventArray, 68 | // startWithMonth: moment().add('month', 1), 69 | // clickEvents: { 70 | // click: function(target) { 71 | // console.log(target); 72 | // } 73 | // } 74 | // }); 75 | 76 | // bind both clndrs to the left and right arrow keys 77 | $(document).keydown( function(e) { 78 | if(e.keyCode == 37) { 79 | // left arrow 80 | calendars.clndr1.back(); 81 | calendars.clndr2.back(); 82 | } 83 | if(e.keyCode == 39) { 84 | // right arrow 85 | calendars.clndr1.forward(); 86 | calendars.clndr2.forward(); 87 | } 88 | }); 89 | 90 | }); -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/js/underscore-min.js: -------------------------------------------------------------------------------- 1 | // Underscore.js 1.5.2 2 | // http://underscorejs.org 3 | // (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors 4 | // Underscore may be freely distributed under the MIT license. 5 | (function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,h=e.reduce,v=e.reduceRight,g=e.filter,d=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,w=Object.keys,_=i.bind,j=function(n){return n instanceof j?n:this instanceof j?(this._wrapped=n,void 0):new j(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=j),exports._=j):n._=j,j.VERSION="1.5.2";var A=j.each=j.forEach=function(n,t,e){if(null!=n)if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a=j.keys(n),u=0,i=a.length;i>u;u++)if(t.call(e,n[a[u]],a[u],n)===r)return};j.map=j.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e.push(t.call(r,n,u,i))}),e)};var E="Reduce of empty array with no initial value";j.reduce=j.foldl=j.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduce===h)return e&&(t=j.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(E);return r},j.reduceRight=j.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduceRight===v)return e&&(t=j.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=j.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(E);return r},j.find=j.detect=function(n,t,r){var e;return O(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},j.filter=j.select=function(n,t,r){var e=[];return null==n?e:g&&n.filter===g?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&e.push(n)}),e)},j.reject=function(n,t,r){return j.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},j.every=j.all=function(n,t,e){t||(t=j.identity);var u=!0;return null==n?u:d&&n.every===d?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var O=j.some=j.any=function(n,t,e){t||(t=j.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};j.contains=j.include=function(n,t){return null==n?!1:y&&n.indexOf===y?n.indexOf(t)!=-1:O(n,function(n){return n===t})},j.invoke=function(n,t){var r=o.call(arguments,2),e=j.isFunction(t);return j.map(n,function(n){return(e?t:n[t]).apply(n,r)})},j.pluck=function(n,t){return j.map(n,function(n){return n[t]})},j.where=function(n,t,r){return j.isEmpty(t)?r?void 0:[]:j[r?"find":"filter"](n,function(n){for(var r in t)if(t[r]!==n[r])return!1;return!0})},j.findWhere=function(n,t){return j.where(n,t,!0)},j.max=function(n,t,r){if(!t&&j.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.max.apply(Math,n);if(!t&&j.isEmpty(n))return-1/0;var e={computed:-1/0,value:-1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a>e.computed&&(e={value:n,computed:a})}),e.value},j.min=function(n,t,r){if(!t&&j.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.min.apply(Math,n);if(!t&&j.isEmpty(n))return 1/0;var e={computed:1/0,value:1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;ae||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index-t.index}),"value")};var F=function(n){return function(t,r,e){var u={},i=null==r?j.identity:k(r);return A(t,function(r,a){var o=i.call(e,r,a,t);n(u,o,r)}),u}};j.groupBy=F(function(n,t,r){(j.has(n,t)?n[t]:n[t]=[]).push(r)}),j.indexBy=F(function(n,t,r){n[t]=r}),j.countBy=F(function(n,t){j.has(n,t)?n[t]++:n[t]=1}),j.sortedIndex=function(n,t,r,e){r=null==r?j.identity:k(r);for(var u=r.call(e,t),i=0,a=n.length;a>i;){var o=i+a>>>1;r.call(e,n[o])=0})})},j.difference=function(n){var t=c.apply(e,o.call(arguments,1));return j.filter(n,function(n){return!j.contains(t,n)})},j.zip=function(){for(var n=j.max(j.pluck(arguments,"length").concat(0)),t=new Array(n),r=0;n>r;r++)t[r]=j.pluck(arguments,""+r);return t},j.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},j.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=j.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},j.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},j.range=function(n,t,r){arguments.length<=1&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=new Array(e);e>u;)i[u++]=n,n+=r;return i};var R=function(){};j.bind=function(n,t){var r,e;if(_&&n.bind===_)return _.apply(n,o.call(arguments,1));if(!j.isFunction(n))throw new TypeError;return r=o.call(arguments,2),e=function(){if(!(this instanceof e))return n.apply(t,r.concat(o.call(arguments)));R.prototype=n.prototype;var u=new R;R.prototype=null;var i=n.apply(u,r.concat(o.call(arguments)));return Object(i)===i?i:u}},j.partial=function(n){var t=o.call(arguments,1);return function(){return n.apply(this,t.concat(o.call(arguments)))}},j.bindAll=function(n){var t=o.call(arguments,1);if(0===t.length)throw new Error("bindAll must be passed function names");return A(t,function(t){n[t]=j.bind(n[t],n)}),n},j.memoize=function(n,t){var r={};return t||(t=j.identity),function(){var e=t.apply(this,arguments);return j.has(r,e)?r[e]:r[e]=n.apply(this,arguments)}},j.delay=function(n,t){var r=o.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},j.defer=function(n){return j.delay.apply(j,[n,1].concat(o.call(arguments,1)))},j.throttle=function(n,t,r){var e,u,i,a=null,o=0;r||(r={});var c=function(){o=r.leading===!1?0:new Date,a=null,i=n.apply(e,u)};return function(){var l=new Date;o||r.leading!==!1||(o=l);var f=t-(l-o);return e=this,u=arguments,0>=f?(clearTimeout(a),a=null,o=l,i=n.apply(e,u)):a||r.trailing===!1||(a=setTimeout(c,f)),i}},j.debounce=function(n,t,r){var e,u,i,a,o;return function(){i=this,u=arguments,a=new Date;var c=function(){var l=new Date-a;t>l?e=setTimeout(c,t-l):(e=null,r||(o=n.apply(i,u)))},l=r&&!e;return e||(e=setTimeout(c,t)),l&&(o=n.apply(i,u)),o}},j.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},j.wrap=function(n,t){return function(){var r=[n];return a.apply(r,arguments),t.apply(this,r)}},j.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},j.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},j.keys=w||function(n){if(n!==Object(n))throw new TypeError("Invalid object");var t=[];for(var r in n)j.has(n,r)&&t.push(r);return t},j.values=function(n){for(var t=j.keys(n),r=t.length,e=new Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},j.pairs=function(n){for(var t=j.keys(n),r=t.length,e=new Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},j.invert=function(n){for(var t={},r=j.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},j.functions=j.methods=function(n){var t=[];for(var r in n)j.isFunction(n[r])&&t.push(r);return t.sort()},j.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},j.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},j.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)j.contains(r,u)||(t[u]=n[u]);return t},j.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]===void 0&&(n[r]=t[r])}),n},j.clone=function(n){return j.isObject(n)?j.isArray(n)?n.slice():j.extend({},n):n},j.tap=function(n,t){return t(n),n};var S=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof j&&(n=n._wrapped),t instanceof j&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==String(t);case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;var a=n.constructor,o=t.constructor;if(a!==o&&!(j.isFunction(a)&&a instanceof a&&j.isFunction(o)&&o instanceof o))return!1;r.push(n),e.push(t);var c=0,f=!0;if("[object Array]"==u){if(c=n.length,f=c==t.length)for(;c--&&(f=S(n[c],t[c],r,e)););}else{for(var s in n)if(j.has(n,s)&&(c++,!(f=j.has(t,s)&&S(n[s],t[s],r,e))))break;if(f){for(s in t)if(j.has(t,s)&&!c--)break;f=!c}}return r.pop(),e.pop(),f};j.isEqual=function(n,t){return S(n,t,[],[])},j.isEmpty=function(n){if(null==n)return!0;if(j.isArray(n)||j.isString(n))return 0===n.length;for(var t in n)if(j.has(n,t))return!1;return!0},j.isElement=function(n){return!(!n||1!==n.nodeType)},j.isArray=x||function(n){return"[object Array]"==l.call(n)},j.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){j["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),j.isArguments(arguments)||(j.isArguments=function(n){return!(!n||!j.has(n,"callee"))}),"function"!=typeof/./&&(j.isFunction=function(n){return"function"==typeof n}),j.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},j.isNaN=function(n){return j.isNumber(n)&&n!=+n},j.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},j.isNull=function(n){return null===n},j.isUndefined=function(n){return n===void 0},j.has=function(n,t){return f.call(n,t)},j.noConflict=function(){return n._=t,this},j.identity=function(n){return n},j.times=function(n,t,r){for(var e=Array(Math.max(0,n)),u=0;n>u;u++)e[u]=t.call(r,u);return e},j.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))};var I={escape:{"&":"&","<":"<",">":">",'"':""","'":"'"}};I.unescape=j.invert(I.escape);var T={escape:new RegExp("["+j.keys(I.escape).join("")+"]","g"),unescape:new RegExp("("+j.keys(I.unescape).join("|")+")","g")};j.each(["escape","unescape"],function(n){j[n]=function(t){return null==t?"":(""+t).replace(T[n],function(t){return I[n][t]})}}),j.result=function(n,t){if(null==n)return void 0;var r=n[t];return j.isFunction(r)?r.call(n):r},j.mixin=function(n){A(j.functions(n),function(t){var r=j[t]=n[t];j.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),z.call(this,r.apply(j,n))}})};var N=0;j.uniqueId=function(n){var t=++N+"";return n?n+t:t},j.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var q=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},D=/\\|'|\r|\n|\t|\u2028|\u2029/g;j.template=function(n,t,r){var e;r=j.defaults({},r,j.templateSettings);var u=new RegExp([(r.escape||q).source,(r.interpolate||q).source,(r.evaluate||q).source].join("|")+"|$","g"),i=0,a="__p+='";n.replace(u,function(t,r,e,u,o){return a+=n.slice(i,o).replace(D,function(n){return"\\"+B[n]}),r&&(a+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(a+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),u&&(a+="';\n"+u+"\n__p+='"),i=o+t.length,t}),a+="';\n",r.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{e=new Function(r.variable||"obj","_",a)}catch(o){throw o.source=a,o}if(t)return e(t,j);var c=function(n){return e.call(this,n,j)};return c.source="function("+(r.variable||"obj")+"){\n"+a+"}",c},j.chain=function(n){return j(n).chain()};var z=function(n){return this._chain?j(n).chain():n};j.mixin(j),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];j.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],z.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];j.prototype[n]=function(){return z.call(this,t.apply(this._wrapped,arguments))}}),j.extend(j.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this); 6 | //# sourceMappingURL=underscore-min.map -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/login.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2 | <% 3 | request.setCharacterEncoding("UTF-8"); 4 | response.setCharacterEncoding("UTF-8"); 5 | %> 6 | 7 | 8 | 9 | 10 | Login 11 | 12 | 15 | 16 | 18 | 19 | 20 | 23 | 25 | 26 | 28 | 29 | 30 | 39 | 40 |

基于hadoop的web日志分析平台

41 | 66 | 67 |
68 |

Copyright © 2016.zhang wei All rights reserved

69 |
70 | 71 | 72 | -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/tablecloth/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Welcome to Tablecloth 6 | 7 | 8 | 9 | 10 | 11 | 12 | 57 | 58 | 59 | 60 | 61 | 62 |
63 |

Tablecloth: Example

64 | 65 |
66 | 67 | 68 | 69 | 70 |

Table with top headings

71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 |
TitleTitleTitleTitle
DataDataDataData
DataDataDataData
DataDataDataData
DataDataDataData
104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 |
TitleTitleTitleTitleTitleTitleTitleTitleTitleTitleTitleTitle
DataDataDataDataDataDataDataDataDataDataDataData
DataDataDataDataDataDataDataDataDataDataDataData
DataDataDataDataDataDataDataDataDataDataDataData
DataDataDataDataDataDataDataDataDataDataDataData
DataDataDataDataDataDataDataDataDataDataDataData
DataDataDataDataDataDataDataDataDataDataDataData
DataDataDataDataDataDataDataDataDataDataDataData
219 | 220 |

Table with side headings

221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 |
TitleDataDataData
TitleDataDataData
TitleDataDataData
TitleDataDataData
TitleDataDataData
254 | 255 |

Table with top and side headings

256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 |
 TitleTitleTitle
TitleDataDataData
TitleDataDataData
TitleDataDataData
TitleDataDataData
TitleDataDataData
295 | 296 | 297 |
298 |
299 |

Tablecloth is brought to you by Css Globe

300 | 301 | 302 | 303 | 304 | -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/tablecloth/tablecloth/_notes/dwsync.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/tablecloth/tablecloth/tablecloth.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | TableCloth 4 | by Alen Grakalic, brought to you by cssglobe.com 5 | 6 | */ 7 | 8 | /* general styles */ 9 | 10 | table, td{ 11 | font:100% Arial, Helvetica, sans-serif; 12 | } 13 | table{width:100%;border-collapse:collapse;margin:1em 0;} 14 | th, td{text-align:left;padding:.5em;border:1px solid #fff;} 15 | th{background:#328aa4 url(tr_back.gif) repeat-x;color:#fff;} 16 | td{background:#e5f1f4;} 17 | 18 | /* tablecloth styles */ 19 | 20 | tr.even td{background:#e5f1f4;} 21 | tr.odd td{background:#f8fbfc;} 22 | 23 | th.over, tr.even th.over, tr.odd th.over{background:#4a98af;} 24 | th.down, tr.even th.down, tr.odd th.down{background:#bce774;} 25 | th.selected, tr.even th.selected, tr.odd th.selected{} 26 | 27 | td.over, tr.even td.over, tr.odd td.over{background:#ecfbd4;} 28 | td.down, tr.even td.down, tr.odd td.down{background:#bce774;color:#fff;} 29 | td.selected, tr.even td.selected, tr.odd td.selected{background:#bce774;color:#555;} 30 | 31 | /* use this if you want to apply different styleing to empty table cells*/ 32 | td.empty, tr.odd td.empty, tr.even td.empty{background:#fff;} -------------------------------------------------------------------------------- /web_analytics/src/main/webapp/tablecloth/tablecloth/tablecloth.js: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Tablecloth 4 | written by Alen Grakalic, provided by Css Globe (cssglobe.com) 5 | please visit http://cssglobe.com/lab/tablecloth/ 6 | 7 | */ 8 | 9 | this.tablecloth = function(){ 10 | 11 | // CONFIG 12 | 13 | // if set to true then mouseover a table cell will highlight entire column (except sibling headings) 14 | var highlightCols = true; 15 | 16 | // if set to true then mouseover a table cell will highlight entire row (except sibling headings) 17 | var highlightRows = false; 18 | 19 | // if set to true then click on a table sell will select row or column based on config 20 | var selectable = true; 21 | 22 | // this function is called when 23 | // add your own code if you want to add action 24 | // function receives object that has been clicked 25 | this.clickAction = function(obj){ 26 | //alert(obj.innerHTML); 27 | 28 | }; 29 | 30 | 31 | 32 | // END CONFIG (do not edit below this line) 33 | 34 | 35 | var tableover = false; 36 | this.start = function(){ 37 | var tables = document.getElementsByTagName("table"); 38 | for (var i=0;i 2 | 5 | 9 | 10 | 11 | 12 | 13 | index.jsp 14 | login.jsp 15 | change_pwd_success.jsp 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /web_analytics/target/classes/log4j.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Log4J Settings for log4j 1.2.x (via jakarta-commons-logging) 3 | # 4 | # The five logging levels used by Log are (in order): 5 | # 6 | # 1. DEBUG (the least serious) 7 | # 2. INFO 8 | # 3. WARN 9 | # 4. ERROR 10 | # 5. FATAL (the most serious) 11 | 12 | 13 | # Set root logger level to WARN and append to stdout 14 | log4j.rootLogger=INFO, stdout 15 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 16 | log4j.appender.stdout.Target=System.out 17 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 18 | 19 | # Pattern to output the caller's file name and line number. 20 | log4j.appender.stdout.layout.ConversionPattern=%d %5p (%c:%L) - %m%n 21 | 22 | # Print only messages of level ERROR or above in the package noModule. 23 | log4j.logger.noModule=FATAL 24 | 25 | log4j.logger.com.opensymphony.xwork2=DEBUG 26 | log4j.logger.org.apache.struts2=DEBUG 27 | -------------------------------------------------------------------------------- /web_analytics/target/classes/messageResource_zh_CN.properties: -------------------------------------------------------------------------------- 1 | struts.messages.error.content.type.not.allowed=/u4E0A/u4F20/u7C7B/u578B/u9519/u8BEF 2 | struts.messages.error.file.too.large=/u4E0A/u4F20/u6587/u4EF6/u592A/u5927 -------------------------------------------------------------------------------- /web_analytics/target/classes/struts.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | /error.jsp 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /web_analytics/target/m2e-wtp/web-resources/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Build-Jdk: 1.7.0_79 3 | Built-By: wei 4 | Created-By: Maven Integration for Eclipse 5 | 6 | -------------------------------------------------------------------------------- /web_analytics/target/m2e-wtp/web-resources/META-INF/maven/om.weblog.zw/web_analytics/pom.properties: -------------------------------------------------------------------------------- 1 | #Generated by Maven Integration for Eclipse 2 | #Wed May 04 10:25:10 CST 2016 3 | version=0.0.1-SNAPSHOT 4 | groupId=om.weblog.zw 5 | m2e.projectName=web_analytics 6 | m2e.projectLocation=D\:\\java_workspace\\web_analytics 7 | artifactId=web_analytics 8 | -------------------------------------------------------------------------------- /web_analytics/target/m2e-wtp/web-resources/META-INF/maven/om.weblog.zw/web_analytics/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | om.weblog.zw 5 | web_analytics 6 | war 7 | 0.0.1-SNAPSHOT 8 | web_analytics Maven Webapp 9 | http://maven.apache.org 10 | 11 | 12 | 13 | 14 | 5.3.1 15 | 16 | 3.2.4 17 | 18 | 1.6.6 19 | 1.2.9 20 | 21 | 22 | 23 | 24 | 25 | 26 | org.springframework 27 | spring-core 28 | ${spring.version} 29 | 30 | 31 | 32 | org.springframework 33 | spring-web 34 | ${spring.version} 35 | 36 | 37 | 38 | org.springframework 39 | spring-oxm 40 | ${spring.version} 41 | 42 | 43 | 44 | org.springframework 45 | spring-tx 46 | ${spring.version} 47 | 48 | 49 | 50 | org.springframework 51 | spring-jdbc 52 | ${spring.version} 53 | 54 | 55 | 56 | org.springframework 57 | spring-webmvc 58 | ${spring.version} 59 | 60 | 61 | 62 | org.springframework 63 | spring-aop 64 | ${spring.version} 65 | 66 | 67 | 68 | org.springframework 69 | spring-context-support 70 | ${spring.version} 71 | 72 | 73 | 74 | org.springframework 75 | spring-aop 76 | ${spring.version} 77 | 78 | 79 | 80 | org.springframework 81 | spring-test 82 | ${spring.version} 83 | 84 | 85 | 86 | 87 | 88 | org.mybatis 89 | mybatis 90 | ${mybatis.version} 91 | 92 | 93 | 94 | org.mybatis 95 | mybatis-spring 96 | 1.2.2 97 | 98 | 99 | 100 | mysql 101 | mysql-connector-java 102 | 8.0.16 103 | 104 | 105 | 106 | junit 107 | junit 108 | 4.13.1 109 | test 110 | 111 | 112 | 113 | com.alibaba 114 | druid 115 | 1.0.2 116 | 117 | 118 | 119 | 120 | org.codehaus.jackson 121 | jackson-mapper-asl 122 | 1.9.13 123 | 124 | 125 | 126 | 127 | 128 | log4j 129 | log4j 130 | ${log4j.version} 131 | 132 | 133 | org.slf4j 134 | slf4j-api 135 | ${slf4j.version} 136 | 137 | 138 | org.slf4j 139 | slf4j-log4j12 140 | ${slf4j.version} 141 | 142 | 143 | 144 | org.apache.struts 145 | struts2-core 146 | 2.3.34 147 | 148 | 149 | jstl 150 | jstl 151 | 1.2 152 | 153 | 154 | javax.servlet 155 | javax.servlet-api 156 | 3.0.1 157 | 158 | 159 | 160 | 161 | 162 | web_analytics 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /weblog/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /weblog/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | weblog 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /weblog/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/main/java=UTF-8 3 | encoding//src/test/java=UTF-8 4 | encoding/=UTF-8 5 | -------------------------------------------------------------------------------- /weblog/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 3 | org.eclipse.jdt.core.compiler.compliance=1.5 4 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 5 | org.eclipse.jdt.core.compiler.source=1.5 6 | -------------------------------------------------------------------------------- /weblog/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /weblog/cleaned.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/weblog/cleaned.jar -------------------------------------------------------------------------------- /weblog/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com 6 | weblog 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | weblog 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 16 | 17 | 18 | 19 | junit 20 | junit 21 | 3.8.1 22 | test 23 | 24 | 25 | org.apache.hadoop 26 | hadoop-client 27 | 1.1.2 28 | 29 | 30 | commons-httpclient 31 | commons-httpclient 32 | 3.1 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /weblog/src/main/java/com/weblog/mr/LogCleaner.java: -------------------------------------------------------------------------------- 1 | package com.weblog.mr; 2 | 3 | import java.io.IOException; 4 | import org.apache.hadoop.conf.Configuration; 5 | import org.apache.hadoop.fs.Path; 6 | import org.apache.hadoop.io.LongWritable; 7 | import org.apache.hadoop.io.NullWritable; 8 | import org.apache.hadoop.io.Text; 9 | import org.apache.hadoop.mapreduce.Job; 10 | import org.apache.hadoop.mapreduce.Mapper; 11 | import org.apache.hadoop.mapreduce.Reducer; 12 | import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; 13 | import org.apache.hadoop.mapreduce.lib.input.TextInputFormat; 14 | import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; 15 | import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat; 16 | import com.weblog.parser.LogParser; 17 | 18 | /** 19 | * mr数据清洗 20 | * 21 | * @author zhangwei 22 | * */ 23 | public class LogCleaner {// extends Configured implements Tool 24 | 25 | static final String INPUT_PATH = "hdfs://hadoop:9000/weblog/"; 26 | static final String OUT_PATH = "hdfs://hadoop:9000/weblog_cleaned"; 27 | 28 | //驱动 29 | public static void main(String[] args) throws Exception { 30 | 31 | final Job job = new Job(new Configuration(), 32 | LogCleaner.class.getSimpleName()); 33 | 34 | // 打包 35 | // job.setJarByClass(LogCleaner.class); 36 | 37 | // 1.1输入目录在哪里 38 | FileInputFormat.setInputPaths(job, INPUT_PATH);// args[0] 39 | // 指定对输入数据进行格式化处理的类 40 | job.setInputFormatClass(TextInputFormat.class); 41 | // 1.2指定自定义的Mapper类 42 | job.setMapperClass(MyMapper.class); 43 | // 指定map输出的类型 44 | job.setMapOutputKeyClass(LongWritable.class); 45 | job.setMapOutputValueClass(Text.class); 46 | // 1.3分区 47 | // job.setPartitionerClass(HashPartitioner.class); 48 | 49 | // job.setNumReduceTasks(1); 50 | // 1.4 TODO 排序 、分组 51 | // 1.5 TODO 规约 (可选) 52 | // 2.2指定自定义的Reducer 类 53 | job.setReducerClass(MyReducer.class); 54 | job.setOutputKeyClass(Text.class); 55 | job.setOutputValueClass(NullWritable.class); 56 | // 2.3指定输出的路径 57 | FileOutputFormat.setOutputPath(job, new Path(OUT_PATH));// new 58 | // Path(args[1]) 59 | // 指定输出的格式化类 60 | job.setOutputFormatClass(TextOutputFormat.class); 61 | 62 | // 把作业提交给JobTracker运行 63 | job.waitForCompletion(true); 64 | } 65 | 66 | 67 | static class MyMapper extends 68 | Mapper { 69 | 70 | LogParser logparser = new LogParser(); 71 | Text v2 = new Text(); 72 | 73 | @Override 74 | protected void map(LongWritable key, Text value, 75 | Mapper.Context context) 76 | throws IOException, InterruptedException { 77 | final String[] parsed = logparser.parse(value.toString()); 78 | 79 | // 过滤静态信息 80 | if (parsed[2].startsWith("GET /static/") 81 | || parsed[2].startsWith("GET /uc_server/")) { 82 | return; 83 | } 84 | 85 | // 过滤掉开头的特定格式的字符串 86 | if (parsed[2].startsWith("GET /")) { 87 | parsed[2] = parsed[2].substring("GET /".length()); 88 | } else if (parsed[2].startsWith("POST /")) { 89 | parsed[2] = parsed[2].substring("POST /".length()); 90 | } 91 | 92 | // 过滤掉结尾的特定格式的字符串 93 | if (parsed[2].endsWith("HTTP/1.1")) { 94 | parsed[2] = parsed[2].substring(0, parsed[2].length() 95 | - "HTTP/1.1".length()); 96 | } 97 | // substring(int beginIndex) substring(int beginIndex, int endIndex) 98 | 99 | v2.set(parsed[0] + "\t" + parsed[1] + "\t" + parsed[2]); 100 | context.write(key, v2); 101 | } 102 | } 103 | 104 | static class MyReducer extends 105 | Reducer { 106 | @Override 107 | protected void reduce(LongWritable k2, Iterable v2s, 108 | Reducer.Context context) 109 | throws IOException, InterruptedException { 110 | for (Text v2 : v2s) { 111 | context.write(v2, NullWritable.get()); 112 | } 113 | 114 | } 115 | } 116 | 117 | } 118 | -------------------------------------------------------------------------------- /weblog/src/main/java/com/weblog/parser/LogParser.java: -------------------------------------------------------------------------------- 1 | package com.weblog.parser; 2 | 3 | import java.text.ParseException; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Date; 6 | import java.util.Locale; 7 | /** 8 | * 解析器 9 | * 10 | * 对原始数据进行解析 11 | * @author zhang wei 12 | * 13 | * */ 14 | 15 | public class LogParser { 16 | 17 | public static final SimpleDateFormat FORMAT = new SimpleDateFormat( 18 | "d/MMM/yyyy:HH:mm:ss", Locale.ENGLISH); 19 | public static final SimpleDateFormat dateformat1 = new SimpleDateFormat( 20 | "yyyyMMddHHmmss"); 21 | 22 | /** 23 | * 解析英文时间字符串 24 | * 25 | * @param string 26 | * @return 27 | * @throws ParseException 28 | */ 29 | private Date parseDateFormat(String string) { 30 | Date parse = null; 31 | try { 32 | parse = FORMAT.parse(string); 33 | } catch (ParseException e) { 34 | e.printStackTrace(); 35 | } 36 | return parse; 37 | } 38 | 39 | /** 40 | * 解析日志的行记录 41 | * 42 | * @param line 43 | * @return 数组含有5个元素,分别是ip、时间、url、状态、流量 44 | */ 45 | public String[] parse(String line) { 46 | String ip = parseIP(line); 47 | String time = parseTime(line); 48 | String url = parseURL(line); 49 | String status = parseStatus(line); 50 | String traffic = parseTraffic(line); 51 | 52 | return new String[] { ip, time, url, status, traffic }; 53 | } 54 | 55 | private String parseTraffic(String line) { 56 | final String trim = line.substring(line.lastIndexOf("\"") + 1) 57 | .trim(); 58 | String traffic = trim.split(" ")[1]; 59 | return traffic; 60 | } 61 | 62 | private String parseStatus(String line) { 63 | final String trim = line.substring(line.lastIndexOf("\"") + 1) 64 | .trim(); 65 | String status = trim.split(" ")[0]; 66 | return status; 67 | } 68 | 69 | private String parseURL(String line) { 70 | final int first = line.indexOf("\""); 71 | final int last = line.lastIndexOf("\""); 72 | String url = line.substring(first + 1, last); 73 | return url; 74 | } 75 | 76 | private String parseTime(String line) { 77 | final int first = line.indexOf("["); 78 | final int last = line.indexOf("+0800]"); 79 | String time = line.substring(first + 1, last).trim(); 80 | Date date = parseDateFormat(time); 81 | return dateformat1.format(date); 82 | } 83 | 84 | private String parseIP(String line) { 85 | String ip = line.split("- -")[0].trim(); 86 | return ip; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /weblog/src/main/java/com/weblog/shell/weblog_common.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #get yesterday format string 4 | #yesterday=`date --date='1 days ago' +%Y_%m_%d` 5 | yesterday=$1 6 | 7 | #upload logs to hdfs 8 | hadoop fs -put access_${yesterday}.log /weblog 9 | 10 | #cleaning data 11 | hadoop jar cleaned.jar /weblog/access_${yesterday}.log /weblog_cleaned/${yesterday} 1>/dev/null 12 | 13 | 14 | #alter hive table and then add partition to existed table 15 | hive -e "ALTER TABLE weblog ADD PARTITION(logdate='${yesterday}') LOCATION '/weblog_cleaned/${yesterday}';" 16 | 17 | #create hive table everyday 18 | hive -e "CREATE TABLE weblog_pv_${yesterday} AS SELECT COUNT(1) AS PV FROM weblog WHERE logdate='${yesterday}';" 19 | hive -e "CREATE TABLE weblog_reguser_${yesterday} AS SELECT COUNT(1) AS REGUSER FROM weblog WHERE logdate='${yesterday}' AND INSTR(url,'member.php?mod=register')>0;" 20 | hive -e "CREATE TABLE weblog_ip_${yesterday} AS SELECT COUNT(DISTINCT ip) AS IP FROM weblog WHERE logdate='${yesterday}';" 21 | hive -e "CREATE TABLE weblog_jumper_${yesterday} AS SELECT COUNT(1) AS jumper FROM (SELECT COUNT(ip) AS times FROM weblog WHERE logdate='${yesterday}' GROUP BY ip HAVING times=1) e;" 22 | hive -e "CREATE TABLE weblog_${yesterday} AS SELECT '${yesterday}', a.pv, b.reguser, c.ip, d.jumper FROM weblog_pv_${yesterday} a JOIN weblog_reguser_${yesterday} b ON 1=1 JOIN weblog_ip_${yesterday} c ON 1=1 JOIN weblog_jumper_${yesterday} d ON 1=1;" 23 | 24 | #delete hive tables 25 | hive -e "drop table weblog_pv_${yesterday};" 26 | hive -e "drop table weblog_reguser_${yesterday};" 27 | hive -e "drop table weblog_ip_${yesterday};" 28 | hive -e "drop table weblog_jumper_${yesterday};" 29 | 30 | #sqoop export to mysql 31 | sqoop export --connect jdbc:mysql://hadoop:3306/weblog --username root --password admin --table weblog_logs_stat --fields-terminated-by '\001' --export-dir '/hive/weblog_${yesterday}' 32 | 33 | #delete hive tables 34 | hive -e "drop table weblog_${yesterday};" 35 | -------------------------------------------------------------------------------- /weblog/src/main/java/com/weblog/shell/weblog_daily.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | yesterday=`date --date='1 days ago' +%Y_%m_%d` 4 | weblog_common.sh $yesterday 5 | -------------------------------------------------------------------------------- /weblog/src/main/java/com/weblog/shell/weblog_init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #hive -e "CREATE EXTERNAL TABLE weblog(ip string, atime string, url string) PARTITIONED BY (logdate string) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LOCATION '/weblog_cleaned';" 4 | 5 | s1=`date --date="$1" +%s` 6 | s2=`date +%s` 7 | s3=$((($s2-$s1)/3600/24)) 8 | 9 | 10 | for ((i=$s3; i>0; i--)) 11 | do 12 | tmp=`date --date="$i days ago" +%Y_%m_%d` 13 | weblog_common.sh $tmp 14 | done 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /weblog/src/main/java/org/apache/hadoop/fs/FileUtil.java: -------------------------------------------------------------------------------- 1 | package org.apache.hadoop.fs; 2 | /** 3 | * Licensed to the Apache Software Foundation (ASF) under one 4 | * or more contributor license agreements. See the NOTICE file 5 | * distributed with this work for additional information 6 | * regarding copyright ownership. The ASF licenses this file 7 | * to you under the Apache License, Version 2.0 (the 8 | * "License"); you may not use this file except in compliance 9 | * with the License. You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | */ 19 | 20 | 21 | import java.io.*; 22 | import java.util.Enumeration; 23 | import java.util.zip.ZipEntry; 24 | import java.util.zip.ZipFile; 25 | import org.apache.commons.logging.Log; 26 | import org.apache.commons.logging.LogFactory; 27 | import org.apache.hadoop.conf.Configuration; 28 | import org.apache.hadoop.fs.permission.FsAction; 29 | import org.apache.hadoop.fs.permission.FsPermission; 30 | import org.apache.hadoop.io.IOUtils; 31 | import org.apache.hadoop.io.nativeio.NativeIO; 32 | import org.apache.hadoop.util.StringUtils; 33 | import org.apache.hadoop.util.Shell; 34 | import org.apache.hadoop.util.Shell.ShellCommandExecutor; 35 | 36 | /** 37 | * A collection of file-processing util methods 38 | */ 39 | public class FileUtil { 40 | private static final Log LOG = LogFactory.getLog(FileUtil.class); 41 | 42 | /** 43 | * convert an array of FileStatus to an array of Path 44 | * 45 | * @param stats 46 | * an array of FileStatus objects 47 | * @return an array of paths corresponding to the input 48 | */ 49 | public static Path[] stat2Paths(FileStatus[] stats) { 50 | if (stats == null) 51 | return null; 52 | Path[] ret = new Path[stats.length]; 53 | for (int i = 0; i < stats.length; ++i) { 54 | ret[i] = stats[i].getPath(); 55 | } 56 | return ret; 57 | } 58 | 59 | /** 60 | * convert an array of FileStatus to an array of Path. 61 | * If stats if null, return path 62 | * @param stats 63 | * an array of FileStatus objects 64 | * @param path 65 | * default path to return in stats is null 66 | * @return an array of paths corresponding to the input 67 | */ 68 | public static Path[] stat2Paths(FileStatus[] stats, Path path) { 69 | if (stats == null) 70 | return new Path[]{path}; 71 | else 72 | return stat2Paths(stats); 73 | } 74 | 75 | /** 76 | * Delete a directory and all its contents. If 77 | * we return false, the directory may be partially-deleted. 78 | */ 79 | public static boolean fullyDelete(File dir) throws IOException { 80 | if (!fullyDeleteContents(dir)) { 81 | return false; 82 | } 83 | return dir.delete(); 84 | } 85 | 86 | /** 87 | * Delete the contents of a directory, not the directory itself. If 88 | * we return false, the directory may be partially-deleted. 89 | */ 90 | public static boolean fullyDeleteContents(File dir) throws IOException { 91 | boolean deletionSucceeded = true; 92 | File contents[] = dir.listFiles(); 93 | if (contents != null) { 94 | for (int i = 0; i < contents.length; i++) { 95 | if (contents[i].isFile()) { 96 | if (!contents[i].delete()) { 97 | deletionSucceeded = false; 98 | continue; // continue deletion of other files/dirs under dir 99 | } 100 | } else { 101 | //try deleting the directory 102 | // this might be a symlink 103 | boolean b = false; 104 | b = contents[i].delete(); 105 | if (b){ 106 | //this was indeed a symlink or an empty directory 107 | continue; 108 | } 109 | // if not an empty directory or symlink let 110 | // fullydelete handle it. 111 | if (!fullyDelete(contents[i])) { 112 | deletionSucceeded = false; 113 | continue; // continue deletion of other files/dirs under dir 114 | } 115 | } 116 | } 117 | } 118 | return deletionSucceeded; 119 | } 120 | 121 | /** 122 | * Recursively delete a directory. 123 | * 124 | * @param fs {@link FileSystem} on which the path is present 125 | * @param dir directory to recursively delete 126 | * @throws IOException 127 | * @deprecated Use {@link FileSystem#delete(Path, boolean)} 128 | */ 129 | @Deprecated 130 | public static void fullyDelete(FileSystem fs, Path dir) 131 | throws IOException { 132 | fs.delete(dir, true); 133 | } 134 | 135 | // 136 | // If the destination is a subdirectory of the source, then 137 | // generate exception 138 | // 139 | private static void checkDependencies(FileSystem srcFS, 140 | Path src, 141 | FileSystem dstFS, 142 | Path dst) 143 | throws IOException { 144 | if (srcFS == dstFS) { 145 | String srcq = src.makeQualified(srcFS).toString() + Path.SEPARATOR; 146 | String dstq = dst.makeQualified(dstFS).toString() + Path.SEPARATOR; 147 | if (dstq.startsWith(srcq)) { 148 | if (srcq.length() == dstq.length()) { 149 | throw new IOException("Cannot copy " + src + " to itself."); 150 | } else { 151 | throw new IOException("Cannot copy " + src + " to its subdirectory " + 152 | dst); 153 | } 154 | } 155 | } 156 | } 157 | 158 | /** Copy files between FileSystems. */ 159 | public static boolean copy(FileSystem srcFS, Path src, 160 | FileSystem dstFS, Path dst, 161 | boolean deleteSource, 162 | Configuration conf) throws IOException { 163 | return copy(srcFS, src, dstFS, dst, deleteSource, true, conf); 164 | } 165 | 166 | public static boolean copy(FileSystem srcFS, Path[] srcs, 167 | FileSystem dstFS, Path dst, 168 | boolean deleteSource, 169 | boolean overwrite, Configuration conf) 170 | throws IOException { 171 | boolean gotException = false; 172 | boolean returnVal = true; 173 | StringBuffer exceptions = new StringBuffer(); 174 | 175 | if (srcs.length == 1) 176 | return copy(srcFS, srcs[0], dstFS, dst, deleteSource, overwrite, conf); 177 | 178 | // Check if dest is directory 179 | if (!dstFS.exists(dst)) { 180 | throw new IOException("`" + dst +"': specified destination directory " + 181 | "doest not exist"); 182 | } else { 183 | FileStatus sdst = dstFS.getFileStatus(dst); 184 | if (!sdst.isDir()) 185 | throw new IOException("copying multiple files, but last argument `" + 186 | dst + "' is not a directory"); 187 | } 188 | 189 | for (Path src : srcs) { 190 | try { 191 | if (!copy(srcFS, src, dstFS, dst, deleteSource, overwrite, conf)) 192 | returnVal = false; 193 | } catch (IOException e) { 194 | gotException = true; 195 | exceptions.append(e.getMessage()); 196 | exceptions.append("\n"); 197 | } 198 | } 199 | if (gotException) { 200 | throw new IOException(exceptions.toString()); 201 | } 202 | return returnVal; 203 | } 204 | 205 | /** Copy files between FileSystems. */ 206 | public static boolean copy(FileSystem srcFS, Path src, 207 | FileSystem dstFS, Path dst, 208 | boolean deleteSource, 209 | boolean overwrite, 210 | Configuration conf) throws IOException { 211 | dst = checkDest(src.getName(), dstFS, dst, overwrite); 212 | 213 | if (srcFS.getFileStatus(src).isDir()) { 214 | checkDependencies(srcFS, src, dstFS, dst); 215 | if (!dstFS.mkdirs(dst)) { 216 | return false; 217 | } 218 | FileStatus contents[] = srcFS.listStatus(src); 219 | for (int i = 0; i < contents.length; i++) { 220 | copy(srcFS, contents[i].getPath(), dstFS, 221 | new Path(dst, contents[i].getPath().getName()), 222 | deleteSource, overwrite, conf); 223 | } 224 | } else if (srcFS.isFile(src)) { 225 | InputStream in=null; 226 | OutputStream out = null; 227 | try { 228 | in = srcFS.open(src); 229 | out = dstFS.create(dst, overwrite); 230 | IOUtils.copyBytes(in, out, conf, true); 231 | } catch (IOException e) { 232 | IOUtils.closeStream(out); 233 | IOUtils.closeStream(in); 234 | throw e; 235 | } 236 | } else { 237 | throw new IOException(src.toString() + ": No such file or directory"); 238 | } 239 | if (deleteSource) { 240 | return srcFS.delete(src, true); 241 | } else { 242 | return true; 243 | } 244 | 245 | } 246 | 247 | /** Copy all files in a directory to one output file (merge). */ 248 | public static boolean copyMerge(FileSystem srcFS, Path srcDir, 249 | FileSystem dstFS, Path dstFile, 250 | boolean deleteSource, 251 | Configuration conf, String addString) throws IOException { 252 | dstFile = checkDest(srcDir.getName(), dstFS, dstFile, false); 253 | 254 | if (!srcFS.getFileStatus(srcDir).isDir()) 255 | return false; 256 | 257 | OutputStream out = dstFS.create(dstFile); 258 | 259 | try { 260 | FileStatus contents[] = srcFS.listStatus(srcDir); 261 | for (int i = 0; i < contents.length; i++) { 262 | if (!contents[i].isDir()) { 263 | InputStream in = srcFS.open(contents[i].getPath()); 264 | try { 265 | IOUtils.copyBytes(in, out, conf, false); 266 | if (addString!=null) 267 | out.write(addString.getBytes("UTF-8")); 268 | 269 | } finally { 270 | in.close(); 271 | } 272 | } 273 | } 274 | } finally { 275 | out.close(); 276 | } 277 | 278 | 279 | if (deleteSource) { 280 | return srcFS.delete(srcDir, true); 281 | } else { 282 | return true; 283 | } 284 | } 285 | 286 | /** Copy local files to a FileSystem. */ 287 | public static boolean copy(File src, 288 | FileSystem dstFS, Path dst, 289 | boolean deleteSource, 290 | Configuration conf) throws IOException { 291 | dst = checkDest(src.getName(), dstFS, dst, false); 292 | 293 | if (src.isDirectory()) { 294 | if (!dstFS.mkdirs(dst)) { 295 | return false; 296 | } 297 | File contents[] = listFiles(src); 298 | for (int i = 0; i < contents.length; i++) { 299 | copy(contents[i], dstFS, new Path(dst, contents[i].getName()), 300 | deleteSource, conf); 301 | } 302 | } else if (src.isFile()) { 303 | InputStream in = null; 304 | OutputStream out =null; 305 | try { 306 | in = new FileInputStream(src); 307 | out = dstFS.create(dst); 308 | IOUtils.copyBytes(in, out, conf); 309 | } catch (IOException e) { 310 | IOUtils.closeStream( out ); 311 | IOUtils.closeStream( in ); 312 | throw e; 313 | } 314 | } else { 315 | throw new IOException(src.toString() + 316 | ": No such file or directory"); 317 | } 318 | if (deleteSource) { 319 | return FileUtil.fullyDelete(src); 320 | } else { 321 | return true; 322 | } 323 | } 324 | 325 | /** Copy FileSystem files to local files. */ 326 | public static boolean copy(FileSystem srcFS, Path src, 327 | File dst, boolean deleteSource, 328 | Configuration conf) throws IOException { 329 | if (srcFS.getFileStatus(src).isDir()) { 330 | if (!dst.mkdirs()) { 331 | return false; 332 | } 333 | FileStatus contents[] = srcFS.listStatus(src); 334 | for (int i = 0; i < contents.length; i++) { 335 | copy(srcFS, contents[i].getPath(), 336 | new File(dst, contents[i].getPath().getName()), 337 | deleteSource, conf); 338 | } 339 | } else if (srcFS.isFile(src)) { 340 | InputStream in = srcFS.open(src); 341 | IOUtils.copyBytes(in, new FileOutputStream(dst), conf); 342 | } else { 343 | throw new IOException(src.toString() + 344 | ": No such file or directory"); 345 | } 346 | if (deleteSource) { 347 | return srcFS.delete(src, true); 348 | } else { 349 | return true; 350 | } 351 | } 352 | 353 | private static Path checkDest(String srcName, FileSystem dstFS, Path dst, 354 | boolean overwrite) throws IOException { 355 | if (dstFS.exists(dst)) { 356 | FileStatus sdst = dstFS.getFileStatus(dst); 357 | if (sdst.isDir()) { 358 | if (null == srcName) { 359 | throw new IOException("Target " + dst + " is a directory"); 360 | } 361 | return checkDest(null, dstFS, new Path(dst, srcName), overwrite); 362 | } else if (!overwrite) { 363 | throw new IOException("Target " + dst + " already exists"); 364 | } 365 | } 366 | return dst; 367 | } 368 | 369 | /** 370 | * This class is only used on windows to invoke the cygpath command. 371 | */ 372 | private static class CygPathCommand extends Shell { 373 | String[] command; 374 | String result; 375 | CygPathCommand(String path) throws IOException { 376 | command = new String[]{"cygpath", "-u", path}; 377 | run(); 378 | } 379 | String getResult() throws IOException { 380 | return result; 381 | } 382 | protected String[] getExecString() { 383 | return command; 384 | } 385 | protected void parseExecResult(BufferedReader lines) throws IOException { 386 | String line = lines.readLine(); 387 | if (line == null) { 388 | throw new IOException("Can't convert '" + command[2] + 389 | " to a cygwin path"); 390 | } 391 | result = line; 392 | } 393 | } 394 | 395 | /** 396 | * Convert a os-native filename to a path that works for the shell. 397 | * @param filename The filename to convert 398 | * @return The unix pathname 399 | * @throws IOException on windows, there can be problems with the subprocess 400 | */ 401 | public static String makeShellPath(String filename) throws IOException { 402 | if (Path.WINDOWS) { 403 | return new CygPathCommand(filename).getResult(); 404 | } else { 405 | return filename; 406 | } 407 | } 408 | 409 | /** 410 | * Convert a os-native filename to a path that works for the shell. 411 | * @param file The filename to convert 412 | * @return The unix pathname 413 | * @throws IOException on windows, there can be problems with the subprocess 414 | */ 415 | public static String makeShellPath(File file) throws IOException { 416 | return makeShellPath(file, false); 417 | } 418 | 419 | /** 420 | * Convert a os-native filename to a path that works for the shell. 421 | * @param file The filename to convert 422 | * @param makeCanonicalPath 423 | * Whether to make canonical path for the file passed 424 | * @return The unix pathname 425 | * @throws IOException on windows, there can be problems with the subprocess 426 | */ 427 | public static String makeShellPath(File file, boolean makeCanonicalPath) 428 | throws IOException { 429 | if (makeCanonicalPath) { 430 | return makeShellPath(file.getCanonicalPath()); 431 | } else { 432 | return makeShellPath(file.toString()); 433 | } 434 | } 435 | 436 | /** 437 | * Takes an input dir and returns the du on that local directory. Very basic 438 | * implementation. 439 | * 440 | * @param dir 441 | * The input dir to get the disk space of this local dir 442 | * @return The total disk space of the input local directory 443 | */ 444 | public static long getDU(File dir) { 445 | long size = 0; 446 | if (!dir.exists()) 447 | return 0; 448 | if (!dir.isDirectory()) { 449 | return dir.length(); 450 | } else { 451 | File[] allFiles = dir.listFiles(); 452 | if(allFiles != null) { 453 | for (int i = 0; i < allFiles.length; i++) { 454 | boolean isSymLink; 455 | try { 456 | isSymLink = org.apache.commons.io.FileUtils.isSymlink(allFiles[i]); 457 | } catch(IOException ioe) { 458 | isSymLink = true; 459 | } 460 | if(!isSymLink) { 461 | size += getDU(allFiles[i]); 462 | } 463 | } 464 | } 465 | return size; 466 | } 467 | } 468 | 469 | /** 470 | * Given a File input it will unzip the file in a the unzip directory 471 | * passed as the second parameter 472 | * @param inFile The zip file as input 473 | * @param unzipDir The unzip directory where to unzip the zip file. 474 | * @throws IOException 475 | */ 476 | public static void unZip(File inFile, File unzipDir) throws IOException { 477 | Enumeration entries; 478 | ZipFile zipFile = new ZipFile(inFile); 479 | 480 | try { 481 | entries = zipFile.entries(); 482 | while (entries.hasMoreElements()) { 483 | ZipEntry entry = entries.nextElement(); 484 | if (!entry.isDirectory()) { 485 | InputStream in = zipFile.getInputStream(entry); 486 | try { 487 | File file = new File(unzipDir, entry.getName()); 488 | if (!file.getParentFile().mkdirs()) { 489 | if (!file.getParentFile().isDirectory()) { 490 | throw new IOException("Mkdirs failed to create " + 491 | file.getParentFile().toString()); 492 | } 493 | } 494 | OutputStream out = new FileOutputStream(file); 495 | try { 496 | byte[] buffer = new byte[8192]; 497 | int i; 498 | while ((i = in.read(buffer)) != -1) { 499 | out.write(buffer, 0, i); 500 | } 501 | } finally { 502 | out.close(); 503 | } 504 | } finally { 505 | in.close(); 506 | } 507 | } 508 | } 509 | } finally { 510 | zipFile.close(); 511 | } 512 | } 513 | 514 | /** 515 | * Given a Tar File as input it will untar the file in a the untar directory 516 | * passed as the second parameter 517 | * 518 | * This utility will untar ".tar" files and ".tar.gz","tgz" files. 519 | * 520 | * @param inFile The tar file as input. 521 | * @param untarDir The untar directory where to untar the tar file. 522 | * @throws IOException 523 | */ 524 | public static void unTar(File inFile, File untarDir) throws IOException { 525 | if (!untarDir.mkdirs()) { 526 | if (!untarDir.isDirectory()) { 527 | throw new IOException("Mkdirs failed to create " + untarDir); 528 | } 529 | } 530 | 531 | StringBuffer untarCommand = new StringBuffer(); 532 | boolean gzipped = inFile.toString().endsWith("gz"); 533 | if (gzipped) { 534 | untarCommand.append(" gzip -dc '"); 535 | untarCommand.append(FileUtil.makeShellPath(inFile)); 536 | untarCommand.append("' | ("); 537 | } 538 | untarCommand.append("cd '"); 539 | untarCommand.append(FileUtil.makeShellPath(untarDir)); 540 | untarCommand.append("' ; "); 541 | untarCommand.append("tar -xf "); 542 | 543 | if (gzipped) { 544 | untarCommand.append(" -)"); 545 | } else { 546 | untarCommand.append(FileUtil.makeShellPath(inFile)); 547 | } 548 | String[] shellCmd = { "bash", "-c", untarCommand.toString() }; 549 | ShellCommandExecutor shexec = new ShellCommandExecutor(shellCmd); 550 | shexec.execute(); 551 | int exitcode = shexec.getExitCode(); 552 | if (exitcode != 0) { 553 | throw new IOException("Error untarring file " + inFile + 554 | ". Tar process exited with exit code " + exitcode); 555 | } 556 | } 557 | 558 | /** 559 | * Create a soft link between a src and destination 560 | * only on a local disk. HDFS does not support this 561 | * @param target the target for symlink 562 | * @param linkname the symlink 563 | * @return value returned by the command 564 | */ 565 | public static int symLink(String target, String linkname) throws IOException{ 566 | String cmd = "ln -s " + target + " " + linkname; 567 | Process p = Runtime.getRuntime().exec(cmd, null); 568 | int returnVal = -1; 569 | try{ 570 | returnVal = p.waitFor(); 571 | } catch(InterruptedException e){ 572 | //do nothing as of yet 573 | } 574 | if (returnVal != 0) { 575 | LOG.warn("Command '" + cmd + "' failed " + returnVal + 576 | " with: " + copyStderr(p)); 577 | } 578 | return returnVal; 579 | } 580 | 581 | private static String copyStderr(Process p) throws IOException { 582 | InputStream err = p.getErrorStream(); 583 | StringBuilder result = new StringBuilder(); 584 | byte[] buff = new byte[4096]; 585 | int len = err.read(buff); 586 | while (len > 0) { 587 | result.append(new String(buff, 0 , len)); 588 | len = err.read(buff); 589 | } 590 | return result.toString(); 591 | } 592 | 593 | /** 594 | * Change the permissions on a filename. 595 | * @param filename the name of the file to change 596 | * @param perm the permission string 597 | * @return the exit code from the command 598 | * @throws IOException 599 | * @throws InterruptedException 600 | */ 601 | public static int chmod(String filename, String perm 602 | ) throws IOException, InterruptedException { 603 | return chmod(filename, perm, false); 604 | } 605 | 606 | /** 607 | * Change the permissions on a file / directory, recursively, if 608 | * needed. 609 | * @param filename name of the file whose permissions are to change 610 | * @param perm permission string 611 | * @param recursive true, if permissions should be changed recursively 612 | * @return the exit code from the command. 613 | * @throws IOException 614 | * @throws InterruptedException 615 | */ 616 | public static int chmod(String filename, String perm, boolean recursive) 617 | throws IOException { 618 | StringBuffer cmdBuf = new StringBuffer(); 619 | cmdBuf.append("chmod "); 620 | if (recursive) { 621 | cmdBuf.append("-R "); 622 | } 623 | cmdBuf.append(perm).append(" "); 624 | cmdBuf.append(filename); 625 | String[] shellCmd = {"bash", "-c" ,cmdBuf.toString()}; 626 | ShellCommandExecutor shExec = new ShellCommandExecutor(shellCmd); 627 | try { 628 | shExec.execute(); 629 | }catch(IOException e) { 630 | if(LOG.isDebugEnabled()) { 631 | LOG.debug("Error while changing permission : " + filename 632 | +" Exception: " + StringUtils.stringifyException(e)); 633 | } 634 | } 635 | return shExec.getExitCode(); 636 | } 637 | 638 | /** 639 | * Set permissions to the required value. Uses the java primitives instead 640 | * of forking if group == other. 641 | * @param f the file to change 642 | * @param permission the new permissions 643 | * @throws IOException 644 | */ 645 | public static void setPermission(File f, FsPermission permission 646 | ) throws IOException { 647 | FsAction user = permission.getUserAction(); 648 | FsAction group = permission.getGroupAction(); 649 | FsAction other = permission.getOtherAction(); 650 | 651 | // use the native/fork if the group/other permissions are different 652 | // or if the native is available 653 | if (group != other || NativeIO.isAvailable()) { 654 | execSetPermission(f, permission); 655 | return; 656 | } 657 | 658 | boolean rv = true; 659 | 660 | // read perms 661 | rv = f.setReadable(group.implies(FsAction.READ), false); 662 | checkReturnValue(rv, f, permission); 663 | if (group.implies(FsAction.READ) != user.implies(FsAction.READ)) { 664 | f.setReadable(user.implies(FsAction.READ), true); 665 | checkReturnValue(rv, f, permission); 666 | } 667 | 668 | // write perms 669 | rv = f.setWritable(group.implies(FsAction.WRITE), false); 670 | checkReturnValue(rv, f, permission); 671 | if (group.implies(FsAction.WRITE) != user.implies(FsAction.WRITE)) { 672 | f.setWritable(user.implies(FsAction.WRITE), true); 673 | checkReturnValue(rv, f, permission); 674 | } 675 | 676 | // exec perms 677 | rv = f.setExecutable(group.implies(FsAction.EXECUTE), false); 678 | checkReturnValue(rv, f, permission); 679 | if (group.implies(FsAction.EXECUTE) != user.implies(FsAction.EXECUTE)) { 680 | f.setExecutable(user.implies(FsAction.EXECUTE), true); 681 | checkReturnValue(rv, f, permission); 682 | } 683 | } 684 | 685 | private static void checkReturnValue(boolean rv, File p, 686 | FsPermission permission 687 | ) throws IOException { 688 | } 689 | 690 | private static void execSetPermission(File f, 691 | FsPermission permission 692 | ) throws IOException { 693 | if (NativeIO.isAvailable()) { 694 | NativeIO.chmod(f.getCanonicalPath(), permission.toShort()); 695 | } else { 696 | execCommand(f, Shell.SET_PERMISSION_COMMAND, 697 | String.format("%04o", permission.toShort())); 698 | } 699 | } 700 | 701 | static String execCommand(File f, String... cmd) throws IOException { 702 | String[] args = new String[cmd.length + 1]; 703 | System.arraycopy(cmd, 0, args, 0, cmd.length); 704 | args[cmd.length] = f.getCanonicalPath(); 705 | String output = Shell.execCommand(args); 706 | return output; 707 | } 708 | 709 | /** 710 | * Create a tmp file for a base file. 711 | * @param basefile the base file of the tmp 712 | * @param prefix file name prefix of tmp 713 | * @param isDeleteOnExit if true, the tmp will be deleted when the VM exits 714 | * @return a newly created tmp file 715 | * @exception IOException If a tmp file cannot created 716 | * @see java.io.File#createTempFile(String, String, File) 717 | * @see java.io.File#deleteOnExit() 718 | */ 719 | public static final File createLocalTempFile(final File basefile, 720 | final String prefix, 721 | final boolean isDeleteOnExit) 722 | throws IOException { 723 | File tmp = File.createTempFile(prefix + basefile.getName(), 724 | "", basefile.getParentFile()); 725 | if (isDeleteOnExit) { 726 | tmp.deleteOnExit(); 727 | } 728 | return tmp; 729 | } 730 | 731 | /** 732 | * Move the src file to the name specified by target. 733 | * @param src the source file 734 | * @param target the target file 735 | * @exception IOException If this operation fails 736 | */ 737 | public static void replaceFile(File src, File target) throws IOException { 738 | /* renameTo() has two limitations on Windows platform. 739 | * src.renameTo(target) fails if 740 | * 1) If target already exists OR 741 | * 2) If target is already open for reading/writing. 742 | */ 743 | if (!src.renameTo(target)) { 744 | int retries = 5; 745 | while (target.exists() && !target.delete() && retries-- >= 0) { 746 | try { 747 | Thread.sleep(1000); 748 | } catch (InterruptedException e) { 749 | throw new IOException("replaceFile interrupted."); 750 | } 751 | } 752 | if (!src.renameTo(target)) { 753 | throw new IOException("Unable to rename " + src + 754 | " to " + target); 755 | } 756 | } 757 | } 758 | 759 | /** 760 | * A wrapper for {@link File#listFiles()}. This java.io API returns null 761 | * when a dir is not a directory or for any I/O error. Instead of having 762 | * null check everywhere File#listFiles() is used, we will add utility API 763 | * to get around this problem. For the majority of cases where we prefer 764 | * an IOException to be thrown. 765 | * @param dir directory for which listing should be performed 766 | * @return list of files or empty list 767 | * @exception IOException for invalid directory or for a bad disk. 768 | */ 769 | public static File[] listFiles(File dir) throws IOException { 770 | File[] files = dir.listFiles(); 771 | if(files == null) { 772 | throw new IOException("Invalid directory or I/O error occurred for dir: " 773 | + dir.toString()); 774 | } 775 | return files; 776 | } 777 | 778 | /** 779 | * A wrapper for {@link File#list()}. This java.io API returns null 780 | * when a dir is not a directory or for any I/O error. Instead of having 781 | * null check everywhere File#list() is used, we will add utility API 782 | * to get around this problem. For the majority of cases where we prefer 783 | * an IOException to be thrown. 784 | * @param dir directory for which listing should be performed 785 | * @return list of file names or empty string list 786 | * @exception IOException for invalid directory or for a bad disk. 787 | */ 788 | public static String[] list(File dir) throws IOException { 789 | String[] fileNames = dir.list(); 790 | if(fileNames == null) { 791 | throw new IOException("Invalid directory or I/O error occurred for dir: " 792 | + dir.toString()); 793 | } 794 | return fileNames; 795 | } 796 | } 797 | -------------------------------------------------------------------------------- /weblog/src/test/java/com/weblog/AppTest.java: -------------------------------------------------------------------------------- 1 | package com.weblog; 2 | 3 | import junit.framework.Test; 4 | import junit.framework.TestCase; 5 | import junit.framework.TestSuite; 6 | 7 | /** 8 | * Unit test for simple App. 9 | */ 10 | public class AppTest 11 | extends TestCase 12 | { 13 | /** 14 | * Create the test case 15 | * 16 | * @param testName name of the test case 17 | */ 18 | public AppTest( String testName ) 19 | { 20 | super( testName ); 21 | } 22 | 23 | /** 24 | * @return the suite of tests being tested 25 | */ 26 | public static Test suite() 27 | { 28 | return new TestSuite( AppTest.class ); 29 | } 30 | 31 | /** 32 | * Rigourous Test :-) 33 | */ 34 | public void testApp() 35 | { 36 | assertTrue( true ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /weblog/target/classes/com/weblog/mr/LogCleaner$MyMapper.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/weblog/target/classes/com/weblog/mr/LogCleaner$MyMapper.class -------------------------------------------------------------------------------- /weblog/target/classes/com/weblog/mr/LogCleaner$MyReducer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/weblog/target/classes/com/weblog/mr/LogCleaner$MyReducer.class -------------------------------------------------------------------------------- /weblog/target/classes/com/weblog/mr/LogCleaner.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/weblog/target/classes/com/weblog/mr/LogCleaner.class -------------------------------------------------------------------------------- /weblog/target/classes/com/weblog/parser/LogParser.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/weblog/target/classes/com/weblog/parser/LogParser.class -------------------------------------------------------------------------------- /weblog/target/classes/com/weblog/shell/weblog_common.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #get yesterday format string 4 | #yesterday=`date --date='1 days ago' +%Y_%m_%d` 5 | yesterday=$1 6 | 7 | #upload logs to hdfs 8 | hadoop fs -put access_${yesterday}.log /weblog 9 | 10 | #cleaning data 11 | hadoop jar cleaned.jar /weblog/access_${yesterday}.log /weblog_cleaned/${yesterday} 1>/dev/null 12 | 13 | 14 | #alter hive table and then add partition to existed table 15 | hive -e "ALTER TABLE weblog ADD PARTITION(logdate='${yesterday}') LOCATION '/weblog_cleaned/${yesterday}';" 16 | 17 | #create hive table everyday 18 | hive -e "CREATE TABLE weblog_pv_${yesterday} AS SELECT COUNT(1) AS PV FROM weblog WHERE logdate='${yesterday}';" 19 | hive -e "CREATE TABLE weblog_reguser_${yesterday} AS SELECT COUNT(1) AS REGUSER FROM weblog WHERE logdate='${yesterday}' AND INSTR(url,'member.php?mod=register')>0;" 20 | hive -e "CREATE TABLE weblog_ip_${yesterday} AS SELECT COUNT(DISTINCT ip) AS IP FROM weblog WHERE logdate='${yesterday}';" 21 | hive -e "CREATE TABLE weblog_jumper_${yesterday} AS SELECT COUNT(1) AS jumper FROM (SELECT COUNT(ip) AS times FROM weblog WHERE logdate='${yesterday}' GROUP BY ip HAVING times=1) e;" 22 | hive -e "CREATE TABLE weblog_${yesterday} AS SELECT '${yesterday}', a.pv, b.reguser, c.ip, d.jumper FROM weblog_pv_${yesterday} a JOIN weblog_reguser_${yesterday} b ON 1=1 JOIN weblog_ip_${yesterday} c ON 1=1 JOIN weblog_jumper_${yesterday} d ON 1=1;" 23 | 24 | #delete hive tables 25 | hive -e "drop table weblog_pv_${yesterday};" 26 | hive -e "drop table weblog_reguser_${yesterday};" 27 | hive -e "drop table weblog_ip_${yesterday};" 28 | hive -e "drop table weblog_jumper_${yesterday};" 29 | 30 | #sqoop export to mysql 31 | sqoop export --connect jdbc:mysql://hadoop:3306/weblog --username root --password admin --table weblog_logs_stat --fields-terminated-by '\001' --export-dir '/hive/weblog_${yesterday}' 32 | 33 | #delete hive tables 34 | hive -e "drop table weblog_${yesterday};" 35 | -------------------------------------------------------------------------------- /weblog/target/classes/com/weblog/shell/weblog_daily.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | yesterday=`date --date='1 days ago' +%Y_%m_%d` 4 | weblog_common.sh $yesterday 5 | -------------------------------------------------------------------------------- /weblog/target/classes/com/weblog/shell/weblog_init.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #hive -e "CREATE EXTERNAL TABLE weblog(ip string, atime string, url string) PARTITIONED BY (logdate string) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LOCATION '/weblog_cleaned';" 4 | 5 | s1=`date --date="$1" +%s` 6 | s2=`date +%s` 7 | s3=$((($s2-$s1)/3600/24)) 8 | 9 | 10 | for ((i=$s3; i>0; i--)) 11 | do 12 | tmp=`date --date="$i days ago" +%Y_%m_%d` 13 | weblog_common.sh $tmp 14 | done 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /weblog/target/classes/org/apache/hadoop/fs/FileUtil$CygPathCommand.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/weblog/target/classes/org/apache/hadoop/fs/FileUtil$CygPathCommand.class -------------------------------------------------------------------------------- /weblog/target/classes/org/apache/hadoop/fs/FileUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/weblog/target/classes/org/apache/hadoop/fs/FileUtil.class -------------------------------------------------------------------------------- /weblog/target/test-classes/com/weblog/AppTest.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chaplinthink/weblog/35940ffbb66ee7b041be51d2537eb33bad509b72/weblog/target/test-classes/com/weblog/AppTest.class --------------------------------------------------------------------------------