├── requirements.txt ├── dump └── fetch_data │ ├── mongo.bson │ ├── celery.bson │ ├── mongo.metadata.json │ ├── system.indexes.bson │ └── celery.metadata.json ├── data_analysis ├── images │ ├── bg.gif │ └── style.css ├── static │ ├── images │ │ └── AdMaster_Logo.png │ ├── javascript │ │ ├── dataConverter.js │ │ ├── glimpse.toastr.js │ │ ├── pie.js │ │ ├── CodeFlower.js │ │ ├── rainbow-min.js │ │ ├── main.js │ │ ├── data.json │ │ ├── toastr.js │ │ ├── detector.js │ │ ├── serial.js │ │ └── d3.geom.js │ └── stylesheet │ │ ├── toastr.css │ │ ├── blue.css │ │ └── pure-min.css ├── package.json ├── __init__.py ├── run.py ├── Gruntfile.js ├── models.py ├── templates │ └── posts │ │ ├── d3.html │ │ ├── trouble.html │ │ └── index.html └── views.py ├── .gitignore ├── README.md └── LICENSE /requirements.txt: -------------------------------------------------------------------------------- 1 | flask 2 | flask-mongoengine 3 | -------------------------------------------------------------------------------- /dump/fetch_data/mongo.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dongweiming/data-analysis/HEAD/dump/fetch_data/mongo.bson -------------------------------------------------------------------------------- /data_analysis/images/bg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dongweiming/data-analysis/HEAD/data_analysis/images/bg.gif -------------------------------------------------------------------------------- /dump/fetch_data/celery.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dongweiming/data-analysis/HEAD/dump/fetch_data/celery.bson -------------------------------------------------------------------------------- /dump/fetch_data/mongo.metadata.json: -------------------------------------------------------------------------------- 1 | { "indexes" : [ { "v" : 1, "key" : { "_id" : 1 }, "ns" : "fetch_data.mongo", "name" : "_id_" } ] } -------------------------------------------------------------------------------- /dump/fetch_data/system.indexes.bson: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dongweiming/data-analysis/HEAD/dump/fetch_data/system.indexes.bson -------------------------------------------------------------------------------- /data_analysis/static/images/AdMaster_Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dongweiming/data-analysis/HEAD/data_analysis/static/images/AdMaster_Logo.png -------------------------------------------------------------------------------- /data_analysis/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tencent_data", 3 | "version": "0.1.0", 4 | "devDependencies": { 5 | "grunt": "*", 6 | "grunt-contrib-watch": "*" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /data_analysis/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | from flask.ext.mongoengine import MongoEngine 3 | 4 | app = Flask(__name__) 5 | app.config["MONGODB_SETTINGS"] = {'DB': "fetch_data"} 6 | app.config["SECRET_KEY"] = "Keepssdf12q" 7 | 8 | db = MongoEngine(app) 9 | -------------------------------------------------------------------------------- /data_analysis/run.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | sys.path.append(os.path.abspath( 5 | os.path.join(os.path.dirname(__file__), '..'))) 6 | 7 | from data_analysis.views import posts 8 | from data_analysis import app 9 | app.register_blueprint(posts) 10 | 11 | if __name__ == "__main__": 12 | app.run(host='0.0.0.0', debug=True) 13 | -------------------------------------------------------------------------------- /dump/fetch_data/celery.metadata.json: -------------------------------------------------------------------------------- 1 | { "indexes" : [ { "v" : 1, "key" : { "_id" : 1 }, "ns" : "fetch_data.celery", "name" : "_id_" }, { "v" : 1, "key" : { "time" : -1 }, "ns" : "fetch_data.celery", "name" : "time_-1" }, { "v" : 1, "key" : { "cost" : -1 }, "ns" : "fetch_data.celery", "name" : "cost_-1" }, { "v" : 1, "key" : { "task" : 1 }, "ns" : "fetch_data.celery", "name" : "task_1" } ] } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | 3 | # C extensions 4 | *.so 5 | 6 | # Packages 7 | *.egg 8 | *.egg-info 9 | dist 10 | build 11 | eggs 12 | parts 13 | bin 14 | var 15 | sdist 16 | develop-eggs 17 | .installed.cfg 18 | lib 19 | lib64 20 | __pycache__ 21 | 22 | # Installer logs 23 | pip-log.txt 24 | 25 | # Unit test / coverage reports 26 | .coverage 27 | .tox 28 | nosetests.xml 29 | 30 | # Translations 31 | *.mo 32 | 33 | # Mr Developer 34 | .mr.developer.cfg 35 | .project 36 | .pydevproject 37 | -------------------------------------------------------------------------------- /data_analysis/images/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #D9D9D9; 3 | margin-left: 20px; 4 | margin-top: 20px; 5 | margin-right: 20px; 6 | margin-bottom: 20px; 7 | background-image: url(../images/bg.gif); 8 | font-family: Arial; 9 | font-size: 12px; 10 | line-height:16px; 11 | } 12 | 13 | hr{ 14 | border: 1px solid #FFFFFF; 15 | } 16 | 17 | a:link{ 18 | color:#0055CC; 19 | } 20 | a:visited{ 21 | color:#990099; 22 | } 23 | a:hover{ 24 | color:#CC0000; 25 | } 26 | 27 | th{ 28 | background-color:#FFFFFF; 29 | font-weight:bold; 30 | } 31 | 32 | td{ 33 | background-color:#ecf7fe; 34 | text-align:center; 35 | } -------------------------------------------------------------------------------- /data_analysis/Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | 3 | grunt.initConfig({ 4 | pkg: grunt.file.readJSON('package.json'), 5 | watch: { 6 | scripts: { 7 | //files: ['static/javascript/*.js'], 8 | files: ['templates/posts/index.html', 9 | 'static/javascript/main.js'], 10 | options: { 11 | livereload: true, 12 | }, 13 | } 14 | } 15 | }); 16 | 17 | grunt.loadNpmTasks('grunt-contrib-watch'); 18 | 19 | grunt.registerTask('default', ['watch']); 20 | 21 | }; 22 | -------------------------------------------------------------------------------- /data_analysis/models.py: -------------------------------------------------------------------------------- 1 | from data_analysis import db 2 | 3 | class Apidist(db.Document): 4 | name = db.StringField(max_length=255, required=True) 5 | call = db.IntField(required=True) 6 | include = db.StringField(max_length=255, required=True) 7 | 8 | class Celery(db.Document): 9 | cost = db.FloatField(required=True) 10 | time = db.DateTimeField(required=True) 11 | file = db.StringField(max_length=25, required=True) 12 | task = db.StringField(max_length=255, required=True) 13 | 14 | class Mongo(db.Document): 15 | total = db.IntField(required=True) 16 | database = db.StringField(max_length=255, required=True) 17 | hour = db.DictField(required=True) 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | data-analysis 2 | ============= 3 | 4 | A data analysis site by flask and mongoengine 5 | 6 | ![6](https://user-images.githubusercontent.com/841395/31398950-4516db04-adb0-11e7-8735-81e313992fab.png) 7 | ![7](https://user-images.githubusercontent.com/841395/31398952-457c3ee0-adb0-11e7-9557-ea1f2eddcec0.png) 8 | ![8](https://user-images.githubusercontent.com/841395/31398954-45b66660-adb0-11e7-8feb-3322d701c390.png) 9 | ![9](https://user-images.githubusercontent.com/841395/31398955-45f7b2c8-adb0-11e7-9e00-165de67a6a1f.png) 10 | ![10](https://user-images.githubusercontent.com/841395/31398957-463a0506-adb0-11e7-82ee-60227efea4e1.png) 11 | ![11](https://user-images.githubusercontent.com/841395/31398959-46700c78-adb0-11e7-9424-4c229809b5b1.png) 12 | ![12](https://user-images.githubusercontent.com/841395/31398961-46ada7fe-adb0-11e7-8c8c-210edbed8c2a.png) 13 | 14 | 15 | #### USEAGE 16 | 17 | ``` 18 | $pip install -r requirements.txt 19 | $cd /path/to/data-analysis 20 | $npm install 21 | $mongorestore -d fetch_data --directoryperdb dump/fetch_data 22 | $python run.py 23 | ``` 24 | -------------------------------------------------------------------------------- /data_analysis/templates/posts/d3.html: -------------------------------------------------------------------------------- 1 | {% extends "posts/index.html" %} 2 | {% block media %} 3 | 4 | 5 | 6 | 7 | 8 | 36 | 48 | {% endblock %} 49 | {% block select %} 50 | {% endblock %} -------------------------------------------------------------------------------- /data_analysis/static/javascript/dataConverter.js: -------------------------------------------------------------------------------- 1 | var convertToJSON = function(data, origin) { 2 | return (origin == 'cloc') ? convertFromClocToJSON(data) : convertFromWcToJSON(data); 3 | }; 4 | 5 | /** 6 | * Convert the output of cloc in csv to JSON format 7 | * 8 | * > cloc . --csv --exclude-dir=vendor,tmp --by-file --report-file=data.cloc 9 | */ 10 | var convertFromClocToJSON = function(data) { 11 | var lines = data.split("\n"); 12 | lines.shift(); // drop the header line 13 | 14 | var json = {}; 15 | lines.forEach(function(line) { 16 | var cols = line.split(','); 17 | var filename = cols[1]; 18 | if (!filename) return; 19 | var elements = filename.split(/[\/\\]/); 20 | var current = json; 21 | elements.forEach(function(element) { 22 | if (!current[element]) { 23 | current[element] = {}; 24 | } 25 | current = current[element]; 26 | }); 27 | current.api = cols[0]; 28 | current.size = parseInt(cols[4], 10); 29 | }); 30 | 31 | json = getChildren(json)[0]; 32 | json.name = 'root'; 33 | 34 | return json; 35 | }; 36 | 37 | /** 38 | * Convert the output of wc to JSON format 39 | * 40 | * > git ls-files | xargs wc -l 41 | */ 42 | var convertFromWcToJSON = function(data) { 43 | var lines = data.split("\n"); 44 | 45 | var json = {}; 46 | var filename, size, cols, elements, current; 47 | lines.forEach(function(line) { 48 | cols = line.trim().split(' '); 49 | size = parseInt(cols[0], 10); 50 | if (!size) return; 51 | filename = cols[1]; 52 | if (filename === "total") return; 53 | if (!filename) return; 54 | elements = filename.split(/[\/\\]/); 55 | current = json; 56 | elements.forEach(function(element) { 57 | if (!current[element]) { 58 | current[element] = {}; 59 | } 60 | current = current[element]; 61 | }); 62 | current.size = size; 63 | }); 64 | 65 | json.children = getChildren(json); 66 | json.name = 'root'; 67 | 68 | return json; 69 | }; 70 | 71 | /** 72 | * Convert a simple json object into another specifying children as an array 73 | * Works recursively 74 | * 75 | * example input: 76 | * { a: { b: { c: { size: 12 }, d: { size: 34 } }, e: { size: 56 } } } 77 | * example output 78 | * { name: a, children: [ 79 | * { name: b, children: [ 80 | * { name: c, size: 12 }, 81 | * { name: d, size: 34 } 82 | * ] }, 83 | * { name: e, size: 56 } 84 | * ] } } 85 | */ 86 | var getChildren = function(json) { 87 | var children = []; 88 | if (json.api) return children; 89 | for (var key in json) { 90 | var child = { name: key }; 91 | if (json[key].size) { 92 | // value node 93 | child.size = json[key].size; 94 | child.api = json[key].api; 95 | } else { 96 | // children node 97 | var childChildren = getChildren(json[key]); 98 | if (childChildren) child.children = childChildren; 99 | } 100 | children.push(child); 101 | delete json[key]; 102 | } 103 | return children; 104 | }; 105 | 106 | // Recursively count all elements in a tree 107 | var countElements = function(node) { 108 | var nbElements = 1; 109 | if (node.children) { 110 | nbElements += node.children.reduce(function(p, v) { return p + countElements(v); }, 0); 111 | } 112 | return nbElements; 113 | }; 114 | -------------------------------------------------------------------------------- /data_analysis/static/javascript/glimpse.toastr.js: -------------------------------------------------------------------------------- 1 | ; (function ($, pubsub, tab, render, toastr) { 2 | 'use strict'; 3 | 4 | if (!toastr) { 5 | pubsub.subscribe('action.panel.showed.toastr', function (args) { 6 | render.engine.insert(args.panel, 'Toastr is not available on this screen. Plugin disabled.'); 7 | }); 8 | return; 9 | } 10 | 11 | var preexistingToasts = []; 12 | var rendered = false; 13 | var toastrPanel; 14 | var headerRow = [ 15 | 'Id', 16 | 'Type', 17 | 'State', 18 | 'Message', 19 | 'Start', 20 | 'End', 21 | 'LifeTime', 22 | 'This Toast\'s Options', 23 | 'All Toastr Options' 24 | ]; 25 | 26 | toastr.subscribe(receiveToasts); 27 | 28 | function receiveToasts(args) { 29 | var data = args; 30 | !rendered ? preexistingToasts.push(data) : write(data); 31 | } 32 | 33 | function elapsedMs(start, end) { 34 | return end && start ? end.getTime() - start.getTime() + ' ms' : ''; 35 | } 36 | 37 | function formatDateTime(date) { 38 | var sep = ':'; 39 | return !!(date && date.getMonth) ? date.getFullYear().toString() + sep + 40 | padDigits(date.getMonth() + 1) + sep + 41 | padDigits(date.getDate()) + sep + 42 | padDigits(date.getHours()) + sep + 43 | padDigits(date.getMinutes()) + sep + 44 | padDigits(date.getSeconds()) + sep + 45 | padDigits(date.getMilliseconds(), '0', 3) : ''; 46 | 47 | function padDigits(val, pad, count) { 48 | var value = val.toString ? val.toString() : val; 49 | count = count || 2; 50 | var padding = Array(count + 1).join(pad || '0'); 51 | return (padding + (value)).slice(-count); 52 | } 53 | } 54 | 55 | function write(data) { 56 | if (data.length) { 57 | for (var i = 0; i < data.length; i++) { 58 | write(data[i]); 59 | } 60 | return; 61 | } 62 | 63 | var startTime = formatDateTime(data.startTime); 64 | var endTime = formatDateTime(data.endTime); 65 | var lifetime = elapsedMs(data.startTime, data.endTime); 66 | 67 | // Must match sequence of headers 68 | var pivotedData = [ 69 | data.toastId, 70 | data.map.type, 71 | data.state, 72 | data.map.message, 73 | startTime, 74 | endTime, 75 | lifetime, 76 | data.map, 77 | data.options, 78 | getStateStyle(data) 79 | ]; 80 | render.engine.prepend(toastrPanel, [headerRow, pivotedData]); 81 | } 82 | 83 | function getStateStyle(data) { 84 | return data.state === 'visible' ? 'info' : ''; 85 | } 86 | 87 | pubsub.subscribe('action.panel.rendered.toastr', function (args) { 88 | toastrPanel = args.panel; 89 | rendered = true; 90 | render.engine.insert(toastrPanel, [headerRow]); 91 | if (preexistingToasts.length) { 92 | for (var i = 0; i < preexistingToasts.length; i++) { 93 | write(preexistingToasts[i]); 94 | } 95 | } 96 | }); 97 | 98 | var config = { 99 | key: 'toastr', 100 | payload: { 101 | name: 'toastr', 102 | version: '0.2.0', 103 | isPermanent: true, 104 | data: 'Loading glimpse.toastr ...' 105 | }, 106 | metadata: { 107 | documentationUri: "http://jpapa.me/c7toastr" 108 | } 109 | }; 110 | 111 | tab.register(config); 112 | 113 | })(jQueryGlimpse, glimpse.pubsub, glimpse.tab, glimpse.render, window.toastr); -------------------------------------------------------------------------------- /data_analysis/static/javascript/pie.js: -------------------------------------------------------------------------------- 1 | AmCharts.AmPieChart=AmCharts.Class({inherits:AmCharts.AmSlicedChart,construct:function(){AmCharts.AmPieChart.base.construct.call(this);this.pieBrightnessStep=30;this.minRadius=10;this.depth3D=0;this.startAngle=90;this.angle=this.innerRadius=0;this.startRadius="500%";this.pullOutRadius="20%";this.labelRadius=30;this.labelText="[[title]]: [[percents]]%";this.balloonText="[[title]]: [[percents]]% ([[value]])\n[[description]]";this.previousScale=1},drawChart:function(){AmCharts.AmPieChart.base.drawChart.call(this); 2 | var e=this.chartData;if(AmCharts.ifArray(e)){if(0a&&(f=a)),h=AmCharts.toCoordinate(this.pullOutRadius,f),f=(0<=s?f-1.8*(s+h):f-1.8*h)/2);f=f&&(d=f-1);l=AmCharts.fitToBounds(this.startAngle,0,360);0=this.hideLabelsPercent){var m=l+n/2,n=s;isNaN(b.labelRadius)||(n=b.labelRadius);var t=w+r*(f+n),u=x+y*(f+n),z,v=0;if(0<=n){var A;90>=m&&0<=m?(A=0,z="start",v=8):90<=m&&180>m?(A=1,z="start",v=8):180<=m&&270>m?(A=2,z="end",v=-8):270<=m&&360>m&&(A=3,z="end",v=-8);b.labelQuarter=A}else z="middle";var m=this.formatString(this.labelText,b),B=b.labelColor;B||(B=this.color); 6 | m=AmCharts.text(c,m,B,this.fontFamily,this.fontSize,z);m.translate(t+1.5*v,u);b.tx=t+1.5*v;b.ty=u;u=d+(f-d)/2;b.pulled&&(u+=this.pullOutRadiusReal);b.balloonX=r*u+w;b.balloonY=y*u+x;0<=n?p.push(m):this.freeLabelsSet.push(m);b.label=m;b.tx=t;b.tx2=t+v;b.tx0=w+r*f;b.ty0=x+y*f}b.startX=Math.round(r*q);b.startY=Math.round(y*q);b.pullX=Math.round(r*h);b.pullY=Math.round(y*h);this.graphsSet.push(p);(0===b.alpha||0c?a.toFront():180<=c&&a.toBack()}},arrangeLabels:function(){var e=this.chartData,g=e.length,c,a;for(a=g-1;0<=a;a--)c=e[a],0!==c.labelQuarter||c.hidden||this.checkOverlapping(a, 8 | c,0,!0,0);for(a=0;ah&&(d=g.ty+3*g.iy,g.ty=d,l.translate(g.tx2,d),this.checkOverlapping(e,g,c,a,h+1))}},checkOverlappingReal:function(e,g,c){var a=!1,h=e.label,d=g.label;e.labelQuarter!=c||e.hidden||g.hidden||!d||(h=h.getBBox(),c={},c.width=h.width,c.height=h.height,c.y=e.ty,c.x=e.tx,e=d.getBBox(),d={},d.width=e.width,d.height=e.height,d.y=g.ty,d.x=g.tx,AmCharts.hitTest(c,d)&&(a=!0));return a}}); -------------------------------------------------------------------------------- /data_analysis/templates/posts/trouble.html: -------------------------------------------------------------------------------- 1 | {% extends "posts/index.html" %} 2 | {% block media %} 3 | {% endblock %} 4 | {% block body %} 5 |
6 |

