├── yandextank
├── plugins
│ ├── Report
│ │ ├── __init__.py
│ │ ├── static
│ │ │ ├── css
│ │ │ │ ├── custom.css
│ │ │ │ ├── rickshaw.css
│ │ │ │ ├── bootstrap-theme.min.css
│ │ │ │ ├── bootstrap-theme.css.map
│ │ │ │ └── bootstrap-theme.css
│ │ │ ├── favicon.ico
│ │ │ ├── fonts
│ │ │ │ ├── glyphicons-halflings-regular.eot
│ │ │ │ ├── glyphicons-halflings-regular.ttf
│ │ │ │ └── glyphicons-halflings-regular.woff
│ │ │ └── js
│ │ │ │ ├── angular-rickshaw.coffee
│ │ │ │ ├── angular-rickshaw.js
│ │ │ │ ├── ws.coffee
│ │ │ │ ├── ws.js
│ │ │ │ └── vendor
│ │ │ │ ├── cubism.min.js
│ │ │ │ ├── bootstrap.min.js
│ │ │ │ └── socket.io.min.js
│ │ ├── templates
│ │ │ ├── brief.jade
│ │ │ ├── monitoring.jade
│ │ │ ├── index.jade
│ │ │ └── offline.jade
│ │ ├── plugin.py
│ │ └── server.py
│ └── __init__.py
└── __init__.py
├── .gitignore
├── setup.py
└── README.md
/yandextank/plugins/Report/__init__.py:
--------------------------------------------------------------------------------
1 | from plugin import Plugin
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 | dist/
3 | yatank_online.egg-info/
4 | *.pyc
5 |
--------------------------------------------------------------------------------
/yandextank/plugins/Report/static/css/custom.css:
--------------------------------------------------------------------------------
1 | .fs {
2 | height: 100vh;
3 | }
4 |
--------------------------------------------------------------------------------
/yandextank/plugins/Report/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yandex-load/yatank-online/HEAD/yandextank/plugins/Report/static/favicon.ico
--------------------------------------------------------------------------------
/yandextank/plugins/Report/static/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yandex-load/yatank-online/HEAD/yandextank/plugins/Report/static/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/yandextank/plugins/Report/static/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yandex-load/yatank-online/HEAD/yandextank/plugins/Report/static/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/yandextank/plugins/Report/static/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/yandex-load/yatank-online/HEAD/yandextank/plugins/Report/static/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/yandextank/__init__.py:
--------------------------------------------------------------------------------
1 | # this is a namespace package
2 | try:
3 | import pkg_resources
4 | pkg_resources.declare_namespace(__name__)
5 | except ImportError:
6 | import pkgutil
7 | __path__ = pkgutil.extend_path(__path__, __name__)
8 |
--------------------------------------------------------------------------------
/yandextank/plugins/__init__.py:
--------------------------------------------------------------------------------
1 | # this is a namespace package
2 | try:
3 | import pkg_resources
4 | pkg_resources.declare_namespace(__name__)
5 | except ImportError:
6 | import pkgutil
7 | __path__ = pkgutil.extend_path(__path__, __name__)
8 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | from setuptools import setup
4 |
5 | setup(name='yatank-online',
6 | version='1.8.1',
7 | description='Yandex.Tank Report plugin',
8 | author='Alexey Lavrenuke',
9 | author_email='direvius@gmail.com',
10 | url='https://github.com/yandex-load/yatank-online/',
11 | packages=['yandextank.plugins.Report'],
12 | package_data={'yandextank.plugins.Report': [
13 | 'templates/*',
14 | 'static/favicon.ico',
15 | 'static/css/*',
16 | 'static/js/*.js',
17 | 'static/js/*.coffee',
18 | 'static/js/vendor/*.js',
19 | 'static/fonts/*',
20 | ]},
21 | namespace_packages=['yandextank', 'yandextank.plugins'],
22 | install_requires=[
23 | 'tornado',
24 | 'tornadio2',
25 | 'pyjade>=4.0.0',
26 | ], )
27 |
--------------------------------------------------------------------------------
/yandextank/plugins/Report/templates/brief.jade:
--------------------------------------------------------------------------------
1 | !!! 5
2 | {% autoescape None %}
3 | html(lang="en")
4 | head
5 | meta(charset="utf-8")
6 | meta(http-equiv="X-UA-Compatible", content="IE=edge")
7 | meta(name="viewport", content="width=device-width, initial-scale=1")
8 | title YndxTnk brief
9 | link(rel="shortcut icon", href="static/favicon.ico", type="image/x-icon")
10 | link(rel="icon", href="static/favicon.ico", type="image/x-icon")
11 | link(rel="stylesheet", href="static/css/bootstrap.min.css")
12 | link(rel="stylesheet", href="static/css/bootstrap-theme.min.css")
13 | link(rel="stylesheet", href="static/css/rickshaw.css")
14 | link(rel="stylesheet", href="static/css/custom.css")
15 | script(src="static/js/vendor/socket.io.min.js")
16 | script(src="static/js/vendor/jquery.min.js")
17 | script(src="static/js/vendor/angular.min.js")
18 | script(src="static/js/vendor/bootstrap.min.js")
19 | script(src="static/js/vendor/d3.min.js")
20 | script(src="static/js/vendor/rickshaw.min.js")
21 | script(src="static/js/angular-rickshaw.js")
22 | script(src="static/js/ws.js")
23 | script(type="text/javascript")
24 | document.cached_data = {{cached_data}};
25 | body
26 | .app(ng-app="ng-tank-report", ng-controller="TankReport")
27 | .fs
28 | h2 {{!quantiles.name}}
29 | rickshaw(
30 | rickshaw-series="quantiles.series",
31 | rickshaw-options="quantiles.options",
32 | rickshaw-features="quantiles.features"
33 | )
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Attention please!
2 |
3 | This plugin is not the prefered way to build reports currently. Use Yandex [Overload](https://overload.yandex.net/mainpage/guide#install) instead.
4 |
5 | This doc is for new version of a plugin (currently work-in-progress). The old one (code and doc) is here: https://github.com/yandex-load/yatank-online/tree/1.7_branch
6 |
7 | # yatank-online
8 |
9 | Yandex.Tank OnlineReport plugin. Shows you some charts while you're shooting and saves a report in the end.
10 |
11 | ## How to enable
12 | Install with ```pip install yatank-online``` and specify these lines in your Tank configuration:
13 | ```
14 | [tank]
15 | plugin_web=yandextank.plugins.Report
16 | ```
17 | Then start your shooting and go to ```http://localhost:8001/```
18 |
19 | ## WebSockets and Nginx configuration
20 |
21 | If you want to run online interface behind nginx, then this would be useful:
22 |
23 | http {
24 |
25 | <...>
26 |
27 | map $http_upgrade $connection_upgrade {
28 | default upgrade;
29 | '' close;
30 | }
31 |
32 | upstream backend {
33 | server 127.0.0.1:8001;
34 | }
35 |
36 | server {
37 |
38 | <...>
39 |
40 | location / {
41 |
42 | proxy_pass http://backend;
43 |
44 | proxy_http_version 1.1;
45 |
46 | proxy_set_header Host $host;
47 | proxy_set_header Origin $upstream_addr;
48 | proxy_set_header Upgrade $http_upgrade;
49 | proxy_set_header Connection $connection_upgrade;
50 |
51 | }
52 |
53 | <...>
54 |
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/yandextank/plugins/Report/templates/monitoring.jade:
--------------------------------------------------------------------------------
1 | !!! 5
2 | {% autoescape None %}
3 | html(lang="en")
4 | head
5 | meta(charset="utf-8")
6 | meta(http-equiv="X-UA-Compatible", content="IE=edge")
7 | meta(name="viewport", content="width=device-width, initial-scale=1")
8 | title Yandex.Tank monitoring
9 | link(rel="shortcut icon", href="static/favicon.ico", type="image/x-icon")
10 | link(rel="icon", href="static/favicon.ico", type="image/x-icon")
11 | link(rel="stylesheet", href="static/css/bootstrap.min.css")
12 | link(rel="stylesheet", href="static/css/bootstrap-theme.min.css")
13 | link(rel="stylesheet", href="static/css/rickshaw.css")
14 | link(rel="stylesheet", href="static/css/custom.css")
15 | script(src="static/js/vendor/socket.io.min.js")
16 | script(src="static/js/vendor/jquery.min.js")
17 | script(src="static/js/vendor/angular.min.js")
18 | script(src="static/js/vendor/bootstrap.min.js")
19 | script(src="static/js/vendor/d3.min.js")
20 | script(src="static/js/vendor/rickshaw.min.js")
21 | script(src="static/js/angular-rickshaw.js")
22 | script(src="static/js/ws.js")
23 | script(type="text/javascript")
24 | document.cached_data = {{cached_data}};
25 | body
26 | .app.container(ng-app="ng-tank-report", ng-controller="TankReport")
27 | .host(ng-repeat="host in monitoringGraphData")
28 | h3 {{!host.hostname}}
29 | .row
30 | .col-md-5(ng-repeat="chart in host.charts")
31 | .panel.panel-default
32 | .panel-heading
33 | h3.panel-title {{!chart.name}}
34 | .panel-body
35 | rickshaw(
36 | rickshaw-series="chart.series",
37 | rickshaw-options="chart.options",
38 | rickshaw-features="chart.features"
39 | )
40 |
--------------------------------------------------------------------------------
/yandextank/plugins/Report/templates/index.jade:
--------------------------------------------------------------------------------
1 | !!! 5
2 | {% autoescape None %}
3 | html(lang="en")
4 | head
5 | meta(charset="utf-8")
6 | meta(http-equiv="X-UA-Compatible", content="IE=edge")
7 | meta(name="viewport", content="width=device-width, initial-scale=1")
8 | title Yandex.Tank online report
9 | link(rel="shortcut icon", href="static/favicon.ico", type="image/x-icon")
10 | link(rel="icon", href="static/favicon.ico", type="image/x-icon")
11 | link(rel="stylesheet", href="static/css/bootstrap.min.css")
12 | link(rel="stylesheet", href="static/css/bootstrap-theme.min.css")
13 | link(rel="stylesheet", href="static/css/rickshaw.css")
14 | link(rel="stylesheet", href="static/css/custom.css")
15 | script(src="static/js/vendor/socket.io.min.js")
16 | script(src="static/js/vendor/jquery.min.js")
17 | script(src="static/js/vendor/angular.min.js")
18 | script(src="static/js/vendor/bootstrap.min.js")
19 | script(src="static/js/vendor/d3.min.js")
20 | script(src="static/js/vendor/rickshaw.min.js")
21 | script(src="static/js/angular-rickshaw.js")
22 | script(src="static/js/ws.js")
23 | script(type="text/javascript").
24 | document.cached_data = {{cached_data}};
25 | body
26 | .app.container(ng-app="ng-tank-report", ng-controller="TankReport")
27 | h1.page-header Yandex.Tank online report
28 | #status {{!status}}
29 | #timings
30 | .panel.panel-default
31 | .panel-heading
32 | h3.panel-title {{!quantiles.name}}
33 | .panel-body
34 | rickshaw.panel-body(
35 | rickshaw-series="quantiles.series",
36 | rickshaw-options="quantiles.options",
37 | rickshaw-features="quantiles.features"
38 | )
39 | .panel.panel-default
40 | .panel-heading
41 | h3.panel-title {{!rps.name}}
42 | .panel-body
43 | rickshaw(
44 | rickshaw-series="rps.series",
45 | rickshaw-options="rps.options",
46 | rickshaw-features="rps.features"
47 | )
48 | #codes
49 | .panel.panel-default
50 | .panel-heading
51 | h3.panel-title {{!protoCodes.name}}
52 | .panel-body
53 | rickshaw(
54 | rickshaw-series="protoCodes.series",
55 | rickshaw-options="protoCodes.options",
56 | rickshaw-features="protoCodes.features"
57 | )
58 | .panel.panel-default
59 | .panel-heading
60 | h3.panel-title {{!netCodes.name}}
61 | .panel-body
62 | rickshaw(
63 | rickshaw-series="netCodes.series",
64 | rickshaw-options="netCodes.options",
65 | rickshaw-features="netCodes.features"
66 | )
67 | #monitoring
68 | .host(ng-repeat="host in monitoringData")
69 | h3 {{!host.hostname}}
70 | .panel.panel-default(ng-repeat="group in host.groups")
71 | .panel-heading
72 | h3.panel-title {{!group.name}}
73 | .panel-body
74 | rickshaw(
75 | rickshaw-series="group.series",
76 | rickshaw-options="group.options",
77 | rickshaw-features="group.features"
78 | )
79 |
--------------------------------------------------------------------------------
/yandextank/plugins/Report/static/js/angular-rickshaw.coffee:
--------------------------------------------------------------------------------
1 | ###*
2 | Based on https://github.com/ngyewch/angular-rickshaw
3 | ###
4 | "use strict"
5 |
6 | angular.module("angular-rickshaw", []).directive "rickshaw", ($compile) ->
7 | restrict: "EA"
8 | scope:
9 | options: "=rickshawOptions"
10 | series: "=rickshawSeries"
11 | features: "=rickshawFeatures"
12 |
13 |
14 | # replace: true,
15 | link: (scope, element, attrs) ->
16 | getSettings = (el) ->
17 | settings = angular.copy(scope.options)
18 | settings.element = el
19 | settings.series = scope.series
20 | settings
21 | update = ->
22 | mainEl = angular.element(element)
23 | mainEl.append graphEl
24 | mainEl.empty()
25 | graphEl = $compile("
")(scope)
26 | mainEl.append graphEl
27 | settings = getSettings(graphEl[0])
28 | Rickshaw.Series.zeroFill(settings.series)
29 | scope.graph = new Rickshaw.Graph(settings)
30 | if scope.features and scope.features.hover
31 | hoverConfig = graph: scope.graph
32 | hoverConfig.xFormatter = scope.features.hover.xFormatter
33 | hoverConfig.yFormatter = scope.features.hover.yFormatter
34 | hoverConfig.formatter = scope.features.hover.formatter
35 | hoverDetail = new Rickshaw.Graph.HoverDetail(hoverConfig)
36 | if scope.features and scope.features.palette
37 | palette = new Rickshaw.Color.Palette(scheme: scope.features.palette)
38 | i = 0
39 |
40 | while i < settings.series.length
41 | settings.series[i].color = palette.color() if !settings.series[i].color
42 | i++
43 | scope.graph.render()
44 | if scope.features and scope.features.xAxis
45 | xAxisConfig = graph: scope.graph
46 | if scope.features.xAxis.timeUnit
47 | time = new Rickshaw.Fixtures.Time()
48 | xAxisConfig.timeUnit = time.unit(scope.features.xAxis.timeUnit)
49 | xAxis = new Rickshaw.Graph.Axis.Time(xAxisConfig)
50 | xAxis.render()
51 | if scope.features and scope.features.yAxis
52 | yAxisConfig = graph: scope.graph, orientation: 'left'
53 | yAxisConfig.tickFormat = Rickshaw.Fixtures.Number[scope.features.yAxis.tickFormat] if scope.features.yAxis.tickFormat
54 | yAxis = new Rickshaw.Graph.Axis.Y(yAxisConfig)
55 | yAxis.render()
56 | if scope.features and scope.features.yAxisSecondary
57 | yAxisSecondaryConfig = graph: scope.graph, orientation: 'right'
58 | yAxisSecondaryConfig.tickFormat = Rickshaw.Fixtures.Number[scope.features.yAxisSecondary.tickFormat] if scope.features.yAxisSecondary.tickFormat
59 | yAxisSecondary = new Rickshaw.Graph.Axis.Y(yAxisSecondaryConfig)
60 | yAxisSecondary.render()
61 | if scope.features and scope.features.legend
62 | legendEl = $compile("")(scope)
63 | mainEl.append legendEl
64 | legend = new Rickshaw.Graph.Legend(
65 | graph: scope.graph
66 | element: legendEl[0]
67 | )
68 | if scope.features.legend.toggle
69 | shelving = new Rickshaw.Graph.Behavior.Series.Toggle(
70 | graph: scope.graph
71 | legend: legend
72 | )
73 | if scope.features.legend.highlight
74 | highlighter = new Rickshaw.Graph.Behavior.Series.Highlight(
75 | graph: scope.graph
76 | legend: legend
77 | )
78 | return
79 | scope.graph = undefined
80 | scope.$watch "options", (newValue, oldValue) ->
81 | update() unless angular.equals(newValue, oldValue)
82 | return
83 |
84 | scope.$watch "series", (newValue, oldValue) ->
85 | update() unless angular.equals(newValue, oldValue)
86 | return
87 |
88 | scope.$watch "features", (newValue, oldValue) ->
89 | update() unless angular.equals(newValue, oldValue)
90 | return
91 |
92 | scope.$on "DataUpdated", () ->
93 | scope.graph.update()
94 |
95 | update()
96 |
97 | controller: ($scope, $element, $attrs) ->
98 |
--------------------------------------------------------------------------------
/yandextank/plugins/Report/plugin.py:
--------------------------------------------------------------------------------
1 | import time
2 | import json
3 | from threading import Thread
4 |
5 | from ..Telegraf import Plugin as ReportPlugin
6 | from ..Aggregator import AggregatorPlugin
7 | from ...core.interfaces import AbstractPlugin
8 |
9 | from .server import ReportServer
10 |
11 | import logging
12 |
13 | logger = logging.getLogger(__name__)
14 |
15 |
16 | def uts(dt):
17 | return int(time.mktime(dt.timetuple()))
18 |
19 |
20 | class Plugin(AbstractPlugin, Thread):
21 | '''Interactive report plugin '''
22 | SECTION = "report"
23 |
24 | @staticmethod
25 | def get_key():
26 | return __file__
27 |
28 | def __init__(self, core):
29 | AbstractPlugin.__init__(self, core)
30 | Thread.__init__(self)
31 | self.daemon = True # Thread auto-shutdown
32 | self.port = 8080
33 | self.last_sec = None
34 | self.server = None
35 | self.data = []
36 | self.stats = []
37 | self.monitoring = []
38 |
39 | def get_all_data(self):
40 | return {"data": self.data,
41 | "stats": self.stats,
42 | "monitoring": self.monitoring, }
43 |
44 | def get_available_options(self):
45 | return ["port"]
46 |
47 | def configure(self):
48 | self.port = int(self.get_option("port", self.port))
49 | try:
50 | aggregator = self.core.get_plugin_of_type(AggregatorPlugin)
51 | aggregator.add_result_listener(self)
52 | except KeyError:
53 | logger.warning(
54 | "No aggregator module, no valid report will be available")
55 |
56 | try:
57 | mon = self.core.get_plugin_of_type(ReportPlugin)
58 | if mon.monitoring:
59 | mon.monitoring.add_listener(self)
60 | except KeyError:
61 | logger.warning("No monitoring module, monitroing report disabled")
62 |
63 | def prepare_test(self):
64 | try:
65 | self.server = ReportServer(self)
66 | self.server.owner = self
67 | except Exception, ex:
68 | logger.warning("Failed to start web results server: %s", ex)
69 |
70 | def start_test(self):
71 | self.start()
72 |
73 | def end_test(self, retcode):
74 | logger.info("Ended test. Sending command to reload pages.")
75 | self.server.reload()
76 | return retcode
77 |
78 | def run(self):
79 | if (self.server):
80 | self.server.serve()
81 | logger.info("Server started.")
82 |
83 | def on_aggregated_data(self, data, stats):
84 | """
85 | @data: aggregated data
86 | @stats: stats about gun
87 | """
88 | if data:
89 | self.data.append(data)
90 | if stats:
91 | self.stats.append(stats)
92 | if self.server is not None and (data or stats):
93 | message = {'data': data, 'stats': stats}
94 | self.server.send({k: v for k, v in message.iteritems() if v})
95 |
96 | def monitoring_data(self, data):
97 | if data:
98 | self.monitoring += data
99 | message = {'monitoring': data, }
100 | if self.server is not None:
101 | self.server.send(message)
102 |
103 | def post_process(self, retcode):
104 | report_json = self.core.mkstemp(".json", "report_")
105 | logger.info("Saving JSON report to %s", report_json)
106 | self.core.add_artifact_file(report_json)
107 | with open(report_json, 'w') as report_json_file:
108 | json.dump(self.get_all_data(), report_json_file, indent=2)
109 | report_html = self.core.mkstemp(".html", "report_")
110 | logger.info("Saving HTML report to %s", report_html)
111 | self.core.add_artifact_file(report_html)
112 | with open(report_html, 'w') as report_html_file:
113 | report_html_file.write(self.server.render_offline())
114 | # raw_input('Press Enter to stop report server.')
115 | self.server.stop()
116 | del self.server
117 | self.server = None
118 | return retcode
119 |
--------------------------------------------------------------------------------
/yandextank/plugins/Report/server.py:
--------------------------------------------------------------------------------
1 | import tornado.ioloop
2 | import tornado.web
3 | import os.path
4 | import json
5 | import uuid
6 |
7 | import logging
8 | logger = logging.getLogger(__name__)
9 |
10 | from tornado import template
11 | from pyjade.ext.tornado import patch_tornado
12 | patch_tornado()
13 |
14 | from tornadio2 import SocketConnection, TornadioRouter, event
15 | from tornadio2.server import SocketServer
16 |
17 | from threading import Thread
18 |
19 |
20 | class Client(SocketConnection):
21 | CONNECTIONS = set()
22 |
23 | def on_open(self, info):
24 | logger.info('Client connected')
25 | self.CONNECTIONS.add(self)
26 |
27 | def on_message(self, msg):
28 | logger.info('Got %s', msg)
29 |
30 | def on_close(self):
31 | logger.info('Client disconnected')
32 | self.CONNECTIONS.remove(self)
33 |
34 | @event('heartbeat')
35 | def on_heartbeat(self):
36 | pass
37 |
38 |
39 | class MainHandler(tornado.web.RequestHandler):
40 | def initialize(self, template, reportUUID, cacher):
41 | self.template = template
42 | self.reportUUID = reportUUID
43 | self.cacher = cacher
44 |
45 | def get(self):
46 | if self.cacher is not None:
47 | cached_data = {
48 | 'data': self.cacher.get_all_data(),
49 | 'uuid': self.reportUUID,
50 | }
51 | else:
52 | cached_data = {'data': {}, 'uuid': self.reportUUID, }
53 | self.render(self.template, cached_data=json.dumps(cached_data))
54 |
55 |
56 | class JsonHandler(tornado.web.RequestHandler):
57 | def initialize(self, reportUUID, cacher):
58 | self.reportUUID = reportUUID
59 | self.cacher = cacher
60 |
61 | def get(self):
62 | if self.cacher is not None:
63 | cached_data = {
64 | 'data': self.cacher.get_all_data(),
65 | 'uuid': self.reportUUID,
66 | }
67 | else:
68 | cached_data = {'data': {}, 'uuid': self.reportUUID, }
69 | self.set_status(200)
70 | self.set_header("Content-type", "application/json")
71 | self.finish(json.dumps(cached_data))
72 |
73 |
74 | class ReportServer(object):
75 | def __init__(self, cacher):
76 | router = TornadioRouter(Client)
77 | self.server = None
78 | self.cacher = cacher
79 | self.reportUUID = uuid.uuid4().hex
80 | self.app = tornado.web.Application(
81 | router.apply_routes([
82 | (r"/", MainHandler, dict(template='index.jade',
83 | reportUUID=self.reportUUID,
84 | cacher=cacher)),
85 | (r"/offline\.html", MainHandler,
86 | dict(template='offline.jade',
87 | reportUUID=self.reportUUID,
88 | cacher=cacher)),
89 | (r"/brief\.html$", MainHandler,
90 | dict(template='brief.jade',
91 | reportUUID=self.reportUUID,
92 | cacher=cacher)),
93 | (r"/monitoring\.html$", MainHandler,
94 | dict(template='monitoring.jade',
95 | reportUUID=self.reportUUID,
96 | cacher=cacher)),
97 | (r"/data\.json$", JsonHandler, dict(reportUUID=self.reportUUID,
98 | cacher=cacher)),
99 | ]),
100 | template_path=os.path.join(
101 | os.path.dirname(__file__), "templates"),
102 | static_path=os.path.join(
103 | os.path.dirname(__file__), "static"),
104 | debug=True, )
105 |
106 | def serve(self):
107 | def run_server(server):
108 | tornado.ioloop.IOLoop.instance().start()
109 |
110 | self.server = SocketServer(self.app)
111 | th = Thread(target=run_server, args=(self.server, ))
112 | th.start()
113 |
114 | def stop(self):
115 | if (self.server):
116 | self.server.stop()
117 |
118 | def send(self, data):
119 | for connection in Client.CONNECTIONS:
120 | data['uuid'] = self.reportUUID
121 | connection.send(json.dumps(data))
122 |
123 | def reload(self):
124 | for connection in Client.CONNECTIONS:
125 | connection.emit('reload')
126 |
127 | def render_offline(self):
128 | loader = template.Loader(os.path.join(
129 | os.path.dirname(__file__), "templates"))
130 | cached_data = {
131 | 'data': self.cacher.get_all_data(),
132 | 'uuid': self.reportUUID,
133 | }
134 | return loader.load('offline.jade').generate(
135 | cached_data=json.dumps(cached_data))
136 |
--------------------------------------------------------------------------------
/yandextank/plugins/Report/static/js/angular-rickshaw.js:
--------------------------------------------------------------------------------
1 | // Generated by CoffeeScript 1.9.1
2 |
3 | /**
4 | Based on https://github.com/ngyewch/angular-rickshaw
5 | */
6 |
7 | (function() {
8 | "use strict";
9 | angular.module("angular-rickshaw", []).directive("rickshaw", function($compile) {
10 | return {
11 | restrict: "EA",
12 | scope: {
13 | options: "=rickshawOptions",
14 | series: "=rickshawSeries",
15 | features: "=rickshawFeatures"
16 | },
17 | link: function(scope, element, attrs) {
18 | var getSettings, update;
19 | getSettings = function(el) {
20 | var settings;
21 | settings = angular.copy(scope.options);
22 | settings.element = el;
23 | settings.series = scope.series;
24 | return settings;
25 | };
26 | update = function() {
27 | var graphEl, highlighter, hoverConfig, hoverDetail, i, legend, legendEl, mainEl, palette, settings, shelving, time, xAxis, xAxisConfig, yAxis, yAxisConfig, yAxisSecondary, yAxisSecondaryConfig;
28 | mainEl = angular.element(element);
29 | mainEl.append(graphEl);
30 | mainEl.empty();
31 | graphEl = $compile("")(scope);
32 | mainEl.append(graphEl);
33 | settings = getSettings(graphEl[0]);
34 | Rickshaw.Series.zeroFill(settings.series);
35 | scope.graph = new Rickshaw.Graph(settings);
36 | if (scope.features && scope.features.hover) {
37 | hoverConfig = {
38 | graph: scope.graph
39 | };
40 | hoverConfig.xFormatter = scope.features.hover.xFormatter;
41 | hoverConfig.yFormatter = scope.features.hover.yFormatter;
42 | hoverConfig.formatter = scope.features.hover.formatter;
43 | hoverDetail = new Rickshaw.Graph.HoverDetail(hoverConfig);
44 | }
45 | if (scope.features && scope.features.palette) {
46 | palette = new Rickshaw.Color.Palette({
47 | scheme: scope.features.palette
48 | });
49 | i = 0;
50 | while (i < settings.series.length) {
51 | settings.series[i].color = palette.color();
52 | i++;
53 | }
54 | }
55 | scope.graph.render();
56 | if (scope.features && scope.features.xAxis) {
57 | xAxisConfig = {
58 | graph: scope.graph
59 | };
60 | if (scope.features.xAxis.timeUnit) {
61 | time = new Rickshaw.Fixtures.Time();
62 | xAxisConfig.timeUnit = time.unit(scope.features.xAxis.timeUnit);
63 | }
64 | xAxis = new Rickshaw.Graph.Axis.Time(xAxisConfig);
65 | xAxis.render();
66 | }
67 | if (scope.features && scope.features.yAxis) {
68 | yAxisConfig = {
69 | graph: scope.graph,
70 | orientation: 'left'
71 | };
72 | if (scope.features.yAxis.tickFormat) {
73 | yAxisConfig.tickFormat = Rickshaw.Fixtures.Number[scope.features.yAxis.tickFormat];
74 | }
75 | yAxis = new Rickshaw.Graph.Axis.Y(yAxisConfig);
76 | yAxis.render();
77 | }
78 | if (scope.features && scope.features.yAxisSecondary) {
79 | yAxisSecondaryConfig = {
80 | graph: scope.graph,
81 | orientation: 'right'
82 | };
83 | if (scope.features.yAxisSecondary.tickFormat) {
84 | yAxisSecondaryConfig.tickFormat = Rickshaw.Fixtures.Number[scope.features.yAxisSecondary.tickFormat];
85 | }
86 | yAxisSecondary = new Rickshaw.Graph.Axis.Y(yAxisSecondaryConfig);
87 | yAxisSecondary.render();
88 | }
89 | if (scope.features && scope.features.legend) {
90 | legendEl = $compile("")(scope);
91 | mainEl.append(legendEl);
92 | legend = new Rickshaw.Graph.Legend({
93 | graph: scope.graph,
94 | element: legendEl[0]
95 | });
96 | if (scope.features.legend.toggle) {
97 | shelving = new Rickshaw.Graph.Behavior.Series.Toggle({
98 | graph: scope.graph,
99 | legend: legend
100 | });
101 | }
102 | if (scope.features.legend.highlight) {
103 | highlighter = new Rickshaw.Graph.Behavior.Series.Highlight({
104 | graph: scope.graph,
105 | legend: legend
106 | });
107 | }
108 | }
109 | };
110 | scope.graph = void 0;
111 | scope.$watch("options", function(newValue, oldValue) {
112 | if (!angular.equals(newValue, oldValue)) {
113 | update();
114 | }
115 | });
116 | scope.$watch("series", function(newValue, oldValue) {
117 | if (!angular.equals(newValue, oldValue)) {
118 | update();
119 | }
120 | });
121 | scope.$watch("features", function(newValue, oldValue) {
122 | if (!angular.equals(newValue, oldValue)) {
123 | update();
124 | }
125 | });
126 | scope.$on("DataUpdated", function() {
127 | return scope.graph.update();
128 | });
129 | return update();
130 | },
131 | controller: function($scope, $element, $attrs) {}
132 | };
133 | });
134 |
135 | }).call(this);
136 |
--------------------------------------------------------------------------------
/yandextank/plugins/Report/static/js/ws.coffee:
--------------------------------------------------------------------------------
1 | app = angular.module("ng-tank-report", ["angular-rickshaw"])
2 |
3 | collect_subtree = (storage, subtree, ts) ->
4 | for key, node of subtree
5 | if typeof node is 'number' or typeof node is 'array'
6 | storage[key].push
7 | x: ts
8 | y: node
9 | else
10 | collect_subtree(storage[key], node, ts)
11 |
12 | collect_stats = (stats) ->
13 | result = {}
14 | for statItem in stats
15 | for metric, value of statItem.metrics
16 | result[metric] = [] if not result[metric]
17 | result[metric].push
18 | x: +statItem.ts
19 | y: +value
20 | result
21 |
22 | collect_monitoring = (monitoring) ->
23 | result = {}
24 | for monItem in monitoring
25 | for host, hostData of monItem.data
26 | result[host] = {comment: hostData.comment, metrics: {}} if not result[host]
27 | for metric, value of hostData.metrics
28 | subgroup = metric.split("_", 1)
29 | result[host].metrics[subgroup] = {} if not result[host].metrics[subgroup]
30 | result[host].metrics[subgroup][metric] = [] if not result[host].metrics[subgroup][metric]
31 | result[host].metrics[subgroup][metric].push
32 | x: +monItem.timestamp
33 | y: +value
34 | result
35 |
36 | collect_quantiles = (data) ->
37 |
38 | result = {
39 | overall:
40 | interval_real:
41 | q: {}
42 | tagged: {}
43 | }
44 | for dataItem in data
45 | for i in [0...dataItem.overall.interval_real.q.q.length]
46 | result.overall.interval_real.q[dataItem.overall.interval_real.q.q[i]] = [] if not result.overall.interval_real.q[dataItem.overall.interval_real.q.q[i]]
47 | result.overall.interval_real.q[dataItem.overall.interval_real.q.q[i]].push
48 | x: dataItem.ts
49 | y: dataItem.overall.interval_real.q.value[i]
50 | for tag, tagData of dataItem.tagged
51 | result.tagged[tag] = {interval_real: { q: {}}} if not result.tagged[tag]
52 |
53 | for i in [0...tagData.interval_real.q.q.length]
54 | result.tagged[tag].interval_real.q[tagData.interval_real.q.q[i]] = [] if not result.tagged[tag].interval_real.q[tagData.interval_real.q.q[i]]
55 | result.tagged[tag].interval_real.q[tagData.interval_real.q.q[i]].push
56 | x: dataItem.ts
57 | y: tagData.interval_real.q.value[i]
58 | result
59 |
60 | app.controller "TankReport", ($scope, $element) ->
61 | $scope.status = "Disconnected"
62 | $scope.data = document.cached_data.data
63 | $scope.uuid = document.cached_data.uuid
64 | $scope.updateData = (tankData) ->
65 | for ts, storages of tankData
66 | for storage, data of storages
67 | collect_subtree $scope.data[storage], data, +ts
68 | $scope.$broadcast 'DataUpdated'
69 | $scope.buildSeries = () ->
70 | cache = document.cached_data.data
71 | if cache.stats and cache.data and cache.monitoring
72 | overallData = {} # TODO
73 | taggedData = {} # TODO
74 | quantilesData = collect_quantiles(cache.data)
75 | statsData = collect_stats(cache.stats)
76 | monitoringData = collect_monitoring(cache.monitoring)
77 | else
78 | overallData = {}
79 | taggedData = {}
80 | quantilesData = {}
81 | statsData = {}
82 | monitoringData = {}
83 | setTimeout((() -> location.reload(true)), 3000)
84 | areaGraphs = ['CPU', 'Memory']
85 | # $scope.monitoringData = (
86 | # ({
87 | # hostname: hostname
88 | # groups: ({
89 | # name: groupName
90 | # features:
91 | # palette: 'spectrum14'
92 | # hover: {}
93 | # xAxis: {}
94 | # yAxis: {}
95 | # legend:
96 | # toggle: true
97 | # highlight: true
98 | # options:
99 | # renderer: if groupName in areaGraphs then 'area' else 'line'
100 | # series: ({
101 | # name: name
102 | # data: data
103 | # } for name, data of series)
104 | # } for groupName, series of groups)
105 | # } for hostname, groups of monitoringData)
106 | # )
107 | $scope.monitoringGraphData = ({
108 | hostname: hostname
109 | charts: ({
110 | name: subgroup
111 | features:
112 | palette: 'spectrum14'
113 | hover: {}
114 | xAxis: {}
115 | yAxis: {}
116 | ySecondaryAxis:
117 | scale: null
118 | legend:
119 | toggle: true
120 | highlight: true
121 | options:
122 | renderer: if subgroup in areaGraphs then "area" else "line"
123 | series: ({
124 | name: metric
125 | data: series
126 | } for metric, series of metrics)
127 | }) for subgroup, metrics of hostData.metrics
128 | } for hostname, hostData of monitoringData
129 | )
130 | $scope.quantilesGraphData =
131 | name: "Response time quantiles"
132 | features:
133 | palette: 'classic9'
134 | hover: {}
135 | xAxis: {}
136 | yAxis: {}
137 | legend:
138 | toggle: true
139 | highlight: true
140 | options:
141 | renderer: 'area'
142 | stack: false
143 | height: $element[0].offsetHeight - 45 - 62
144 | series: ({
145 | name: name
146 | data: data
147 | } for name, data of quantilesData.overall.interval_real.q).sort (a, b) ->
148 | return if parseFloat(a.name) <= parseFloat(b.name) then 1 else -1
149 | $scope.rps =
150 | name: "Requests per second"
151 | features:
152 | palette: 'spectrum14'
153 | hover: {}
154 | xAxis: {}
155 | yAxis: {}
156 | legend:
157 | toggle: true
158 | highlight: true
159 | options:
160 | renderer: 'line'
161 | series: [{
162 | name: "req/s"
163 | color: "red"
164 | data: statsData.reqps
165 | }]
166 |
167 | $scope.protoCodes =
168 | name: "Protocol return codes"
169 | features:
170 | palette: 'spectrum14'
171 | hover: {}
172 | xAxis: {}
173 | yAxis: {}
174 | legend:
175 | toggle: true
176 | highlight: true
177 | options:
178 | renderer: 'area'
179 | stack: true
180 | height: $element[0].offsetHeight - 45 - 62
181 | series: ({
182 | name: name
183 | data: data
184 | } for name, data of overallData.http_codes).sort (a, b) ->
185 | return if parseFloat(a.name) <= parseFloat(b.name) then 1 else -1
186 |
187 | $scope.netCodes =
188 | name: "Network return codes"
189 | features:
190 | palette: 'spectrum14'
191 | hover: {}
192 | xAxis: {}
193 | yAxis: {}
194 | legend:
195 | toggle: true
196 | highlight: true
197 | options:
198 | renderer: 'area'
199 | stack: true
200 | height: $element[0].offsetHeight - 45 - 62
201 | series: ({
202 | name: name
203 | data: data
204 | } for name, data of overallData.net_codes).sort (a, b) ->
205 | return if parseFloat(a.name) <= parseFloat(b.name) then 1 else -1
206 |
207 | $scope.buildSeries()
208 | #
209 | # conn = new io.connect("http://#{window.location.host}",
210 | # 'reconnection limit' : 1000
211 | # 'max reconnection attempts' : 'Infinity'
212 | # )
213 | # setInterval((
214 | # () ->conn.emit('heartbeat')
215 | # ), 3000)
216 | # conn.on 'connect', () =>
217 | # console.log("Connection opened...")
218 | # $scope.status = "Connected"
219 | #
220 | # $scope.$apply()
221 | #
222 | # conn.on 'disconnect', () =>
223 | # console.log("Connection closed...")
224 | # $scope.status = "Disonnected"
225 | # $scope.$apply()
226 | # conn.on 'reload', () =>
227 | # location.reload(true)
228 | # conn.on 'message', (msg) =>
229 | # tankData = JSON.parse msg
230 | # if tankData.uuid and $scope.uuid != tankData.uuid
231 | # location.reload(true)
232 | # else
233 | # $scope.updateData(tankData.data)
234 |
--------------------------------------------------------------------------------
/yandextank/plugins/Report/static/css/rickshaw.css:
--------------------------------------------------------------------------------
1 | .rickshaw_graph .detail {
2 | pointer-events: none;
3 | position: absolute;
4 | top: 0;
5 | z-index: 2;
6 | background: rgba(0, 0, 0, 0.1);
7 | bottom: 0;
8 | width: 1px;
9 | transition: opacity 0.25s linear;
10 | -moz-transition: opacity 0.25s linear;
11 | -o-transition: opacity 0.25s linear;
12 | -webkit-transition: opacity 0.25s linear;
13 | }
14 | .rickshaw_graph .detail.inactive {
15 | opacity: 0;
16 | }
17 | .rickshaw_graph .detail .item.active {
18 | opacity: 1;
19 | }
20 | .rickshaw_graph .detail .x_label {
21 | font-family: Arial, sans-serif;
22 | border-radius: 3px;
23 | padding: 6px;
24 | opacity: 0.5;
25 | border: 1px solid #e0e0e0;
26 | font-size: 12px;
27 | position: absolute;
28 | background: white;
29 | white-space: nowrap;
30 | }
31 | .rickshaw_graph .detail .x_label.left {
32 | left: 0;
33 | }
34 | .rickshaw_graph .detail .x_label.right {
35 | right: 0;
36 | }
37 | .rickshaw_graph .detail .item {
38 | position: absolute;
39 | z-index: 2;
40 | border-radius: 3px;
41 | padding: 0.25em;
42 | font-size: 12px;
43 | font-family: Arial, sans-serif;
44 | opacity: 0;
45 | background: rgba(0, 0, 0, 0.4);
46 | color: white;
47 | border: 1px solid rgba(0, 0, 0, 0.4);
48 | margin-left: 1em;
49 | margin-right: 1em;
50 | margin-top: -1em;
51 | white-space: nowrap;
52 | }
53 | .rickshaw_graph .detail .item.left {
54 | left: 0;
55 | }
56 | .rickshaw_graph .detail .item.right {
57 | right: 0;
58 | }
59 | .rickshaw_graph .detail .item.active {
60 | opacity: 1;
61 | background: rgba(0, 0, 0, 0.8);
62 | }
63 | .rickshaw_graph .detail .item:after {
64 | position: absolute;
65 | display: block;
66 | width: 0;
67 | height: 0;
68 |
69 | content: "";
70 |
71 | border: 5px solid transparent;
72 | }
73 | .rickshaw_graph .detail .item.left:after {
74 | top: 1em;
75 | left: -5px;
76 | margin-top: -5px;
77 | border-right-color: rgba(0, 0, 0, 0.8);
78 | border-left-width: 0;
79 | }
80 | .rickshaw_graph .detail .item.right:after {
81 | top: 1em;
82 | right: -5px;
83 | margin-top: -5px;
84 | border-left-color: rgba(0, 0, 0, 0.8);
85 | border-right-width: 0;
86 | }
87 | .rickshaw_graph .detail .dot {
88 | width: 4px;
89 | height: 4px;
90 | margin-left: -3px;
91 | margin-top: -3.5px;
92 | border-radius: 5px;
93 | position: absolute;
94 | box-shadow: 0 0 2px rgba(0, 0, 0, 0.6);
95 | box-sizing: content-box;
96 | -moz-box-sizing: content-box;
97 | background: white;
98 | border-width: 2px;
99 | border-style: solid;
100 | display: none;
101 | background-clip: padding-box;
102 | }
103 | .rickshaw_graph .detail .dot.active {
104 | display: block;
105 | }
106 | /* graph */
107 |
108 | .rickshaw_graph {
109 | position: relative;
110 | }
111 | .rickshaw_graph svg {
112 | display: block;
113 | overflow: hidden;
114 | }
115 |
116 | /* ticks */
117 |
118 | .rickshaw_graph .x_tick {
119 | position: absolute;
120 | top: 0;
121 | bottom: 0;
122 | width: 0px;
123 | border-left: 1px dotted rgba(0, 0, 0, 0.2);
124 | pointer-events: none;
125 | }
126 | .rickshaw_graph .x_tick .title {
127 | position: absolute;
128 | font-size: 12px;
129 | font-family: Arial, sans-serif;
130 | opacity: 0.5;
131 | white-space: nowrap;
132 | margin-left: 3px;
133 | bottom: 1px;
134 | }
135 |
136 | /* annotations */
137 |
138 | .rickshaw_annotation_timeline {
139 | height: 1px;
140 | border-top: 1px solid #e0e0e0;
141 | margin-top: 10px;
142 | position: relative;
143 | }
144 | .rickshaw_annotation_timeline .annotation {
145 | position: absolute;
146 | height: 6px;
147 | width: 6px;
148 | margin-left: -2px;
149 | top: -3px;
150 | border-radius: 5px;
151 | background-color: rgba(0, 0, 0, 0.25);
152 | }
153 | .rickshaw_graph .annotation_line {
154 | position: absolute;
155 | top: 0;
156 | bottom: -6px;
157 | width: 0px;
158 | border-left: 2px solid rgba(0, 0, 0, 0.3);
159 | display: none;
160 | }
161 | .rickshaw_graph .annotation_line.active {
162 | display: block;
163 | }
164 |
165 | .rickshaw_graph .annotation_range {
166 | background: rgba(0, 0, 0, 0.1);
167 | display: none;
168 | position: absolute;
169 | top: 0;
170 | bottom: -6px;
171 | }
172 | .rickshaw_graph .annotation_range.active {
173 | display: block;
174 | }
175 | .rickshaw_graph .annotation_range.active.offscreen {
176 | display: none;
177 | }
178 |
179 | .rickshaw_annotation_timeline .annotation .content {
180 | background: white;
181 | color: black;
182 | opacity: 0.9;
183 | padding: 5px 5px;
184 | box-shadow: 0 0 2px rgba(0, 0, 0, 0.8);
185 | border-radius: 3px;
186 | position: relative;
187 | z-index: 20;
188 | font-size: 12px;
189 | padding: 6px 8px 8px;
190 | top: 18px;
191 | left: -11px;
192 | width: 160px;
193 | display: none;
194 | cursor: pointer;
195 | }
196 | .rickshaw_annotation_timeline .annotation .content:before {
197 | content: "\25b2";
198 | position: absolute;
199 | top: -11px;
200 | color: white;
201 | text-shadow: 0 -1px 1px rgba(0, 0, 0, 0.8);
202 | }
203 | .rickshaw_annotation_timeline .annotation.active,
204 | .rickshaw_annotation_timeline .annotation:hover {
205 | background-color: rgba(0, 0, 0, 0.8);
206 | cursor: none;
207 | }
208 | .rickshaw_annotation_timeline .annotation .content:hover {
209 | z-index: 50;
210 | }
211 | .rickshaw_annotation_timeline .annotation.active .content {
212 | display: block;
213 | }
214 | .rickshaw_annotation_timeline .annotation:hover .content {
215 | display: block;
216 | z-index: 50;
217 | }
218 | .rickshaw_graph .y_axis,
219 | .rickshaw_graph .x_axis_d3 {
220 | fill: none;
221 | }
222 | .rickshaw_graph .y_ticks .tick line,
223 | .rickshaw_graph .x_ticks_d3 .tick {
224 | stroke: rgba(0, 0, 0, 0.16);
225 | stroke-width: 2px;
226 | shape-rendering: crisp-edges;
227 | pointer-events: none;
228 | }
229 | .rickshaw_graph .y_grid .tick,
230 | .rickshaw_graph .x_grid_d3 .tick {
231 | z-index: -1;
232 | stroke: rgba(0, 0, 0, 0.20);
233 | stroke-width: 1px;
234 | stroke-dasharray: 1 1;
235 | }
236 | .rickshaw_graph .y_grid .tick[data-y-value="0"] {
237 | stroke-dasharray: 1 0;
238 | }
239 | .rickshaw_graph .y_grid path,
240 | .rickshaw_graph .x_grid_d3 path {
241 | fill: none;
242 | stroke: none;
243 | }
244 | .rickshaw_graph .y_ticks path,
245 | .rickshaw_graph .x_ticks_d3 path {
246 | fill: none;
247 | stroke: #808080;
248 | }
249 | .rickshaw_graph .y_ticks text,
250 | .rickshaw_graph .x_ticks_d3 text {
251 | opacity: 0.5;
252 | font-size: 12px;
253 | pointer-events: none;
254 | }
255 | .rickshaw_graph .x_tick.glow .title,
256 | .rickshaw_graph .y_ticks.glow text {
257 | fill: black;
258 | color: black;
259 | text-shadow:
260 | -1px 1px 0 rgba(255, 255, 255, 0.1),
261 | 1px -1px 0 rgba(255, 255, 255, 0.1),
262 | 1px 1px 0 rgba(255, 255, 255, 0.1),
263 | 0px 1px 0 rgba(255, 255, 255, 0.1),
264 | 0px -1px 0 rgba(255, 255, 255, 0.1),
265 | 1px 0px 0 rgba(255, 255, 255, 0.1),
266 | -1px 0px 0 rgba(255, 255, 255, 0.1),
267 | -1px -1px 0 rgba(255, 255, 255, 0.1);
268 | }
269 | .rickshaw_graph .x_tick.inverse .title,
270 | .rickshaw_graph .y_ticks.inverse text {
271 | fill: white;
272 | color: white;
273 | text-shadow:
274 | -1px 1px 0 rgba(0, 0, 0, 0.8),
275 | 1px -1px 0 rgba(0, 0, 0, 0.8),
276 | 1px 1px 0 rgba(0, 0, 0, 0.8),
277 | 0px 1px 0 rgba(0, 0, 0, 0.8),
278 | 0px -1px 0 rgba(0, 0, 0, 0.8),
279 | 1px 0px 0 rgba(0, 0, 0, 0.8),
280 | -1px 0px 0 rgba(0, 0, 0, 0.8),
281 | -1px -1px 0 rgba(0, 0, 0, 0.8);
282 | }
283 | .rickshaw_legend {
284 | font-family: Arial;
285 | font-size: 12px;
286 | color: white;
287 | background: #404040;
288 | display: inline-block;
289 | padding: 12px 5px;
290 | border-radius: 2px;
291 | position: relative;
292 | }
293 | .rickshaw_legend:hover {
294 | z-index: 10;
295 | }
296 | .rickshaw_legend .swatch {
297 | width: 10px;
298 | height: 10px;
299 | border: 1px solid rgba(0, 0, 0, 0.2);
300 | }
301 | .rickshaw_legend .line {
302 | clear: both;
303 | line-height: 140%;
304 | padding-right: 15px;
305 | }
306 | .rickshaw_legend .line .swatch {
307 | display: inline-block;
308 | margin-right: 3px;
309 | border-radius: 2px;
310 | }
311 | .rickshaw_legend .label {
312 | margin: 0;
313 | white-space: nowrap;
314 | display: inline;
315 | font-size: inherit;
316 | background-color: transparent;
317 | color: inherit;
318 | font-weight: normal;
319 | line-height: normal;
320 | padding: 0px;
321 | text-shadow: none;
322 | }
323 | .rickshaw_legend .action:hover {
324 | opacity: 0.6;
325 | }
326 | .rickshaw_legend .action {
327 | margin-right: 0.2em;
328 | font-size: 10px;
329 | opacity: 0.2;
330 | cursor: pointer;
331 | font-size: 14px;
332 | }
333 | .rickshaw_legend .line.disabled {
334 | opacity: 0.4;
335 | }
336 | .rickshaw_legend ul {
337 | list-style-type: none;
338 | margin: 0;
339 | padding: 0;
340 | margin: 2px;
341 | cursor: pointer;
342 | }
343 | .rickshaw_legend li {
344 | display: inline-block;
345 | padding: 0 0 0 2px;
346 | min-width: 80px;
347 | white-space: nowrap;
348 | }
349 | .rickshaw_legend li:hover {
350 | background: rgba(255, 255, 255, 0.08);
351 | border-radius: 3px;
352 | }
353 | .rickshaw_legend li:active {
354 | background: rgba(255, 255, 255, 0.2);
355 | border-radius: 3px;
356 | }
357 |
--------------------------------------------------------------------------------
/yandextank/plugins/Report/static/js/ws.js:
--------------------------------------------------------------------------------
1 | // Generated by CoffeeScript 1.9.1
2 | (function() {
3 | var app, collect_monitoring, collect_quantiles, collect_stats, collect_subtree,
4 | indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
5 |
6 | app = angular.module("ng-tank-report", ["angular-rickshaw"]);
7 |
8 | collect_subtree = function(storage, subtree, ts) {
9 | var key, node, results;
10 | results = [];
11 | for (key in subtree) {
12 | node = subtree[key];
13 | if (typeof node === 'number' || typeof node === 'array') {
14 | results.push(storage[key].push({
15 | x: ts,
16 | y: node
17 | }));
18 | } else {
19 | results.push(collect_subtree(storage[key], node, ts));
20 | }
21 | }
22 | return results;
23 | };
24 |
25 | collect_stats = function(stats) {
26 | var j, len, metric, ref, result, statItem, value;
27 | result = {};
28 | for (j = 0, len = stats.length; j < len; j++) {
29 | statItem = stats[j];
30 | ref = statItem.metrics;
31 | for (metric in ref) {
32 | value = ref[metric];
33 | if (!result[metric]) {
34 | result[metric] = [];
35 | }
36 | result[metric].push({
37 | x: +statItem.ts,
38 | y: +value
39 | });
40 | }
41 | }
42 | return result;
43 | };
44 |
45 | collect_monitoring = function(monitoring) {
46 | var host, hostData, j, len, metric, monItem, ref, ref1, result, subgroup, value;
47 | result = {};
48 | for (j = 0, len = monitoring.length; j < len; j++) {
49 | monItem = monitoring[j];
50 | ref = monItem.data;
51 | for (host in ref) {
52 | hostData = ref[host];
53 | if (!result[host]) {
54 | result[host] = {
55 | comment: hostData.comment,
56 | metrics: {}
57 | };
58 | }
59 | ref1 = hostData.metrics;
60 | for (metric in ref1) {
61 | value = ref1[metric];
62 | subgroup = metric.split("_", 1);
63 | if (!result[host].metrics[subgroup]) {
64 | result[host].metrics[subgroup] = {};
65 | }
66 | if (!result[host].metrics[subgroup][metric]) {
67 | result[host].metrics[subgroup][metric] = [];
68 | }
69 | result[host].metrics[subgroup][metric].push({
70 | x: +monItem.timestamp,
71 | y: +value
72 | });
73 | }
74 | }
75 | }
76 | return result;
77 | };
78 |
79 | collect_quantiles = function(data) {
80 | var dataItem, i, j, k, l, len, ref, ref1, ref2, result, tag, tagData;
81 | result = {
82 | overall: {
83 | interval_real: {
84 | q: {}
85 | }
86 | },
87 | tagged: {}
88 | };
89 | for (j = 0, len = data.length; j < len; j++) {
90 | dataItem = data[j];
91 | for (i = k = 0, ref = dataItem.overall.interval_real.q.q.length; 0 <= ref ? k < ref : k > ref; i = 0 <= ref ? ++k : --k) {
92 | if (!result.overall.interval_real.q[dataItem.overall.interval_real.q.q[i]]) {
93 | result.overall.interval_real.q[dataItem.overall.interval_real.q.q[i]] = [];
94 | }
95 | result.overall.interval_real.q[dataItem.overall.interval_real.q.q[i]].push({
96 | x: dataItem.ts,
97 | y: dataItem.overall.interval_real.q.value[i]
98 | });
99 | }
100 | ref1 = dataItem.tagged;
101 | for (tag in ref1) {
102 | tagData = ref1[tag];
103 | if (!result.tagged[tag]) {
104 | result.tagged[tag] = {
105 | interval_real: {
106 | q: {}
107 | }
108 | };
109 | }
110 | for (i = l = 0, ref2 = tagData.interval_real.q.q.length; 0 <= ref2 ? l < ref2 : l > ref2; i = 0 <= ref2 ? ++l : --l) {
111 | if (!result.tagged[tag].interval_real.q[tagData.interval_real.q.q[i]]) {
112 | result.tagged[tag].interval_real.q[tagData.interval_real.q.q[i]] = [];
113 | }
114 | result.tagged[tag].interval_real.q[tagData.interval_real.q.q[i]].push({
115 | x: dataItem.ts,
116 | y: tagData.interval_real.q.value[i]
117 | });
118 | }
119 | }
120 | }
121 | return result;
122 | };
123 |
124 | app.controller("TankReport", function($scope, $element) {
125 | $scope.status = "Disconnected";
126 | $scope.data = document.cached_data.data;
127 | $scope.uuid = document.cached_data.uuid;
128 | $scope.updateData = function(tankData) {
129 | var data, storage, storages, ts;
130 | for (ts in tankData) {
131 | storages = tankData[ts];
132 | for (storage in storages) {
133 | data = storages[storage];
134 | collect_subtree($scope.data[storage], data, +ts);
135 | }
136 | }
137 | return $scope.$broadcast('DataUpdated');
138 | };
139 | $scope.buildSeries = function() {
140 | var areaGraphs, cache, data, hostData, hostname, metric, metrics, monitoringData, name, overallData, quantilesData, series, statsData, subgroup, taggedData;
141 | cache = document.cached_data.data;
142 | if (cache.stats && cache.data && cache.monitoring) {
143 | overallData = {};
144 | taggedData = {};
145 | quantilesData = collect_quantiles(cache.data);
146 | statsData = collect_stats(cache.stats);
147 | monitoringData = collect_monitoring(cache.monitoring);
148 | } else {
149 | overallData = {};
150 | taggedData = {};
151 | quantilesData = {};
152 | statsData = {};
153 | monitoringData = {};
154 | setTimeout((function() {
155 | return location.reload(true);
156 | }), 3000);
157 | }
158 | areaGraphs = ['CPU', 'Memory'];
159 | $scope.monitoringGraphData = (function() {
160 | var results;
161 | results = [];
162 | for (hostname in monitoringData) {
163 | hostData = monitoringData[hostname];
164 | results.push({
165 | hostname: hostname,
166 | charts: (function() {
167 | var ref, results1;
168 | ref = hostData.metrics;
169 | results1 = [];
170 | for (subgroup in ref) {
171 | metrics = ref[subgroup];
172 | results1.push({
173 | name: subgroup,
174 | features: {
175 | palette: 'spectrum14',
176 | hover: {},
177 | xAxis: {},
178 | yAxis: {},
179 | ySecondaryAxis: {
180 | scale: null
181 | },
182 | legend: {
183 | toggle: true,
184 | highlight: true
185 | }
186 | },
187 | options: {
188 | renderer: indexOf.call(areaGraphs, subgroup) >= 0 ? "area" : "line"
189 | },
190 | series: (function() {
191 | var results2;
192 | results2 = [];
193 | for (metric in metrics) {
194 | series = metrics[metric];
195 | results2.push({
196 | name: metric,
197 | data: series
198 | });
199 | }
200 | return results2;
201 | })()
202 | });
203 | }
204 | return results1;
205 | })()
206 | });
207 | }
208 | return results;
209 | })();
210 | $scope.quantilesGraphData = {
211 | name: "Response time quantiles",
212 | features: {
213 | palette: 'classic9',
214 | hover: {},
215 | xAxis: {},
216 | yAxis: {},
217 | legend: {
218 | toggle: true,
219 | highlight: true
220 | }
221 | },
222 | options: {
223 | renderer: 'area',
224 | stack: false,
225 | height: $element[0].offsetHeight - 45 - 62
226 | },
227 | series: ((function() {
228 | var ref, results;
229 | ref = quantilesData.overall.interval_real.q;
230 | results = [];
231 | for (name in ref) {
232 | data = ref[name];
233 | results.push({
234 | name: name,
235 | data: data
236 | });
237 | }
238 | return results;
239 | })()).sort(function(a, b) {
240 | if (parseFloat(a.name) <= parseFloat(b.name)) {
241 | return 1;
242 | } else {
243 | return -1;
244 | }
245 | })
246 | };
247 | $scope.rps = {
248 | name: "Requests per second",
249 | features: {
250 | palette: 'spectrum14',
251 | hover: {},
252 | xAxis: {},
253 | yAxis: {},
254 | legend: {
255 | toggle: true,
256 | highlight: true
257 | }
258 | },
259 | options: {
260 | renderer: 'line'
261 | },
262 | series: [
263 | {
264 | name: "req/s",
265 | color: "red",
266 | data: statsData.reqps
267 | }
268 | ]
269 | };
270 | $scope.protoCodes = {
271 | name: "Protocol return codes",
272 | features: {
273 | palette: 'spectrum14',
274 | hover: {},
275 | xAxis: {},
276 | yAxis: {},
277 | legend: {
278 | toggle: true,
279 | highlight: true
280 | }
281 | },
282 | options: {
283 | renderer: 'area',
284 | stack: true,
285 | height: $element[0].offsetHeight - 45 - 62
286 | },
287 | series: ((function() {
288 | var ref, results;
289 | ref = overallData.http_codes;
290 | results = [];
291 | for (name in ref) {
292 | data = ref[name];
293 | results.push({
294 | name: name,
295 | data: data
296 | });
297 | }
298 | return results;
299 | })()).sort(function(a, b) {
300 | if (parseFloat(a.name) <= parseFloat(b.name)) {
301 | return 1;
302 | } else {
303 | return -1;
304 | }
305 | })
306 | };
307 | return $scope.netCodes = {
308 | name: "Network return codes",
309 | features: {
310 | palette: 'spectrum14',
311 | hover: {},
312 | xAxis: {},
313 | yAxis: {},
314 | legend: {
315 | toggle: true,
316 | highlight: true
317 | }
318 | },
319 | options: {
320 | renderer: 'area',
321 | stack: true,
322 | height: $element[0].offsetHeight - 45 - 62
323 | },
324 | series: ((function() {
325 | var ref, results;
326 | ref = overallData.net_codes;
327 | results = [];
328 | for (name in ref) {
329 | data = ref[name];
330 | results.push({
331 | name: name,
332 | data: data
333 | });
334 | }
335 | return results;
336 | })()).sort(function(a, b) {
337 | if (parseFloat(a.name) <= parseFloat(b.name)) {
338 | return 1;
339 | } else {
340 | return -1;
341 | }
342 | })
343 | };
344 | };
345 | return $scope.buildSeries();
346 | });
347 |
348 | }).call(this);
349 |
--------------------------------------------------------------------------------
/yandextank/plugins/Report/static/js/vendor/cubism.min.js:
--------------------------------------------------------------------------------
1 | (function(a){function d(a){return a}function e(){}function j(a){return Math.floor(a/1e3)}function k(a){var b=a.indexOf("|"),c=a.substring(0,b),d=c.lastIndexOf(","),e=c.lastIndexOf(",",d-1),f=c.lastIndexOf(",",e-1),g=c.substring(f+1,e)*1e3,h=c.substring(d+1)*1e3;return a.substring(b+1).split(",").slice(1).map(function(a){return+a})}function l(a){if(!(a instanceof e))throw new Error("invalid context");this.context=a}function o(a,b){return function(c,d,e,f){a(new Date(+c+b),new Date(+d+b),e,f)}}function p(a,b){l.call(this,a),b=+b;var c=b+"";this.valueOf=function(){return b},this.toString=function(){return c}}function r(a,b){function c(b,c){if(c instanceof l){if(b.context!==c.context)throw new Error("mismatch context")}else c=new p(b.context,c);l.call(this,b.context),this.left=b,this.right=c,this.toString=function(){return b+" "+a+" "+c}}var d=c.prototype=Object.create(l.prototype);return d.valueAt=function(a){return b(this.left.valueAt(a),this.right.valueAt(a))},d.shift=function(a){return new c(this.left.shift(a),this.right.shift(a))},d.on=function(a,b){return arguments.length<2?this.left.on(a):(this.left.on(a,b),this.right.on(a,b),this)},function(a){return new c(this,a)}}function u(a){return a&16777214}function v(a){return(a+1&16777214)-1}function z(a){a.style("position","absolute").style("top",0).style("bottom",0).style("width","1px").style("pointer-events","none")}function A(a){return a+"px"}var b=a.cubism={version:"1.6.0"},c=0;b.option=function(a,c){var d=b.options(a);return d.length?d[0]:c},b.options=function(a,b){var c=location.search.substring(1).split("&"),d=[],e=-1,f=c.length,g;while(++e0&&a.focus(--o);break;case 39:o==null&&(o=d-2),o=c)return c;if(a<=b)return b;var d,e,f;for(f=a;f<=c;f++){d=avail_rsts.indexOf(f);if(d>-1){e=avail_rsts[d];break}}var g;for(f=a;f>=b;f--){d=avail_rsts.indexOf(f);if(d>-1){g=avail_rsts[d];break}}return e-ae?3600:(i=f(c),d>g&&i<900?900:d>h&&i<60?60:i)}var d={},e=this;auth_string="Basic "+btoa(a+":"+c),avail_rsts=[1,60,900,3600];var j=function(a){function d(b,d,e){var f="compose="+a+"&start_time="+b+"&end_time="+d+"&resolution="+g(b,d,e);return c+"?"+f}function e(a,b,c,d){var e=[];for(i=a;i<=b;i+=c){var f=[];while(d.length&&d[0].measure_time<=i)f.push(d.shift().value);var g;f.length?g=f.reduce(function(a,b){return a+b})/f.length:g=e.length?e[e.length-1]:0,e.push(g)}return e}var c="https://metrics-api.librato.com/v1/metrics";return request={},request.fire=function(a,c,f,g){function i(j){d3.json(j).header("X-Requested-With","XMLHttpRequest").header("Authorization",auth_string).header("Librato-User-Agent","cubism/"+b.version).get(function(b,j){if(!b){if(j.measurements.length===0)return;j.measurements[0].series.forEach(function(a){h.push(a)});var k="query"in j&&"next_time"in j.query;if(k)i(d(j.query.next_time,c,f));else{var l=e(a,c,f,h);g(l)}}})}var h=[];i(d(a,c,f))},request};return d.metric=function(a){return e.metric(function(b,c,d,e){j(a).fire(h(b),h(c),h(d),function(a){e(null,a)})},a+="")},d.toString=function(){return"librato"},d};var h=function(a){return Math.floor(a/1e3)};f.graphite=function(a){arguments.length||(a="");var b={},c=this;return b.metric=function(b){var d="sum",e=c.metric(function(c,e,f,g){var h=b;f!==1e4&&(h="summarize("+h+",'"+(f%36e5?f%6e4?f/1e3+"sec":f/6e4+"min":f/36e5+"hour")+"','"+d+"')"),d3.text(a+"/render?format=raw"+"&target="+encodeURIComponent("alias("+h+",'')")+"&from="+j(c-2*f)+"&until="+j(e-1e3),function(a){if(!a)return g(new Error("unable to load data"));g(null,k(a))})},b+="");return e.summarize=function(a){return d=a,e},e},b.find=function(b,c){d3.json(a+"/metrics/find?format=completer"+"&query="+encodeURIComponent(b),function(a){if(!a)return c(new Error("unable to find metrics"));c(null,a.metrics.map(function(a){return a.path}))})},b.toString=function(){return a},b},f.gangliaWeb=function(a){var b="",c="/ganglia2/";arguments.length&&(a.host&&(b=a.host),a.uriPathPrefix&&(c=a.uriPathPrefix,c[0]!="/"&&(c="/"+c),c[c.length-1]!="/"&&(c+="/")));var d={},e=this;return d.metric=function(a){var d=a.clusterName,f=a.metricName,g=a.hostName,h=a.isReport||!1,i=a.titleGenerator||function(a){return"clusterName:"+d+" metricName:"+f+(g?" hostName:"+g:"")},j=a.onChangeCallback,k=h?"g":"m",l=e.metric(function(a,e,h,i){function j(){return"c="+d+"&"+k+"="+f+(g?"&h="+g:"")+"&cs="+a/1e3+"&ce="+e/1e3+"&step="+h/1e3+"&graphlot=1"}d3.json(b+c+"graph.php?"+j(),function(a){if(!a)return i(new Error("Unable to fetch GangliaWeb data"));i(null,a[0].data)})},i(a));return l.toString=function(){return i(a)},j&&l.on("change",j),l},d.toString=function(){return b+c},d};var m=l.prototype;b.metric=l,m.valueAt=function(){return NaN},m.alias=function(a){return this.toString=function(){return a},this},m.extent=function(){var a=0,b=this.context.size(),c,d=Infinity,e=-Infinity;while(++ae&&(e=c);return[d,e]},m.on=function(a,b){return arguments.length<2?null:this},m.shift=function(){return this},m.on=function(){return arguments.length<2?null:this},f.metric=function(a,b){function r(b,c){var d=Math.min(j,Math.round((b-g)/i));if(!d||q)return;q=!0,d=Math.min(j,d+n);var f=new Date(c-d*i);a(f,c,i,function(a,b){q=!1;if(a)return console.warn(a);var d=isFinite(g)?Math.round((f-g)/i):0;for(var h=0,j=b.length;h1&&(e.toString=function(){return b}),e};var n=6,q=p.prototype=Object.create(l.prototype);q.valueAt=function(){return+this},q.extent=function(){return[+this,+this]},m.add=r("+",function(a,b){return a+b}),m.subtract=r("-",function(a,b){return a-b}),m.multiply=r("*",function(a,b){return a*b}),m.divide=r("/",function(a,b){return a/b}),f.horizon=function(){function o(o){o.on("mousemove.horizon",function(){a.focus(Math.round(d3.mouse(this)[0]))}).on("mouseout.horizon",function(){a.focus(null)}),o.append("canvas").attr("width",f).attr("height",g),o.append("span").attr("class","title").text(k),o.append("span").attr("class","value"),o.each(function(k,o){function B(c,d){w.save();var i=r.extent();A=i.every(isFinite),t!=null&&(i=t);var j=0,k=Math.max(-i[0],i[1]);if(this===a){if(k==y){j=f-n;var l=(c-u)/v;if(l=0)continue;w.fillRect(x,h(-C),1,q-h(-C))}}}w.restore()}function C(a){a==null&&(a=f-1);var b=r.valueAt(a);x.datum(b).text(isNaN(b)?null:l)}var p=this,q=++c,r=typeof i=="function"?i.call(p,k,o):i,s=typeof m=="function"?m.call(p,k,o):m,t=typeof j=="function"?j.call(p,k,o):j,u=-Infinity,v=a.step(),w=d3.select(p).select("canvas"),x=d3.select(p).select(".value"),y,z=s.length>>1,A;w.datum({id:q,metric:r}),w=w.node().getContext("2d"),a.on("change.horizon-"+q,B),a.on("focus.horizon-"+q,C),r.on("change.horizon-"+q,function(a,b){B(a,b),C(),A&&r.on("change.horizon-"+q,d)})})}var a=this,b="offset",e=document.createElement("canvas"),f=e.width=a.size(),g=e.height=30,h=d3.scale.linear().interpolate(d3.interpolateRound),i=d,j=null,k=d,l=d3.format(".2s"),m=["#08519c","#3182bd","#6baed6","#bdd7e7","#bae4b3","#74c476","#31a354","#006d2c"];return o.remove=function(b){function c(b){b.metric.on("change.horizon-"+b.id,null),a.on("change.horizon-"+b.id,null),a.on("focus.horizon-"+b.id,null)}b.on("mousemove.horizon",null).on("mouseout.horizon",null),b.selectAll("canvas").each(c).remove(),b.selectAll(".title,.value").remove()},o.mode=function(a){return arguments.length?(b=a+"",o):b},o.height=function(a){return arguments.length?(e.height=g=+a,o):g},o.metric=function(a){return arguments.length?(i=a,o):i},o.scale=function(a){return arguments.length?(h=a,o):h},o.extent=function(a){return arguments.length?(j=a,o):j},o.title=function(a){return arguments.length?(k=a,o):k},o.format=function(a){return arguments.length?(l=a,o):l},o.colors=function(a){return arguments.length?(m=a,o):m},o},f.comparison=function(){function o(o){o.on("mousemove.comparison",function(){a.focus(Math.round(d3.mouse(this)[0]))}).on("mouseout.comparison",function(){a.focus(null)}),o.append("canvas").attr("width",b).attr("height",e),o.append("span").attr("class","title").text(j),o.append("span").attr("class","value primary"),o.append("span").attr("class","value change"),o.each(function(j,o){function B(c,d){x.save(),x.clearRect(0,0,b,e);var g=r.extent(),h=s.extent(),i=t==null?g:t;f.domain(i).range([e,0]),A=g.concat(h).every(isFinite);var j=c/a.step()&1?v:u;x.fillStyle=m[2];for(var k=0,l=b;kp&&x.fillRect(j(k),p,1,o-p)}x.fillStyle=m[3];for(k=0;kp&&x.fillRect(j(k),o-n,1,n)}x.restore()}function C(a){a==null&&(a=b-1);var c=r.valueAt(a),d=s.valueAt(a),e=(c-d)/d;y.datum(c).text(isNaN(c)?null:k),z.datum(e).text(isNaN(e)?null:l).attr("class","value change "+(e>0?"positive":e<0?"negative":""))}function D(a,b){B(a,b),C(),A&&(r.on("change.comparison-"+q,d),s.on("change.comparison-"+q,d))}var p=this,q=++c,r=typeof g=="function"?g.call(p,j,o):g,s=typeof h=="function"?h.call(p,j,o):h,t=typeof i=="function"?i.call(p,j,o):i,w=d3.select(p),x=w.select("canvas"),y=w.select(".value.primary"),z=w.select(".value.change"),A;x.datum({id:q,primary:r,secondary:s}),x=x.node().getContext("2d"),r.on("change.comparison-"+q,D),s.on("change.comparison-"+q,D),a.on("change.comparison-"+q,B),a.on("focus.comparison-"+q,C)})}var a=this,b=a.size(),e=120,f=d3.scale.linear().interpolate(d3.interpolateRound),g=function(a){return a[0]},h=function(a){return a[1]},i=null,j=d,k=s,l=t,m=["#9ecae1","#225b84","#a1d99b","#22723a"],n=1.5;return o.remove=function(b){function c(b){b.primary.on("change.comparison-"+b.id,null),b.secondary.on("change.comparison-"+b.id,null),a.on("change.comparison-"+b.id,null),a.on("focus.comparison-"+b.id,null)}b.on("mousemove.comparison",null).on("mouseout.comparison",null),b.selectAll("canvas").each(c).remove(),b.selectAll(".title,.value").remove()},o.height=function(a){return arguments.length?(e=+a,o):e},o.primary=function(a){return arguments.length?(g=a,o):g},o.secondary=function(a){return arguments.length?(h=a,o):h},o.scale=function(a){return arguments.length?(f=a,o):f},o.extent=function(a){return arguments.length?(i=a,o):i},o.title=function(a){return arguments.length?(j=a,o):j},o.formatPrimary=function(a){return arguments.length?(k=a,o):k},o.formatChange=function(a){return arguments.length?(l=a,o):l},o.colors=function(a){return arguments.length?(m=a,o):m},o.strokeWidth=function(a){return arguments.length?(n=a,o):n},o};var s=d3.format(".2s"),t=d3.format("+.0%");f.axis=function(){function g(e){var h=++c,i,j=e.append("svg").datum({id:h}).attr("width",a.size()).attr("height",Math.max(28,-g.tickSize())).append("g").attr("transform","translate(0,"+(d.orient()==="top"?27:4)+")").call(d);a.on("change.axis-"+h,function(){j.call(d),i||(i=d3.select(j.node().appendChild(j.selectAll("text").node().cloneNode(!0))).style("display","none").text(null))}),a.on("focus.axis-"+h,function(a){if(i)if(a==null)i.style("display","none"),j.selectAll("text").style("fill-opacity",null);else{i.style("display",null).attr("x",a).text(f(b.invert(a)));var c=i.node().getComputedTextLength()+6;j.selectAll("text").style("fill-opacity",function(d){return Math.abs(b(d)-a)li>a:hover,.dropdown-menu>li>a:focus{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-color:#357ebd;background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-o-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#357ebd));background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f3f3f3));background-image:linear-gradient(to bottom,#ebebeb 0,#f3f3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x}.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#222 0,#282828 100%);background-image:-o-linear-gradient(top,#222 0,#282828 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#222),to(#282828));background-image:linear-gradient(to bottom,#222 0,#282828 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:-o-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#3071a9));background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:-o-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#3278b3));background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);background-repeat:repeat-x;border-color:#3278b3}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-o-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#428bca),to(#357ebd));background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)}
--------------------------------------------------------------------------------
/yandextank/plugins/Report/static/css/bootstrap-theme.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"bootstrap-theme.css","sources":["less/theme.less","less/mixins/vendor-prefixes.less","bootstrap-theme.css","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":"AAeA;;;;;;EAME,0CAAA;EC+CA,6FAAA;EACQ,qFAAA;EC5DT;AFiBC;;;;;;;;;;;;EC0CA,0DAAA;EACQ,kDAAA;EC7CT;AFqCC;;EAEE,wBAAA;EEnCH;AFwCD;EG/CI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EA+B2C,2BAAA;EAA2B,oBAAA;EE7BvE;AFAC;;EAEE,2BAAA;EACA,8BAAA;EEEH;AFCC;;EAEE,2BAAA;EACA,uBAAA;EECH;AFEC;;EAEE,2BAAA;EACA,wBAAA;EEAH;AFeD;EGhDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EE0BD;AFxBC;;EAEE,2BAAA;EACA,8BAAA;EE0BH;AFvBC;;EAEE,2BAAA;EACA,uBAAA;EEyBH;AFtBC;;EAEE,2BAAA;EACA,wBAAA;EEwBH;AFRD;EGjDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EEkDD;AFhDC;;EAEE,2BAAA;EACA,8BAAA;EEkDH;AF/CC;;EAEE,2BAAA;EACA,uBAAA;EEiDH;AF9CC;;EAEE,2BAAA;EACA,wBAAA;EEgDH;AF/BD;EGlDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EE0ED;AFxEC;;EAEE,2BAAA;EACA,8BAAA;EE0EH;AFvEC;;EAEE,2BAAA;EACA,uBAAA;EEyEH;AFtEC;;EAEE,2BAAA;EACA,wBAAA;EEwEH;AFtDD;EGnDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EEkGD;AFhGC;;EAEE,2BAAA;EACA,8BAAA;EEkGH;AF/FC;;EAEE,2BAAA;EACA,uBAAA;EEiGH;AF9FC;;EAEE,2BAAA;EACA,wBAAA;EEgGH;AF7ED;EGpDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EE0HD;AFxHC;;EAEE,2BAAA;EACA,8BAAA;EE0HH;AFvHC;;EAEE,2BAAA;EACA,uBAAA;EEyHH;AFtHC;;EAEE,2BAAA;EACA,wBAAA;EEwHH;AF7FD;;ECbE,oDAAA;EACQ,4CAAA;EC8GT;AFvFD;;EGvEI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHsEF,2BAAA;EE6FD;AF3FD;;;EG5EI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH4EF,2BAAA;EEiGD;AFvFD;EG1FI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ECnBF,qEAAA;EJ4GA,oBAAA;EC9CA,6FAAA;EACQ,qFAAA;EC4IT;AFlGD;EG1FI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EF2CF,0DAAA;EACQ,kDAAA;ECqJT;AF/FD;;EAEE,gDAAA;EEiGD;AF7FD;EG5GI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ECnBF,qEAAA;EFgOD;AFrGD;EG5GI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EF2CF,yDAAA;EACQ,iDAAA;EC0KT;AF9GD;;EAWI,2CAAA;EEuGH;AFlGD;;;EAGE,kBAAA;EEoGD;AF1FD;EACE,+CAAA;EC3FA,4FAAA;EACQ,oFAAA;ECwLT;AFlFD;EGtJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EE8FD;AFzFD;EGvJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EEsGD;AFhGD;EGxJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EE8GD;AFvGD;EGzJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EEsHD;AFtGD;EGlKI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED2QH;AFnGD;EG5KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDkRH;AFzGD;EG7KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDyRH;AF/GD;EG9KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDgSH;AFrHD;EG/KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDuSH;AF3HD;EGhLI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED8SH;AF9HD;EGnJI,+MAAA;EACA,0MAAA;EACA,uMAAA;EDoRH;AF1HD;EACE,oBAAA;EC/IA,oDAAA;EACQ,4CAAA;EC4QT;AF3HD;;;EAGE,+BAAA;EGpME,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHkMF,uBAAA;EEiID;AFvHD;ECjKE,mDAAA;EACQ,2CAAA;EC2RT;AFjHD;EG1NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED8UH;AFvHD;EG3NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDqVH;AF7HD;EG5NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED4VH;AFnID;EG7NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDmWH;AFzID;EG9NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED0WH;AF/ID;EG/NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDiXH;AF9ID;EGvOI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHqOF,uBAAA;EC1LA,2FAAA;EACQ,mFAAA;EC+UT","sourcesContent":["\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n\n &:disabled,\n &[disabled] {\n background-color: darken(@btn-color, 12%);\n background-image: none;\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-bg, 5%); @end-color: darken(@navbar-default-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-bg; @end-color: lighten(@navbar-inverse-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255,255,255,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n}\n\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They will be removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility){\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n &::-moz-placeholder { color: @color; // Firefox\n opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n",null,"// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]}
--------------------------------------------------------------------------------
/yandextank/plugins/Report/templates/offline.jade:
--------------------------------------------------------------------------------
1 | !!! 5
2 | {% autoescape None %}
3 | html(lang="en")
4 | head
5 | meta(charset="utf-8")
6 | meta(http-equiv="X-UA-Compatible", content="IE=edge")
7 | meta(name="viewport", content="width=device-width, initial-scale=1")
8 | title Yandex.Tank online report
9 |
10 | link(rel="stylesheet", href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css")
11 | link(rel="stylesheet", href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css")
12 |
13 | link(rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/rickshaw/1.4.6/rickshaw.min.css")
14 | script(src="https://code.jquery.com/jquery.min.js")
15 | script(src="https://code.angularjs.org/1.2.24/angular.min.js")
16 | script(src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js")
17 | script(src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js")
18 |
19 | script(src="https://cdnjs.cloudflare.com/ajax/libs/rickshaw/1.4.6/rickshaw.min.js")
20 |
21 | style(type='text/css').
22 | .rickshaw_legend li {
23 | display: inline-block;
24 | padding: 0 0 0 2px;
25 | min-width: 80px;
26 | white-space: nowrap;
27 | }
28 |
29 | script(type="text/javascript").
30 |
31 | document.cached_data = {{cached_data}};
32 | (function() {
33 | // angular-rickshaw.js
34 | "use strict";
35 | angular.module("angular-rickshaw", []).directive("rickshaw", function($compile) {
36 | return {
37 | restrict: "EA",
38 | scope: {
39 | options: "=rickshawOptions",
40 | series: "=rickshawSeries",
41 | features: "=rickshawFeatures"
42 | },
43 | link: function(scope, element, attrs) {
44 | var getSettings, update;
45 | getSettings = function(el) {
46 | var settings;
47 | settings = angular.copy(scope.options);
48 | settings.element = el;
49 | settings.series = scope.series;
50 | return settings;
51 | };
52 | update = function() {
53 | var graphEl, highlighter, hoverConfig, hoverDetail, i, legend, legendEl, mainEl, palette, settings, shelving, time, xAxis, xAxisConfig, yAxis, yAxisConfig, yAxisSecondary, yAxisSecondaryConfig;
54 | mainEl = angular.element(element);
55 | mainEl.append(graphEl);
56 | mainEl.empty();
57 | graphEl = $compile("")(scope);
58 | mainEl.append(graphEl);
59 | settings = getSettings(graphEl[0]);
60 | Rickshaw.Series.zeroFill(settings.series);
61 | scope.graph = new Rickshaw.Graph(settings);
62 | if (scope.features && scope.features.hover) {
63 | hoverConfig = {
64 | graph: scope.graph
65 | };
66 | hoverConfig.xFormatter = scope.features.hover.xFormatter;
67 | hoverConfig.yFormatter = scope.features.hover.yFormatter;
68 | hoverConfig.formatter = scope.features.hover.formatter;
69 | hoverDetail = new Rickshaw.Graph.HoverDetail(hoverConfig);
70 | }
71 | if (scope.features && scope.features.palette) {
72 | palette = new Rickshaw.Color.Palette({
73 | scheme: scope.features.palette
74 | });
75 | i = 0;
76 | while (i < settings.series.length) {
77 | settings.series[i].color = palette.color();
78 | i++;
79 | }
80 | }
81 | scope.graph.render();
82 | if (scope.features && scope.features.xAxis) {
83 | xAxisConfig = {
84 | graph: scope.graph
85 | };
86 | if (scope.features.xAxis.timeUnit) {
87 | time = new Rickshaw.Fixtures.Time();
88 | xAxisConfig.timeUnit = time.unit(scope.features.xAxis.timeUnit);
89 | }
90 | xAxis = new Rickshaw.Graph.Axis.Time(xAxisConfig);
91 | xAxis.render();
92 | }
93 | if (scope.features && scope.features.yAxis) {
94 | yAxisConfig = {
95 | graph: scope.graph,
96 | orientation: 'left'
97 | };
98 | if (scope.features.yAxis.tickFormat) {
99 | yAxisConfig.tickFormat = Rickshaw.Fixtures.Number[scope.features.yAxis.tickFormat];
100 | }
101 | yAxis = new Rickshaw.Graph.Axis.Y(yAxisConfig);
102 | yAxis.render();
103 | }
104 | if (scope.features && scope.features.yAxisSecondary) {
105 | yAxisSecondaryConfig = {
106 | graph: scope.graph,
107 | orientation: 'right'
108 | };
109 | if (scope.features.yAxisSecondary.tickFormat) {
110 | yAxisSecondaryConfig.tickFormat = Rickshaw.Fixtures.Number[scope.features.yAxisSecondary.tickFormat];
111 | }
112 | yAxisSecondary = new Rickshaw.Graph.Axis.Y(yAxisSecondaryConfig);
113 | yAxisSecondary.render();
114 | }
115 | if (scope.features && scope.features.legend) {
116 | legendEl = $compile("")(scope);
117 | mainEl.append(legendEl);
118 | legend = new Rickshaw.Graph.Legend({
119 | graph: scope.graph,
120 | element: legendEl[0]
121 | });
122 | if (scope.features.legend.toggle) {
123 | shelving = new Rickshaw.Graph.Behavior.Series.Toggle({
124 | graph: scope.graph,
125 | legend: legend
126 | });
127 | }
128 | if (scope.features.legend.highlight) {
129 | highlighter = new Rickshaw.Graph.Behavior.Series.Highlight({
130 | graph: scope.graph,
131 | legend: legend
132 | });
133 | }
134 | }
135 | };
136 | scope.graph = void 0;
137 | scope.$watch("options", function(newValue, oldValue) {
138 | if (!angular.equals(newValue, oldValue)) {
139 | update();
140 | }
141 | });
142 | scope.$watch("series", function(newValue, oldValue) {
143 | if (!angular.equals(newValue, oldValue)) {
144 | update();
145 | }
146 | });
147 | scope.$watch("features", function(newValue, oldValue) {
148 | if (!angular.equals(newValue, oldValue)) {
149 | update();
150 | }
151 | });
152 | scope.$on("DataUpdated", function() {
153 | return scope.graph.update();
154 | });
155 | return update();
156 | },
157 | controller: function($scope, $element, $attrs) {}
158 | };
159 | });
160 |
161 | // ws.js
162 | var app, collect_monitoring, collect_quantiles, collect_stats, collect_subtree,
163 | indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
164 |
165 | app = angular.module("ng-tank-report", ["angular-rickshaw"]);
166 |
167 | collect_subtree = function(storage, subtree, ts) {
168 | var key, node, results;
169 | results = [];
170 | for (key in subtree) {
171 | node = subtree[key];
172 | if (typeof node === 'number' || typeof node === 'array') {
173 | results.push(storage[key].push({
174 | x: ts,
175 | y: node
176 | }));
177 | } else {
178 | results.push(collect_subtree(storage[key], node, ts));
179 | }
180 | }
181 | return results;
182 | };
183 |
184 | collect_stats = function(stats) {
185 | var j, len, metric, ref, result, statItem, value;
186 | result = {};
187 | for (j = 0, len = stats.length; j < len; j++) {
188 | statItem = stats[j];
189 | ref = statItem.metrics;
190 | for (metric in ref) {
191 | value = ref[metric];
192 | if (!result[metric]) {
193 | result[metric] = [];
194 | }
195 | result[metric].push({
196 | x: +statItem.ts,
197 | y: +value
198 | });
199 | }
200 | }
201 | return result;
202 | };
203 |
204 | collect_monitoring = function(monitoring) {
205 | var host, hostData, j, len, metric, monItem, ref, ref1, result, subgroup, value;
206 | result = {};
207 | for (j = 0, len = monitoring.length; j < len; j++) {
208 | monItem = monitoring[j];
209 | ref = monItem.data;
210 | for (host in ref) {
211 | hostData = ref[host];
212 | if (!result[host]) {
213 | result[host] = {
214 | comment: hostData.comment,
215 | metrics: {}
216 | };
217 | }
218 | ref1 = hostData.metrics;
219 | for (metric in ref1) {
220 | value = ref1[metric];
221 | subgroup = metric.split("_", 1);
222 | if (!result[host].metrics[subgroup]) {
223 | result[host].metrics[subgroup] = {};
224 | }
225 | if (!result[host].metrics[subgroup][metric]) {
226 | result[host].metrics[subgroup][metric] = [];
227 | }
228 | result[host].metrics[subgroup][metric].push({
229 | x: +monItem.timestamp,
230 | y: +value
231 | });
232 | }
233 | }
234 | }
235 | return result;
236 | };
237 |
238 | collect_quantiles = function(data) {
239 | var dataItem, i, j, k, l, len, ref, ref1, ref2, result, tag, tagData;
240 | result = {
241 | overall: {
242 | interval_real: {
243 | q: {}
244 | }
245 | },
246 | tagged: {}
247 | };
248 | for (j = 0, len = data.length; j < len; j++) {
249 | dataItem = data[j];
250 | for (i = k = 0, ref = dataItem.overall.interval_real.q.q.length; 0 <= ref ? k < ref : k > ref; i = 0 <= ref ? ++k : --k) {
251 | if (!result.overall.interval_real.q[dataItem.overall.interval_real.q.q[i]]) {
252 | result.overall.interval_real.q[dataItem.overall.interval_real.q.q[i]] = [];
253 | }
254 | result.overall.interval_real.q[dataItem.overall.interval_real.q.q[i]].push({
255 | x: dataItem.ts,
256 | y: dataItem.overall.interval_real.q.value[i]
257 | });
258 | }
259 | ref1 = dataItem.tagged;
260 | for (tag in ref1) {
261 | tagData = ref1[tag];
262 | if (!result.tagged[tag]) {
263 | result.tagged[tag] = {
264 | interval_real: {
265 | q: {}
266 | }
267 | };
268 | }
269 | for (i = l = 0, ref2 = tagData.interval_real.q.q.length; 0 <= ref2 ? l < ref2 : l > ref2; i = 0 <= ref2 ? ++l : --l) {
270 | if (!result.tagged[tag].interval_real.q[tagData.interval_real.q.q[i]]) {
271 | result.tagged[tag].interval_real.q[tagData.interval_real.q.q[i]] = [];
272 | }
273 | result.tagged[tag].interval_real.q[tagData.interval_real.q.q[i]].push({
274 | x: dataItem.ts,
275 | y: tagData.interval_real.q.value[i]
276 | });
277 | }
278 | }
279 | }
280 | return result;
281 | };
282 |
283 | app.controller("TankReport", function($scope, $element) {
284 | $scope.status = "Disconnected";
285 | $scope.data = document.cached_data.data;
286 | $scope.uuid = document.cached_data.uuid;
287 | $scope.updateData = function(tankData) {
288 | var data, storage, storages, ts;
289 | for (ts in tankData) {
290 | storages = tankData[ts];
291 | for (storage in storages) {
292 | data = storages[storage];
293 | collect_subtree($scope.data[storage], data, +ts);
294 | }
295 | }
296 | return $scope.$broadcast('DataUpdated');
297 | };
298 | $scope.buildSeries = function() {
299 | var areaGraphs, cache, data, hostData, hostname, metric, metrics, monitoringData, name, overallData, quantilesData, series, statsData, subgroup, taggedData;
300 | cache = document.cached_data.data;
301 | if (cache.stats && cache.data && cache.monitoring) {
302 | overallData = {};
303 | taggedData = {};
304 | quantilesData = collect_quantiles(cache.data);
305 | statsData = collect_stats(cache.stats);
306 | monitoringData = collect_monitoring(cache.monitoring);
307 | } else {
308 | overallData = {};
309 | taggedData = {};
310 | quantilesData = {};
311 | statsData = {};
312 | monitoringData = {};
313 | setTimeout((function() {
314 | return location.reload(true);
315 | }), 3000);
316 | }
317 | areaGraphs = ['CPU', 'Memory'];
318 | $scope.monitoringGraphData = (function() {
319 | var results;
320 | results = [];
321 | for (hostname in monitoringData) {
322 | hostData = monitoringData[hostname];
323 | results.push({
324 | hostname: hostname,
325 | charts: (function() {
326 | var ref, results1;
327 | ref = hostData.metrics;
328 | results1 = [];
329 | for (subgroup in ref) {
330 | metrics = ref[subgroup];
331 | results1.push({
332 | name: subgroup,
333 | features: {
334 | palette: 'spectrum14',
335 | hover: {},
336 | xAxis: {},
337 | yAxis: {},
338 | ySecondaryAxis: {
339 | scale: null
340 | },
341 | legend: {
342 | toggle: true,
343 | highlight: true
344 | }
345 | },
346 | options: {
347 | renderer: 'multi'
348 | },
349 | series: ((function() {
350 | var results2;
351 | results2 = [];
352 | for (metric in metrics) {
353 | series = metrics[metric];
354 | results2.push({
355 | name: metric,
356 | data: series,
357 | renderer: indexOf.call(areaGraphs, subgroup) >= 0 ? "area" : "line"
358 | });
359 | }
360 | return results2;
361 | })()).concat([
362 | {
363 | name: "Requests per second",
364 | color: "red",
365 | renderer: "line",
366 | data: statsData.reqps
367 | }
368 | ])
369 | });
370 | }
371 | return results1;
372 | })()
373 | });
374 | }
375 | return results;
376 | })();
377 | $scope.quantilesGraphData = {
378 | name: "Response time quantiles",
379 | features: {
380 | palette: 'classic9',
381 | hover: {},
382 | xAxis: {},
383 | yAxis: {},
384 | legend: {
385 | toggle: true,
386 | highlight: true
387 | }
388 | },
389 | options: {
390 | renderer: 'area',
391 | stack: false,
392 | height: $element[0].offsetHeight - 45 - 62
393 | },
394 | series: ((function() {
395 | var ref, results;
396 | ref = quantilesData.overall.interval_real.q;
397 | results = [];
398 | for (name in ref) {
399 | data = ref[name];
400 | results.push({
401 | name: name,
402 | data: data
403 | });
404 | }
405 | return results;
406 | })()).sort(function(a, b) {
407 | if (parseFloat(a.name) <= parseFloat(b.name)) {
408 | return 1;
409 | } else {
410 | return -1;
411 | }
412 | })
413 | };
414 | $scope.rps = {
415 | name: "Requests per second",
416 | features: {
417 | palette: 'spectrum14',
418 | hover: {},
419 | xAxis: {},
420 | yAxis: {},
421 | legend: {
422 | toggle: true,
423 | highlight: true
424 | }
425 | },
426 | options: {
427 | renderer: 'line'
428 | },
429 | series: [
430 | {
431 | name: "req/s",
432 | color: "red",
433 | data: statsData.reqps
434 | }
435 | ]
436 | };
437 | $scope.protoCodes = {
438 | name: "Protocol return codes",
439 | features: {
440 | palette: 'spectrum14',
441 | hover: {},
442 | xAxis: {},
443 | yAxis: {},
444 | legend: {
445 | toggle: true,
446 | highlight: true
447 | }
448 | },
449 | options: {
450 | renderer: 'area',
451 | stack: true,
452 | height: $element[0].offsetHeight - 45 - 62
453 | },
454 | series: ((function() {
455 | var ref, results;
456 | ref = overallData.http_codes;
457 | results = [];
458 | for (name in ref) {
459 | data = ref[name];
460 | results.push({
461 | name: name,
462 | data: data
463 | });
464 | }
465 | return results;
466 | })()).sort(function(a, b) {
467 | if (parseFloat(a.name) <= parseFloat(b.name)) {
468 | return 1;
469 | } else {
470 | return -1;
471 | }
472 | })
473 | };
474 | return $scope.netCodes = {
475 | name: "Network return codes",
476 | features: {
477 | palette: 'spectrum14',
478 | hover: {},
479 | xAxis: {},
480 | yAxis: {},
481 | legend: {
482 | toggle: true,
483 | highlight: true
484 | }
485 | },
486 | options: {
487 | renderer: 'area',
488 | stack: true,
489 | height: $element[0].offsetHeight - 45 - 62
490 | },
491 | series: ((function() {
492 | var ref, results;
493 | ref = overallData.net_codes;
494 | results = [];
495 | for (name in ref) {
496 | data = ref[name];
497 | results.push({
498 | name: name,
499 | data: data
500 | });
501 | }
502 | return results;
503 | })()).sort(function(a, b) {
504 | if (parseFloat(a.name) <= parseFloat(b.name)) {
505 | return 1;
506 | } else {
507 | return -1;
508 | }
509 | })
510 | };
511 | };
512 | return $scope.buildSeries();
513 | });
514 |
515 | }).call(this);
516 | body
517 | .app.container(ng-app="ng-tank-report", ng-controller="TankReport")
518 | h1.page-heading Yandex.Tank online report
519 | #status {{!status}}
520 | #quantiles
521 | h2.part-heading Response time metrics
522 | .row
523 | .col-md-10
524 | .panel.panel-default
525 | .panel-heading
526 | h3.panel-title {{!quantilesGraphData.name}}
527 | .panel-body
528 | rickshaw(
529 | rickshaw-series="quantilesGraphData.series",
530 | rickshaw-options="quantilesGraphData.options",
531 | rickshaw-features="quantilesGraphData.features"
532 | )
533 | #monitoring
534 | h2.part-heading Monitoring metrics
535 | .host(ng-repeat="host in monitoringGraphData")
536 | h3 {{!host.hostname}}
537 | .row
538 | .col-md-10(ng-repeat="chart in host.charts")
539 | .panel.panel-default
540 | .panel-heading
541 | h3.panel-title {{!chart.name}}
542 | .panel-body
543 | rickshaw(
544 | rickshaw-series="chart.series",
545 | rickshaw-options="chart.options",
546 | rickshaw-features="chart.features"
547 | )
548 |
--------------------------------------------------------------------------------
/yandextank/plugins/Report/static/css/bootstrap-theme.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap v3.2.0 (http://getbootstrap.com)
3 | * Copyright 2011-2014 Twitter, Inc.
4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 | */
6 |
7 | .btn-default,
8 | .btn-primary,
9 | .btn-success,
10 | .btn-info,
11 | .btn-warning,
12 | .btn-danger {
13 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);
14 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
15 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
16 | }
17 | .btn-default:active,
18 | .btn-primary:active,
19 | .btn-success:active,
20 | .btn-info:active,
21 | .btn-warning:active,
22 | .btn-danger:active,
23 | .btn-default.active,
24 | .btn-primary.active,
25 | .btn-success.active,
26 | .btn-info.active,
27 | .btn-warning.active,
28 | .btn-danger.active {
29 | -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
30 | box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
31 | }
32 | .btn:active,
33 | .btn.active {
34 | background-image: none;
35 | }
36 | .btn-default {
37 | text-shadow: 0 1px 0 #fff;
38 | background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
39 | background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
40 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
41 | background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
42 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
43 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
44 | background-repeat: repeat-x;
45 | border-color: #dbdbdb;
46 | border-color: #ccc;
47 | }
48 | .btn-default:hover,
49 | .btn-default:focus {
50 | background-color: #e0e0e0;
51 | background-position: 0 -15px;
52 | }
53 | .btn-default:active,
54 | .btn-default.active {
55 | background-color: #e0e0e0;
56 | border-color: #dbdbdb;
57 | }
58 | .btn-default:disabled,
59 | .btn-default[disabled] {
60 | background-color: #e0e0e0;
61 | background-image: none;
62 | }
63 | .btn-primary {
64 | background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%);
65 | background-image: -o-linear-gradient(top, #428bca 0%, #2d6ca2 100%);
66 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#2d6ca2));
67 | background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%);
68 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);
69 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
70 | background-repeat: repeat-x;
71 | border-color: #2b669a;
72 | }
73 | .btn-primary:hover,
74 | .btn-primary:focus {
75 | background-color: #2d6ca2;
76 | background-position: 0 -15px;
77 | }
78 | .btn-primary:active,
79 | .btn-primary.active {
80 | background-color: #2d6ca2;
81 | border-color: #2b669a;
82 | }
83 | .btn-primary:disabled,
84 | .btn-primary[disabled] {
85 | background-color: #2d6ca2;
86 | background-image: none;
87 | }
88 | .btn-success {
89 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
90 | background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
91 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
92 | background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
93 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
94 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
95 | background-repeat: repeat-x;
96 | border-color: #3e8f3e;
97 | }
98 | .btn-success:hover,
99 | .btn-success:focus {
100 | background-color: #419641;
101 | background-position: 0 -15px;
102 | }
103 | .btn-success:active,
104 | .btn-success.active {
105 | background-color: #419641;
106 | border-color: #3e8f3e;
107 | }
108 | .btn-success:disabled,
109 | .btn-success[disabled] {
110 | background-color: #419641;
111 | background-image: none;
112 | }
113 | .btn-info {
114 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
115 | background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
116 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
117 | background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
118 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
119 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
120 | background-repeat: repeat-x;
121 | border-color: #28a4c9;
122 | }
123 | .btn-info:hover,
124 | .btn-info:focus {
125 | background-color: #2aabd2;
126 | background-position: 0 -15px;
127 | }
128 | .btn-info:active,
129 | .btn-info.active {
130 | background-color: #2aabd2;
131 | border-color: #28a4c9;
132 | }
133 | .btn-info:disabled,
134 | .btn-info[disabled] {
135 | background-color: #2aabd2;
136 | background-image: none;
137 | }
138 | .btn-warning {
139 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
140 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
141 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
142 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
143 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
144 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
145 | background-repeat: repeat-x;
146 | border-color: #e38d13;
147 | }
148 | .btn-warning:hover,
149 | .btn-warning:focus {
150 | background-color: #eb9316;
151 | background-position: 0 -15px;
152 | }
153 | .btn-warning:active,
154 | .btn-warning.active {
155 | background-color: #eb9316;
156 | border-color: #e38d13;
157 | }
158 | .btn-warning:disabled,
159 | .btn-warning[disabled] {
160 | background-color: #eb9316;
161 | background-image: none;
162 | }
163 | .btn-danger {
164 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
165 | background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
166 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
167 | background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
168 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
169 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
170 | background-repeat: repeat-x;
171 | border-color: #b92c28;
172 | }
173 | .btn-danger:hover,
174 | .btn-danger:focus {
175 | background-color: #c12e2a;
176 | background-position: 0 -15px;
177 | }
178 | .btn-danger:active,
179 | .btn-danger.active {
180 | background-color: #c12e2a;
181 | border-color: #b92c28;
182 | }
183 | .btn-danger:disabled,
184 | .btn-danger[disabled] {
185 | background-color: #c12e2a;
186 | background-image: none;
187 | }
188 | .thumbnail,
189 | .img-thumbnail {
190 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
191 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
192 | }
193 | .dropdown-menu > li > a:hover,
194 | .dropdown-menu > li > a:focus {
195 | background-color: #e8e8e8;
196 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
197 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
198 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
199 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
200 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
201 | background-repeat: repeat-x;
202 | }
203 | .dropdown-menu > .active > a,
204 | .dropdown-menu > .active > a:hover,
205 | .dropdown-menu > .active > a:focus {
206 | background-color: #357ebd;
207 | background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);
208 | background-image: -o-linear-gradient(top, #428bca 0%, #357ebd 100%);
209 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd));
210 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
211 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
212 | background-repeat: repeat-x;
213 | }
214 | .navbar-default {
215 | background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%);
216 | background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%);
217 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8));
218 | background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%);
219 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
220 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
221 | background-repeat: repeat-x;
222 | border-radius: 4px;
223 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
224 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
225 | }
226 | .navbar-default .navbar-nav > .active > a {
227 | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%);
228 | background-image: -o-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%);
229 | background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f3f3f3));
230 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%);
231 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);
232 | background-repeat: repeat-x;
233 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
234 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
235 | }
236 | .navbar-brand,
237 | .navbar-nav > li > a {
238 | text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
239 | }
240 | .navbar-inverse {
241 | background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
242 | background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
243 | background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
244 | background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
245 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
246 | filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
247 | background-repeat: repeat-x;
248 | }
249 | .navbar-inverse .navbar-nav > .active > a {
250 | background-image: -webkit-linear-gradient(top, #222 0%, #282828 100%);
251 | background-image: -o-linear-gradient(top, #222 0%, #282828 100%);
252 | background-image: -webkit-gradient(linear, left top, left bottom, from(#222), to(#282828));
253 | background-image: linear-gradient(to bottom, #222 0%, #282828 100%);
254 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);
255 | background-repeat: repeat-x;
256 | -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
257 | box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
258 | }
259 | .navbar-inverse .navbar-brand,
260 | .navbar-inverse .navbar-nav > li > a {
261 | text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);
262 | }
263 | .navbar-static-top,
264 | .navbar-fixed-top,
265 | .navbar-fixed-bottom {
266 | border-radius: 0;
267 | }
268 | .alert {
269 | text-shadow: 0 1px 0 rgba(255, 255, 255, .2);
270 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
271 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
272 | }
273 | .alert-success {
274 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
275 | background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
276 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
277 | background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
278 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
279 | background-repeat: repeat-x;
280 | border-color: #b2dba1;
281 | }
282 | .alert-info {
283 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
284 | background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
285 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
286 | background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
287 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
288 | background-repeat: repeat-x;
289 | border-color: #9acfea;
290 | }
291 | .alert-warning {
292 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
293 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
294 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
295 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
296 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
297 | background-repeat: repeat-x;
298 | border-color: #f5e79e;
299 | }
300 | .alert-danger {
301 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
302 | background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
303 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
304 | background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
305 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
306 | background-repeat: repeat-x;
307 | border-color: #dca7a7;
308 | }
309 | .progress {
310 | background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
311 | background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
312 | background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
313 | background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
314 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
315 | background-repeat: repeat-x;
316 | }
317 | .progress-bar {
318 | background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%);
319 | background-image: -o-linear-gradient(top, #428bca 0%, #3071a9 100%);
320 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3071a9));
321 | background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%);
322 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);
323 | background-repeat: repeat-x;
324 | }
325 | .progress-bar-success {
326 | background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
327 | background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
328 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
329 | background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
330 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
331 | background-repeat: repeat-x;
332 | }
333 | .progress-bar-info {
334 | background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
335 | background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
336 | background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
337 | background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
338 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
339 | background-repeat: repeat-x;
340 | }
341 | .progress-bar-warning {
342 | background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
343 | background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
344 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
345 | background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
346 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
347 | background-repeat: repeat-x;
348 | }
349 | .progress-bar-danger {
350 | background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
351 | background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
352 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
353 | background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
354 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
355 | background-repeat: repeat-x;
356 | }
357 | .progress-bar-striped {
358 | background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
359 | background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
360 | background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
361 | }
362 | .list-group {
363 | border-radius: 4px;
364 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
365 | box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
366 | }
367 | .list-group-item.active,
368 | .list-group-item.active:hover,
369 | .list-group-item.active:focus {
370 | text-shadow: 0 -1px 0 #3071a9;
371 | background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%);
372 | background-image: -o-linear-gradient(top, #428bca 0%, #3278b3 100%);
373 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3278b3));
374 | background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%);
375 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);
376 | background-repeat: repeat-x;
377 | border-color: #3278b3;
378 | }
379 | .panel {
380 | -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
381 | box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
382 | }
383 | .panel-default > .panel-heading {
384 | background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
385 | background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
386 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
387 | background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
388 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
389 | background-repeat: repeat-x;
390 | }
391 | .panel-primary > .panel-heading {
392 | background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);
393 | background-image: -o-linear-gradient(top, #428bca 0%, #357ebd 100%);
394 | background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd));
395 | background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
396 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
397 | background-repeat: repeat-x;
398 | }
399 | .panel-success > .panel-heading {
400 | background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
401 | background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
402 | background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
403 | background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
404 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
405 | background-repeat: repeat-x;
406 | }
407 | .panel-info > .panel-heading {
408 | background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
409 | background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
410 | background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
411 | background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
412 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
413 | background-repeat: repeat-x;
414 | }
415 | .panel-warning > .panel-heading {
416 | background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
417 | background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
418 | background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
419 | background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
420 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
421 | background-repeat: repeat-x;
422 | }
423 | .panel-danger > .panel-heading {
424 | background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
425 | background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
426 | background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
427 | background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
428 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
429 | background-repeat: repeat-x;
430 | }
431 | .well {
432 | background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
433 | background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
434 | background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
435 | background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
436 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
437 | background-repeat: repeat-x;
438 | border-color: #dcdcdc;
439 | -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
440 | box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
441 | }
442 | /*# sourceMappingURL=bootstrap-theme.css.map */
443 |
--------------------------------------------------------------------------------
/yandextank/plugins/Report/static/js/vendor/bootstrap.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap v3.2.0 (http://getbootstrap.com)
3 | * Copyright 2011-2014 Twitter, Inc.
4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
5 | */
6 | if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){return a(b.target).is(this)?b.handleObj.handler.apply(this,arguments):void 0}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.2.0",d.prototype.close=function(b){function c(){f.detach().trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one("bsTransitionEnd",c).emulateTransitionEnd(150):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.2.0",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),d[e](null==f[b]?this.options[b]:f[b]),setTimeout(a.proxy(function(){"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")&&(c.prop("checked")&&this.$element.hasClass("active")?a=!1:b.find(".active").removeClass("active")),a&&c.prop("checked",!this.$element.hasClass("active")).trigger("change")}a&&this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target);d.hasClass("btn")||(d=d.closest(".btn")),b.call(d,"toggle"),c.preventDefault()})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b).on("keydown.bs.carousel",a.proxy(this.keydown,this)),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.2.0",c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},c.prototype.keydown=function(a){switch(a.which){case 37:this.prev();break;case 39:this.next();break;default:return}a.preventDefault()},c.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},c.prototype.getItemIndex=function(a){return this.$items=a.parent().children(".item"),this.$items.index(a||this.$active)},c.prototype.to=function(b){var c=this,d=this.getItemIndex(this.$active=this.$element.find(".item.active"));return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid.bs.carousel",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},c.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},c.prototype.next=function(){return this.sliding?void 0:this.slide("next")},c.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},c.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}if(e.hasClass("active"))return this.sliding=!1;var j=e[0],k=a.Event("slide.bs.carousel",{relatedTarget:j,direction:g});if(this.$element.trigger(k),!k.isDefaultPrevented()){if(this.sliding=!0,f&&this.pause(),this.$indicators.length){this.$indicators.find(".active").removeClass("active");var l=a(this.$indicators.children()[this.getItemIndex(e)]);l&&l.addClass("active")}var m=a.Event("slid.bs.carousel",{relatedTarget:j,direction:g});return a.support.transition&&this.$element.hasClass("slide")?(e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one("bsTransitionEnd",function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger(m)},0)}).emulateTransitionEnd(1e3*d.css("transition-duration").slice(0,-1))):(d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger(m)),f&&this.cycle(),this}};var d=a.fn.carousel;a.fn.carousel=b,a.fn.carousel.Constructor=c,a.fn.carousel.noConflict=function(){return a.fn.carousel=d,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(c){var d,e=a(this),f=a(e.attr("data-target")||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""));if(f.hasClass("carousel")){var g=a.extend({},f.data(),e.data()),h=e.attr("data-slide-to");h&&(g.interval=!1),b.call(f,g),h&&f.data("bs.carousel").to(h),c.preventDefault()}}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var c=a(this);b.call(c,c.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b);!e&&f.toggle&&"show"==b&&(b=!b),e||d.data("bs.collapse",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};c.VERSION="3.2.0",c.DEFAULTS={toggle:!0},c.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},c.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var c=a.Event("show.bs.collapse");if(this.$element.trigger(c),!c.isDefaultPrevented()){var d=this.$parent&&this.$parent.find("> .panel > .in");if(d&&d.length){var e=d.data("bs.collapse");if(e&&e.transitioning)return;b.call(d,"hide"),e||d.data("bs.collapse",null)}var f=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[f](0),this.transitioning=1;var g=function(){this.$element.removeClass("collapsing").addClass("collapse in")[f](""),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return g.call(this);var h=a.camelCase(["scroll",f].join("-"));this.$element.one("bsTransitionEnd",a.proxy(g,this)).emulateTransitionEnd(350)[f](this.$element[0][h])}}},c.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?void this.$element[c](0).one("bsTransitionEnd",a.proxy(d,this)).emulateTransitionEnd(350):d.call(this)}}},c.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var d=a.fn.collapse;a.fn.collapse=b,a.fn.collapse.Constructor=c,a.fn.collapse.noConflict=function(){return a.fn.collapse=d,this},a(document).on("click.bs.collapse.data-api",'[data-toggle="collapse"]',function(c){var d,e=a(this),f=e.attr("data-target")||c.preventDefault()||(d=e.attr("href"))&&d.replace(/.*(?=#[^\s]+$)/,""),g=a(f),h=g.data("bs.collapse"),i=h?"toggle":e.data(),j=e.attr("data-parent"),k=j&&a(j);h&&h.transitioning||(k&&k.find('[data-toggle="collapse"][data-parent="'+j+'"]').not(e).addClass("collapsed"),e[g.hasClass("in")?"addClass":"removeClass"]("collapsed")),b.call(g,i)})}(jQuery),+function(a){"use strict";function b(b){b&&3===b.which||(a(e).remove(),a(f).each(function(){var d=c(a(this)),e={relatedTarget:this};d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown",e)),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown",e))}))}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function d(b){return this.each(function(){var c=a(this),d=c.data("bs.dropdown");d||c.data("bs.dropdown",d=new g(this)),"string"==typeof b&&d[b].call(c)})}var e=".dropdown-backdrop",f='[data-toggle="dropdown"]',g=function(b){a(b).on("click.bs.dropdown",this.toggle)};g.VERSION="3.2.0",g.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){"ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a('').insertAfter(a(this)).on("click",b);var h={relatedTarget:this};if(f.trigger(d=a.Event("show.bs.dropdown",h)),d.isDefaultPrevented())return;e.trigger("focus"),f.toggleClass("open").trigger("shown.bs.dropdown",h)}return!1}},g.prototype.keydown=function(b){if(/(38|40|27)/.test(b.keyCode)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var e=c(d),g=e.hasClass("open");if(!g||g&&27==b.keyCode)return 27==b.which&&e.find(f).trigger("focus"),d.trigger("click");var h=" li:not(.divider):visible a",i=e.find('[role="menu"]'+h+', [role="listbox"]'+h);if(i.length){var j=i.index(i.filter(":focus"));38==b.keyCode&&j>0&&j--,40==b.keyCode&&j').appendTo(this.$body),this.$element.on("click.dismiss.bs.modal",a.proxy(function(a){a.target===a.currentTarget&&("static"==this.options.backdrop?this.$element[0].focus.call(this.$element[0]):this.hide.call(this))},this)),e&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),!b)return;e?this.$backdrop.one("bsTransitionEnd",b).emulateTransitionEnd(150):b()}else if(!this.isShown&&this.$backdrop){this.$backdrop.removeClass("in");var f=function(){c.removeBackdrop(),b&&b()};a.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one("bsTransitionEnd",f).emulateTransitionEnd(150):f()}else b&&b()},c.prototype.checkScrollbar=function(){document.body.clientWidth>=window.innerWidth||(this.scrollbarWidth=this.scrollbarWidth||this.measureScrollbar())},c.prototype.setScrollbar=function(){var a=parseInt(this.$body.css("padding-right")||0,10);this.scrollbarWidth&&this.$body.css("padding-right",a+this.scrollbarWidth)},c.prototype.resetScrollbar=function(){this.$body.css("padding-right","")},c.prototype.measureScrollbar=function(){var a=document.createElement("div");a.className="modal-scrollbar-measure",this.$body.append(a);var b=a.offsetWidth-a.clientWidth;return this.$body[0].removeChild(a),b};var d=a.fn.modal;a.fn.modal=b,a.fn.modal.Constructor=c,a.fn.modal.noConflict=function(){return a.fn.modal=d,this},a(document).on("click.bs.modal.data-api",'[data-toggle="modal"]',function(c){var d=a(this),e=d.attr("href"),f=a(d.attr("data-target")||e&&e.replace(/.*(?=#[^\s]+$)/,"")),g=f.data("bs.modal")?"toggle":a.extend({remote:!/#/.test(e)&&e},f.data(),d.data());d.is("a")&&c.preventDefault(),f.one("show.bs.modal",function(a){a.isDefaultPrevented()||f.one("hidden.bs.modal",function(){d.is(":visible")&&d.trigger("focus")})}),b.call(f,g,this)})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tooltip"),f="object"==typeof b&&b;(e||"destroy"!=b)&&(e||d.data("bs.tooltip",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.type=this.options=this.enabled=this.timeout=this.hoverState=this.$element=null,this.init("tooltip",a,b)};c.VERSION="3.2.0",c.DEFAULTS={animation:!0,placement:"top",selector:!1,template:'',trigger:"hover focus",title:"",delay:0,html:!1,container:!1,viewport:{selector:"body",padding:0}},c.prototype.init=function(b,c,d){this.enabled=!0,this.type=b,this.$element=a(c),this.options=this.getOptions(d),this.$viewport=this.options.viewport&&a(this.options.viewport.selector||this.options.viewport);for(var e=this.options.trigger.split(" "),f=e.length;f--;){var g=e[f];if("click"==g)this.$element.on("click."+this.type,this.options.selector,a.proxy(this.toggle,this));else if("manual"!=g){var h="hover"==g?"mouseenter":"focusin",i="hover"==g?"mouseleave":"focusout";this.$element.on(h+"."+this.type,this.options.selector,a.proxy(this.enter,this)),this.$element.on(i+"."+this.type,this.options.selector,a.proxy(this.leave,this))}}this.options.selector?this._options=a.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.getOptions=function(b){return b=a.extend({},this.getDefaults(),this.$element.data(),b),b.delay&&"number"==typeof b.delay&&(b.delay={show:b.delay,hide:b.delay}),b},c.prototype.getDelegateOptions=function(){var b={},c=this.getDefaults();return this._options&&a.each(this._options,function(a,d){c[a]!=d&&(b[a]=d)}),b},c.prototype.enter=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="in",c.options.delay&&c.options.delay.show?void(c.timeout=setTimeout(function(){"in"==c.hoverState&&c.show()},c.options.delay.show)):c.show()},c.prototype.leave=function(b){var c=b instanceof this.constructor?b:a(b.currentTarget).data("bs."+this.type);return c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c)),clearTimeout(c.timeout),c.hoverState="out",c.options.delay&&c.options.delay.hide?void(c.timeout=setTimeout(function(){"out"==c.hoverState&&c.hide()},c.options.delay.hide)):c.hide()},c.prototype.show=function(){var b=a.Event("show.bs."+this.type);if(this.hasContent()&&this.enabled){this.$element.trigger(b);var c=a.contains(document.documentElement,this.$element[0]);if(b.isDefaultPrevented()||!c)return;var d=this,e=this.tip(),f=this.getUID(this.type);this.setContent(),e.attr("id",f),this.$element.attr("aria-describedby",f),this.options.animation&&e.addClass("fade");var g="function"==typeof this.options.placement?this.options.placement.call(this,e[0],this.$element[0]):this.options.placement,h=/\s?auto?\s?/i,i=h.test(g);i&&(g=g.replace(h,"")||"top"),e.detach().css({top:0,left:0,display:"block"}).addClass(g).data("bs."+this.type,this),this.options.container?e.appendTo(this.options.container):e.insertAfter(this.$element);var j=this.getPosition(),k=e[0].offsetWidth,l=e[0].offsetHeight;if(i){var m=g,n=this.$element.parent(),o=this.getPosition(n);g="bottom"==g&&j.top+j.height+l-o.scroll>o.height?"top":"top"==g&&j.top-o.scroll-l<0?"bottom":"right"==g&&j.right+k>o.width?"left":"left"==g&&j.left-kg.top+g.height&&(e.top=g.top+g.height-i)}else{var j=b.left-f,k=b.left+f+c;jg.width&&(e.left=g.left+g.width-k)}return e},c.prototype.getTitle=function(){var a,b=this.$element,c=this.options;return a=b.attr("data-original-title")||("function"==typeof c.title?c.title.call(b[0]):c.title)},c.prototype.getUID=function(a){do a+=~~(1e6*Math.random());while(document.getElementById(a));return a},c.prototype.tip=function(){return this.$tip=this.$tip||a(this.options.template)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},c.prototype.validate=function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},c.prototype.enable=function(){this.enabled=!0},c.prototype.disable=function(){this.enabled=!1},c.prototype.toggleEnabled=function(){this.enabled=!this.enabled},c.prototype.toggle=function(b){var c=this;b&&(c=a(b.currentTarget).data("bs."+this.type),c||(c=new this.constructor(b.currentTarget,this.getDelegateOptions()),a(b.currentTarget).data("bs."+this.type,c))),c.tip().hasClass("in")?c.leave(c):c.enter(c)},c.prototype.destroy=function(){clearTimeout(this.timeout),this.hide().$element.off("."+this.type).removeData("bs."+this.type)};var d=a.fn.tooltip;a.fn.tooltip=b,a.fn.tooltip.Constructor=c,a.fn.tooltip.noConflict=function(){return a.fn.tooltip=d,this}}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof b&&b;(e||"destroy"!=b)&&(e||d.data("bs.popover",e=new c(this,f)),"string"==typeof b&&e[b]())})}var c=function(a,b){this.init("popover",a,b)};if(!a.fn.tooltip)throw new Error("Popover requires tooltip.js");c.VERSION="3.2.0",c.DEFAULTS=a.extend({},a.fn.tooltip.Constructor.DEFAULTS,{placement:"right",trigger:"click",content:"",template:''}),c.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),c.prototype.constructor=c,c.prototype.getDefaults=function(){return c.DEFAULTS},c.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content").empty()[this.options.html?"string"==typeof c?"html":"append":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},c.prototype.hasContent=function(){return this.getTitle()||this.getContent()},c.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},c.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},c.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var d=a.fn.popover;a.fn.popover=b,a.fn.popover.Constructor=c,a.fn.popover.noConflict=function(){return a.fn.popover=d,this}}(jQuery),+function(a){"use strict";function b(c,d){var e=a.proxy(this.process,this);this.$body=a("body"),this.$scrollElement=a(a(c).is("body")?window:c),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||"")+" .nav li > a",this.offsets=[],this.targets=[],this.activeTarget=null,this.scrollHeight=0,this.$scrollElement.on("scroll.bs.scrollspy",e),this.refresh(),this.process()}function c(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})}b.VERSION="3.2.0",b.DEFAULTS={offset:10},b.prototype.getScrollHeight=function(){return this.$scrollElement[0].scrollHeight||Math.max(this.$body[0].scrollHeight,document.documentElement.scrollHeight)},b.prototype.refresh=function(){var b="offset",c=0;a.isWindow(this.$scrollElement[0])||(b="position",c=this.$scrollElement.scrollTop()),this.offsets=[],this.targets=[],this.scrollHeight=this.getScrollHeight();var d=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#./.test(e)&&a(e);return f&&f.length&&f.is(":visible")&&[[f[b]().top+c,e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){d.offsets.push(this[0]),d.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.getScrollHeight(),d=this.options.offset+c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(this.scrollHeight!=c&&this.refresh(),b>=d)return g!=(a=f[f.length-1])&&this.activate(a);if(g&&b<=e[0])return g!=(a=f[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parentsUntil(this.options.target,".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")};var d=a.fn.scrollspy;a.fn.scrollspy=c,a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=d,this},a(window).on("load.bs.scrollspy.data-api",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);c.call(b,b.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new c(this)),"string"==typeof b&&e[b]()})}var c=function(b){this.element=a(b)};c.VERSION="3.2.0",c.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.closest("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},c.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one("bsTransitionEnd",e).emulateTransitionEnd(150):e(),f.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(c){c.preventDefault(),b.call(a(this),"show")})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=this.unpin=this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.2.0",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=a(document).height(),d=this.$target.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top(this.$element)),"function"==typeof h&&(h=f.bottom(this.$element));var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=b-h?"bottom":null!=g&&g>=d?"top":!1;if(this.affixed!==i){null!=this.unpin&&this.$element.css("top","");var j="affix"+(i?"-"+i:""),k=a.Event(j+".bs.affix");this.$element.trigger(k),k.isDefaultPrevented()||(this.affixed=i,this.unpin="bottom"==i?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(j).trigger(a.Event(j.replace("affix","affixed"))),"bottom"==i&&this.$element.offset({top:b-this.$element.height()-h}))}}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},d.offsetBottom&&(d.offset.bottom=d.offsetBottom),d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery);
--------------------------------------------------------------------------------
/yandextank/plugins/Report/static/js/vendor/socket.io.min.js:
--------------------------------------------------------------------------------
1 | /*! Socket.IO.min.js build:0.9.16, production. Copyright(c) 2011 LearnBoost MIT Licensed */
2 | var io="undefined"==typeof module?{}:module.exports;(function(){(function(a,b){var c=a;c.version="0.9.16",c.protocol=1,c.transports=[],c.j=[],c.sockets={},c.connect=function(a,d){var e=c.util.parseUri(a),f,g;b&&b.location&&(e.protocol=e.protocol||b.location.protocol.slice(0,-1),e.host=e.host||(b.document?b.document.domain:b.location.hostname),e.port=e.port||b.location.port),f=c.util.uniqueUri(e);var h={host:e.host,secure:"https"==e.protocol,port:e.port||("https"==e.protocol?443:80),query:e.query||""};c.util.merge(h,d);if(h["force new connection"]||!c.sockets[f])g=new c.Socket(h);return!h["force new connection"]&&g&&(c.sockets[f]=g),g=g||c.sockets[f],g.of(e.path.length>1?e.path:"")}})("object"==typeof module?module.exports:this.io={},this),function(a,b){var c=a.util={},d=/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/,e=["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"];c.parseUri=function(a){var b=d.exec(a||""),c={},f=14;while(f--)c[e[f]]=b[f]||"";return c},c.uniqueUri=function(a){var c=a.protocol,d=a.host,e=a.port;return"document"in b?(d=d||document.domain,e=e||(c=="https"&&document.location.protocol!=="https:"?443:document.location.port)):(d=d||"localhost",!e&&c=="https"&&(e=443)),(c||"http")+"://"+d+":"+(e||80)},c.query=function(a,b){var d=c.chunkQuery(a||""),e=[];c.merge(d,c.chunkQuery(b||""));for(var f in d)d.hasOwnProperty(f)&&e.push(f+"="+d[f]);return e.length?"?"+e.join("&"):""},c.chunkQuery=function(a){var b={},c=a.split("&"),d=0,e=c.length,f;for(;db.length?a:b,f=a.length>b.length?b:a;for(var g=0,h=f.length;g0&&a.splice(0,1)[0]!=c.transport.name);a.length?h(a):c.publish("connect_failed")}}},c.options["connect timeout"]))})}c.sessionid=d,c.closeTimeout=f*1e3,c.heartbeatTimeout=e*1e3,c.transports||(c.transports=c.origTransports=g?b.util.intersect(g.split(","),c.options.transports):c.options.transports),c.setHeartbeatTimeout(),h(c.transports),c.once("connect",function(){clearTimeout(c.connectTimeoutTimer),a&&typeof a=="function"&&a()})}),this},d.prototype.setHeartbeatTimeout=function(){clearTimeout(this.heartbeatTimeoutTimer);if(this.transport&&!this.transport.heartbeats())return;var a=this;this.heartbeatTimeoutTimer=setTimeout(function(){a.transport.onClose()},this.heartbeatTimeout)},d.prototype.packet=function(a){return this.connected&&!this.doBuffer?this.transport.packet(a):this.buffer.push(a),this},d.prototype.setBuffer=function(a){this.doBuffer=a,!a&&this.connected&&this.buffer.length&&(this.options.manualFlush||this.flushBuffer())},d.prototype.flushBuffer=function(){this.transport.payload(this.buffer),this.buffer=[]},d.prototype.disconnect=function(){if(this.connected||this.connecting)this.open&&this.of("").packet({type:"disconnect"}),this.onDisconnect("booted");return this},d.prototype.disconnectSync=function(){var a=b.util.request(),c=["http"+(this.options.secure?"s":"")+":/",this.options.host+":"+this.options.port,this.options.resource,b.protocol,"",this.sessionid].join("/")+"/?disconnect=1";a.open("GET",c,!1),a.send(null),this.onDisconnect("booted")},d.prototype.isXDomain=function(){var a=c.location.port||("https:"==c.location.protocol?443:80);return this.options.host!==c.location.hostname||this.options.port!=a},d.prototype.onConnect=function(){this.connected||(this.connected=!0,this.connecting=!1,this.doBuffer||this.setBuffer(!1),this.emit("connect"))},d.prototype.onOpen=function(){this.open=!0},d.prototype.onClose=function(){this.open=!1,clearTimeout(this.heartbeatTimeoutTimer)},d.prototype.onPacket=function(a){this.of(a.endpoint).onPacket(a)},d.prototype.onError=function(a){a&&a.advice&&a.advice==="reconnect"&&(this.connected||this.connecting)&&(this.disconnect(),this.options.reconnect&&this.reconnect()),this.publish("error",a&&a.reason?a.reason:a)},d.prototype.onDisconnect=function(a){var b=this.connected,c=this.connecting;this.connected=!1,this.connecting=!1,this.open=!1;if(b||c)this.transport.close(),this.transport.clearTimeouts(),b&&(this.publish("disconnect",a),"booted"!=a&&this.options.reconnect&&!this.reconnecting&&this.reconnect())},d.prototype.reconnect=function(){function e(){if(a.connected){for(var b in a.namespaces)a.namespaces.hasOwnProperty(b)&&""!==b&&a.namespaces[b].packet({type:"connect"});a.publish("reconnect",a.transport.name,a.reconnectionAttempts)}clearTimeout(a.reconnectionTimer),a.removeListener("connect_failed",f),a.removeListener("connect",f),a.reconnecting=!1,delete a.reconnectionAttempts,delete a.reconnectionDelay,delete a.reconnectionTimer,delete a.redoTransports,a.options["try multiple transports"]=c}function f(){if(!a.reconnecting)return;if(a.connected)return e();if(a.connecting&&a.reconnecting)return a.reconnectionTimer=setTimeout(f,1e3);a.reconnectionAttempts++>=b?a.redoTransports?(a.publish("reconnect_failed"),e()):(a.on("connect_failed",f),a.options["try multiple transports"]=!0,a.transports=a.origTransports,a.transport=a.getTransport(),a.redoTransports=!0,a.connect()):(a.reconnectionDelay=10:!1},c.xdomainCheck=function(){return!0},typeof window!="undefined"&&(WEB_SOCKET_DISABLE_AUTO_INITIALIZATION=!0),b.transports.push("flashsocket")}("undefined"!=typeof io?io.Transport:module.exports,"undefined"!=typeof io?io:module.parent.exports);if("undefined"!=typeof window)var swfobject=function(){function A(){if(t)return;try{var a=i.getElementsByTagName("body")[0].appendChild(Q("span"));a.parentNode.removeChild(a)}catch(b){return}t=!0;var c=l.length;for(var d=0;d0)for(var c=0;c0){var g=P(d);if(g)if(S(m[c].swfVersion)&&!(y.wk&&y.wk<312))U(d,!0),e&&(f.success=!0,f.ref=G(d),e(f));else if(m[c].expressInstall&&H()){var h={};h.data=m[c].expressInstall,h.width=g.getAttribute("width")||"0",h.height=g.getAttribute("height")||"0",g.getAttribute("class")&&(h.styleclass=g.getAttribute("class")),g.getAttribute("align")&&(h.align=g.getAttribute("align"));var i={},j=g.getElementsByTagName("param"),k=j.length;for(var l=0;l');h.outerHTML='",n[n.length]=c.id,g=P(c.id)}else{var m=Q(b);m.setAttribute("type",e);for(var o in c)c[o]!=Object.prototype[o]&&(o.toLowerCase()=="styleclass"?m.setAttribute("class",c[o]):o.toLowerCase()!="classid"&&m.setAttribute(o,c[o]));for(var p in d)d[p]!=Object.prototype[p]&&p.toLowerCase()!="movie"&&M(m,p,d[p]);h.parentNode.replaceChild(m,h),g=m}}return g}function M(a,b,c){var d=Q("param");d.setAttribute("name",b),d.setAttribute("value",c),a.appendChild(d)}function N(a){var b=P(a);b&&b.nodeName=="OBJECT"&&(y.ie&&y.win?(b.style.display="none",function(){b.readyState==4?O(a):setTimeout(arguments.callee,10)}()):b.parentNode.removeChild(b))}function O(a){var b=P(a);if(b){for(var c in b)typeof b[c]=="function"&&(b[c]=null);b.parentNode.removeChild(b)}}function P(a){var b=null;try{b=i.getElementById(a)}catch(c){}return b}function Q(a){return i.createElement(a)}function R(a,b,c){a.attachEvent(b,c),o[o.length]=[a,b,c]}function S(a){var b=y.pv,c=a.split(".");return c[0]=parseInt(c[0],10),c[1]=parseInt(c[1],10)||0,c[2]=parseInt(c[2],10)||0,b[0]>c[0]||b[0]==c[0]&&b[1]>c[1]||b[0]==c[0]&&b[1]==c[1]&&b[2]>=c[2]?!0:!1}function T(c,d,e,f){if(y.ie&&y.mac)return;var g=i.getElementsByTagName("head")[0];if(!g)return;var h=e&&typeof e=="string"?e:"screen";f&&(v=null,w=null);if(!v||w!=h){var j=Q("style");j.setAttribute("type","text/css"),j.setAttribute("media",h),v=g.appendChild(j),y.ie&&y.win&&typeof i.styleSheets!=a&&i.styleSheets.length>0&&(v=i.styleSheets[i.styleSheets.length-1]),w=h}y.ie&&y.win?v&&typeof v.addRule==b&&v.addRule(c,d):v&&typeof i.createTextNode!=a&&v.appendChild(i.createTextNode(c+" {"+d+"}"))}function U(a,b){if(!x)return;var c=b?"visible":"hidden";t&&P(a)?P(a).style.visibility=c:T("#"+a,"visibility:"+c)}function V(b){var c=/[\\\"<>\.;]/,d=c.exec(b)!=null;return d&&typeof encodeURIComponent!=a?encodeURIComponent(b):b}var a="undefined",b="object",c="Shockwave Flash",d="ShockwaveFlash.ShockwaveFlash",e="application/x-shockwave-flash",f="SWFObjectExprInst",g="onreadystatechange",h=window,i=document,j=navigator,k=!1,l=[D],m=[],n=[],o=[],p,q,r,s,t=!1,u=!1,v,w,x=!0,y=function(){var f=typeof i.getElementById!=a&&typeof i.getElementsByTagName!=a&&typeof i.createElement!=a,g=j.userAgent.toLowerCase(),l=j.platform.toLowerCase(),m=l?/win/.test(l):/win/.test(g),n=l?/mac/.test(l):/mac/.test(g),o=/webkit/.test(g)?parseFloat(g.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):!1,p=!1,q=[0,0,0],r=null;if(typeof j.plugins!=a&&typeof j.plugins[c]==b)r=j.plugins[c].description,r&&(typeof j.mimeTypes==a||!j.mimeTypes[e]||!!j.mimeTypes[e].enabledPlugin)&&(k=!0,p=!1,r=r.replace(/^.*\s+(\S+\s+\S+$)/,"$1"),q[0]=parseInt(r.replace(/^(.*)\..*$/,"$1"),10),q[1]=parseInt(r.replace(/^.*\.(.*)\s.*$/,"$1"),10),q[2]=/[a-zA-Z]/.test(r)?parseInt(r.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0);else if(typeof h[["Active"].concat("Object").join("X")]!=a)try{var s=new(window[["Active"].concat("Object").join("X")])(d);s&&(r=s.GetVariable("$version"),r&&(p=!0,r=r.split(" ")[1].split(","),q=[parseInt(r[0],10),parseInt(r[1],10),parseInt(r[2],10)]))}catch(t){}return{w3:f,pv:q,wk:o,ie:p,win:m,mac:n}}(),z=function(){if(!y.w3)return;(typeof i.readyState!=a&&i.readyState=="complete"||typeof i.readyState==a&&(i.getElementsByTagName("body")[0]||i.body))&&A(),t||(typeof i.addEventListener!=a&&i.addEventListener("DOMContentLoaded",A,!1),y.ie&&y.win&&(i.attachEvent(g,function(){i.readyState=="complete"&&(i.detachEvent(g,arguments.callee),A())}),h==top&&function(){if(t)return;try{i.documentElement.doScroll("left")}catch(a){setTimeout(arguments.callee,0);return}A()}()),y.wk&&function(){if(t)return;if(!/loaded|complete/.test(i.readyState)){setTimeout(arguments.callee,0);return}A()}(),C(A))}(),W=function(){y.ie&&y.win&&window.attachEvent("onunload",function(){var a=o.length;for(var b=0;b= 10.0.0 is required.");return}location.protocol=="file:"&&a.error("WARNING: web-socket-js doesn't work in file:///... URL unless you set Flash Security Settings properly. Open the page via Web server i.e. http://..."),WebSocket=function(a,b,c,d,e){var f=this;f.__id=WebSocket.__nextId++,WebSocket.__instances[f.__id]=f,f.readyState=WebSocket.CONNECTING,f.bufferedAmount=0,f.__events={},b?typeof b=="string"&&(b=[b]):b=[],setTimeout(function(){WebSocket.__addTask(function(){WebSocket.__flash.create(f.__id,a,b,c||null,d||0,e||null)})},0)},WebSocket.prototype.send=function(a){if(this.readyState==WebSocket.CONNECTING)throw"INVALID_STATE_ERR: Web Socket connection has not been established";var b=WebSocket.__flash.send(this.__id,encodeURIComponent(a));return b<0?!0:(this.bufferedAmount+=b,!1)},WebSocket.prototype.close=function(){if(this.readyState==WebSocket.CLOSED||this.readyState==WebSocket.CLOSING)return;this.readyState=WebSocket.CLOSING,WebSocket.__flash.close(this.__id)},WebSocket.prototype.addEventListener=function(a,b,c){a in this.__events||(this.__events[a]=[]),this.__events[a].push(b)},WebSocket.prototype.removeEventListener=function(a,b,c){if(!(a in this.__events))return;var d=this.__events[a];for(var e=d.length-1;e>=0;--e)if(d[e]===b){d.splice(e,1);break}},WebSocket.prototype.dispatchEvent=function(a){var b=this.__events[a.type]||[];for(var c=0;c