我也推荐神奇的dex: https://github.com/mongolab/dex

7 | 10 |

索引字段不够(需要复合索引)

11 |
xx/models.py 143-146行
 12 | statuses = list(coll.find(                                                 
 13 |         {"is_update": False},                                                 
 14 |         {"uid": 1}                                                             
 15 |     ).sort('date', -1).limit(200))
16 |

 17 | > db.status_5008fe57b3158aa4709ecd8f_201311.getIndexes()
 18 | [
 19 | 	{
 20 | 		"v" : 1,
 21 | 		"key" : {
 22 | 			"_id" : 1
 23 | 		},
 24 | 		"ns" : "dongwm.status_5008fe57b3158aa4709ecd8f_201311",
 25 | 		"name" : "_id_"
 26 | 	},
 27 | 	{
 28 | 		"v" : 1,
 29 | 		"key" : {
 30 | 			"date" : -1
 31 | 		},
 32 | 		"ns" : "dongwm.status_5008fe57b3158aa4709ecd8f_201311",
 33 | 		"name" : "cdate_-1"
 34 | 	},
 35 | 	{
 36 | 		"v" : 1,
 37 | 		"key" : {
 38 | 			"idate" : -1
 39 | 		},
 40 | 		"ns" : "dongwm.status_5008fe57b3158aa4709ecd8f_201311",
 41 | 		"name" : "idate_-1"
 42 | 	}
 43 | ]
 44 | 		
45 |

 46 | db["status_5008fe57b3158aa4709ecd8f_201311"].ensureIndex({"is_update": 1, "date": 1}, {"background": true})
 47 | 		
48 |

没有索引

49 |
xx/tasks.py 551-564行
 50 | pre_date = update_date - timedelta(hours=1)                            
 51 | pre_infcoll = s_db["inf_%s_%s" % (                       
 52 |     key["_id"], pre_date.strftime("%Y%m")                              
 53 | )]                                                                     
 54 | pre_ho = {}                                                      
 55 | pre_inf = (                                                    
 56 |     pre_infcoll.find_one({                                      
 57 |         "day": update_date.replace(                                    
 58 |             hour=0,                                                  
 59 |             minute=0,                                                 
 60 |             second=0,                                                 
 61 |             microsecond=0                                              
 62 |         )                                                              
 63 |     }) or {}).get(str(pre_date.hour), [])
 64 | 			
65 |

 66 | > db.dongwm.influence_51ee2552fb0dd8d290a7749a_201311.getIndexes()
 67 | [ ]
 68 | 			
69 |

 70 | db["inf_51ee2552fb0dd8d290a7749a_201311"].ensureIndex({"day": 1}, {"background": true})
 71 | 			
72 |

索引顺序问题

74 |
xx/models.py 1110-1119行
 75 | def get_o_s(uid, date):                                                                 
 76 |     return list(db.st.find(                                                                                         
 77 |         {                                                                      
 78 |             'user_id': uid,                                                    
 79 |             'created_at': {'$gte': date},                                      
 80 |             'rs': 0                                           
 81 |         },                                                                     
 82 |         {'rsince_timestamp': 1, 'csince_timestamp': 1, 'last_cid': 1}          
 83 |     ))   
 84 | 		
85 |

 86 | > db.status.getIndexes()
 87 | [
 88 | 	{
 89 | 		"v" : 1,
 90 | 		"key" : {
 91 | 			"_id" : 1
 92 | 		},
 93 | 		"ns" : "dongwm.status",
 94 | 		"name" : "_id_"
 95 | 	}
 96 | ]
 97 | 		
98 |

 99 | db["status"].ensureIndex({"user_id": 1, "rs": 1, "created_at": 1}, {"background": true})
100 | 		
101 | 102 |
103 | 104 | {% endblock %} -------------------------------------------------------------------------------- /data_analysis/static/javascript/CodeFlower.js: -------------------------------------------------------------------------------- 1 | var CodeFlower = function(selector, w, h) { 2 | this.w = w; 3 | this.h = h; 4 | 5 | d3.select(selector).selectAll("svg").remove(); 6 | 7 | this.svg = d3.select(selector).append("svg:svg") 8 | .attr('width', w) 9 | .attr('height', h); 10 | 11 | this.svg.append("svg:rect") 12 | .style("stroke", "#999") 13 | .style("fill", "#fff") 14 | .attr('width', w) 15 | .attr('height', h); 16 | 17 | this.force = d3.layout.force() 18 | .on("tick", this.tick.bind(this)) 19 | .charge(function(d) { return d._children ? -d.size / 100 : -40; }) 20 | .linkDistance(function(d) { return d.target._children ? 80 : 25; }) 21 | .size([h, w]); 22 | }; 23 | 24 | CodeFlower.prototype.update = function(json) { 25 | if (json) this.json = json; 26 | 27 | this.json.fixed = true; 28 | this.json.x = this.w / 2; 29 | this.json.y = this.h / 2; 30 | 31 | var nodes = this.flatten(this.json); 32 | var links = d3.layout.tree().links(nodes); 33 | var total = nodes.length || 1; 34 | 35 | // remove existing text (will readd it afterwards to be sure it's on top) 36 | this.svg.selectAll("text").remove(); 37 | 38 | // Restart the force layout 39 | this.force 40 | .gravity(Math.atan(total / 50) / Math.PI * 0.4) 41 | .nodes(nodes) 42 | .links(links) 43 | .start(); 44 | 45 | // Update the links 46 | this.link = this.svg.selectAll("line.link") 47 | .data(links, function(d) { return d.target.name; }); 48 | 49 | // Enter any new links 50 | this.link.enter().insert("svg:line", ".node") 51 | .attr("class", "link") 52 | .attr("x1", function(d) { return d.source.x; }) 53 | .attr("y1", function(d) { return d.source.y; }) 54 | .attr("x2", function(d) { return d.target.x; }) 55 | .attr("y2", function(d) { return d.target.y; }); 56 | 57 | // Exit any old links. 58 | this.link.exit().remove(); 59 | 60 | // Update the nodes 61 | this.node = this.svg.selectAll("circle.node") 62 | .data(nodes, function(d) { return d.name; }) 63 | .classed("collapsed", function(d) { return d._children ? 1 : 0; }); 64 | 65 | this.node.transition() 66 | .attr("r", function(d) { return d.children ? 3.5 : Math.pow(d.size, 2/5) || 1; }); 67 | 68 | // Enter any new nodes 69 | this.node.enter().append('svg:circle') 70 | .attr("class", "node") 71 | .classed('directory', function(d) { return (d._children || d.children) ? 1 : 0; }) 72 | .attr("r", function(d) { return d.children ? 3.5 : Math.pow(d.size, 2/5) || 1; }) 73 | .style("fill", function color(d) { 74 | return "hsl(" + parseInt(360 / total * d.id, 10) + ",90%,70%)"; 75 | }) 76 | .call(this.force.drag) 77 | .on("click", this.click.bind(this)) 78 | .on("mouseover", this.mouseover.bind(this)) 79 | .on("mouseout", this.mouseout.bind(this)); 80 | 81 | // Exit any old nodes 82 | this.node.exit().remove(); 83 | 84 | this.text = this.svg.append('svg:text') 85 | .attr('class', 'nodetext') 86 | .attr('dy', 0) 87 | .attr('dx', 0) 88 | .attr('text-anchor', 'middle'); 89 | 90 | return this; 91 | }; 92 | 93 | CodeFlower.prototype.flatten = function(root) { 94 | var nodes = [], i = 0; 95 | 96 | function recurse(node) { 97 | if (node.children) { 98 | node.size = node.children.reduce(function(p, v) { 99 | return p + recurse(v); 100 | }, 0); 101 | } 102 | if (!node.id) node.id = ++i; 103 | nodes.push(node); 104 | return node.size; 105 | } 106 | 107 | root.size = recurse(root); 108 | return nodes; 109 | }; 110 | 111 | CodeFlower.prototype.click = function(d) { 112 | // Toggle children on click. 113 | if (d.children) { 114 | d._children = d.children; 115 | d.children = null; 116 | } else { 117 | d.children = d._children; 118 | d._children = null; 119 | } 120 | this.update(); 121 | }; 122 | 123 | CodeFlower.prototype.mouseover = function(d) { 124 | this.text.attr('transform', 'translate(' + d.x + ',' + (d.y - 5 - (d.children ? 3.5 : Math.sqrt(d.size) / 2)) + ')') 125 | .text(d.name + ": " + d.size + " loc") 126 | .style('display', null); 127 | }; 128 | 129 | CodeFlower.prototype.mouseout = function(d) { 130 | this.text.style('display', 'none'); 131 | }; 132 | 133 | CodeFlower.prototype.tick = function() { 134 | var h = this.h; 135 | var w = this.w; 136 | this.link.attr("x1", function(d) { return d.source.x; }) 137 | .attr("y1", function(d) { return d.source.y; }) 138 | .attr("x2", function(d) { return d.target.x; }) 139 | .attr("y2", function(d) { return d.target.y; }); 140 | 141 | this.node.attr("transform", function(d) { 142 | return "translate(" + Math.max(5, Math.min(w - 5, d.x)) + "," + Math.max(5, Math.min(h - 5, d.y)) + ")"; 143 | }); 144 | }; 145 | 146 | CodeFlower.prototype.cleanup = function() { 147 | this.update([]); 148 | this.force.stop(); 149 | }; -------------------------------------------------------------------------------- /data_analysis/templates/posts/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Mongodb数据分析 4 | 5 | 6 | 7 | 8 | 9 | {% block media %} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | {% endblock %} 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 59 |
60 |
61 |

{{ title }}

62 | 63 | 64 |

{{ des }}

65 | 66 |
67 | {% block body %} 68 | {% block select %} 69 |
70 |
71 |
72 | 73 | 78 |
79 |
80 | 81 | 83 |
84 |
85 | 86 | 88 |
89 | 90 |
91 |
92 | {% endblock %} 93 |
94 |
95 |
96 |
97 | {% endblock %} 98 | 129 |
130 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /data_analysis/static/javascript/rainbow-min.js: -------------------------------------------------------------------------------- 1 | 2 | /* Rainbow v1.1.8 rainbowco.de | included languages: generic, javascript, html, css */ 3 | window.Rainbow=function(){function q(a){var b,c=a.getAttribute&&a.getAttribute("data-language")||0;if(!c){a=a.attributes;for(b=0;b=e[d][c])delete e[d][c],delete j[d][c];if(a>=c&&ac&&b'+b+""}function s(a,b,c,h){var f=a.exec(c);if(f){++t;!b.name&&"string"==typeof b.matches[0]&&(b.name=b.matches[0],delete b.matches[0]);var k=f[0],i=f.index,u=f[0].length+i,g=function(){function f(){s(a,b,c,h)}t%100>0?f():setTimeout(f,0)};if(C(i,u))g();else{var m=v(b.matches),l=function(a,c,h){if(a>=c.length)h(k);else{var d=f[c[a]];if(d){var e=b.matches[c[a]],i=e.language,g=e.name&&e.matches? 5 | e.matches:e,j=function(b,d,e){var i;i=0;var g;for(g=1;g/g,">").replace(/&(?![\w\#]+;)/g, 7 | "&"),b,c)}function o(a,b,c){if(b' 68 | // html += '' 69 | //}); 70 | html += '' + chartData.title + '' + '' + chartData.value + '' + '' + chartData.include + '' 71 | $.each(chartData.result, function( index, record ) { 72 | if (index % 2 == 0){ 73 | html += '' + record.name + '' + record.call + '' + record.include + ''; 74 | } 75 | else 76 | { 77 | html += '' + record.name + '' + record.call + '' + record.include + ''; 78 | } 79 | }); 80 | html += ''; 81 | $("#chartdiv").append(html); 82 | }; 83 | 84 | var SelectThis = function (a, toastCount, toastr) { 85 | var b = 0; 86 | var url = window.location.pathname.replace(/(.*)/,"/json$1"); 87 | $.getJSON(url, function(result){ 88 | $.each(result, function(k, v) { 89 | var vt = $('#vt').val(); 90 | if (vt == k) { 91 | if (typeof(a) == 'undefined') { 92 | $.each(v, function(index, type) { 93 | $('#st').append(""); 94 | }); 95 | } 96 | else { 97 | $.each(v, function(index, type) { 98 | if (a == type[0]) { 99 | b = index; 100 | } 101 | })}; 102 | $.each(v[b][1], function(index, type) { 103 | $('#ct').append(""); 104 | }); 105 | } 106 | }); 107 | } 108 | ); 109 | MyChart(); 110 | } 111 | 112 | var Toastr = function (toastCount, toastr, title, msg) { 113 | var shortCutFunction = "success"; 114 | var toastIndex = toastCount++; 115 | var $toast = toastr[shortCutFunction](title, msg); 116 | $toastlast = $toast; 117 | }; 118 | 119 | var MyChart = function () { 120 | var vt = $('#vt').val(); 121 | var type = $('#st').val(); 122 | var chart = $('#ct').val(); 123 | $.ajax( 124 | { 125 | type: "POST", 126 | dataType: "json", 127 | data: {"type": type, "chart": chart, "vt": vt}, 128 | success: function(chartData){ 129 | switch(chartData.chart) 130 | { 131 | case 'pie': 132 | var Chartit = Pie; 133 | break; 134 | case 'simple_column': 135 | var Chartit = SmipleColumn; 136 | break; 137 | case 'multi_column': 138 | var Chartit = MultiColumn; 139 | break; 140 | default: 141 | var Chartit = SmipleColumn; 142 | } 143 | Chartit(chartData); 144 | Toastr(toastCount, toastr, chartData.total, chartData.des); 145 | } 146 | }); 147 | } 148 | 149 | var MultiColumn = function (chartData) { 150 | // SERIAL CHART 151 | chart = new AmCharts.AmSerialChart(); 152 | chart.dataProvider = chartData.result; 153 | chart.categoryField = chartData.title; 154 | chart.color = "#FFFFFF"; 155 | chart.fontSize = 14; 156 | chart.startDuration = 1; 157 | chart.plotAreaFillAlphas = 0.2; 158 | // the following two lines makes chart 3D 159 | chart.angle = 30; 160 | chart.depth3D = 60; 161 | 162 | // AXES 163 | // category 164 | var categoryAxis = chart.categoryAxis; 165 | categoryAxis.gridAlpha = 0.2; 166 | categoryAxis.gridPosition = "start"; 167 | categoryAxis.gridColor = "#FFFFFF"; 168 | categoryAxis.axisColor = "#FFFFFF"; 169 | categoryAxis.axisAlpha = 0.5; 170 | categoryAxis.dashLength = 5; 171 | 172 | // value 173 | var valueAxis = new AmCharts.ValueAxis(); 174 | valueAxis.stackType = "3d"; // This line makes chart 3D stacked (columns are placed one behind another) 175 | valueAxis.gridAlpha = 0.2; 176 | valueAxis.gridColor = "#FFFFFF"; 177 | valueAxis.axisColor = "#FFFFFF"; 178 | valueAxis.axisAlpha = 0.5; 179 | valueAxis.dashLength = 5; 180 | valueAxis.titleColor = "#FFFFFF"; 181 | valueAxis.unit = "%"; 182 | chart.addValueAxis(valueAxis); 183 | 184 | // GRAPHS 185 | // first graph 186 | var graph1 = new AmCharts.AmGraph(); 187 | graph1.title = chartData.titles[0]; 188 | graph1.valueField = chartData.values[0]; 189 | graph1.type = "column"; 190 | graph1.colorField = "color1"; 191 | graph1.lineAlpha = 0; 192 | graph1.fillAlphas = 1; 193 | graph1.balloonText = chartData.titles[0] + " [[category]] : [[value]]"; 194 | chart.addGraph(graph1); 195 | 196 | // second graph 197 | var graph2 = new AmCharts.AmGraph(); 198 | graph2.title = chartData.titles[1]; 199 | graph2.valueField = chartData.values[1]; 200 | graph2.type = "column"; 201 | graph2.colorField = "color2"; 202 | graph2.lineAlpha = 0; 203 | graph2.fillAlphas = 1; 204 | graph2.balloonText = chartData.titles[1] + " [[category]] : [[value]]"; 205 | chart.addGraph(graph2); 206 | 207 | var graph3 = new AmCharts.AmGraph(); 208 | graph3.title = chartData.titles[2]; 209 | graph3.valueField = chartData.values[2]; 210 | graph3.type = "column"; 211 | graph3.colorField = "color3"; 212 | graph3.lineAlpha = 0; 213 | graph3.fillAlphas = 1; 214 | graph3.balloonText = chartData.titles[2] + " [[category]] : [[value]]"; 215 | chart.addGraph(graph3); 216 | 217 | chart.write("chartdiv"); 218 | }; 219 | -------------------------------------------------------------------------------- /data_analysis/static/javascript/data.json: -------------------------------------------------------------------------------- 1 | {"name":"root","children":[{"name":"speed","children":[{"name":"jquery-basis.js","size":4304,"language":"Javascript"},{"name":"filter.html","size":181,"language":"HTML"},{"name":"find.html","size":177,"language":"HTML"},{"name":"benchmarker.js","size":139,"language":"Javascript"},{"name":"css.html","size":68,"language":"HTML"},{"name":"index.html","size":62,"language":"HTML"},{"name":"benchmarker.css","size":52,"language":"CSS"},{"name":"event.html","size":46,"language":"HTML"},{"name":"slice.vs.concat.html","size":37,"language":"HTML"},{"name":"closest.html","size":36,"language":"HTML"},{"name":"benchmark.js","size":12,"language":"Javascript"}],"size":5114},{"name":"test","children":[{"name":"unit","children":[{"name":"event.js","size":1926,"language":"Javascript"},{"name":"ajax.js","size":1745,"language":"Javascript"},{"name":"effects.js","size":1617,"language":"Javascript"},{"name":"manipulation.js","size":1566,"language":"Javascript"},{"name":"core.js","size":1006,"language":"Javascript"},{"name":"attributes.js","size":971,"language":"Javascript"},{"name":"css.js","size":738,"language":"Javascript"},{"name":"traversing.js","size":545,"language":"Javascript"},{"name":"data.js","size":490,"language":"Javascript"},{"name":"offset.js","size":418,"language":"Javascript"},{"name":"deferred.js","size":346,"language":"Javascript"},{"name":"dimensions.js","size":325,"language":"Javascript"},{"name":"callbacks.js","size":271,"language":"Javascript"},{"name":"queue.js","size":247,"language":"Javascript"},{"name":"selector.js","size":127,"language":"Javascript"},{"name":"serialize.js","size":96,"language":"Javascript"},{"name":"support.js","size":31,"language":"Javascript"},{"name":"exports.js","size":5,"language":"Javascript"},{"name":"deprecated.js","size":1,"language":"Javascript"}],"size":12471},{"name":"index.html","size":288,"language":"HTML"},{"name":"data","children":[{"name":"testrunner.js","size":245,"language":"Javascript"},{"name":"testinit.js","size":202,"language":"Javascript"},{"name":"testsuite.css","size":112,"language":"CSS"},{"name":"selector","children":[{"name":"html5_selector.html","size":94,"language":"HTML"},{"name":"sizzle_cache.html","size":19,"language":"HTML"}],"size":113},{"name":"offset","children":[{"name":"table.html","size":43,"language":"HTML"},{"name":"absolute.html","size":41,"language":"HTML"},{"name":"scroll.html","size":39,"language":"HTML"},{"name":"fixed.html","size":34,"language":"HTML"},{"name":"relative.html","size":31,"language":"HTML"},{"name":"static.html","size":31,"language":"HTML"},{"name":"body.html","size":26,"language":"HTML"}],"size":245},{"name":"manipulation","children":[{"name":"iframe-denied.html","size":33,"language":"HTML"}],"size":33},{"name":"support","children":[{"name":"bodyBackground.html","size":27,"language":"HTML"},{"name":"shrinkWrapBlocks.html","size":23,"language":"HTML"},{"name":"csp.php","size":17,"language":"PHP"},{"name":"testElementCrash.html","size":17,"language":"HTML"},{"name":"csp.js","size":3,"language":"Javascript"}],"size":87},{"name":"with_fries.xml","size":25,"language":"XML"},{"name":"ajax","children":[{"name":"unreleasedXHR.html","size":24,"language":"HTML"}],"size":24},{"name":"name.php","size":23,"language":"PHP"},{"name":"core","children":[{"name":"cc_on.html","size":22,"language":"HTML"}],"size":22},{"name":"dimensions","children":[{"name":"documentSmall.html","size":21,"language":"HTML"},{"name":"documentLarge.html","size":17,"language":"HTML"}],"size":38},{"name":"readywaitloader.js","size":19,"language":"Javascript"},{"name":"event","children":[{"name":"onbeforeunload.html","size":19,"language":"HTML"},{"name":"syncReady.html","size":17,"language":"HTML"},{"name":"promiseReady.html","size":16,"language":"HTML"},{"name":"longLoadScript.php","size":4,"language":"PHP"}],"size":56},{"name":"etag.php","size":16,"language":"PHP"},{"name":"if_modified_since.php","size":15,"language":"PHP"},{"name":"jsonp.php","size":14,"language":"PHP"},{"name":"params_html.php","size":12,"language":"PHP"},{"name":"json.php","size":12,"language":"PHP"},{"name":"text.php","size":12,"language":"PHP"},{"name":"headers.php","size":12,"language":"PHP"},{"name":"script.php","size":11,"language":"PHP"},{"name":"dashboard.xml","size":11,"language":"XML"},{"name":"iframe.html","size":8,"language":"HTML"},{"name":"test.php","size":7,"language":"PHP"},{"name":"with_fries_over_jsonp.php","size":7,"language":"PHP"},{"name":"test.html","size":7,"language":"HTML"},{"name":"cleanScript.html","size":7,"language":"HTML"},{"name":"test2.html","size":5,"language":"HTML"},{"name":"errorWithJSON.php","size":4,"language":"PHP"},{"name":"atom+xml.php","size":4,"language":"PHP"},{"name":"statusText.php","size":3,"language":"PHP"},{"name":"errorWithText.php","size":3,"language":"PHP"},{"name":"test.js","size":3,"language":"Javascript"},{"name":"test3.html","size":3,"language":"HTML"},{"name":"nocontent.php","size":3,"language":"PHP"},{"name":"badjson.js","size":1,"language":"Javascript"},{"name":"badcall.js","size":1,"language":"Javascript"},{"name":"readywaitasset.js","size":1,"language":"Javascript"},{"name":"evalScript.php","size":1,"language":"PHP"},{"name":"echoQuery.php","size":1,"language":"PHP"},{"name":"json_obj.js","size":1,"language":"Javascript"},{"name":"jquery-1.8.2.ajax_xhr.min.js","size":1,"language":"Javascript"},{"name":"echoData.php","size":1,"language":"PHP"},{"name":"name.html","size":1,"language":"HTML"}],"size":1432},{"name":"delegatetest.html","size":214,"language":"HTML"},{"name":"hovertest.html","size":148,"language":"HTML"},{"name":"networkerror.html","size":76,"language":"HTML"},{"name":"localfile.html","size":74,"language":"HTML"},{"name":"readywait.html","size":61,"language":"HTML"},{"name":"xhtml.php","size":4,"language":"PHP"},{"name":"jquery.js","size":4,"language":"Javascript"}],"size":14772},{"name":"src","children":[{"name":"event.js","size":588,"language":"Javascript"},{"name":"effects.js","size":560,"language":"Javascript"},{"name":"ajax.js","size":525,"language":"Javascript"},{"name":"core.js","size":518,"language":"Javascript"},{"name":"manipulation.js","size":454,"language":"Javascript"},{"name":"css.js","size":389,"language":"Javascript"},{"name":"attributes.js","size":374,"language":"Javascript"},{"name":"traversing.js","size":226,"language":"Javascript"},{"name":"data.js","size":202,"language":"Javascript"},{"name":"callbacks.js","size":138,"language":"Javascript"},{"name":"offset.js","size":121,"language":"Javascript"},{"name":"queue.js","size":117,"language":"Javascript"},{"name":"deferred.js","size":103,"language":"Javascript"},{"name":"selector-native.js","size":100,"language":"Javascript"},{"name":"ajax","children":[{"name":"xhr.js","size":82,"language":"Javascript"},{"name":"script.js","size":51,"language":"Javascript"},{"name":"jsonp.js","size":50,"language":"Javascript"}],"size":183},{"name":"serialize.js","size":71,"language":"Javascript"},{"name":"support.js","size":60,"language":"Javascript"},{"name":"dimensions.js","size":25,"language":"Javascript"},{"name":"event-alias.js","size":12,"language":"Javascript"},{"name":"sizzle-jquery.js","size":8,"language":"Javascript"},{"name":"exports.js","size":8,"language":"Javascript"},{"name":"outro.js","size":1,"language":"Javascript"},{"name":"intro.js","size":1,"language":"Javascript"},{"name":"deprecated.js","size":1,"language":"Javascript"}],"size":4785},{"name":"Gruntfile.js","size":335,"language":"Javascript"},{"name":"build","children":[{"name":"release.js","size":193,"language":"Javascript"},{"name":"release-notes.js","size":46,"language":"Javascript"}],"size":239}],"size":25245} -------------------------------------------------------------------------------- /data_analysis/static/stylesheet/toastr.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Toastr 3 | * Version 2.0.1 4 | * Copyright 2012 John Papa and Hans Fjällemark. 5 | * All Rights Reserved. 6 | * Use, reproduction, distribution, and modification of this code is subject to the terms and 7 | * conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php 8 | * 9 | * Author: John Papa and Hans Fjällemark 10 | * Project: https://github.com/CodeSeven/toastr 11 | */ 12 | .toast-title { 13 | font-weight: bold; 14 | } 15 | .toast-message { 16 | -ms-word-wrap: break-word; 17 | word-wrap: break-word; 18 | } 19 | .toast-message a, 20 | .toast-message label { 21 | color: #ffffff; 22 | } 23 | .toast-message a:hover { 24 | color: #cccccc; 25 | text-decoration: none; 26 | } 27 | 28 | .toast-close-button { 29 | position: relative; 30 | right: -0.3em; 31 | top: -0.3em; 32 | float: right; 33 | font-size: 20px; 34 | font-weight: bold; 35 | color: #ffffff; 36 | -webkit-text-shadow: 0 1px 0 #ffffff; 37 | text-shadow: 0 1px 0 #ffffff; 38 | opacity: 0.8; 39 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); 40 | filter: alpha(opacity=80); 41 | } 42 | .toast-close-button:hover, 43 | .toast-close-button:focus { 44 | color: #000000; 45 | text-decoration: none; 46 | cursor: pointer; 47 | opacity: 0.4; 48 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=40); 49 | filter: alpha(opacity=40); 50 | } 51 | 52 | /*Additional properties for button version 53 | iOS requires the button element instead of an anchor tag. 54 | If you want the anchor version, it requires `href="#"`.*/ 55 | button.toast-close-button { 56 | padding: 0; 57 | cursor: pointer; 58 | background: transparent; 59 | border: 0; 60 | -webkit-appearance: none; 61 | } 62 | .toast-top-full-width { 63 | top: 0; 64 | right: 0; 65 | width: 100%; 66 | } 67 | .toast-bottom-full-width { 68 | bottom: 0; 69 | right: 0; 70 | width: 100%; 71 | } 72 | .toast-top-left { 73 | top: 12px; 74 | left: 12px; 75 | } 76 | .toast-top-right { 77 | top: 12px; 78 | right: 12px; 79 | } 80 | .toast-bottom-right { 81 | right: 12px; 82 | bottom: 12px; 83 | } 84 | .toast-bottom-left { 85 | bottom: 12px; 86 | left: 12px; 87 | } 88 | #toast-container { 89 | position: fixed; 90 | z-index: 999999; 91 | /*overrides*/ 92 | 93 | } 94 | #toast-container * { 95 | -moz-box-sizing: border-box; 96 | -webkit-box-sizing: border-box; 97 | box-sizing: border-box; 98 | } 99 | #toast-container > div { 100 | margin: 0 0 6px; 101 | padding: 15px 15px 15px 50px; 102 | width: 300px; 103 | -moz-border-radius: 3px 3px 3px 3px; 104 | -webkit-border-radius: 3px 3px 3px 3px; 105 | border-radius: 3px 3px 3px 3px; 106 | background-position: 15px center; 107 | background-repeat: no-repeat; 108 | -moz-box-shadow: 0 0 12px #999999; 109 | -webkit-box-shadow: 0 0 12px #999999; 110 | box-shadow: 0 0 12px #999999; 111 | color: #ffffff; 112 | opacity: 0.8; 113 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=80); 114 | filter: alpha(opacity=80); 115 | } 116 | #toast-container > :hover { 117 | -moz-box-shadow: 0 0 12px #000000; 118 | -webkit-box-shadow: 0 0 12px #000000; 119 | box-shadow: 0 0 12px #000000; 120 | opacity: 1; 121 | -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100); 122 | filter: alpha(opacity=100); 123 | cursor: pointer; 124 | } 125 | #toast-container > .toast-info { 126 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=") !important; 127 | } 128 | #toast-container > .toast-error { 129 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=") !important; 130 | } 131 | #toast-container > .toast-success { 132 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==") !important; 133 | } 134 | #toast-container > .toast-warning { 135 | background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=") !important; 136 | } 137 | #toast-container.toast-top-full-width > div, 138 | #toast-container.toast-bottom-full-width > div { 139 | width: 96%; 140 | margin: auto; 141 | } 142 | .toast { 143 | background-color: #030303; 144 | } 145 | .toast-success { 146 | background-color: #51a351; 147 | } 148 | .toast-error { 149 | background-color: #bd362f; 150 | } 151 | .toast-info { 152 | background-color: #2f96b4; 153 | } 154 | .toast-warning { 155 | background-color: #f89406; 156 | } 157 | /*Responsive Design*/ 158 | @media all and (max-width: 240px) { 159 | #toast-container > div { 160 | padding: 8px 8px 8px 50px; 161 | width: 11em; 162 | } 163 | #toast-container .toast-close-button { 164 | right: -0.2em; 165 | top: -0.2em; 166 | } 167 | } 168 | @media all and (min-width: 241px) and (max-width: 480px) { 169 | #toast-container > div { 170 | padding: 8px 8px 8px 50px; 171 | width: 18em; 172 | } 173 | #toast-container .toast-close-button { 174 | right: -0.2em; 175 | top: -0.2em; 176 | } 177 | } 178 | @media all and (min-width: 481px) and (max-width: 768px) { 179 | #toast-container > div { 180 | padding: 15px 15px 15px 50px; 181 | width: 25em; 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /data_analysis/static/javascript/toastr.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Toastr 3 | * Version 2.0.1 4 | * Copyright 2012 John Papa and Hans Fjällemark. 5 | * All Rights Reserved. 6 | * Use, reproduction, distribution, and modification of this code is subject to the terms and 7 | * conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php 8 | * 9 | * Author: John Papa and Hans Fjällemark 10 | * Project: https://github.com/CodeSeven/toastr 11 | */ 12 | ; (function (define) { 13 | define(['jquery'], function ($) { 14 | return (function () { 15 | var version = '2.0.1'; 16 | var $container; 17 | var listener; 18 | var toastId = 0; 19 | var toastType = { 20 | error: 'error', 21 | info: 'info', 22 | success: 'success', 23 | warning: 'warning' 24 | }; 25 | 26 | var toastr = { 27 | clear: clear, 28 | error: error, 29 | getContainer: getContainer, 30 | info: info, 31 | options: {}, 32 | subscribe: subscribe, 33 | success: success, 34 | version: version, 35 | warning: warning 36 | }; 37 | 38 | return toastr; 39 | 40 | //#region Accessible Methods 41 | function error(message, title, optionsOverride) { 42 | return notify({ 43 | type: toastType.error, 44 | iconClass: getOptions().iconClasses.error, 45 | message: message, 46 | optionsOverride: optionsOverride, 47 | title: title 48 | }); 49 | } 50 | 51 | function info(message, title, optionsOverride) { 52 | return notify({ 53 | type: toastType.info, 54 | iconClass: getOptions().iconClasses.info, 55 | message: message, 56 | optionsOverride: optionsOverride, 57 | title: title 58 | }); 59 | } 60 | 61 | function subscribe(callback) { 62 | listener = callback; 63 | } 64 | 65 | function success(message, title, optionsOverride) { 66 | return notify({ 67 | type: toastType.success, 68 | iconClass: getOptions().iconClasses.success, 69 | message: message, 70 | optionsOverride: optionsOverride, 71 | title: title 72 | }); 73 | } 74 | 75 | function warning(message, title, optionsOverride) { 76 | return notify({ 77 | type: toastType.warning, 78 | iconClass: getOptions().iconClasses.warning, 79 | message: message, 80 | optionsOverride: optionsOverride, 81 | title: title 82 | }); 83 | } 84 | 85 | function clear($toastElement) { 86 | var options = getOptions(); 87 | if (!$container) { getContainer(options); } 88 | if ($toastElement && $(':focus', $toastElement).length === 0) { 89 | $toastElement[options.hideMethod]({ 90 | duration: options.hideDuration, 91 | easing: options.hideEasing, 92 | complete: function () { removeToast($toastElement); } 93 | }); 94 | return; 95 | } 96 | if ($container.children().length) { 97 | $container[options.hideMethod]({ 98 | duration: options.hideDuration, 99 | easing: options.hideEasing, 100 | complete: function () { $container.remove(); } 101 | }); 102 | } 103 | } 104 | //#endregion 105 | 106 | //#region Internal Methods 107 | 108 | function getDefaults() { 109 | return { 110 | tapToDismiss: true, 111 | toastClass: 'toast', 112 | containerId: 'toast-container', 113 | debug: false, 114 | 115 | showMethod: 'fadeIn', //fadeIn, slideDown, and show are built into jQuery 116 | showDuration: 300, 117 | showEasing: 'swing', //swing and linear are built into jQuery 118 | onShown: undefined, 119 | hideMethod: 'fadeOut', 120 | hideDuration: 1000, 121 | hideEasing: 'swing', 122 | onHidden: undefined, 123 | 124 | extendedTimeOut: 1000, 125 | iconClasses: { 126 | error: 'toast-error', 127 | info: 'toast-info', 128 | success: 'toast-success', 129 | warning: 'toast-warning' 130 | }, 131 | iconClass: 'toast-info', 132 | positionClass: 'toast-top-right', 133 | timeOut: 5000, // Set timeOut and extendedTimeout to 0 to make it sticky 134 | titleClass: 'toast-title', 135 | messageClass: 'toast-message', 136 | target: 'body', 137 | closeHtml: '', 138 | newestOnTop: true 139 | }; 140 | } 141 | 142 | function publish(args) { 143 | if (!listener) { 144 | return; 145 | } 146 | listener(args); 147 | } 148 | 149 | function notify(map) { 150 | var 151 | options = getOptions(), 152 | iconClass = map.iconClass || options.iconClass; 153 | 154 | if (typeof (map.optionsOverride) !== 'undefined') { 155 | options = $.extend(options, map.optionsOverride); 156 | iconClass = map.optionsOverride.iconClass || iconClass; 157 | } 158 | 159 | toastId++; 160 | 161 | $container = getContainer(options); 162 | var 163 | intervalId = null, 164 | $toastElement = $('
'), 165 | $titleElement = $('
'), 166 | $messageElement = $('
'), 167 | $closeElement = $(options.closeHtml), 168 | response = { 169 | toastId: toastId, 170 | state: 'visible', 171 | startTime: new Date(), 172 | options: options, 173 | map: map 174 | }; 175 | 176 | if (map.iconClass) { 177 | $toastElement.addClass(options.toastClass).addClass(iconClass); 178 | } 179 | 180 | if (map.title) { 181 | $titleElement.append(map.title).addClass(options.titleClass); 182 | $toastElement.append($titleElement); 183 | } 184 | 185 | if (map.message) { 186 | $messageElement.append(map.message).addClass(options.messageClass); 187 | $toastElement.append($messageElement); 188 | } 189 | 190 | if (options.closeButton) { 191 | $closeElement.addClass('toast-close-button'); 192 | $toastElement.prepend($closeElement); 193 | } 194 | 195 | $toastElement.hide(); 196 | if (options.newestOnTop) { 197 | $container.prepend($toastElement); 198 | } else { 199 | $container.append($toastElement); 200 | } 201 | 202 | 203 | $toastElement[options.showMethod]( 204 | { duration: options.showDuration, easing: options.showEasing, complete: options.onShown } 205 | ); 206 | if (options.timeOut > 0) { 207 | intervalId = setTimeout(hideToast, options.timeOut); 208 | } 209 | 210 | $toastElement.hover(stickAround, delayedhideToast); 211 | if (!options.onclick && options.tapToDismiss) { 212 | $toastElement.click(hideToast); 213 | } 214 | if (options.closeButton && $closeElement) { 215 | $closeElement.click(function (event) { 216 | event.stopPropagation(); 217 | hideToast(true); 218 | }); 219 | } 220 | 221 | if (options.onclick) { 222 | $toastElement.click(function () { 223 | options.onclick(); 224 | hideToast(); 225 | }); 226 | } 227 | 228 | publish(response); 229 | 230 | if (options.debug && console) { 231 | console.log(response); 232 | } 233 | 234 | return $toastElement; 235 | 236 | function hideToast(override) { 237 | if ($(':focus', $toastElement).length && !override) { 238 | return; 239 | } 240 | return $toastElement[options.hideMethod]({ 241 | duration: options.hideDuration, 242 | easing: options.hideEasing, 243 | complete: function () { 244 | removeToast($toastElement); 245 | if (options.onHidden) { 246 | options.onHidden(); 247 | } 248 | response.state = 'hidden'; 249 | response.endTime = new Date(), 250 | publish(response); 251 | } 252 | }); 253 | } 254 | 255 | function delayedhideToast() { 256 | if (options.timeOut > 0 || options.extendedTimeOut > 0) { 257 | intervalId = setTimeout(hideToast, options.extendedTimeOut); 258 | } 259 | } 260 | 261 | function stickAround() { 262 | clearTimeout(intervalId); 263 | $toastElement.stop(true, true)[options.showMethod]( 264 | { duration: options.showDuration, easing: options.showEasing } 265 | ); 266 | } 267 | } 268 | function getContainer(options) { 269 | if (!options) { options = getOptions(); } 270 | $container = $('#' + options.containerId); 271 | if ($container.length) { 272 | return $container; 273 | } 274 | $container = $('
') 275 | .attr('id', options.containerId) 276 | .addClass(options.positionClass); 277 | $container.appendTo($(options.target)); 278 | return $container; 279 | } 280 | 281 | function getOptions() { 282 | return $.extend({}, getDefaults(), toastr.options); 283 | } 284 | 285 | function removeToast($toastElement) { 286 | if (!$container) { $container = getContainer(); } 287 | if ($toastElement.is(':visible')) { 288 | return; 289 | } 290 | $toastElement.remove(); 291 | $toastElement = null; 292 | if ($container.children().length === 0) { 293 | $container.remove(); 294 | } 295 | } 296 | //#endregion 297 | 298 | })(); 299 | }); 300 | }(typeof define === 'function' && define.amd ? define : function (deps, factory) { 301 | if (typeof module !== 'undefined' && module.exports) { //Node 302 | module.exports = factory(require(deps[0])); 303 | } else { 304 | window['toastr'] = factory(window['jQuery']); 305 | } 306 | })); 307 | -------------------------------------------------------------------------------- /data_analysis/views.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | import random 3 | import datetime 4 | from flask import (Blueprint, request, redirect, render_template, url_for, 5 | jsonify) 6 | from flask.views import MethodView 7 | from data_analysis.models import Apidist, Celery, Mongo 8 | 9 | posts = Blueprint('posts', __name__, template_folder='templates') 10 | 11 | color = ["#FF0F00", "#FF6600", "#FF9E01", "#FCD202", "#F8FF01", "#B0DE09", 12 | "#04D215", "#0D8ECF", "#0D52D1", "#2A0CD0", "#8A0CCF", "#CD0D74", 13 | "#754DEB", "#2c3e50", "#2c3e50", "#e67e22", "#e74c3c", "#ecf0f1", 14 | "#95a5a6", "#d35400", "#8e44ad", "#8e44ad", "#bdc3c7", "#d35400", 15 | "#1abc9c", "#2ecc71", "#3498db", "#9b59b6", "#34495e"] 16 | 17 | celery = dict(task=[('count', ["simple_column", "pie"]), 18 | ('cost', ["multi_column"])], 19 | time=[('count', ["simple_column", "pie"])]) 20 | 21 | mongo = dict(all=[('getmore', ["multi_column"]), ('update', ["multi_column"]), 22 | ('insert', ["multi_column"]), ('command', ["multi_column"]), 23 | ('query', ["multi_column"])], 24 | sentiment=[('getmore', ["multi_column"]), ('update', ["multi_column"]), 25 | ('insert', ["multi_column"]), ('command', ["multi_column"]), 26 | ('query', ["multi_column"])], 27 | qq_online=[('getmore', ["multi_column"]), ('update', ["multi_column"]), 28 | ('insert', ["multi_column"]), ('command', ["multi_column"]), 29 | ('query', ["multi_column"])], 30 | total=[('getmore', ["simple_column", "pie"]), 31 | ('update', ["simple_column", "pie"]), 32 | ('insert', ["simple_column", "pie"]), 33 | ('command', ["simple_column", "pie"]), 34 | ('query', ["simple_column", "pie"]), 35 | ('all_op', ["simple_column", "pie"]), 36 | ('all_slow', ["simple_column", "pie"])]) 37 | d3 = dict() 38 | 39 | 40 | def make_json(res, title, category, value, chart, key, des, total, titles=None, 41 | values=None): 42 | color1, color2, color3 = None, None, None 43 | if titles is not None: 44 | func= lambda x:x[values[key]] 45 | else: 46 | func= lambda x:x[value] 47 | dict_list = sorted(res, key=func, reverse=True) 48 | if titles is None: 49 | l = len(dict_list) 50 | color_choice = random.sample(color, l) 51 | for num, d in enumerate(dict_list): 52 | d['color'] = color_choice[num] 53 | else: 54 | color_choice = random.sample(color, 3) 55 | for d in dict_list: 56 | d['color1'] = color_choice[0] 57 | d['color2'] = color_choice[1] 58 | d['color3'] = color_choice[2] 59 | return jsonify(result=dict_list, title=title, category=category, des=des, 60 | value=value, titles=titles, values=values, chart=chart, 61 | total=total) 62 | 63 | def make_factory(change_dict): 64 | dict = {'title': 'name', 'value': 'call'} 65 | dict.update(change_dict) 66 | return dict 67 | 68 | class JsonView(MethodView): 69 | 70 | def get(self, url): 71 | if url == 'celery': 72 | return jsonify(celery) 73 | elif url == 'mongo': 74 | return jsonify(mongo) 75 | 76 | class IndexView(MethodView): 77 | 78 | def get(self): 79 | return redirect(url_for('.mongo')) 80 | 81 | class D3View(MethodView): 82 | 83 | def get(self): 84 | return render_template('posts/d3.html', des=u'celery任务调用次数略览', 85 | title=u'Celery Task调用分布') 86 | 87 | class TroubleView(MethodView): 88 | 89 | def get(self): 90 | return render_template('posts/trouble.html', title=u'Mongodb存在问题分析', 91 | des=u'总结错误索引原因和解决方案') 92 | 93 | class MongoView(MethodView): 94 | 95 | def get(self): 96 | l = Mongo.objects.distinct(field="database") 97 | #l.insert(0, 'all') 98 | l.insert(0, 'total') 99 | return render_template('posts/index.html', first_type=u'Mongodb分析', 100 | title=u'Mongodb使用数据分析', l=l, 101 | des=u'数据库操作数据分析') 102 | 103 | def all(self, type): 104 | return self.time('all', type) 105 | 106 | def sentiment(self, type): 107 | return self.time('sentiment', type) 108 | 109 | def qq_online(self, type): 110 | return self.time('qq_online', type) 111 | 112 | def time(self, database, type): 113 | if database == 'all': 114 | obj = Mongo.objects()['hour'] 115 | else: 116 | obj = Mongo.objects(database=database)[0]['hour'] 117 | o = [] 118 | all_total = 0 119 | slow_total = 0 120 | for i in range(24): 121 | i = str(i) 122 | d = {} 123 | d['name'] = u'{0}时'.format(str(i)) 124 | d['op'] = obj[i]['op'][type] 125 | d['slow'] = obj[i]['slow'][type] 126 | all_total += d['op'] 127 | slow_total += d['slow'] 128 | o.append(d) 129 | titles = (u'慢查询', u'全部查询') 130 | values = ('slow', 'op') 131 | return make_factory({'titles': titles, type: o, 132 | 'total': '慢查询:{0}, 全部查询:{1}'.format( 133 | slow_total, all_total), 134 | 'des': '[数据库{0} 类型{1}] 总量'.format(database, 135 | type), 136 | 'category': u'mongodb分析', 'values': values}) 137 | 138 | def total_data(self, type): 139 | getmore, insert, update, command, query = 0, 0, 0, 0, 0 140 | for i in range(24): 141 | for obj in Mongo.objects(): 142 | insert += obj['hour'][str(i)][type]['insert'] 143 | update += obj['hour'][str(i)][type]['update'] 144 | command += obj['hour'][str(i)][type]['command'] 145 | query += obj['hour'][str(i)][type]['query'] 146 | getmore += obj['hour'][str(i)][type]['getmore'] 147 | count = [] 148 | for name, call in ((u'查询', query), (u'插入', insert), 149 | (u'命令', command), (u'更新', update), 150 | ('getomre', getmore)): 151 | d = {} 152 | d['name'] = name 153 | d['call'] = call 154 | count.append(d) 155 | total = getmore + insert + update + command + query 156 | return count, total 157 | 158 | def all_op(self): 159 | data = self.total_data('op') 160 | return make_factory({'all_op': data[0], 'des': u'数据库操作总量', 161 | 'category': u'mongodb操作分布', 162 | 'total': data[1]}) 163 | 164 | def all_slow(self): 165 | data = self.total_data('slow') 166 | return make_factory({'all_slow': data[0], 'des': u'数据库慢查询总量', 167 | 'category': u'mongodb慢操作分布', 168 | 'total': data[1]}) 169 | 170 | def total(self, type): 171 | if type == 'all_op': 172 | return self.all_op() 173 | elif type == 'all_slow': 174 | return self.all_slow() 175 | call = 0 176 | call_total = 0 177 | count = [] 178 | for i in range(24): 179 | d = {} 180 | for obj in Mongo.objects(): 181 | call += obj['hour'][str(i)]['total'] 182 | d['name'] = u'{0}时'.format(str(i)) 183 | d['call'] = call 184 | call_total += call 185 | call = 0 186 | count.append(d) 187 | return make_factory({type: count, 'category':u'mongodb分布', 188 | 'des': u'数据库查询总量', 189 | 'total': call_total}) 190 | 191 | def post(self): 192 | return get_form(request, self, mongo, key=1) 193 | 194 | 195 | def get_form(request, self, type, key=2): 196 | vt = request.form.getlist('vt')[0] 197 | data_type = request.form.getlist('type')[0] 198 | data_type = data_type if data_type else type[vt][0][0] 199 | chart = request.form.getlist('chart')[0] 200 | if not chart: 201 | for t in type[vt]: 202 | if data_type == t[0]: 203 | chart = t[1][0] 204 | data = getattr(self, vt)(data_type) 205 | if chart in ["simple_column", "pie"]: 206 | return make_json(data[data_type], data['title'], data['category'], 207 | data['value'], chart, key, data['des'], data['total']) 208 | elif chart == 'multi_column': 209 | return make_json(data[data_type], data['title'], data['category'], 210 | data['value'], chart, key, data['des'], data['total'], 211 | titles=data['titles'], values=data['values']) 212 | 213 | 214 | class CeleryView(MethodView): 215 | def time(self, type): 216 | count = [] 217 | total = 0 218 | for i in range(23): 219 | d = {} 220 | d['name'] = u'{0}时'.format(str(i)) 221 | d['call'] = Celery.objects( 222 | time__gte=datetime.datetime(2013, 10, 27, i), 223 | time__lt=datetime.datetime(2013, 10, 27, i+1)).count() 224 | total += d['call'] 225 | count.append(d) 226 | return make_factory(dict(count=count, category=u'celery分布', 227 | des=u'celery总量', total=total)) 228 | 229 | def post(self): 230 | return get_form(request, self, celery) 231 | 232 | def task(self, type): 233 | count = [] 234 | cost = [] 235 | total = 0 236 | for i in Celery.objects.distinct(field='task'): 237 | d = {} 238 | c = {} 239 | data = Celery.objects(task=i) 240 | d['call'] = data.count() 241 | d['name'], c['name'] = i, i 242 | c['avg'] = data.order_by('cost')[0].cost, # min 243 | c['min'] = data.average('cost'), 244 | c['max'] = data.order_by('-cost')[0].cost # max 245 | total += d['call'] 246 | cost.append(c) 247 | count.append(d) 248 | titles = (u'最小值', u'平均值', u'最大值') 249 | values = ('avg', 'min', 'max') 250 | return make_factory(dict(titles=titles, count=count, cost=cost, 251 | category=u'celery分析', values=values, 252 | des=u'celery总量', total=total)) 253 | 254 | def get(self): 255 | l = ['task', 'time'] 256 | return render_template('posts/index.html', first_type=u'监控类型', 257 | title=u'mongo日志分析', 258 | des=u'分析mongodb全天日志整理的分布数据', l=l) 259 | 260 | posts.add_url_rule('/mongo/', view_func=MongoView.as_view('mongo')) 261 | posts.add_url_rule('/', view_func=IndexView.as_view('index')) 262 | posts.add_url_rule('/celery/', view_func=CeleryView.as_view('celery')) 263 | posts.add_url_rule('/json//', view_func=JsonView.as_view('json')) 264 | posts.add_url_rule('/d3/', view_func=D3View.as_view('d3')) 265 | posts.add_url_rule('/trouble/', view_func=TroubleView.as_view('trouble')) 266 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /data_analysis/static/stylesheet/blue.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #777; 3 | } 4 | 5 | body, 6 | .pure-g [class *= "pure-u"], 7 | .pure-g-r [class *= "pure-u"] { 8 | font-family: "proxima-nova", sans-serif; 9 | } 10 | 11 | 12 | /* Add transition to containers so they can push in and out */ 13 | #layout, 14 | #menu, 15 | .pure-menu-link { 16 | -webkit-transition: all 0.2s ease-out; 17 | -moz-transition: all 0.2s ease-out; 18 | -ms-transition: all 0.2s ease-out; 19 | -o-transition: all 0.2s ease-out; 20 | transition: all 0.2s ease-out; 21 | } 22 | 23 | 24 | /* -------------------------- 25 | * Element Styles 26 | * -------------------------- 27 | */ 28 | 29 | 30 | h1, h2, h3, h4, h5, h6 { 31 | font-weight: bold; 32 | color: rgb(75, 75, 75); 33 | } 34 | h3 { 35 | font-size: 1.25em; 36 | } 37 | h4 { 38 | font-size: 1.125em; 39 | } 40 | 41 | a { 42 | color: #3b8bba; /* block-background-text-normal */ 43 | text-decoration: none; 44 | } 45 | 46 | a:visited { 47 | color: #265778; /* block-normal-text-normal */ 48 | } 49 | 50 | dt { 51 | font-weight: bold; 52 | } 53 | dd { 54 | margin: 0 0 10px 0; 55 | } 56 | 57 | /* -------------------------- 58 | * Layout Styles 59 | * -------------------------- 60 | */ 61 | 62 | #layout { 63 | padding-left: 150px; /* left col width "#menu" */ 64 | left: 0; 65 | } 66 | 67 | 68 | /* Apply the .box class on the immediate parent of any grid element (pure-u-*) to apply some padding. */ 69 | .l-box { 70 | padding: 1.3em; 71 | } 72 | 73 | .l-vbox { 74 | padding: 1.3em 0; 75 | } 76 | 77 | .l-hbox { 78 | padding: 0 1.3em; 79 | } 80 | 81 | .l-centered { 82 | text-align: center; 83 | } 84 | 85 | 86 | /* -------------------------- 87 | * Header Module Styles 88 | * -------------------------- 89 | */ 90 | .header { 91 | min-height: 80px; 92 | margin: 0; 93 | color: #333; 94 | padding: 1em 2em; 95 | text-align: center; 96 | border-bottom: 1px solid #eee; 97 | background: #fff; 98 | } 99 | .header h1 { 100 | font-family: "omnes-pro", sans-serif; 101 | margin: 0.2em 0; 102 | font-size: 3em; 103 | font-weight: 300; 104 | } 105 | .header h2 { 106 | font-weight: 300; 107 | margin: 0; 108 | color: #ccc; 109 | } 110 | 111 | aside { 112 | background: #1f8dd6; /* same color as selected state on site menu */ 113 | padding: 0.3em 1em; 114 | border-radius: 3px; 115 | color: #fff; 116 | } 117 | aside a, aside a:visited { 118 | color: rgb(169, 226, 255); 119 | } 120 | 121 | 122 | /* -------------------------- 123 | * Content Module Styles 124 | * -------------------------- 125 | */ 126 | 127 | /* The content div is placed as a wrapper around all the docs */ 128 | .content { 129 | margin: 0 auto; 130 | padding: 0 2em; 131 | max-width: 800px; 132 | margin-bottom: 50px; 133 | } 134 | .content p { 135 | line-height: 1.6em; 136 | font-size: 1.125em; 137 | } 138 | 139 | .content .content-subhead { 140 | margin: 50px 0 20px 0; 141 | font-weight: 300; 142 | color: #888; 143 | position: relative; 144 | } 145 | 146 | .content .content-spaced { 147 | line-height: 1.8em; 148 | } 149 | 150 | /* A code snippet that has been syntax highlighted */ 151 | .content .snippet { 152 | margin: 1.3em 0 1em; 153 | padding: 1.3em; 154 | } 155 | 156 | .content .content-quote { 157 | font-family: "Georgia", serif; 158 | color: #666; 159 | font-style: italic; 160 | line-height: 1.8em; 161 | border-left: 5px solid #ddd; 162 | padding-left: 1.5em; 163 | } 164 | 165 | .content-link { 166 | position: absolute; 167 | top: 0; 168 | right: 0; 169 | display: block; 170 | height: 100%; 171 | width: 20px; 172 | background: transparent url('/img/link-icon.png') no-repeat center center; 173 | background-size: 20px 20px; 174 | } 175 | 176 | @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { 177 | .content-link { 178 | background-image: url('/img/link-icon@2x.png'); 179 | } 180 | } 181 | 182 | /* -------------------------- 183 | * Footer Module Styles 184 | * -------------------------- 185 | */ 186 | .legal { 187 | font-size: 87.5%; 188 | border-top: 1px solid #eee; 189 | padding: 0.5em 1.1429em; 190 | background: rgb(250, 250, 250); 191 | line-height: 1.6em; 192 | } 193 | 194 | .legal-license { 195 | margin: 0; 196 | } 197 | .legal-copyright, 198 | .legal-links { 199 | text-align: right; 200 | margin: 0; 201 | } 202 | .legal-links { 203 | list-style: none; 204 | padding: 0; 205 | } 206 | .legal-logo { 207 | text-align: center; 208 | } 209 | 210 | /* -------------------------- 211 | * Main Navigation Bar Styles 212 | * -------------------------- 213 | */ 214 | 215 | #menu { 216 | margin-left: -150px; /* "#menu" width */ 217 | width: 150px; 218 | position: fixed; 219 | top: 0; 220 | left: 150px; 221 | bottom: 0; 222 | z-index: 1000; /* so the menu or its navicon stays above all content */ 223 | background: #191818; 224 | overflow-y: auto; 225 | -webkit-overflow-scroll: touch; 226 | } 227 | #menu a { 228 | color: #999; 229 | border: none; 230 | text-align: center; 231 | white-space: normal; 232 | padding: 0.6em 0 0.6em 0.6em; 233 | } 234 | 235 | #menu .pure-menu-open { 236 | background: transparent; 237 | border: 0; 238 | } 239 | 240 | #menu .pure-menu ul { 241 | border: none; 242 | background: transparent; 243 | } 244 | 245 | #menu .pure-menu ul, 246 | #menu .pure-menu .menu-item-divided { 247 | border-top: 1px solid #333; 248 | } 249 | 250 | #menu .pure-menu li a:hover, 251 | #menu .pure-menu li a:focus { 252 | background: #333; 253 | } 254 | 255 | .pure-menu-link { 256 | display: none; /* show this only on small screens */ 257 | top: 0; 258 | left: 150px; /* "#menu width" */ 259 | background: #000; 260 | background: rgba(0,0,0,0.7); 261 | font-size: 10px; /* change this value to increase/decrease button size */ 262 | z-index: 10; 263 | width: 2em; 264 | height: auto; 265 | padding: 2.1em 1.6em; 266 | } 267 | 268 | .pure-menu-link:hover, 269 | .pure-menu-link:focus { 270 | background: #000; 271 | } 272 | 273 | .pure-menu-link span { 274 | position: relative; 275 | display: block; 276 | } 277 | 278 | .pure-menu-link span, 279 | .pure-menu-link span:before, 280 | .pure-menu-link span:after { 281 | background-color: #fff; 282 | width: 100%; 283 | height: .2em; 284 | -webkit-transition: all 0.8s; 285 | -moz-transition: all 0.8s; 286 | -ms-transition: all 0.8s; 287 | -o-transition: all 0.8s; 288 | transition: all 0.8s; 289 | } 290 | 291 | .pure-menu-link span:before, 292 | .pure-menu-link span:after { 293 | position: absolute; 294 | margin-top: -.6em; 295 | content: " "; 296 | } 297 | 298 | .pure-menu-link span:after { 299 | margin-top: .6em; 300 | } 301 | 302 | .pure-menu-link.active span { 303 | background: transparent; 304 | } 305 | 306 | .pure-menu-link.active span:before { 307 | -webkit-transform: rotate(45deg) translate(.5em, .4em); 308 | -moz-transform: rotate(45deg) translate(.5em, .4em); 309 | -ms-transform: rotate(45deg) translate(.5em, .4em); 310 | -o-transform: rotate(45deg) translate(.5em, .4em); 311 | transform: rotate(45deg) translate(.5em, .4em); 312 | } 313 | 314 | .pure-menu-link.active span:after { 315 | -webkit-transform: rotate(-45deg) translate(.45em, -.35em); 316 | -moz-transform: rotate(-45deg) translate(.45em, -.35em); 317 | -ms-transform: rotate(-45deg) translate(.45em, -.35em); 318 | -o-transform: rotate(-45deg) translate(.45em, -.35em); 319 | transform: rotate(-45deg) translate(.45em, -.35em); 320 | } 321 | 322 | #menu .pure-menu-heading { 323 | font-size: 110%; 324 | color: #fff; 325 | } 326 | #menu .pure-menu-heading:hover, 327 | #menu .pure-menu-heading:focus { 328 | color: #999; 329 | } 330 | 331 | #menu .pure-menu-selected { 332 | background: #1f8dd6; 333 | } 334 | 335 | #menu .pure-menu-selected a { 336 | color: #fff; 337 | } 338 | 339 | #menu li.pure-menu-selected a:hover, 340 | #menu li.pure-menu-selected a:focus { 341 | background: none; 342 | } 343 | 344 | 345 | 346 | /* --------------------- 347 | * Smaller Module Styles 348 | * --------------------- 349 | */ 350 | 351 | /* example code blocks */ 352 | .example-snippet { 353 | margin: 2em 0; 354 | font-size: 85%; 355 | } 356 | 357 | /* green call to action button class */ 358 | .notice { 359 | background-color: #61B842; 360 | color: white; 361 | } 362 | 363 | .pure-button { 364 | font-family: inherit; 365 | } 366 | a.pure-button-primary { 367 | color: white; 368 | } 369 | 370 | .muted { 371 | color: #ccc; 372 | } 373 | 374 | /* -------------------------- 375 | * Responsive Styles 376 | * -------------------------- 377 | */ 378 | 379 | @media (max-width: 870px) { 380 | 381 | /* Navigation Push Styles */ 382 | #layout { 383 | position: relative; 384 | padding-left: 0; 385 | } 386 | #layout.active { 387 | position: relative; 388 | left: 150px; 389 | } 390 | #layout.active #menu { 391 | left: 150px; 392 | width: 150px; 393 | } 394 | 395 | #menu { 396 | left: 0; 397 | } 398 | 399 | .pure-menu-link { 400 | position: fixed; 401 | left: 0; 402 | display: block; 403 | } 404 | 405 | #layout.active .pure-menu-link { 406 | left: 150px; 407 | } 408 | } 409 | 410 | @media (max-width: 767px) { 411 | 412 | .header, 413 | .content { 414 | font-size: 87.5%; 415 | } 416 | 417 | .header, 418 | .content, 419 | .legal { 420 | padding-left: 1.1429em; 421 | padding-right: 1.1429em; 422 | } 423 | 424 | .legal-license, 425 | .legal-copyright, 426 | .legal-links, 427 | .legal-links li { 428 | text-align: center; 429 | } 430 | 431 | /* normalize paddings on small screens*/ 432 | .l-hbox { 433 | padding: 1.3em; 434 | } 435 | } 436 | 437 | /** 438 | * Baby Blue theme for RainbowJS 439 | * 440 | * @author tilomitra 441 | */ 442 | 443 | pre { 444 | word-wrap: break-word; 445 | padding: 6px 10; 446 | line-height: 1.3em; 447 | margin-bottom: 20; 448 | border: 1px solid #eee; 449 | } 450 | 451 | code { 452 | border: none; 453 | margin: 0 2px; 454 | font-size: 0.8em; 455 | padding: 0.4em 0.6em; 456 | white-space: nowrap; 457 | } 458 | 459 | pre code { 460 | padding: 0; 461 | margin: 0; 462 | font-size: 0.95em; 463 | white-space: pre-wrap; 464 | } 465 | 466 | pre, code { 467 | font-family: Consolas, 'Liberation Mono', Courier, monospace; 468 | color: #333; 469 | background: rgb(250, 250, 250); 470 | } 471 | 472 | 473 | pre .comment { 474 | color: #999; 475 | } 476 | 477 | 478 | pre .tag, pre .tag-name, pre .support.tag-name { 479 | color: rgb(85, 85, 85); 480 | } 481 | 482 | pre .keyword, pre .css-property, pre .vendor-prefix, pre .sass, pre .class, pre .id, pre .css-value, pre .entity.function, pre .storage.function { 483 | font-weight: bold; 484 | } 485 | 486 | pre .css-property, pre .css-value, pre .vendor-prefix, pre .support.namespace { 487 | color: #333; 488 | } 489 | 490 | pre .constant.numeric, pre .keyword.unit, pre .hex-color { 491 | font-weight: normal; 492 | color: #099; 493 | } 494 | 495 | pre .attribute, pre .variable, pre .support { 496 | color: #757575; /* skinbuilder block-page-text-normal with #1f8dd6 as primary */ 497 | } 498 | 499 | pre .string, pre .support.value { 500 | font-weight: normal; 501 | color: #3b8bba; /* skinbuilder block-mine-text-low with #1f8dd6 as primary */ 502 | } 503 | 504 | 505 | #menu .ads-label-personal, #menu .ads-label-work, 506 | #menu .ads-label-travel { 507 | width: 15px; 508 | height: 15px; 509 | display: inline-block; 510 | margin-right: 0.5em; 511 | border-radius: 3px; 512 | } 513 | #menu .ads-label-personal { 514 | background: #ffc94c; 515 | } 516 | #menu .ads-label-work { 517 | background: #41ccb4; 518 | } 519 | #menu .ads-label-travel { 520 | background: #40c365; 521 | } -------------------------------------------------------------------------------- /data_analysis/static/javascript/detector.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Chrome AppSniffer 3 | * 4 | * Detect apps run on current page and send back to background page. 5 | * Some part of this script was refered from Wappalyzer Firefox Addon. 6 | * 7 | * @author Bao Nguyen 8 | * @license GPLv3 9 | **/ 10 | 11 | (function () { 12 | var _apps = {}; 13 | var doc = document.documentElement; 14 | var a 15 | 16 | // 1: detect by meta tags, the first matching group will be version 17 | var metas = doc.getElementsByTagName("meta"); 18 | var meta_tests = { 19 | 'generator': { 20 | 'Joomla': /joomla!?\s*([\d\.]+)?/i, 21 | 'vBulletin': /vBulletin\s*(.*)/i, 22 | 'WordPress': /WordPress\s*(.*)/i, 23 | 'XOOPS': /xoops/i, 24 | 'Plone': /plone/i, 25 | 'MediaWiki': /MediaWiki/i, 26 | 'CMSMadeSimple': /CMS Made Simple/i, 27 | 'SilverStripe': /SilverStripe/i, 28 | 'Movable Type': /Movable Type/i, 29 | 'Amiro.CMS': /Amiro/i, 30 | 'Koobi': /koobi/i, 31 | 'bbPress': /bbPress/i, 32 | 'DokuWiki': /dokuWiki/i, 33 | 'TYPO3': /TYPO3/i, 34 | 'PHP-Nuke': /PHP-Nuke/i, 35 | 'DotNetNuke': /DotNetNuke/i, 36 | 'Sitefinity': /Sitefinity\s+(.*)/i, 37 | 'WebGUI': /WebGUI/i, 38 | 'ez Publish': /eZ\s*Publish/i, 39 | 'BIGACE': /BIGACE/i, 40 | 'TypePad': /typepad\.com/i, 41 | 'Blogger': /blogger/i, 42 | 'PrestaShop': /PrestaShop/i, 43 | 'SharePoint': /SharePoint/, 44 | 'JaliosJCMS': /Jalios JCMS/i, 45 | 'ZenCart': /zen-cart/i, 46 | 'WPML': /WPML/i, 47 | 'PivotX': /PivotX/i, 48 | 'OpenACS': /OpenACS/i, 49 | 'AlphaCMS': /alphacms\s+(.*)/i, 50 | 'concrete5': /concrete5 -\s*(.*)$/, 51 | 'Webnode': /Webnode/, 52 | 'GetSimple': /GetSimple/, 53 | 'DataLifeEngine': /DataLife Engine/, 54 | 'ClanSphere': /ClanSphere/, 55 | }, 56 | 'copyright': { 57 | 'phpBB': /phpBB/i 58 | }, 59 | 'elggrelease': { 60 | 'Elgg': /.+/ 61 | }, 62 | 'powered-by': { 63 | 'Serendipity': /Serendipity/i, 64 | }, 65 | 'author': { 66 | 'Avactis': /Avactis Team/i 67 | } 68 | }; 69 | 70 | for (var idx in metas) 71 | { 72 | var m = metas[idx]; 73 | var name = m.name ? m.name.toLowerCase() : ""; 74 | 75 | if (!meta_tests[name]) continue; 76 | 77 | for (var t in meta_tests[name]) 78 | { 79 | if (t in _apps) continue; 80 | 81 | var r = meta_tests[name][t].exec(m.content); 82 | if (r) 83 | { 84 | _apps[t] = r[1] ? r[1] : -1; 85 | } 86 | } 87 | } 88 | 89 | // 2: detect by script tags 90 | var scripts = doc.getElementsByTagName("script"); 91 | 92 | var script_tests = { 93 | 'Google Analytics': /google-analytics.com\/(ga|urchin).js/i, 94 | 'Quantcast': /quantserve\.com\/quant\.js/i, 95 | 'Prototype': /prototype\.js/i, 96 | 'Joomla': /\/components\/com_/, 97 | 'Ubercart': /uc_cart/i, 98 | 'Closure': /\/goog\/base\.js/i, 99 | 'MODx': /\/min\/b=.*f=.*/, 100 | 'MooTools': /mootools/i, 101 | 'Dojo': /dojo(\.xd)?\.js/i, 102 | 'script.aculo.us': /scriptaculous\.js/i, 103 | 'Disqus': /disqus.com\/forums/i, 104 | 'GetSatisfaction': /getsatisfaction\.com\/feedback/i, 105 | 'Wibiya': /wibiya\.com\/Loaders\//i, 106 | 'reCaptcha': /(google\.com\/recaptcha|api\.recaptcha\.net\/)/i, 107 | 'Mollom': /mollom\/mollom\.js/i, // only work on Drupal now 108 | 'ZenPhoto': /zp-core\/js/i, 109 | 'Gallery2': /main\.php\?.*g2_.*/i, 110 | 'AdSense': /pagead\/show_ads\.js/, 111 | 'XenForo': /js\/xenforo\//i, 112 | 'Cappuccino': /Frameworks\/Objective-J\/Objective-J\.js/, 113 | 'Avactis': /\/avactis-themes\//i, 114 | 'Volusion': /a\/j\/javascripts\.js/, 115 | 'AddThis': /addthis\.com\/js/, 116 | 'BuySellAds': /buysellads.com\/.*bsa\.js/, 117 | 'Weebly': /weebly\.com\/weebly\//, 118 | 'Bootstrap': /bootstrap-.*\.js/, 119 | 'Jigsy': /javascripts\/asterion\.js/, // may change later 120 | 'Yola': /analytics\.yola\.net/, // may change later 121 | 'Alfresco': /(alfresco)+(-min)?(\/scripts\/menu)?\.js/ // both Alfresco Share and Explorer apps 122 | }; 123 | 124 | for (var idx in scripts) 125 | { 126 | var s = scripts[idx]; 127 | if (!s.src) continue; 128 | s = s.src; 129 | 130 | for (var t in script_tests) 131 | { 132 | if (t in _apps) continue; 133 | if (script_tests[t].test(s)) 134 | { 135 | _apps[t] = -1; 136 | } 137 | } 138 | } 139 | 140 | // 3: detect by domains 141 | 142 | // 4: detect by regexp 143 | var text = document.documentElement.outerHTML; 144 | var text_tests = { 145 | 'SMF': /