Repository: open-falcon/falcon-plus Branch: master Commit: 93491806585f Files: 560 Total size: 2.2 MB Directory structure: gitextract_lxxa1vqu/ ├── .dockerignore ├── .gitignore ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── Dockerfile.module ├── Dockerfile_arm64 ├── LICENSE ├── Makefile ├── NOTICE ├── README.md ├── VERSION ├── api-standard.md ├── cmd/ │ ├── check.go │ ├── monitor.go │ ├── reload.go │ ├── restart.go │ ├── start.go │ └── stop.go ├── common/ │ ├── .gitignore │ ├── LICENSE │ ├── NOTICE │ ├── backend_pool/ │ │ ├── rpc_backends.go │ │ └── tsdb_backends.go │ ├── db/ │ │ └── db.go │ ├── model/ │ │ ├── agent.go │ │ ├── event.go │ │ ├── expression.go │ │ ├── graph.go │ │ ├── host.go │ │ ├── influxdb.go │ │ ├── judge.go │ │ ├── metric.go │ │ ├── nodata.go │ │ ├── prometheus.go │ │ ├── rpc.go │ │ ├── strategy.go │ │ ├── template.go │ │ ├── transfer.go │ │ └── tsdb.go │ ├── proc/ │ │ └── proc.go │ ├── sdk/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── requests/ │ │ │ ├── auth_request.go │ │ │ └── post.go │ │ └── sender/ │ │ ├── linkedlist.go │ │ ├── make.go │ │ ├── push.go │ │ └── sender.go │ └── utils/ │ ├── counter.go │ ├── date.go │ ├── formatter.go │ ├── func.go │ ├── func_test.go │ ├── map.go │ ├── md5.go │ ├── md5_test.go │ ├── objpool.go │ ├── statistics.go │ ├── tags.go │ └── tags_test.go ├── config/ │ ├── agent.json │ ├── aggregator.json │ ├── alarm.json │ ├── api.json │ ├── confgen.sh │ ├── falcon2p8s.json │ ├── gateway.json │ ├── graph.json │ ├── hbs.json │ ├── judge.json │ ├── nodata.json │ └── transfer.json ├── docker/ │ ├── README.md │ ├── confgen4docker.sh │ ├── ctrl.sh │ ├── k8s-cluster/ │ │ ├── Dockerfile.tpl │ │ ├── README.md │ │ ├── build.sh │ │ ├── init.sh │ │ └── modules/ │ │ ├── falcon-agent.yaml │ │ ├── falcon-aggregator.yaml │ │ ├── falcon-alarm.yaml │ │ ├── falcon-api.yaml │ │ ├── falcon-dashboard.yaml │ │ ├── falcon-graph-01.yaml │ │ ├── falcon-hbs.yaml │ │ ├── falcon-judge.yaml │ │ ├── falcon-nodata.yaml │ │ └── falcon-transfer.yaml │ ├── k8s-example/ │ │ ├── README.md │ │ ├── init_mysql_data.sh │ │ ├── mysql.yaml │ │ ├── openfalcon-dashboard.yaml │ │ ├── openfalcon-plus.yaml │ │ └── redis.yaml │ ├── mysql-init/ │ │ ├── Dockerfile │ │ └── init_mysql_data.sh │ └── supervisord.conf ├── docker-compose.yml ├── docker_test.sh ├── docs/ │ ├── LICENSE.md │ ├── Makefile │ ├── README.md │ ├── _config.yml │ ├── _includes/ │ │ └── nav.html │ ├── _layouts/ │ │ └── default.html │ ├── _posts/ │ │ ├── 2017-01-01-authentication.md │ │ ├── 2017-01-01-response-status-codes.md │ │ ├── Admin/ │ │ │ ├── 2017-01-01-admin_change_role.md │ │ │ ├── 2017-01-01-admin_change_user_passwd.md │ │ │ ├── 2017-01-01-admin_delete_user.md │ │ │ └── 2017-12-07-admin_login.md │ │ ├── Aggregator/ │ │ │ ├── 2017-01-01-aggreator_create.md │ │ │ ├── 2017-01-01-aggreator_delete.md │ │ │ ├── 2017-01-01-aggreator_of_hostgroup.md │ │ │ ├── 2017-01-01-aggreator_update.md │ │ │ └── 2017-01-01-get_aggreator_by_id.md │ │ ├── Alarm/ │ │ │ ├── 2017-01-01-alarm_eventcases_get_by_id.md │ │ │ ├── 2017-01-01-alarm_eventcases_list.md │ │ │ ├── 2017-01-01-alarm_eventnote_create.md │ │ │ ├── 2017-01-01-alarm_eventnote_get.md │ │ │ └── 2017-01-01-alarm_events_create.md │ │ ├── DashboardGraph/ │ │ │ ├── 2017-01-01-dashboard_graph_create.md │ │ │ ├── 2017-01-01-dashboard_graph_create_tmpgraph.md │ │ │ ├── 2017-01-01-dashboard_graph_delete.md │ │ │ ├── 2017-01-01-dashboard_graph_get.md │ │ │ ├── 2017-01-01-dashboard_graph_get_tmpgraph_by_id.md │ │ │ ├── 2017-01-01-dashboard_graph_update.md │ │ │ └── 2017-01-01-dashboard_graphs_gets_by_screenid.md │ │ ├── DashboardScreen/ │ │ │ ├── 2017-01-01-dashboard_screen_create.md │ │ │ ├── 2017-01-01-dashboard_screen_delete.md │ │ │ ├── 2017-01-01-dashboard_screen_get_by_id.md │ │ │ ├── 2017-01-01-dashboard_screen_gets_all.md │ │ │ ├── 2017-01-01-dashboard_screen_gets_by_pid.md │ │ │ └── 2017-01-01-dashboard_screen_update.md │ │ ├── Expression/ │ │ │ ├── 2017-01-01-expression_create.md │ │ │ ├── 2017-01-01-expression_delete.md │ │ │ ├── 2017-01-01-expression_info_by_id.md │ │ │ ├── 2017-01-01-expression_list.md │ │ │ └── 2017-01-01-expression_update.md │ │ ├── Graph/ │ │ │ ├── 2017-01-01-endpoint_counter.md │ │ │ ├── 2017-01-01-endpoints.md │ │ │ ├── 2017-01-01-grafana.md │ │ │ └── 2017-01-01-graph_histroy.md │ │ ├── Host/ │ │ │ ├── 2017-01-01-host_maintain.md │ │ │ ├── 2017-01-01-host_related_hostgroup.md │ │ │ ├── 2017-01-01-host_related_template.md │ │ │ └── 2017-01-01-host_reset.md │ │ ├── HostGroup/ │ │ │ ├── 2017-01-01-hostgroup_add_host.md │ │ │ ├── 2017-01-01-hostgroup_create.md │ │ │ ├── 2017-01-01-hostgroup_delete.md │ │ │ ├── 2017-01-01-hostgroup_get_info_by_id.md │ │ │ ├── 2017-01-01-hostgroup_list.md │ │ │ ├── 2017-01-01-hostgroup_template_bind.md │ │ │ ├── 2017-01-01-hostgroup_template_list.md │ │ │ ├── 2017-01-01-hostgroup_template_unbind.md │ │ │ ├── 2017-01-01-hostgroup_unbind_host.md │ │ │ ├── 2017-01-01-hostgroup_update.md │ │ │ └── 2017-08-22-hostgroup_update_partial_hosts.md │ │ ├── NoData/ │ │ │ ├── 2017-01-01-nodata_create.md │ │ │ ├── 2017-01-01-nodata_delete.md │ │ │ ├── 2017-01-01-nodata_info_by_id.md │ │ │ ├── 2017-01-01-nodata_list.md │ │ │ └── 2017-01-01-nodata_update.md │ │ ├── Plugin/ │ │ │ ├── 2017-01-01-plugin_create.md │ │ │ ├── 2017-01-01-plugin_delete.md │ │ │ └── 2017-01-01-plugin_info_by_id.md │ │ ├── Strategy/ │ │ │ ├── 2017-01-01-metric_tmplist.md │ │ │ ├── 2017-01-01-strategy_create.md │ │ │ ├── 2017-01-01-strategy_delete.md │ │ │ ├── 2017-01-01-strategy_info_by_id.md │ │ │ ├── 2017-01-01-strategy_list.md │ │ │ └── 2017-01-01-strategy_update.md │ │ ├── Team/ │ │ │ ├── 2017-01-01-team_create.md │ │ │ ├── 2017-01-01-team_delete_by_id.md │ │ │ ├── 2017-01-01-team_info_by_id.md │ │ │ ├── 2017-01-01-team_info_by_name.md │ │ │ ├── 2017-01-01-team_list.md │ │ │ ├── 2017-01-01-team_update.md │ │ │ └── 2018-11-19-add-user-to-team.md │ │ ├── Template/ │ │ │ ├── 2017-01-01-tpl_action_create.md │ │ │ ├── 2017-01-01-tpl_action_update.md │ │ │ ├── 2017-01-01-tpl_create.md │ │ │ ├── 2017-01-01-tpl_delete.md │ │ │ ├── 2017-01-01-tpl_hgp_list.md │ │ │ ├── 2017-01-01-tpl_info_by_id.md │ │ │ ├── 2017-01-01-tpl_list.md │ │ │ └── 2017-01-01-tpl_update.md │ │ └── User/ │ │ ├── 2017-01-01-user_change_password.md │ │ ├── 2017-01-01-user_create.md │ │ ├── 2017-01-01-user_current.md │ │ ├── 2017-01-01-user_get_info_by_id.md │ │ ├── 2017-01-01-user_get_info_by_name.md │ │ ├── 2017-01-01-user_get_teams.md │ │ ├── 2017-01-01-user_is_in_teams.md │ │ ├── 2017-01-01-user_list.md │ │ ├── 2017-01-01-user_login.md │ │ ├── 2017-01-01-user_logout.md │ │ ├── 2017-01-01-user_update.md │ │ └── 2019-04-14-update-specific-user.md │ ├── assets.css │ ├── assets.js │ ├── doc/ │ │ ├── admin.html │ │ ├── admin.html.json │ │ ├── aggregator.html │ │ ├── aggregator.html.json │ │ ├── alarm.html │ │ ├── alarm.html.json │ │ ├── expression.html │ │ ├── expression.html.json │ │ ├── graph.html │ │ ├── graph.html.json │ │ ├── host.html │ │ ├── host.html.json │ │ ├── hostgroup.html │ │ ├── hostgroup.html.json │ │ ├── nodata.html │ │ ├── nodata.html.json │ │ ├── plugin.html │ │ ├── plugin.html.json │ │ ├── team.html │ │ ├── team.html.json │ │ ├── template.html │ │ ├── template.html.json │ │ ├── user.html │ │ └── user.html.json │ ├── index.html │ └── robots.txt ├── g/ │ ├── g.go │ ├── tool.go │ └── tool_test.go ├── go.mod ├── go.sum ├── main.go ├── modules/ │ ├── agent/ │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── NOTICE │ │ ├── README.md │ │ ├── cfg.example.json │ │ ├── control │ │ ├── cron/ │ │ │ ├── builtin.go │ │ │ ├── collector.go │ │ │ ├── ips.go │ │ │ ├── plugin.go │ │ │ └── reporter.go │ │ ├── funcs/ │ │ │ ├── agent.go │ │ │ ├── checker.go │ │ │ ├── common.go │ │ │ ├── cpustat.go │ │ │ ├── dfstat.go │ │ │ ├── diskstats.go │ │ │ ├── du.go │ │ │ ├── du_test.go │ │ │ ├── funcs.go │ │ │ ├── gpu.go │ │ │ ├── ifstat.go │ │ │ ├── kernel.go │ │ │ ├── loadavg.go │ │ │ ├── meminfo.go │ │ │ ├── netstat.go │ │ │ ├── portstat.go │ │ │ ├── procs.go │ │ │ ├── snmp.go │ │ │ ├── sockstat.go │ │ │ └── urlstat.go │ │ ├── g/ │ │ │ ├── cfg.go │ │ │ ├── const.go │ │ │ ├── g.go │ │ │ ├── logger.go │ │ │ ├── rpc.go │ │ │ ├── tool.go │ │ │ ├── transfer.go │ │ │ ├── var.go │ │ │ └── var_test.go │ │ ├── http/ │ │ │ ├── admin.go │ │ │ ├── cpu.go │ │ │ ├── df.go │ │ │ ├── health.go │ │ │ ├── http.go │ │ │ ├── iostat.go │ │ │ ├── kernel.go │ │ │ ├── memory.go │ │ │ ├── page.go │ │ │ ├── plugin.go │ │ │ ├── push.go │ │ │ ├── run.go │ │ │ └── system.go │ │ ├── main.go │ │ ├── plugins/ │ │ │ ├── plugins.go │ │ │ ├── reader.go │ │ │ └── scheduler.go │ │ ├── public/ │ │ │ ├── css/ │ │ │ │ ├── font-awesome/ │ │ │ │ │ ├── css/ │ │ │ │ │ │ └── archive/ │ │ │ │ │ │ ├── font-awesome-ie7.css │ │ │ │ │ │ └── font-awesome.css │ │ │ │ │ └── font/ │ │ │ │ │ └── FontAwesome.otf │ │ │ │ ├── g.css │ │ │ │ ├── odometer.css │ │ │ │ ├── pages/ │ │ │ │ │ └── dashboard.css │ │ │ │ └── style.css │ │ │ ├── index.html │ │ │ └── js/ │ │ │ ├── base.js │ │ │ ├── bootstrap.js │ │ │ ├── dashboard.js │ │ │ ├── jquery.js │ │ │ └── odometer.js │ │ └── version.go │ ├── aggregator/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── cfg.example.json │ │ ├── control │ │ ├── cron/ │ │ │ ├── computer.go │ │ │ ├── query.go │ │ │ ├── run.go │ │ │ ├── run_test.go │ │ │ ├── updater.go │ │ │ └── worker.go │ │ ├── db/ │ │ │ ├── db.go │ │ │ └── reader.go │ │ ├── g/ │ │ │ ├── cfg.go │ │ │ ├── g.go │ │ │ └── items.go │ │ ├── http/ │ │ │ ├── common.go │ │ │ ├── http.go │ │ │ └── proc.go │ │ ├── main.go │ │ ├── sdk/ │ │ │ ├── sdk.go │ │ │ └── sdk_test.go │ │ └── version.go │ ├── alarm/ │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── NOTICE │ │ ├── README.md │ │ ├── api/ │ │ │ ├── links.go │ │ │ ├── portal.go │ │ │ ├── portal_test.go │ │ │ ├── uic.go │ │ │ └── uic_test.go │ │ ├── cfg.example.json │ │ ├── control │ │ ├── cron/ │ │ │ ├── builder.go │ │ │ ├── callback.go │ │ │ ├── combiner.go │ │ │ ├── event_cleaner.go │ │ │ ├── event_consumer.go │ │ │ ├── event_reader.go │ │ │ ├── im_sender.go │ │ │ ├── init_sender.go │ │ │ ├── mail_sender.go │ │ │ ├── model.go │ │ │ └── sms_sender.go │ │ ├── g/ │ │ │ ├── cfg.go │ │ │ ├── eventdto.go │ │ │ ├── g.go │ │ │ ├── logger.go │ │ │ └── redis.go │ │ ├── gitversion │ │ ├── http/ │ │ │ ├── controller.go │ │ │ └── http.go │ │ ├── main.go │ │ ├── model/ │ │ │ ├── database.go │ │ │ ├── event/ │ │ │ │ ├── event.go │ │ │ │ └── event_operation.go │ │ │ ├── im.go │ │ │ ├── mail.go │ │ │ └── sms.go │ │ ├── redi/ │ │ │ ├── msg_reader.go │ │ │ └── msg_writer.go │ │ └── version.go │ ├── falcon2p8s/ │ │ ├── .gitignore │ │ ├── ReadMe.md │ │ ├── cfg.example.json │ │ ├── control │ │ ├── g/ │ │ │ ├── cfg.go │ │ │ ├── const.go │ │ │ ├── g.go │ │ │ ├── logger.go │ │ │ └── var.go │ │ ├── http/ │ │ │ ├── common.go │ │ │ ├── cron.go │ │ │ ├── helper.go │ │ │ └── http.go │ │ ├── main.go │ │ ├── middlewares/ │ │ │ └── scraping.go │ │ ├── rpc/ │ │ │ ├── model.go │ │ │ ├── receiver.go │ │ │ └── rpc.go │ │ ├── sm.example.yaml │ │ ├── utils/ │ │ │ └── func.go │ │ └── version.go │ ├── gateway/ │ │ └── README.md │ ├── graph/ │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── NOTICE │ │ ├── README.md │ │ ├── api/ │ │ │ ├── graph.go │ │ │ └── rpc.go │ │ ├── cfg.example.json │ │ ├── control │ │ ├── cron/ │ │ │ └── clean.go │ │ ├── doc/ │ │ │ └── README.md │ │ ├── g/ │ │ │ ├── cfg.go │ │ │ ├── db.go │ │ │ ├── g.go │ │ │ ├── git.go │ │ │ ├── logger.go │ │ │ ├── utils.go │ │ │ └── utils_test.go │ │ ├── http/ │ │ │ ├── common.go │ │ │ ├── helper.go │ │ │ ├── http.go │ │ │ ├── index.go │ │ │ └── proc.go │ │ ├── index/ │ │ │ ├── cache.go │ │ │ ├── index.go │ │ │ ├── index_update_all_task.go │ │ │ └── index_update_incr_task.go │ │ ├── main.go │ │ ├── proc/ │ │ │ └── proc.go │ │ ├── rrdtool/ │ │ │ ├── migrate.go │ │ │ ├── rrdtool.go │ │ │ ├── sync_disk.go │ │ │ └── utils.go │ │ ├── store/ │ │ │ ├── history.go │ │ │ ├── linkedlist.go │ │ │ └── store.go │ │ ├── test/ │ │ │ ├── debug │ │ │ ├── graph.list │ │ │ └── http.recv.history │ │ └── version.go │ ├── hbs/ │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── NOTICE │ │ ├── README.md │ │ ├── cache/ │ │ │ ├── agents.go │ │ │ ├── cache.go │ │ │ ├── expressions.go │ │ │ ├── groups.go │ │ │ ├── hosts.go │ │ │ ├── plugins.go │ │ │ ├── strategies.go │ │ │ └── templates.go │ │ ├── cfg.example.json │ │ ├── control │ │ ├── db/ │ │ │ ├── agent.go │ │ │ ├── db.go │ │ │ ├── expression.go │ │ │ ├── group.go │ │ │ ├── host.go │ │ │ ├── plugin.go │ │ │ ├── strategy.go │ │ │ └── template.go │ │ ├── g/ │ │ │ ├── cfg.go │ │ │ └── g.go │ │ ├── http/ │ │ │ ├── common.go │ │ │ ├── http.go │ │ │ └── proc.go │ │ ├── main.go │ │ ├── rpc/ │ │ │ ├── agent.go │ │ │ ├── hbs.go │ │ │ └── rpc.go │ │ └── version.go │ ├── judge/ │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── NOTICE │ │ ├── README.md │ │ ├── cfg.example.json │ │ ├── control │ │ ├── cron/ │ │ │ ├── cleaner.go │ │ │ └── strategy.go │ │ ├── g/ │ │ │ ├── cfg.go │ │ │ ├── g.go │ │ │ ├── redis.go │ │ │ ├── rpc.go │ │ │ └── var.go │ │ ├── http/ │ │ │ ├── common.go │ │ │ ├── http.go │ │ │ └── info.go │ │ ├── main.go │ │ ├── rpc/ │ │ │ ├── receiver.go │ │ │ └── rpc.go │ │ ├── store/ │ │ │ ├── func.go │ │ │ ├── history.go │ │ │ ├── judge.go │ │ │ └── linkedlist.go │ │ └── version.go │ ├── nodata/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── cfg.example.json │ │ ├── collector/ │ │ │ ├── collector.go │ │ │ └── collector_cron.go │ │ ├── config/ │ │ │ ├── config.go │ │ │ ├── config_cron.go │ │ │ └── service/ │ │ │ ├── db.go │ │ │ ├── host.go │ │ │ └── mockcfg.go │ │ ├── control │ │ ├── g/ │ │ │ ├── cfg.go │ │ │ ├── g.go │ │ │ ├── git.go │ │ │ └── proc.go │ │ ├── http/ │ │ │ ├── common.go │ │ │ ├── debug_http.go │ │ │ ├── http.go │ │ │ └── proc_http.go │ │ ├── judge/ │ │ │ ├── judge.go │ │ │ ├── judge_cron.go │ │ │ └── status.go │ │ ├── main.go │ │ ├── scripts/ │ │ │ ├── debug │ │ │ └── nodata-db-schema.sql │ │ ├── sender/ │ │ │ └── sender.go │ │ └── version.go │ └── transfer/ │ ├── .gitignore │ ├── LICENSE │ ├── NOTICE │ ├── README.md │ ├── cfg.example.json │ ├── control │ ├── g/ │ │ ├── cfg.go │ │ ├── g.go │ │ └── git.go │ ├── http/ │ │ ├── api.go │ │ ├── common.go │ │ ├── debug_http.go │ │ ├── http.go │ │ └── proc_http.go │ ├── main.go │ ├── proc/ │ │ └── proc.go │ ├── receiver/ │ │ ├── receiver.go │ │ ├── rpc/ │ │ │ ├── rpc.go │ │ │ └── rpc_transfer.go │ │ └── socket/ │ │ ├── socket.go │ │ └── socket_telnet.go │ ├── scripts/ │ │ ├── info │ │ ├── info.py │ │ ├── last │ │ ├── last_raw │ │ ├── query │ │ └── query.py │ ├── sender/ │ │ ├── conn_pools.go │ │ ├── node_rings.go │ │ ├── send_queues.go │ │ ├── send_tasks.go │ │ ├── sender.go │ │ └── sender_cron.go │ ├── test/ │ │ ├── debug │ │ └── rpcclient.py │ └── version.go ├── scripts/ │ └── mysql/ │ ├── .gitignore │ ├── LICENSE │ ├── NOTICE │ └── db_schema/ │ ├── 1_uic-db-schema.sql │ ├── 2_portal-db-schema.sql │ ├── 3_dashboard-db-schema.sql │ ├── 4_graph-db-schema.sql │ └── 5_alarms-db-schema.sql ├── test/ │ └── README.md ├── vagrant/ │ └── Vagrantfile └── version.go ================================================ FILE CONTENTS ================================================ ================================================ FILE: .dockerignore ================================================ docs/ outrun/ tmp/ bin/ *.tar.gz open-falcon ================================================ FILE: .gitignore ================================================ bin/ out/ *.swp *.swo *.tar.gz docs/_site .idea open-falcon build ================================================ FILE: .travis.yml ================================================ sudo: required language: go arch: - amd64 - arm64 go: - "1.15" env: - DB_USER=root DB_PASSWORD=test123456 DB_HOST=127.0.0.1 DB_PORT=13306 REDIS_HOST=127.0.0.1 REDIS_PORT=16379 API_PORT=18080 API_HOST=127.0.0.1 services: - docker before_install: - tmpdaemon=$(mktemp) - sudo jq '."registry-mirrors" += ["https://mirror.gcr.io"]' /etc/docker/daemon.json > $tmpdaemon - sudo mv $tmpdaemon /etc/docker/daemon.json - sudo systemctl daemon-reload - sudo systemctl restart docker - docker system info script: - go get -u github.com/go-sql-driver/mysql - make fmt - make fmt-check - make misspell-check - make all - bash ./docker_test.sh after_success: - go test -race -coverprofile=coverage.txt -covermode=atomic github.com/open-falcon/falcon-plus/modules/api/test - bash <(curl -s https://codecov.io/bash) ================================================ FILE: CODE_OF_CONDUCT.md ================================================ # Code of Conduct ## 1. Purpose A primary goal of Open-Falcon is to be inclusive to the largest number of contributors, with the most varied and diverse backgrounds possible. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sexual orientation, ability, ethnicity, socioeconomic status, and religion (or lack thereof). This code of conduct outlines our expectations for all those who participate in our community, as well as the consequences for unacceptable behavior. We invite all those who participate in Open-Falcon to help us create safe and positive experiences for everyone. ## 2. Open Source Citizenship A supplemental goal of this Code of Conduct is to increase open source citizenship by encouraging participants to recognize and strengthen the relationships between our actions and their effects on our community. Communities mirror the societies in which they exist and positive action is essential to counteract the many forms of inequality and abuses of power that exist in society. If you see someone who is making an extra effort to ensure our community is welcoming, friendly, and encourages all participants to contribute to the fullest extent, we want to know. ## 3. Expected Behavior The following behaviors are expected and requested of all community members: * Participate in an authentic and active way. In doing so, you contribute to the health and longevity of this community. * Exercise consideration and respect in your speech and actions. * Attempt collaboration before conflict. * Refrain from demeaning, discriminatory, or harassing behavior and speech. * Be mindful of your surroundings and of your fellow participants. Alert community leaders if you notice a dangerous situation, someone in distress, or violations of this Code of Conduct, even if they seem inconsequential. * Remember that community event venues may be shared with members of the public; please be respectful to all patrons of these locations. ## 4. Unacceptable Behavior The following behaviors are considered harassment and are unacceptable within our community: * Violence, threats of violence or violent language directed against another person. * Sexist, racist, homophobic, transphobic, ableist or otherwise discriminatory jokes and language. * Posting or displaying sexually explicit or violent material. * Posting or threatening to post other people’s personally identifying information ("doxing"). * Personal insults, particularly those related to gender, sexual orientation, race, religion, or disability. * Inappropriate photography or recording. * Inappropriate physical contact. You should have someone’s consent before touching them. * Unwelcome sexual attention. This includes, sexualized comments or jokes; inappropriate touching, groping, and unwelcomed sexual advances. * Deliberate intimidation, stalking or following (online or in person). * Advocating for, or encouraging, any of the above behavior. * Sustained disruption of community events, including talks and presentations. ## 5. Consequences of Unacceptable Behavior Unacceptable behavior from any community member, including sponsors and those with decision-making authority, will not be tolerated. Anyone asked to stop unacceptable behavior is expected to comply immediately. If a community member engages in unacceptable behavior, the community organizers may take any action they deem appropriate, up to and including a temporary ban or permanent expulsion from the community without warning (and without refund in the case of a paid event). ## 6. Reporting Guidelines If you are subject to or witness unacceptable behavior, or have any other concerns, please notify a community organizer as soon as possible. root@open-falcon.com. Additionally, community organizers are available to help community members engage with local law enforcement or to otherwise help those experiencing unacceptable behavior feel safe. In the context of in-person events, organizers will also provide escorts as desired by the person experiencing distress. ## 7. Addressing Grievances If you feel you have been falsely or unfairly accused of violating this Code of Conduct, you should notify Open Falcon with a concise description of your grievance. Your grievance will be handled in accordance with our existing governing policies. ## 8. Scope We expect all community participants (contributors, paid or otherwise; sponsors; and other guests) to abide by this Code of Conduct in all community venues–online and in-person–as well as in all one-on-one communications pertaining to community business. This code of conduct and its related procedures also applies to unacceptable behavior occurring outside the scope of community activities when such behavior has the potential to adversely affect the safety and well-being of community members. ## 9. Contact info root@open-falcon.com ## 10. License and attribution This Code of Conduct is distributed under a [Creative Commons Attribution-ShareAlike license](http://creativecommons.org/licenses/by-sa/3.0/). Portions of text derived from the [Django Code of Conduct](https://www.djangoproject.com/conduct/) and the [Geek Feminism Anti-Harassment Policy](http://geekfeminism.wikia.com/wiki/Conference_anti-harassment/Policy). Retrieved on November 22, 2016 from [http://citizencodeofconduct.org/](http://citizencodeofconduct.org/) ================================================ FILE: CONTRIBUTING.md ================================================ ### COMMUNITY Open-Falcon is developed in the open. Here are some of the channels we use to communicate and contribute: **Mailing lists:** - [openfalcon-users](https://groups.google.com/forum/#!forum/openfalcon-users) – for discussions around openfalcon usage and community support - [openfalcon-developers](https://groups.google.com/forum/#!forum/openfalcon-developers) – for discussions around openfalcon development **Issue tracker:** - Use the GitHub issue tracker for the various [Open-Falcon repositories](http://github.com/open-falcon) to file bugs and features request. If you need support, please send your questions to the [openfalcon-users](https://groups.google.com/forum/#!forum/openfalcon-users) mailing list rather than filing a GitHub issue. *Please do not ask individual project members for support. Use the channels above instead, where the whole community can help you and benefit from the solutions provided. If community support is insufficient for your situation, please refer to the Commercial Support section below.* ### CONTRIBUTING We welcome community contributions! Open-Falcon uses GitHub to manage reviews of pull requests. - If you have a trivial fix or improvement, go ahead and create a pull request, addressing (with `@...`) the maintainer of this repository in the description of the pull request. - If you plan to do something more involved, first discuss your ideas on our [mailing list](https://groups.google.com/forum/#!forum/openfalcon-developers). This will avoid unnecessary work and surely give you and us a good deal of inspiration. ================================================ FILE: Dockerfile ================================================ # Build container; FROM openfalcon/makegcc-golang:1.15-alpine LABEL maintainer laiwei.ustc@gmail.com USER root ENV FALCON_DIR=/open-falcon PROJ_PATH=${GOPATH}/src/github.com/open-falcon/falcon-plus RUN mkdir -p $FALCON_DIR && \ mkdir -p $FALCON_DIR/logs && \ apk add --no-cache ca-certificates bash git supervisor COPY . ${PROJ_PATH} WORKDIR ${PROJ_PATH} RUN make all \ && make pack4docker \ && tar -zxf open-falcon-v*.tar.gz -C ${FALCON_DIR} \ && rm -rf ${PROJ_PATH} # Final container; FROM alpine:3.13 LABEL maintainer laiwei.ustc@gmail.com USER root ENV FALCON_DIR=/open-falcon RUN mkdir -p $FALCON_DIR/logs && \ apk add --no-cache ca-certificates bash git supervisor ADD docker/supervisord.conf /etc/supervisord.conf COPY --from=0 ${FALCON_DIR} ${FALCON_DIR} EXPOSE 8433 8080 WORKDIR ${FALCON_DIR} CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"] ================================================ FILE: Dockerfile.module ================================================ # Build container; FROM openfalcon/makegcc-golang:1.15-alpine LABEL maintainer laiwei.ustc@gmail.com USER root ENV FALCON_DIR=/open-falcon PROJ_PATH=${GOPATH}/src/github.com/open-falcon/falcon-plus RUN mkdir -p $FALCON_DIR && \ apk add --no-cache ca-certificates git COPY . ${PROJ_PATH} WORKDIR ${PROJ_PATH} ARG MODULE RUN make $MODULE \ && make pack4docker CMD=$MODULE \ && tar -zxf open-falcon-v*.tar.gz -C ${FALCON_DIR} \ && rm -rf ${PROJ_PATH} # Final container; FROM alpine:3.13 LABEL maintainer laiwei.ustc@gmail.com USER root ENV FALCON_DIR=/open-falcon RUN mkdir -p $FALCON_DIR/logs && \ apk update && \ apk add --no-cache ca-certificates bash git iproute2 COPY --from=0 ${FALCON_DIR} ${FALCON_DIR} EXPOSE 8433 8080 WORKDIR ${FALCON_DIR} ================================================ FILE: Dockerfile_arm64 ================================================ FROM jimmytinsley/makegcc-golang LABEL maintainer laiwei.ustc@gmail.com USER root ENV FALCON_DIR=/open-falcon PROJ_PATH=${GOPATH}/src/github.com/open-falcon/falcon-plus RUN mkdir -p $FALCON_DIR && \ mkdir -p $FALCON_DIR/logs && \ apk add --no-cache ca-certificates bash git supervisor COPY . ${PROJ_PATH} WORKDIR ${PROJ_PATH} RUN make all \ && make pack4docker \ && tar -zxf open-falcon-v*.tar.gz -C ${FALCON_DIR} \ && rm -rf ${PROJ_PATH} # Final container; FROM alpine:3.7 LABEL maintainer laiwei.ustc@gmail.com USER root ENV FALCON_DIR=/open-falcon RUN mkdir -p $FALCON_DIR/logs && \ apk add --no-cache ca-certificates bash git supervisor ADD docker/supervisord.conf /etc/supervisord.conf COPY --from=0 ${FALCON_DIR} ${FALCON_DIR} EXPOSE 8433 8080 WORKDIR ${FALCON_DIR} CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"] ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: Makefile ================================================ CMD = agent aggregator graph hbs judge nodata transfer gateway api alarm falcon2p8s TARGET = open-falcon PACKAGES ?= $(shell go list ./... | grep -v /vendor/) GOFILES := $(shell find . -name "*.go" -type f -not -path "./vendor/*") GOFMT ?= gofmt "-s" VERSION := $(shell cat VERSION) all: $(CMD) $(TARGET) .PHONY: misspell-check misspell-check: @hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ go get -u github.com/client9/misspell/cmd/misspell; \ fi misspell -error $(GOFILES) .PHONY: misspell misspell: @hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ go get -u github.com/client9/misspell/cmd/misspell; \ fi misspell -w $(GOFILES) vet: go vet $(PACKAGES) fmt: $(GOFMT) -w $(GOFILES) .PHONY: fmt-check fmt-check: # get all go files and run go fmt on them @diff=$$($(GOFMT) -d $(GOFILES)); \ if [ -n "$$diff" ]; then \ echo "Please run 'make fmt' and commit the result:"; \ echo "$${diff}"; \ exit 1; \ fi; $(CMD): if [ $@ = "gateway" ]; then \ GO111MODULE=on go build -ldflags "-X main.BinaryName=gateway -X main.GitCommit=`git rev-parse --short HEAD` -X main.Version=$(VERSION)" \ -o bin/gateway/falcon-gateway ./modules/transfer ; \ else \ GO111MODULE=on go build -ldflags "-X main.BinaryName=$@ -X main.GitCommit=`git rev-parse --short HEAD` -X main.Version=$(VERSION)" \ -o bin/$@/falcon-$@ ./modules/$@ ; \ fi .PHONY: $(TARGET) $(TARGET): $(GOFILES) GO111MODULE=on go build -ldflags "-X main.BinaryName=Open-Falcon -X main.GitCommit=`git rev-parse --short HEAD` -X main.Version=$(VERSION)" -o open-falcon checkbin: bin/ config/ open-falcon pack: checkbin @if [ -e out ] ; then rm -rf out; fi @mkdir out @$(foreach var,$(CMD),mkdir -p ./out/$(var)/bin;) @$(foreach var,$(CMD),mkdir -p ./out/$(var)/config;) @$(foreach var,$(CMD),mkdir -p ./out/$(var)/logs;) @$(foreach var,$(CMD),cp ./config/$(var).json ./out/$(var)/config/cfg.json;) @$(foreach var,$(CMD),cp ./bin/$(var)/falcon-$(var) ./out/$(var)/bin;) @cp -r ./modules/agent/public ./out/agent/ @(cd ./out && ln -s ./agent/public ./public) @(cd ./out && mkdir -p ./agent/plugin && ln -s ./agent/plugin ./plugin) @cp -r ./modules/api/data ./out/api/ @mkdir out/graph/data @bash ./config/confgen.sh @cp $(TARGET) ./out/$(TARGET) tar -C out -zcf open-falcon-v$(VERSION).tar.gz . @rm -rf out pack4docker: checkbin @if [ -e out ] ; then rm -rf out; fi @mkdir out @$(foreach var,$(CMD),mkdir -p ./out/$(var)/bin;) @$(foreach var,$(CMD),mkdir -p ./out/$(var)/config;) @$(foreach var,$(CMD),mkdir -p ./out/$(var)/logs;) @$(foreach var,$(CMD),cp ./config/$(var).json ./out/$(var)/config/cfg.json;) @$(foreach var,$(CMD),cp ./bin/$(var)/falcon-$(var) ./out/$(var)/bin;) @if expr "$(CMD)" : "agent" > /dev/null; then \ (cp -r ./modules/agent/public ./out/agent/); \ (cd ./out && ln -s ./agent/public ./public); \ (cd ./out && mkdir -p ./agent/plugin && ln -s ./agent/plugin ./plugin); \ fi @if expr "$(CMD)" : "api" > /dev/null; then \ cp -r ./modules/api/data ./out/api/; \ fi @if expr "$(CMD)" : "graph" > /dev/null; then \ mkdir out/graph/data; \ fi @cp ./docker/ctrl.sh ./out/ && chmod +x ./out/ctrl.sh @cp $(TARGET) ./out/$(TARGET) tar -C out -zcf open-falcon-v$(VERSION).tar.gz . @rm -rf out .PHONY: test test: @go test ./modules/api/test clean: @rm -rf ./bin @rm -rf ./out @rm -rf ./$(TARGET) @rm -rf open-falcon-v$(VERSION).tar.gz .PHONY: clean all agent aggregator graph hbs judge nodata transfer gateway api alarm ================================================ FILE: NOTICE ================================================ Open-Falcon Copyright (c) 2014-2017 Xiaomi, Inc. All Rights Reserved. This product is licensed to you under the Apache License, Version 2.0 (the "License"). You may not use this product except in compliance with the License. This product may include a number of subcomponents with separate copyright notices and license terms. Your use of these subcomponents is subject to the terms and conditions of the subcomponent's license, as noted in the LICENSE file. ================================================ FILE: README.md ================================================ # Falcon+ ![Open-Falcon](./logo.png) [![Build Status](https://travis-ci.org/open-falcon/falcon-plus.svg?branch=plus-dev)](https://travis-ci.org/open-falcon/falcon-plus) [![License](https://img.shields.io/badge/LICENSE-Apache2.0-ff69b4.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) [![Backers on Open Collective](https://opencollective.com/falcon-plus/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/falcon-plus/sponsors/badge.svg)](#sponsors) # Notice If you are heavily using k8s and adopting microservices architecture, we recommend you to upgrade to use [Nightingale](https://github.com/ccfos/nightingale) building your modern monitoring system. - [Nightingale](https://github.com/ccfos/nightingale) is an enterprise-level cloud-native monitoring tool, which can be used as drop-in replacement of Prometheus for alerting and management. - [Categraf](https://github.com/flashcatcloud/categraf) is one-stop telemetry collector for Nightingale / Prometheus / M3DB / VictoriaMetrics / Thanos / Influxdb / TDengine. It is recommended that you use [FlashDuty](https://flashcat.cloud/product/flashduty?from=categraf) as the OnCall system to realize alarm aggregation convergence, claiming, upgrading, scheduling, and coordination, so that the alarm can be reached efficiently and ensure that the alarm processing is not missed. # Documentations - [Usage](http://book.open-falcon.org) - [Open-Falcon API](http://open-falcon.org/falcon-plus) # Prerequisite - Git >= 1.7.5 - Go >= 1.6 # Getting Started ## Docker Please refer to ./docker/[README.md](https://github.com/open-falcon/falcon-plus/blob/master/docker/README.md). ## Build from source **before start, please make sure you prepared this:** ``` yum install -y redis yum install -y mysql-server ``` *NOTE: be sure to check redis and mysql-server have successfully started.* And then ``` # Please make sure that you have set `$GOPATH` and `$GOROOT` correctly. # If you have not golang in your host, please follow [https://golang.org/doc/install] to install golang. mkdir -p $GOPATH/src/github.com/open-falcon cd $GOPATH/src/github.com/open-falcon git clone https://github.com/open-falcon/falcon-plus.git ``` **And do not forget to init the database first (if you have not loaded the database schema before)** ``` cd $GOPATH/src/github.com/open-falcon/falcon-plus/scripts/mysql/db_schema/ mysql -h 127.0.0.1 -u root -p < 1_uic-db-schema.sql mysql -h 127.0.0.1 -u root -p < 2_portal-db-schema.sql mysql -h 127.0.0.1 -u root -p < 3_dashboard-db-schema.sql mysql -h 127.0.0.1 -u root -p < 4_graph-db-schema.sql mysql -h 127.0.0.1 -u root -p < 5_alarms-db-schema.sql ``` **NOTE: if you are upgrading from v0.1 to v0.2.0(or above),then**. [More upgrading instruction](http://www.jianshu.com/p/6fb2c2b4d030) mysql -h 127.0.0.1 -u root -p < 5_alarms-db-schema.sql # Compilation ``` cd $GOPATH/src/github.com/open-falcon/falcon-plus/ # make all modules make all # make specified module make agent # pack all modules make pack ``` * *after `make pack` you will got `open-falcon-vx.x.x.tar.gz`* * *if you want to edit configure file for each module, you can edit `config/xxx.json` before you do `make pack`* # Unpack and Decompose ``` export WorkDir="$HOME/open-falcon" mkdir -p $WorkDir tar -xzvf open-falcon-vx.x.x.tar.gz -C $WorkDir cd $WorkDir ``` # Start all modules in single host ``` cd $WorkDir ./open-falcon start # check modules status ./open-falcon check ``` # Run More Open-Falcon Commands for example: ``` # ./open-falcon [start|stop|restart|check|monitor|reload] module ./open-falcon start agent ./open-falcon check falcon-graph UP 53007 falcon-hbs UP 53014 falcon-judge UP 53020 falcon-transfer UP 53026 falcon-nodata UP 53032 falcon-aggregator UP 53038 falcon-agent UP 53044 falcon-gateway UP 53050 falcon-api UP 53056 falcon-alarm UP 53063 ``` * For debugging , You can check `$WorkDir/$moduleName/logs/xxx.log` # Install Frontend Dashboard - Follow [this](https://github.com/open-falcon/dashboard). **NOTE: if you want to use grafana as the dashboard, please check [this](https://github.com/open-falcon/grafana-openfalcon-datasource).** # Package Release ``` make clean all pack ``` # API Standard - [API Standard](https://github.com/open-falcon/falcon-plus/blob/master/api-standard.md) # Q&A - Any issue or question is welcome, Please feel free to open [github issues](https://github.com/open-falcon/falcon-plus/issues) :) - [FAQ](http://book.open-falcon.org/zh_0_2/faq/) ## Contributors This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)]. ================================================ FILE: VERSION ================================================ 0.3.x ================================================ FILE: api-standard.md ================================================ # HTTP API建议规范 ## 说明 本规范参考阮一峰的《[RESTful API设计指南](http://www.ruanyifeng.com/blog/2014/05/restful_api.html)》编写,部分内容做了适应性的调整和修改。 ## 协议 本文档目前只针对HTTP与HTTPS协议,提供参考规范和建议。 ## 域名 应尽量将API模块部署在专用域名之下。 ``` http://api.open-falcon.com ``` ## 版本(Versioning) 应将API版本号放入URL。 ``` http://api.open-falcon.com/v1/ ``` ## 路径(Endpoint) 路径又称``“终点”(endpoint)``,表示API的具体网址。 路径中以``“/”``区分的每一项都应该是``小写英文单词``,若包含多个单词,需要用``下划线``分隔。 在RESTful架构中,每个网址代表一种``资源(resource)``,所以网址中不应包含动词,如show、delete等。只能有名词,而且所用的名词往往与数据库的表格名对应。 一般来说,数据库中的表都是同种记录的``“集合”(collection)``,所以API中的名词也应该使用``复数``。 以Open-Falcon举例,API模块提供各种关于监控系统的信息,包括数据及报警: ``` · http://api.open-falcon.com/v1/counters · http://api.open-falcon.com/v1/strategies · http://api.open-falcon.com/v1/points ``` ## HTTP动词 对于资源的具体操作类型,由HTTP动词表示。 常用的HTTP动词有下面五个(括号里是对应的SQL命令)。 ``` · GET(SELECT):从服务器取出资源(一项或多项) · POST(CREATE):在服务器新建一个资源 · PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源) · PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性) · DELETE(DELETE):从服务器删除资源 ``` PATCH一般不常用,更新资源建议使用```PUT```。 还有两个不常用的动词。 ``` HEAD:获取资源的元数据。 OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的。 ``` 以下是一些例子 ``` · GET /v1/users : 获取所有的用户 · GET /v1/users/{int:ID} : 获取指定的用户信息 · POST /v1/users : 新增一个用户 · PUT /v1/users/{int:ID} : 更新某个指定用户的信息(提供用户的全部信息) · PATCH /v1/users/{int:ID} : 更新某个指定用户的信息(提供用户的部分信息) ``` ## 请求参数、请求体 如果记录数很多,服务器不可能都将他们返回给用户。API应该提供参数,支持过滤结果返回。 下面是一些常见的参数。 ``` · ?limit=10 : 指定返回记录的数量 · ?offset=10 : 指定返回记录的开始位置 · ?page=2&per_page=100 : 指定第几页,以及每页的记录数 · ?sortby=name&order=asc : 指定返回结果按照哪个属性排序,以及排序顺序 · ?type_id=1 : 指定筛选条件 ``` 其中,参数的命名规则为``snake_case``,即单词全部小写,单词间使用下划线分隔。 参数的设计允许存在``冗余``,即允许API路径和URL参数偶尔有重复。比如,GET /services/ID/domains 与 GET /services?domain_id=ID 的含义是相同的。 另外,参考HTTP协议(1.0版和1.1版)的主要设计者Roy Thomas Fielding所言,任何HTTP请求都允许包含请求体,但发送一个请求体非空的GET请求是没有意义的。因此GET请求请求体应该为``空``。 对于POST、PUT、DELETE请求,若请求体不为空,则请求体格式应该为JSON,如: ``` { "id" : 1, "name" : "ZhangSan" } ``` 需要注意的是,JSON中key的命名规则同样需要遵循``snake_case``。 ## 状态码(Status Code) 服务器向用户返回的状态码和提示信息,常见的有以下一些(方括号中是该状态码对应的HTTP动词)。 ``` · 200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。 · 201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。 · 202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务) · 204 NO CONTENT - [DELETE]:用户删除数据成功。 · 400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。 · 401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。 · 403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。 · 404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。 · 406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。 · 410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。 · 422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。 · 500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。 ``` 状态码的完整列表,参见[这里](https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)。 ## 返回结果 服务器返回的数据格式,统一为``JSON``。针对资源的不同操作,服务器向用户返回的结果 应该符合以下规范: ``` · GET /collection : 返回资源对象的列表(数组) · DELETE /collection/resource : 返回如下的json响应,其中data为被删除对象. · GET /collection/resource : 返回单个资源对象 · POST /collection : 返回新生成的资源对象 · PUT /collection/resource : 返回更改后的完整的资源对象 ``` 响应格式统一如下: ``此处草版略复杂,待讨论修正`` ``` { "code": 200, // http status code "data": data, // return data if success "ret_msg": "return message if failed", // return message if failed, when success, it's empty "debug_msg": "used for debug", // used for debug when failed,when success, it's emptuy "url_manual": "manual url to show if failed", // manual url to show if failed "url_redirect": "used for 3xx results", // used for 3xx results “response_type": "application/json" // response body type } ``` ================================================ FILE: cmd/check.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "fmt" "strings" "github.com/open-falcon/falcon-plus/g" "github.com/spf13/cobra" ) var Check = &cobra.Command{ Use: "check [Module ...]", Short: "Check the status of Open-Falcon modules", Long: ` Check if the specified Open-Falcon modules are running. Modules: ` + "all " + strings.Join(g.AllModulesInOrder, " "), RunE: check, } func check(c *cobra.Command, args []string) error { args = g.RmDup(args) if len(args) == 0 { args = g.AllModulesInOrder } for _, moduleName := range args { if !g.HasModule(moduleName) { return fmt.Errorf("%s doesn't exist", moduleName) } if g.IsRunning(moduleName) { fmt.Printf("%20s %10s %15s \n", g.ModuleApps[moduleName], "UP", g.Pid(moduleName)) } else { fmt.Printf("%20s %10s %15s \n", g.ModuleApps[moduleName], "DOWN", "-") } } return nil } ================================================ FILE: cmd/monitor.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "fmt" "os" "os/exec" "strings" "github.com/open-falcon/falcon-plus/g" "github.com/spf13/cobra" ) var Monitor = &cobra.Command{ Use: "monitor [Module ...]", Short: "Display an Open-Falcon module's log", Long: ` Display the log of the specified Open-Falcon module. A module represents a single node in a cluster. Modules: ` + strings.Join(g.AllModulesInOrder, " "), RunE: monitor, } func checkMonReq(name string) error { if !g.HasModule(name) { return fmt.Errorf("%s doesn't exist", name) } if !g.HasLogfile(name) { r := g.Rel(g.LogPath(name)) return fmt.Errorf("expect logfile: %s", r) } return nil } func monitor(c *cobra.Command, args []string) error { if len(args) < 1 { return c.Usage() } var tailArgs []string = []string{"-f"} for _, moduleName := range args { if err := checkMonReq(moduleName); err != nil { return err } tailArgs = append(tailArgs, g.LogPath(moduleName)) } cmd := exec.Command("tail", tailArgs...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr return cmd.Run() } ================================================ FILE: cmd/reload.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import "github.com/spf13/cobra" var Reload = &cobra.Command{ Use: "reload [Module ...]", Short: "Reload an Open-Falcon module's configuration file", Long: ` Reload the configuration file of the specified Open-Falcon module. A module represents a single node in a cluster. Modules: `, RunE: reload, } func reload(c *cobra.Command, args []string) error { if len(args) != 1 { return c.Usage() } return nil } ================================================ FILE: cmd/restart.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "strings" "time" "github.com/open-falcon/falcon-plus/g" "github.com/spf13/cobra" ) var Restart = &cobra.Command{ Use: "restart [Module ...]", Short: "Restart Open-Falcon modules", Long: ` Restart the specified Open-Falcon modules and run until a stop command is received. A module represents a single node in a cluster. Modules: ` + "all " + strings.Join(g.AllModulesInOrder, " "), RunE: restart, } func restart(c *cobra.Command, args []string) error { args = g.RmDup(args) if len(args) == 0 { args = g.AllModulesInOrder } for _, moduleName := range args { if err := stop(c, []string{moduleName}); err != nil { return err } if strings.Contains(moduleName, "graph") { time.Sleep(2 * time.Second) } else { time.Sleep(1 * time.Second) } if err := start(c, []string{moduleName}); err != nil { return err } } return nil } ================================================ FILE: cmd/start.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "fmt" "os" "os/exec" "strings" "time" "github.com/open-falcon/falcon-plus/g" "github.com/spf13/cobra" ) var Start = &cobra.Command{ Use: "start [Module ...]", Short: "Start Open-Falcon modules", Long: ` Start the specified Open-Falcon modules and run until a stop command is received. A module represents a single node in a cluster. Modules: ` + "all " + strings.Join(g.AllModulesInOrder, " "), RunE: start, SilenceUsage: true, SilenceErrors: true, } var PreqOrderFlag bool var ConsoleOutputFlag bool func cmdArgs(name string) []string { return []string{"-c", g.Cfg(name)} } func openLogFile(name string) (*os.File, error) { logDir := g.LogDir(name) if err := os.MkdirAll(logDir, 0755); err != nil { return nil, err } logPath := g.LogPath(name) logOutput, err := os.OpenFile(logPath, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666) if err != nil { return nil, err } return logOutput, nil } func execModule(co bool, name string) error { cmd := exec.Command(g.Bin(name), cmdArgs(name)...) if co { cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr return cmd.Run() } logOutput, err := openLogFile(name) if err != nil { return err } defer logOutput.Close() cmd.Stdout = logOutput cmd.Stderr = logOutput return cmd.Start() } func checkStartReq(name string) error { if !g.HasModule(name) { return fmt.Errorf("%s doesn't exist", name) } if !g.HasCfg(name) { r := g.Rel(g.Cfg(name)) return fmt.Errorf("expect config file: %s", r) } return nil } func isStarted(name string) bool { ticker := time.NewTicker(time.Millisecond * 100) defer ticker.Stop() timeout := time.After(time.Second) for { select { case <-ticker.C: if g.IsRunning(name) { return true } case <-timeout: return false } } } func start(c *cobra.Command, args []string) error { args = g.RmDup(args) if PreqOrderFlag { args = g.PreqOrder(args) } if len(args) == 0 { args = g.AllModulesInOrder } for _, moduleName := range args { if err := checkStartReq(moduleName); err != nil { return err } // Skip starting if the module is already running if g.IsRunning(moduleName) { fmt.Print("[", g.ModuleApps[moduleName], "] ", g.Pid(moduleName), "\n") continue } if err := execModule(ConsoleOutputFlag, moduleName); err != nil { return err } if isStarted(moduleName) { fmt.Print("[", g.ModuleApps[moduleName], "] ", g.Pid(moduleName), "\n") continue } return fmt.Errorf("[%s] failed to start", g.ModuleApps[moduleName]) } return nil } ================================================ FILE: cmd/stop.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cmd import ( "fmt" "os" "os/exec" "strings" "github.com/open-falcon/falcon-plus/g" "github.com/spf13/cobra" ) var Stop = &cobra.Command{ Use: "stop [Module ...]", Short: "Stop Open-Falcon modules", Long: ` Stop the specified Open-Falcon modules. A module represents a single node in a cluster. Modules: ` + "all " + strings.Join(g.AllModulesInOrder, " "), RunE: stop, } func stop(c *cobra.Command, args []string) error { args = g.RmDup(args) if len(args) == 0 { args = g.AllModulesInOrder } for _, moduleName := range args { if !g.HasModule(moduleName) { return fmt.Errorf("%s doesn't exist", moduleName) } if !g.IsRunning(moduleName) { fmt.Print("[", g.ModuleApps[moduleName], "] down\n") continue } cmd := exec.Command("kill", "-TERM", g.Pid(moduleName)) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err := cmd.Run() if err == nil { fmt.Print("[", g.ModuleApps[moduleName], "] down\n") continue } return err } return nil } ================================================ FILE: common/.gitignore ================================================ *.swp *.swo /var .DS_Store *.iml *.idea ================================================ FILE: common/LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: common/NOTICE ================================================ Open-Falcon Copyright (c) 2014-2015 Xiaomi, Inc. All Rights Reserved. This product is licensed to you under the Apache License, Version 2.0 (the "License"). You may not use this product except in compliance with the License. This product may include a number of subcomponents with separate copyright notices and license terms. Your use of these subcomponents is subject to the terms and conditions of the subcomponent's license, as noted in the LICENSE file. ================================================ FILE: common/backend_pool/rpc_backends.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package backend_pool import ( "fmt" "net" "net/rpc" "net/rpc/jsonrpc" "sync" "time" connp "github.com/toolkits/conn_pool" rpcpool "github.com/toolkits/conn_pool/rpc_conn_pool" ) // ConnPools Manager type SafeRpcConnPools struct { sync.RWMutex M map[string]*connp.ConnPool MaxConns int MaxIdle int ConnTimeout int CallTimeout int } func CreateSafeRpcConnPools(maxConns, maxIdle, connTimeout, callTimeout int, cluster []string) *SafeRpcConnPools { cp := &SafeRpcConnPools{M: make(map[string]*connp.ConnPool), MaxConns: maxConns, MaxIdle: maxIdle, ConnTimeout: connTimeout, CallTimeout: callTimeout} ct := time.Duration(cp.ConnTimeout) * time.Millisecond for _, address := range cluster { if _, exist := cp.M[address]; exist { continue } cp.M[address] = createOneRpcPool(address, address, ct, maxConns, maxIdle) } return cp } func CreateSafeJsonrpcConnPools(maxConns, maxIdle, connTimeout, callTimeout int, cluster []string) *SafeRpcConnPools { cp := &SafeRpcConnPools{M: make(map[string]*connp.ConnPool), MaxConns: maxConns, MaxIdle: maxIdle, ConnTimeout: connTimeout, CallTimeout: callTimeout} ct := time.Duration(cp.ConnTimeout) * time.Millisecond for _, address := range cluster { if _, exist := cp.M[address]; exist { continue } cp.M[address] = createOneJsonrpcPool(address, address, ct, maxConns, maxIdle) } return cp } // 同步发送, 完成发送或超时后 才能返回 func (this *SafeRpcConnPools) Call(addr, method string, args interface{}, resp interface{}) error { connPool, exists := this.Get(addr) if !exists { return fmt.Errorf("%s has no connection pool", addr) } conn, err := connPool.Fetch() if err != nil { return fmt.Errorf("%s get connection fail: conn %v, err %v. proc: %s", addr, conn, err, connPool.Proc()) } rpcClient := conn.(*rpcpool.RpcClient) callTimeout := time.Duration(this.CallTimeout) * time.Millisecond done := make(chan error, 1) go func() { done <- rpcClient.Call(method, args, resp) }() select { case <-time.After(callTimeout): connPool.ForceClose(conn) return fmt.Errorf("%s, call timeout", addr) case err = <-done: if err != nil { connPool.ForceClose(conn) err = fmt.Errorf("%s, call failed, err %v. proc: %s", addr, err, connPool.Proc()) } else { connPool.Release(conn) } return err } } func (this *SafeRpcConnPools) Get(address string) (*connp.ConnPool, bool) { this.RLock() defer this.RUnlock() p, exists := this.M[address] return p, exists } func (this *SafeRpcConnPools) Destroy() { this.Lock() defer this.Unlock() addresses := make([]string, 0, len(this.M)) for address := range this.M { addresses = append(addresses, address) } for _, address := range addresses { this.M[address].Destroy() delete(this.M, address) } } func (this *SafeRpcConnPools) Proc() []string { procs := []string{} for _, cp := range this.M { procs = append(procs, cp.Proc()) } return procs } func createOneRpcPool(name string, address string, connTimeout time.Duration, maxConns int, maxIdle int) *connp.ConnPool { p := connp.NewConnPool(name, address, int32(maxConns), int32(maxIdle)) p.New = func(connName string) (connp.NConn, error) { _, err := net.ResolveTCPAddr("tcp", p.Address) if err != nil { return nil, err } conn, err := net.DialTimeout("tcp", p.Address, connTimeout) if err != nil { return nil, err } return rpcpool.NewRpcClient(rpc.NewClient(conn), connName), nil } return p } func createOneJsonrpcPool(name string, address string, connTimeout time.Duration, maxConns int, maxIdle int) *connp.ConnPool { p := connp.NewConnPool(name, address, int32(maxConns), int32(maxIdle)) p.New = func(connName string) (connp.NConn, error) { _, err := net.ResolveTCPAddr("tcp", p.Address) if err != nil { return nil, err } conn, err := net.DialTimeout("tcp", p.Address, connTimeout) if err != nil { return nil, err } return rpcpool.NewRpcClientWithCodec(jsonrpc.NewClientCodec(conn), connName), nil } return p } ================================================ FILE: common/backend_pool/tsdb_backends.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package backend_pool import ( "fmt" "net" "time" connp "github.com/toolkits/conn_pool" ) // TSDB type TsdbClient struct { cli *struct{ net.Conn } name string } func (t TsdbClient) Name() string { return t.name } func (t TsdbClient) Closed() bool { return t.cli.Conn == nil } func (t TsdbClient) Close() error { if t.cli != nil { err := t.cli.Close() t.cli.Conn = nil return err } return nil } func newTsdbConnPool(address string, maxConns int, maxIdle int, connTimeout int) *connp.ConnPool { pool := connp.NewConnPool("tsdb", address, int32(maxConns), int32(maxIdle)) pool.New = func(name string) (connp.NConn, error) { _, err := net.ResolveTCPAddr("tcp", address) if err != nil { return nil, err } conn, err := net.DialTimeout("tcp", address, time.Duration(connTimeout)*time.Millisecond) if err != nil { return nil, err } return TsdbClient{ cli: &struct{ net.Conn }{conn}, name: name, }, nil } return pool } type TsdbConnPoolHelper struct { p *connp.ConnPool maxConns int maxIdle int connTimeout int callTimeout int address string } func NewTsdbConnPoolHelper(address string, maxConns, maxIdle, connTimeout, callTimeout int) *TsdbConnPoolHelper { return &TsdbConnPoolHelper{ p: newTsdbConnPool(address, maxConns, maxIdle, connTimeout), maxConns: maxConns, maxIdle: maxIdle, connTimeout: connTimeout, callTimeout: callTimeout, address: address, } } func (t *TsdbConnPoolHelper) Send(data []byte) (err error) { conn, err := t.p.Fetch() if err != nil { return fmt.Errorf("get connection fail: err %v. proc: %s", err, t.p.Proc()) } cli := conn.(TsdbClient).cli done := make(chan error, 1) go func() { _, err = cli.Write(data) done <- err }() select { case <-time.After(time.Duration(t.callTimeout) * time.Millisecond): t.p.ForceClose(conn) return fmt.Errorf("%s, call timeout", t.address) case err = <-done: if err != nil { t.p.ForceClose(conn) err = fmt.Errorf("%s, call failed, err %v. proc: %s", t.address, err, t.p.Proc()) } else { t.p.Release(conn) } return err } } func (t *TsdbConnPoolHelper) Destroy() { if t.p != nil { t.p.Destroy() } } ================================================ FILE: common/db/db.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package db // graph.endpoint type GraphEndpoint struct { Id int64 Endpoint string } // graph.tag_endpoint type GraphTagEndpoint struct { Id int64 Tag string EndpointId int64 } // graph.endpoint_counter type GraphEndpointCounter struct { Id int64 EndpointId int64 Counter string } ================================================ FILE: common/model/agent.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package model import ( "fmt" ) type AgentReportRequest struct { Hostname string IP string AgentVersion string PluginVersion string } func (this *AgentReportRequest) String() string { return fmt.Sprintf( "", this.Hostname, this.IP, this.AgentVersion, this.PluginVersion, ) } type AgentUpdateInfo struct { LastUpdate int64 ReportRequest *AgentReportRequest } type AgentHeartbeatRequest struct { Hostname string Checksum string } func (this *AgentHeartbeatRequest) String() string { return fmt.Sprintf( "", this.Hostname, this.Checksum, ) } type AgentPluginsResponse struct { Plugins []string Timestamp int64 } func (this *AgentPluginsResponse) String() string { return fmt.Sprintf( "", this.Plugins, this.Timestamp, ) } // e.g. net.port.listen or proc.num type BuiltinMetric struct { Metric string Tags string } func (this *BuiltinMetric) String() string { return fmt.Sprintf( "%s/%s", this.Metric, this.Tags, ) } type BuiltinMetricResponse struct { Metrics []*BuiltinMetric Checksum string Timestamp int64 } func (this *BuiltinMetricResponse) String() string { return fmt.Sprintf( "", this.Metrics, this.Checksum, this.Timestamp, ) } type BuiltinMetricSlice []*BuiltinMetric func (this BuiltinMetricSlice) Len() int { return len(this) } func (this BuiltinMetricSlice) Swap(i, j int) { this[i], this[j] = this[j], this[i] } func (this BuiltinMetricSlice) Less(i, j int) bool { return this[i].String() < this[j].String() } ================================================ FILE: common/model/event.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package model import ( "fmt" "github.com/open-falcon/falcon-plus/common/utils" ) // 机器监控和实例监控都会产生Event,共用这么一个struct type Event struct { Id string `json:"id"` Strategy *Strategy `json:"strategy"` Expression *Expression `json:"expression"` Status string `json:"status"` // OK or PROBLEM Endpoint string `json:"endpoint"` LeftValue float64 `json:"leftValue"` CurrentStep int `json:"currentStep"` EventTime int64 `json:"eventTime"` PushedTags map[string]string `json:"pushedTags"` } func (this *Event) FormattedTime() string { return utils.UnixTsFormat(this.EventTime) } func (this *Event) String() string { return fmt.Sprintf( "", this.Endpoint, this.Status, this.Strategy, this.Expression, utils.ReadableFloat(this.LeftValue), this.CurrentStep, this.PushedTags, this.FormattedTime(), ) } func (this *Event) ExpressionId() int { if this.Expression != nil { return this.Expression.Id } return 0 } func (this *Event) StrategyId() int { if this.Strategy != nil { return this.Strategy.Id } return 0 } func (this *Event) TplId() int { if this.Strategy != nil { return this.Strategy.Tpl.Id } return 0 } func (this *Event) Tpl() *Template { if this.Strategy != nil { return this.Strategy.Tpl } return nil } func (this *Event) ActionId() int { if this.Expression != nil { return this.Expression.ActionId } return this.Strategy.Tpl.ActionId } func (this *Event) Priority() int { if this.Strategy != nil { return this.Strategy.Priority } return this.Expression.Priority } func (this *Event) Note() string { if this.Strategy != nil { return this.Strategy.Note } return this.Expression.Note } func (this *Event) Metric() string { if this.Strategy != nil { return this.Strategy.Metric } return this.Expression.Metric } func (this *Event) RightValue() float64 { if this.Strategy != nil { return this.Strategy.RightValue } return this.Expression.RightValue } func (this *Event) Operator() string { if this.Strategy != nil { return this.Strategy.Operator } return this.Expression.Operator } func (this *Event) Func() string { if this.Strategy != nil { return this.Strategy.Func } return this.Expression.Func } func (this *Event) MaxStep() int { if this.Strategy != nil { return this.Strategy.MaxStep } return this.Expression.MaxStep } func (this *Event) Counter() string { return fmt.Sprintf("%s/%s %s", this.Endpoint, this.Metric(), utils.SortedTags(this.PushedTags)) } ================================================ FILE: common/model/expression.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package model import ( "fmt" "github.com/open-falcon/falcon-plus/common/utils" ) type Expression struct { Id int `json:"id"` Metric string `json:"metric"` Tags map[string]string `json:"tags"` Func string `json:"func"` // e.g. max(#3) all(#3) Operator string `json:"operator"` // e.g. < != RightValue float64 `json:"rightValue"` // critical value MaxStep int `json:"maxStep"` Priority int `json:"priority"` Note string `json:"note"` ActionId int `json:"actionId"` } func (this *Expression) String() string { return fmt.Sprintf( "", this.Id, this.Metric, this.Tags, this.Func, this.Operator, utils.ReadableFloat(this.RightValue), this.MaxStep, this.Priority, this.Note, this.ActionId, ) } type ExpressionResponse struct { Expressions []*Expression `json:"expressions"` } ================================================ FILE: common/model/graph.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package model import ( "fmt" "math" MUtils "github.com/open-falcon/falcon-plus/common/utils" ) // DsType 即RRD中的Datasource的类型:GAUGE|COUNTER|DERIVE type GraphItem struct { Endpoint string `json:"endpoint"` Metric string `json:"metric"` Tags map[string]string `json:"tags"` Value float64 `json:"value"` Timestamp int64 `json:"timestamp"` DsType string `json:"dstype"` Step int `json:"step"` Heartbeat int `json:"heartbeat"` Min string `json:"min"` Max string `json:"max"` } func (this *GraphItem) String() string { return fmt.Sprintf( "", this.Endpoint, this.Metric, this.Tags, this.Value, this.Timestamp, MUtils.UnixTsFormat(this.Timestamp), this.DsType, this.Step, this.Heartbeat, this.Min, this.Max, ) } func (this *GraphItem) PrimaryKey() string { return MUtils.PK(this.Endpoint, this.Metric, this.Tags) } func (t *GraphItem) Checksum() string { return MUtils.Checksum(t.Endpoint, t.Metric, t.Tags) } func (this *GraphItem) UUID() string { return MUtils.UUID(this.Endpoint, this.Metric, this.Tags, this.DsType, this.Step) } type GraphDeleteParam struct { Endpoint string `json:"endpoint"` Metric string `json:"metric"` Step int `json:"step"` DsType string `json:"dstype"` Tags string `json:"tags"` } type GraphDeleteResp struct { } // ConsolFun 是RRD中的概念,比如:MIN|MAX|AVERAGE type GraphQueryParam struct { Start int64 `json:"start"` End int64 `json:"end"` ConsolFun string `json:"consolFuc"` Endpoint string `json:"endpoint"` Counter string `json:"counter"` Step int `json:"step"` } type GraphQueryResponse struct { Endpoint string `json:"endpoint"` Counter string `json:"counter"` DsType string `json:"dstype"` Step int `json:"step"` Values []*RRDData `json:"Values"` //大写为了兼容已经再用这个api的用户 } // 页面上已经可以看到DsType和Step了,直接带进查询条件,Graph更易处理 type GraphAccurateQueryParam struct { Checksum string `json:"checksum"` Start int64 `json:"start"` End int64 `json:"end"` ConsolFun string `json:"consolFuc"` DsType string `json:"dsType"` Step int `json:"step"` } type GraphAccurateQueryResponse struct { Values []*RRDData `json:"Values"` } type JsonFloat float64 func (v JsonFloat) MarshalJSON() ([]byte, error) { f := float64(v) if math.IsNaN(f) || math.IsInf(f, 0) { return []byte("null"), nil } else { return []byte(fmt.Sprintf("%f", f)), nil } } type RRDData struct { Timestamp int64 `json:"timestamp"` Value JsonFloat `json:"value"` } func NewRRDData(ts int64, val float64) *RRDData { return &RRDData{Timestamp: ts, Value: JsonFloat(val)} } func (this *RRDData) String() string { return fmt.Sprintf( "", this.Value, this.Timestamp, MUtils.UnixTsFormat(this.Timestamp), ) } type GraphInfoParam struct { Endpoint string `json:"endpoint"` Counter string `json:"counter"` } type GraphInfoResp struct { ConsolFun string `json:"consolFun"` Step int `json:"step"` Filename string `json:"filename"` } type GraphFullyInfo struct { Endpoint string `json:"endpoint"` Counter string `json:"counter"` ConsolFun string `json:"consolFun"` Step int `json:"step"` Filename string `json:"filename"` Addr string `json:"addr"` } type GraphLastParam struct { Endpoint string `json:"endpoint"` Counter string `json:"counter"` } type GraphLastResp struct { Endpoint string `json:"endpoint"` Counter string `json:"counter"` Value *RRDData `json:"value"` } ================================================ FILE: common/model/host.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package model import ( "fmt" ) type Host struct { Id int Name string } func (this *Host) String() string { return fmt.Sprintf( "", this.Id, this.Name, ) } ================================================ FILE: common/model/influxdb.go ================================================ package model type InfluxdbItem struct { Measurement string `json:"metric"` Tags map[string]string `json:"tags"` Fileds map[string]interface{} `json:"fileds"` Timestamp int64 `json:"timestamp"` } ================================================ FILE: common/model/judge.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package model import ( "fmt" "github.com/open-falcon/falcon-plus/common/utils" ) type JudgeItem struct { Endpoint string `json:"endpoint"` Metric string `json:"metric"` Value float64 `json:"value"` Timestamp int64 `json:"timestamp"` JudgeType string `json:"judgeType"` Tags map[string]string `json:"tags"` } func (this *JudgeItem) String() string { return fmt.Sprintf("", this.Endpoint, this.Metric, this.Value, this.Timestamp, this.JudgeType, this.Tags) } func (this *JudgeItem) PrimaryKey() string { return utils.Md5(utils.PK(this.Endpoint, this.Metric, this.Tags)) } type HistoryData struct { Timestamp int64 `json:"timestamp"` Value float64 `json:"value"` } ================================================ FILE: common/model/metric.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package model import ( "fmt" MUtils "github.com/open-falcon/falcon-plus/common/utils" ) type MetricValue struct { Endpoint string `json:"endpoint"` Metric string `json:"metric"` Value interface{} `json:"value"` Step int64 `json:"step"` Type string `json:"counterType"` Tags string `json:"tags"` Timestamp int64 `json:"timestamp"` } func (this *MetricValue) String() string { return fmt.Sprintf( "", this.Endpoint, this.Metric, this.Type, this.Tags, this.Step, this.Timestamp, this.Value, ) } // Same As `MetricValue` type JsonMetaData struct { Metric string `json:"metric"` Endpoint string `json:"endpoint"` Timestamp int64 `json:"timestamp"` Step int64 `json:"step"` Value interface{} `json:"value"` CounterType string `json:"counterType"` Tags string `json:"tags"` } func (t *JsonMetaData) String() string { return fmt.Sprintf("", t.Endpoint, t.Metric, t.Tags, t.CounterType, t.Step, t.Value, t.Timestamp) } type MetaData struct { Metric string `json:"metric"` Endpoint string `json:"endpoint"` Timestamp int64 `json:"timestamp"` Step int64 `json:"step"` Value float64 `json:"value"` CounterType string `json:"counterType"` Tags map[string]string `json:"tags"` } func (t *MetaData) String() string { return fmt.Sprintf("", t.Endpoint, t.Metric, t.Timestamp, t.Step, t.Value, t.Tags) } func (t *MetaData) PK() string { return MUtils.PK(t.Endpoint, t.Metric, t.Tags) } ================================================ FILE: common/model/nodata.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package model import ( "fmt" "github.com/open-falcon/falcon-plus/common/utils" ttime "github.com/toolkits/time" ) type NodataItem struct { Counter string `json:"counter"` Ts int64 `json:"ts"` FStatus string `json:"fstatus"` FTs int64 `json:"fts"` } func (this *NodataItem) String() string { return fmt.Sprintf("{NodataItem counter:%s ts:%s fecthStatus:%s fetchTs:%s}", this.Counter, ttime.FormatTs(this.Ts), this.FStatus, ttime.FormatTs(this.FTs)) } type NodataConfig struct { Id int `json:"id"` Name string `json:"name"` ObjType string `json:"objType"` Endpoint string `json:"endpoint"` Metric string `json:"metric"` Tags map[string]string `json:"tags"` Type string `json:"type"` Step int64 `json:"step"` Mock float64 `json:"mock"` } func NewNodataConfig(id int, name string, objType string, endpoint string, metric string, tags map[string]string, dstype string, step int64, mock float64) *NodataConfig { return &NodataConfig{id, name, objType, endpoint, metric, tags, dstype, step, mock} } func (this *NodataConfig) String() string { return fmt.Sprintf("{NodataConfig id:%d, name:%s, objType:%s, endpoint:%s, metric:%s, tags:%s, type:%s, step:%d, mock:%f}", this.Id, this.Name, this.ObjType, this.Endpoint, this.Metric, utils.SortedTags(this.Tags), this.Type, this.Step, this.Mock) } ================================================ FILE: common/model/prometheus.go ================================================ package model // MetricType Prometheus指标类型:GAUGE|COUNTER type P8sItem struct { Endpoint string `json:"endpoint"` Metric string `json:"metric"` Tags map[string]string `json:"tags"` Value float64 `json:"value"` Timestamp int64 `json:"timestamp"` MetricType string `json:"metric_type"` Step int `json:"step"` } ================================================ FILE: common/model/rpc.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package model import ( "fmt" ) // code == 0 => success // code == 1 => bad request type SimpleRpcResponse struct { Code int `json:"code"` } func (this *SimpleRpcResponse) String() string { return fmt.Sprintf("", this.Code) } type NullRpcRequest struct { } ================================================ FILE: common/model/strategy.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package model import ( "fmt" "github.com/open-falcon/falcon-plus/common/utils" ) type Strategy struct { Id int `json:"id"` Metric string `json:"metric"` Tags map[string]string `json:"tags"` Func string `json:"func"` // e.g. max(#3) all(#3) Operator string `json:"operator"` // e.g. < != RightValue float64 `json:"rightValue"` // critical value MaxStep int `json:"maxStep"` Priority int `json:"priority"` Note string `json:"note"` Tpl *Template `json:"tpl"` } func (this *Strategy) String() string { return fmt.Sprintf( "", this.Id, this.Metric, this.Tags, this.Func, this.Operator, utils.ReadableFloat(this.RightValue), this.MaxStep, this.Priority, this.Note, this.Tpl, ) } type HostStrategy struct { Hostname string `json:"hostname"` Strategies []Strategy `json:"strategies"` } type StrategiesResponse struct { HostStrategies []*HostStrategy `json:"hostStrategies"` } ================================================ FILE: common/model/template.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package model import ( "fmt" ) type Template struct { Id int `json:"id"` Name string `json:"name"` ParentId int `json:"parentId"` ActionId int `json:"actionId"` Creator string `json:"creator"` } func (this *Template) String() string { return fmt.Sprintf( "", this.Id, this.Name, this.ParentId, this.ActionId, this.Creator, ) } ================================================ FILE: common/model/transfer.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package model import ( "fmt" ) type TransferResponse struct { Message string Total int Invalid int Latency int64 } func (this *TransferResponse) String() string { return fmt.Sprintf( "", this.Total, this.Invalid, this.Latency, this.Message, ) } ================================================ FILE: common/model/tsdb.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package model import ( "fmt" "strings" ) type TsdbItem struct { Metric string `json:"metric"` Tags map[string]string `json:"tags"` Value float64 `json:"value"` Timestamp int64 `json:"timestamp"` } func (this *TsdbItem) String() string { return fmt.Sprintf( "", this.Metric, this.Tags, this.Value, this.Timestamp, ) } func (this *TsdbItem) TsdbString() (s string) { s = fmt.Sprintf("put %s %d %.3f ", this.Metric, this.Timestamp, this.Value) for k, v := range this.Tags { key := strings.ToLower(strings.Replace(k, " ", "_", -1)) value := strings.Replace(v, " ", "_", -1) s += key + "=" + value + " " } return s } ================================================ FILE: common/proc/proc.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package proc import ( "sync" "time" ) const ( DefaultOtherMaxSize = 100 // 默认的 自定义统计字段的最大值 DefaultSCounterQpsPeriod = 1 // QPS计算周期, 默认值为1s ) // 基本的计数器 type SCounterBase struct { sync.RWMutex Name string Cnt int64 Time string ts int64 // 自定义统计指标 Other map[string]interface{} } func NewSCounterBase(name string) *SCounterBase { uts := time.Now().Unix() return &SCounterBase{Name: name, Cnt: 0, Time: formatTs(uts), ts: uts, Other: make(map[string]interface{})} } func (this *SCounterBase) Get() *SCounterBase { this.RLock() defer this.RUnlock() return this } // to be abandoned func (this *SCounterBase) Set(cnt int64) { this.Lock() defer this.Unlock() this.Cnt = cnt this.ts = time.Now().Unix() this.Time = formatTs(this.ts) } func (this *SCounterBase) SetCnt(cnt int64) { this.Lock() defer this.Unlock() this.Cnt = cnt this.ts = time.Now().Unix() this.Time = formatTs(this.ts) } func (this *SCounterBase) PutOther(key string, value interface{}) bool { this.Lock() defer this.Unlock() ret := false _, exist := this.Other[key] if exist { this.Other[key] = value ret = true } else { if len(this.Other) < DefaultOtherMaxSize { this.Other[key] = value ret = true } } return ret } func formatTs(ts int64) string { return time.Unix(ts, 0).Format("2006-01-02 15:04:05") } // QPS统计,只支持 增加计数操作 type SCounterQps struct { sync.RWMutex Name string Cnt int64 Qps int64 Time string ts int64 // for qps lastTs int64 lastCnt int64 // 自定义统计指标 Other map[string]interface{} } func NewSCounterQps(name string) *SCounterQps { uts := time.Now().Unix() return &SCounterQps{Name: name, Cnt: 0, Time: formatTs(uts), ts: uts, Qps: 0, lastCnt: 0, lastTs: uts, Other: make(map[string]interface{})} } func (this *SCounterQps) Get() *SCounterQps { this.RLock() defer this.RUnlock() this.incrByDirty(0) // update qps return this } func (this *SCounterQps) Incr() { this.IncrBy(int64(1)) } func (this *SCounterQps) IncrBy(incr int64) { this.Lock() defer this.Unlock() this.incrByDirty(incr) } func (this *SCounterQps) PutOther(key string, value interface{}) bool { this.Lock() defer this.Unlock() ret := false _, exist := this.Other[key] if exist { this.Other[key] = value ret = true } else { if len(this.Other) < DefaultOtherMaxSize { this.Other[key] = value ret = true } } return ret } // 操作我的时候,请加写锁 func (this *SCounterQps) incrByDirty(incr int64) { this.Cnt += incr this.ts = time.Now().Unix() this.Time = formatTs(this.ts) // qps if this.ts-this.lastTs > DefaultSCounterQpsPeriod { this.Qps = int64((this.Cnt - this.lastCnt) / (this.ts - this.lastTs)) this.lastTs = this.ts this.lastCnt = this.Cnt } } ================================================ FILE: common/sdk/.gitignore ================================================ # Compiled Object files, Static and Dynamic libs (Shared Objects) *.o *.a *.so # Folders _obj _test # Architecture specific extensions/prefixes *.[568vq] [568vq].out *.cgo1.go *.cgo2.c _cgo_defun.c _cgo_gotypes.go _cgo_export.* _testmain.go *.exe *.test *.prof *.swp *.swo *.log .idea .DS_Store /sdk* /gitversion ================================================ FILE: common/sdk/README.md ================================================ ================================================ FILE: common/sdk/requests/auth_request.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package requests import ( "encoding/json" "errors" "github.com/toolkits/net/httplib" "time" ) func CurlPlus(uri, method, token_name, token_sig string, headers, params map[string]string) (req *httplib.BeegoHttpRequest, err error) { if method == "GET" { req = httplib.Get(uri) } else if method == "POST" { req = httplib.Post(uri) } else if method == "PUT" { req = httplib.Put(uri) } else if method == "DELETE" { req = httplib.Delete(uri) } else if method == "HEAD" { req = httplib.Head(uri) } else { err = errors.New("invalid http method") return } req = req.SetTimeout(1*time.Second, 5*time.Second) token, _ := json.Marshal(map[string]string{ "name": token_name, "sig": token_sig, }) req.Header("Apitoken", string(token)) for hk, hv := range headers { req.Header(hk, hv) } for pk, pv := range params { req.Param(pk, pv) } return } ================================================ FILE: common/sdk/requests/post.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package requests import ( "bytes" "encoding/json" "io/ioutil" "net/http" ) func PostJsonBody(url string, v interface{}) (response []byte, err error) { bs, err := json.Marshal(v) if err != nil { return response, err } bf := bytes.NewBuffer(bs) resp, err := http.Post(url, "application/json", bf) if err != nil { return response, err } defer resp.Body.Close() return ioutil.ReadAll(resp.Body) } ================================================ FILE: common/sdk/sender/linkedlist.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package sender import ( "container/list" "sync" "github.com/open-falcon/falcon-plus/common/model" ) type SafeLinkedList struct { sync.RWMutex L *list.List } func NewSafeLinkedList() *SafeLinkedList { return &SafeLinkedList{L: list.New()} } func (this *SafeLinkedList) PopBack(limit int) []*model.JsonMetaData { this.RLock() defer this.RUnlock() sz := this.L.Len() if sz == 0 { return []*model.JsonMetaData{} } if sz < limit { limit = sz } ret := make([]*model.JsonMetaData, 0, limit) for i := 0; i < limit; i++ { e := this.L.Back() ret = append(ret, e.Value.(*model.JsonMetaData)) this.L.Remove(e) } return ret } func (this *SafeLinkedList) PushFront(v interface{}) *list.Element { this.Lock() defer this.Unlock() return this.L.PushFront(v) } func (this *SafeLinkedList) Front() *list.Element { this.RLock() defer this.RUnlock() return this.L.Front() } func (this *SafeLinkedList) Len() int { this.RLock() defer this.RUnlock() return this.L.Len() } ================================================ FILE: common/sdk/sender/make.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package sender import ( "time" "github.com/open-falcon/falcon-plus/common/model" ) func MakeMetaData(endpoint, metric, tags string, val interface{}, counterType string, step_and_ts ...int64) *model.JsonMetaData { md := model.JsonMetaData{ Endpoint: endpoint, Metric: metric, Tags: tags, Value: val, CounterType: counterType, } argc := len(step_and_ts) if argc == 0 { md.Step = 60 md.Timestamp = time.Now().Unix() } else if argc == 1 { md.Step = step_and_ts[0] md.Timestamp = time.Now().Unix() } else if argc == 2 { md.Step = step_and_ts[0] md.Timestamp = step_and_ts[1] } return &md } func MakeGaugeValue(endpoint, metric, tags string, val interface{}, step_and_ts ...int64) *model.JsonMetaData { return MakeMetaData(endpoint, metric, tags, val, "GAUGE", step_and_ts...) } func MakeCounterValue(endpoint, metric, tags string, val interface{}, step_and_ts ...int64) *model.JsonMetaData { return MakeMetaData(endpoint, metric, tags, val, "COUNTER", step_and_ts...) } func PushGauge(endpoint, metric, tags string, val interface{}, step_and_ts ...int64) { md := MakeGaugeValue(endpoint, metric, tags, val, step_and_ts...) MetaDataQueue.PushFront(md) } func PushCounter(endpoint, metric, tags string, val interface{}, step_and_ts ...int64) { md := MakeCounterValue(endpoint, metric, tags, val, step_and_ts...) MetaDataQueue.PushFront(md) } func Push(endpoint, metric, tags string, val interface{}, counterType string, step_and_ts ...int64) { md := MakeMetaData(endpoint, metric, tags, val, counterType, step_and_ts...) MetaDataQueue.PushFront(md) } ================================================ FILE: common/sdk/sender/push.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package sender import ( "bytes" "encoding/json" "fmt" "io/ioutil" "log" "net/http" "github.com/open-falcon/falcon-plus/common/model" ) func PostPush(L []*model.JsonMetaData) error { bs, err := json.Marshal(L) if err != nil { return err } bf := bytes.NewBuffer(bs) resp, err := http.Post(PostPushUrl, "application/json", bf) if err != nil { return err } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return err } content := string(body) if resp.StatusCode != 200 { return fmt.Errorf("status code %d != 200, response: %s", resp.StatusCode, content) } if Debug { log.Println("[D] response:", content) } return nil } ================================================ FILE: common/sdk/sender/sender.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package sender import ( "log" "time" ) const LIMIT = 200 var MetaDataQueue = NewSafeLinkedList() var PostPushUrl string var Debug bool func StartSender() { go startSender() } func startSender() { for { L := MetaDataQueue.PopBack(LIMIT) if len(L) == 0 { time.Sleep(time.Millisecond * 200) continue } err := PostPush(L) if err != nil { log.Println("[E] push to transfer fail", err) } } } ================================================ FILE: common/utils/counter.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package utils import ( "fmt" ) func Counter(metric string, tags map[string]string) string { if tags == nil || len(tags) == 0 { return metric } return fmt.Sprintf("%s/%s", metric, SortedTags(tags)) } ================================================ FILE: common/utils/date.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package utils import ( "time" ) func UnixTsFormat(ts int64) string { return time.Unix(ts, 0).Format("2006-01-02 15:04:05") } ================================================ FILE: common/utils/formatter.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package utils import ( "strconv" "strings" ) func ReadableFloat(raw float64) string { val := strconv.FormatFloat(raw, 'f', 5, 64) if strings.Contains(val, ".") { val = strings.TrimRight(val, "0") val = strings.TrimRight(val, ".") } return val } ================================================ FILE: common/utils/func.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package utils import ( "bytes" "math/rand" "strconv" "time" ) func PK(endpoint, metric string, tags map[string]string) string { ret := bufferPool.Get().(*bytes.Buffer) ret.Reset() defer bufferPool.Put(ret) if tags == nil || len(tags) == 0 { ret.WriteString(endpoint) ret.WriteString("/") ret.WriteString(metric) return ret.String() } ret.WriteString(endpoint) ret.WriteString("/") ret.WriteString(metric) ret.WriteString("/") ret.WriteString(SortedTags(tags)) return ret.String() } func PK2(endpoint, counter string) string { ret := bufferPool.Get().(*bytes.Buffer) ret.Reset() defer bufferPool.Put(ret) ret.WriteString(endpoint) ret.WriteString("/") ret.WriteString(counter) return ret.String() } func UUID(endpoint, metric string, tags map[string]string, dstype string, step int) string { ret := bufferPool.Get().(*bytes.Buffer) ret.Reset() defer bufferPool.Put(ret) if tags == nil || len(tags) == 0 { ret.WriteString(endpoint) ret.WriteString("/") ret.WriteString(metric) ret.WriteString("/") ret.WriteString(dstype) ret.WriteString("/") ret.WriteString(strconv.Itoa(step)) return ret.String() } ret.WriteString(endpoint) ret.WriteString("/") ret.WriteString(metric) ret.WriteString("/") ret.WriteString(SortedTags(tags)) ret.WriteString("/") ret.WriteString(dstype) ret.WriteString("/") ret.WriteString(strconv.Itoa(step)) return ret.String() } func Checksum(endpoint string, metric string, tags map[string]string) string { pk := PK(endpoint, metric, tags) return Md5(pk) } func ChecksumOfUUID(endpoint, metric string, tags map[string]string, dstype string, step int64) string { return Md5(UUID(endpoint, metric, tags, dstype, int(step))) } func init() { rand.Seed(time.Now().UTC().UnixNano()) } func RandString(l int) string { bytes := make([]byte, l) for i := 0; i < l; i++ { bytes[i] = byte(RandInt(65, 90)) } return string(bytes) } func RandInt(min int, max int) int { return min + rand.Intn(max-min) } ================================================ FILE: common/utils/func_test.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package utils import ( "fmt" "testing" ) func origPK(endpoint, metric string, tags map[string]string) string { if tags == nil || len(tags) == 0 { return fmt.Sprintf("%s/%s", endpoint, metric) } return fmt.Sprintf("%s/%s/%s", endpoint, metric, SortedTags(tags)) } func origPK2(endpoint, counter string) string { return fmt.Sprintf("%s/%s", endpoint, counter) } func origUUID(endpoint, metric string, tags map[string]string, dstype string, step int) string { if tags == nil || len(tags) == 0 { return fmt.Sprintf("%s/%s/%s/%d", endpoint, metric, dstype, step) } return fmt.Sprintf("%s/%s/%s/%s/%d", endpoint, metric, SortedTags(tags), dstype, step) } var pkCase = []struct { endpoint string metric string tags map[string]string except string }{ {"endpoint1", "metric1", nil, "endpoint1/metric1"}, {"endpoint1", "metric1", map[string]string{}, "endpoint1/metric1"}, {"endpoint1", "metric1", map[string]string{"k1": "v1", "k2": "v2"}, "endpoint1/metric1/k1=v1,k2=v2"}, {"endpoint1", "metric1", map[string]string{"k2": "v2", "k1": "v1"}, "endpoint1/metric1/k1=v1,k2=v2"}, } var pk2Case = []struct { endpoint string counter string except string }{ {"endpoint1", "counter1", "endpoint1/counter1"}, } var uuidCase = []struct { endpoint string metric string tags map[string]string dstype string step int except string }{ {"endpoint1", "metric1", nil, "ds", 10, "endpoint1/metric1/ds/10"}, {"endpoint1", "metric1", map[string]string{}, "ds", 10, "endpoint1/metric1/ds/10"}, {"endpoint1", "metric1", map[string]string{"k1": "v1", "k2": "v2"}, "ds", 10, "endpoint1/metric1/k1=v1,k2=v2/ds/10"}, {"endpoint1", "metric1", map[string]string{"k2": "v2", "k1": "v1"}, "ds", 10, "endpoint1/metric1/k1=v1,k2=v2/ds/10"}, } func Test_PK(t *testing.T) { for _, pk := range pkCase { if PK(pk.endpoint, pk.metric, pk.tags) != origPK(pk.endpoint, pk.metric, pk.tags) || PK(pk.endpoint, pk.metric, pk.tags) != pk.except { t.Error("not except") } } } func Test_PK2(t *testing.T) { for _, pk2 := range pk2Case { if PK2(pk2.endpoint, pk2.counter) != origPK2(pk2.endpoint, pk2.counter) || PK2(pk2.endpoint, pk2.counter) != pk2.except { t.Error("not except") } } } func Test_UUID(t *testing.T) { for _, uuid := range uuidCase { if UUID(uuid.endpoint, uuid.metric, uuid.tags, uuid.dstype, uuid.step) != origUUID(uuid.endpoint, uuid.metric, uuid.tags, uuid.dstype, uuid.step) || UUID(uuid.endpoint, uuid.metric, uuid.tags, uuid.dstype, uuid.step) != uuid.except { t.Error("not except") } } } var ( testTags = map[string]string{"k1": "v1", "k2": "v2"} ) func Benchmark_PK(b *testing.B) { for i := 0; i < b.N; i++ { PK("endpoint1", "metric1", testTags) } } func Benchmark_PK_orig(b *testing.B) { for i := 0; i < b.N; i++ { origPK("endpoint1", "metric1", testTags) } } func Benchmark_PK2(b *testing.B) { for i := 0; i < b.N; i++ { PK2("endpoint1", "counter1") } } func Benchmark_PK2_orig(b *testing.B) { for i := 0; i < b.N; i++ { origPK2("endpoint1", "counter1") } } func Benchmark_UUID(b *testing.B) { for i := 0; i < b.N; i++ { UUID("endpoint1", "metric1", testTags, "dt", 10) } } func Benchmark_UUID_orig(b *testing.B) { for i := 0; i < b.N; i++ { origUUID("endpoint1", "metric1", testTags, "dt", 10) } } ================================================ FILE: common/utils/map.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package utils import ( "sort" ) // TODO 以下的部分, 考虑放到公共组件库 func KeysOfMap(m map[string]string) []string { keys := make(sort.StringSlice, len(m)) i := 0 for key := range m { keys[i] = key i++ } keys.Sort() return []string(keys) } ================================================ FILE: common/utils/md5.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package utils import ( "crypto/md5" "encoding/hex" ) func Md5(raw string) string { h := md5.Sum([]byte(raw)) return hex.EncodeToString(h[:]) } ================================================ FILE: common/utils/md5_test.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package utils import ( "crypto/md5" "fmt" "io" "testing" ) func origMd5(raw string) string { h := md5.New() io.WriteString(h, raw) return fmt.Sprintf("%x", h.Sum(nil)) } func Test_Md5(t *testing.T) { if Md5("1234567890123") != origMd5("1234567890123") { t.Error("not expect") } } func Benchmark_Md5(b *testing.B) { for i := 0; i < b.N; i++ { Md5("1234567890123") } } func Benchmark_Md5_orig(b *testing.B) { for i := 0; i < b.N; i++ { origMd5("1234567890123") } } ================================================ FILE: common/utils/objpool.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package utils import ( "bytes" "sync" ) var bufferPool = sync.Pool{New: func() interface{} { return new(bytes.Buffer) }} ================================================ FILE: common/utils/statistics.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package utils import "math" func ComputeMean(values []float64) float64 { var sum float64 for _, value := range values { sum = sum + value } return (sum / float64(len(values))) } func ComputeStdDeviation(values []float64) float64 { var ( mean float64 vp []float64 stdDiv, temp float64 ) vp = make([]float64, len(values)) /*Calculate mean of the data points*/ mean = ComputeMean(values) /*Calculate standard deviation of individual data points*/ for i, v := range values { temp = v - mean vp[i] = (temp * temp) } /* Finally, Compute standard Deviation of data points * by taking mean of individual std. Deviation. */ stdDiv = ComputeMean(vp) return float64(math.Sqrt(float64(stdDiv))) } ================================================ FILE: common/utils/tags.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package utils import ( "bytes" "fmt" "sort" "strings" ) func SortedTags(tags map[string]string) string { if tags == nil { return "" } size := len(tags) if size == 0 { return "" } ret := bufferPool.Get().(*bytes.Buffer) ret.Reset() defer bufferPool.Put(ret) if size == 1 { for k, v := range tags { ret.WriteString(k) ret.WriteString("=") ret.WriteString(v) } return ret.String() } keys := make([]string, size) i := 0 for k := range tags { keys[i] = k i++ } sort.Strings(keys) for j, key := range keys { ret.WriteString(key) ret.WriteString("=") ret.WriteString(tags[key]) if j != size-1 { ret.WriteString(",") } } return ret.String() } func DictedTagstring(s string) map[string]string { if s == "" { return map[string]string{} } if strings.ContainsRune(s, ' ') { s = strings.Replace(s, " ", "", -1) } tag_dict := make(map[string]string) tags := strings.Split(s, ",") for _, tag := range tags { idx := strings.IndexRune(tag, '=') if idx != -1 { tag_dict[tag[:idx]] = tag[idx+1:] } } return tag_dict } func SplitTagsString(s string) (err error, tags map[string]string) { err = nil tags = make(map[string]string) s = strings.Replace(s, " ", "", -1) if s == "" { return } tagSlice := strings.Split(s, ",") for _, tag := range tagSlice { tag_pair := strings.SplitN(tag, "=", 2) if len(tag_pair) == 2 { tags[tag_pair[0]] = tag_pair[1] } else { err = fmt.Errorf("bad tag %s", tag) return } } return } ================================================ FILE: common/utils/tags_test.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package utils import ( "fmt" "sort" "strings" "testing" ) var testCases4map2string = []struct { tags map[string]string expect string }{ {map[string]string{"1": "1"}, "1=1"}, {map[string]string{"1": "1", "2": "2"}, "1=1,2=2"}, {map[string]string{"1": "1", "2": "2", "0": "0"}, "0=0,1=1,2=2"}, } var testCases4string2map = []struct { tags string expect map[string]string }{ {"1=1", map[string]string{"1": "1"}}, {"1=1,2=2", map[string]string{"1": "1", "2": "2"}}, {"0=0,1=1,2=2", map[string]string{"1": "1", "2": "2", "0": "0"}}, {"0,1=1,2=2", map[string]string{"1": "1", "2": "2"}}, {"0=,1=1,2=2", map[string]string{"0": "", "1": "1", "2": "2"}}, {"=0,1=1,2=2", map[string]string{"": "0", "1": "1", "2": "2"}}, {"0=0, 1=1, 2=2", map[string]string{"0": "0", "1": "1", "2": "2"}}, } func origSortedTags(tags map[string]string) string { if tags == nil { return "" } size := len(tags) if size == 0 { return "" } if size == 1 { for k, v := range tags { return fmt.Sprintf("%s=%s", k, v) } } keys := make([]string, size) i := 0 for k := range tags { keys[i] = k i++ } sort.Strings(keys) ret := make([]string, size) for j, key := range keys { ret[j] = fmt.Sprintf("%s=%s", key, tags[key]) } return strings.Join(ret, ",") } func origDictedTagstring(s string) map[string]string { if s == "" { return map[string]string{} } s = strings.Replace(s, " ", "", -1) tag_dict := make(map[string]string) tags := strings.Split(s, ",") for _, tag := range tags { tag_pair := strings.SplitN(tag, "=", 2) if len(tag_pair) == 2 { tag_dict[tag_pair[0]] = tag_pair[1] } } return tag_dict } func Test_SortedTags(t *testing.T) { for _, testCase := range testCases4map2string { if r := SortedTags(testCase.tags); r != testCase.expect || SortedTags(testCase.tags) != origSortedTags(testCase.tags) { t.Errorf("expect %v, got %v\n", testCase.expect, r) } } } func Test_DictedTagstring(t *testing.T) { for _, testCase := range testCases4string2map { r := DictedTagstring(testCase.tags) origR := origDictedTagstring(testCase.tags) if len(r) != len(testCase.expect) || len(r) != len(origR) { t.FailNow() } for k, v := range r { if expectV, exist := testCase.expect[k]; !exist || v != expectV || v != origR[k] { t.Errorf("expect %v, got %v\n", testCase.expect, r) } } } } func Benchmark_SortedTags_1pair(b *testing.B) { for i := 0; i < b.N; i++ { SortedTags(map[string]string{"1": "1"}) } } func Benchmark_SortedTags_1pair_orig(b *testing.B) { for i := 0; i < b.N; i++ { origSortedTags(map[string]string{"1": "1"}) } } func Benchmark_SortedTags_2pairs(b *testing.B) { for i := 0; i < b.N; i++ { SortedTags(map[string]string{"1": "1", "2": "2"}) } } func Benchmark_SortedTags_2pairs_orig(b *testing.B) { for i := 0; i < b.N; i++ { origSortedTags(map[string]string{"1": "1", "2": "2"}) } } func Benchmark_SortedTags_3pairs(b *testing.B) { for i := 0; i < b.N; i++ { SortedTags(map[string]string{"1": "1", "2": "2", "3": "3"}) } } func Benchmark_SortedTags_3pairs_orig(b *testing.B) { for i := 0; i < b.N; i++ { origSortedTags(map[string]string{"1": "1", "2": "2", "3": "3"}) } } func Benchmark_SortedTags_4pairs(b *testing.B) { for i := 0; i < b.N; i++ { SortedTags(map[string]string{"1": "1", "2": "2", "3": "3", "4": "4"}) } } func Benchmark_SortedTags_4pairs_orig(b *testing.B) { for i := 0; i < b.N; i++ { origSortedTags(map[string]string{"1": "1", "2": "2", "3": "3", "4": "4"}) } } func Benchmark_SortedTags_5pairs(b *testing.B) { for i := 0; i < b.N; i++ { SortedTags(map[string]string{"1": "1", "2": "2", "3": "3", "4": "4", "5": "5"}) } } func Benchmark_SortedTags_5pairs_orig(b *testing.B) { for i := 0; i < b.N; i++ { origSortedTags(map[string]string{"1": "1", "2": "2", "3": "3", "4": "4", "5": "5"}) } } func Benchmark_SortedTags_6pairs(b *testing.B) { for i := 0; i < b.N; i++ { SortedTags(map[string]string{"1": "1", "2": "2", "3": "3", "4": "4", "5": "5", "0": "0"}) } } func Benchmark_SortedTags_6pairs_orig(b *testing.B) { for i := 0; i < b.N; i++ { origSortedTags(map[string]string{"1": "1", "2": "2", "3": "3", "4": "4", "5": "5", "0": "0"}) } } func Benchmark_DictedTagstring_1pair(b *testing.B) { for i := 0; i < b.N; i++ { DictedTagstring("1=1") } } func Benchmark_DictedTagstring_1pair_orig(b *testing.B) { for i := 0; i < b.N; i++ { origDictedTagstring("1=1") } } func Benchmark_DictedTagstring_2pairs(b *testing.B) { for i := 0; i < b.N; i++ { DictedTagstring("1=1,2=2") } } func Benchmark_DictedTagstring_2pairs_orig(b *testing.B) { for i := 0; i < b.N; i++ { origDictedTagstring("1=1,2=2") } } func Benchmark_DictedTagstring_3pairs(b *testing.B) { for i := 0; i < b.N; i++ { DictedTagstring("1=1,2=2,3=3") } } func Benchmark_DictedTagstring_3pairs_orig(b *testing.B) { for i := 0; i < b.N; i++ { origDictedTagstring("1=1,2=2,3=3") } } func Benchmark_DictedTagstring_4pairs(b *testing.B) { for i := 0; i < b.N; i++ { DictedTagstring("1=1,2=2,3=3,4=4") } } func Benchmark_DictedTagstring_4pairs_orig(b *testing.B) { for i := 0; i < b.N; i++ { origDictedTagstring("1=1,2=2,3=3,4=4") } } func Benchmark_DictedTagstring_5pairs(b *testing.B) { for i := 0; i < b.N; i++ { DictedTagstring("1=1,2=2,3=3,4=4,5=5") } } func Benchmark_DictedTagstring_5pairs_orig(b *testing.B) { for i := 0; i < b.N; i++ { origDictedTagstring("1=1,2=2,3=3,4=4,5=5") } } func Benchmark_DictedTagstring_6pairs(b *testing.B) { for i := 0; i < b.N; i++ { DictedTagstring("1=1,2=2,3=3,4=4,5=5,6=6") } } func Benchmark_DictedTagstring_6pairs_orig(b *testing.B) { for i := 0; i < b.N; i++ { origDictedTagstring("1=1,2=2,3=3,4=4,5=5,6=6") } } ================================================ FILE: config/agent.json ================================================ { "debug": true, "hostname": "%%AGENT_HOSTNAME%%", "ip": "", "plugin": { "enabled": false, "dir": "./plugin", "git": "https://github.com/open-falcon/plugin.git", "logs": "./logs" }, "heartbeat": { "enabled": true, "addr": "%%HBS_RPC%%", "interval": 60, "timeout": 1000 }, "transfer": { "enabled": true, "addrs": [ "%%TRANSFER_RPC%%" ], "interval": 60, "timeout": 1000 }, "http": { "enabled": true, "listen": ":1988", "backdoor": false }, "collector": { "ifacePrefix": ["eth", "em"], "mountPoint": [] }, "default_tags": { }, "ignore": { "cpu.busy": true, "df.bytes.free": true, "df.bytes.total": true, "df.bytes.used": true, "df.bytes.used.percent": true, "df.inodes.total": true, "df.inodes.free": true, "df.inodes.used": true, "df.inodes.used.percent": true, "mem.memtotal": true, "mem.memused": true, "mem.memused.percent": true, "mem.memfree": true, "mem.swaptotal": true, "mem.swapused": true, "mem.swapfree": true } } ================================================ FILE: config/aggregator.json ================================================ { "debug": true, "http": { "enabled": true, "listen": "%%AGGREGATOR_HTTP%%" }, "database": { "addr": "%%MYSQL%%/falcon_portal?loc=Local&parseTime=true", "idle": 10, "ids": [1, -1], "interval": 55 }, "api": { "connect_timeout": 500, "request_timeout": 2000, "plus_api": "http://127.0.0.1:8080", "plus_api_token": "%%PLUS_API_DEFAULT_TOKEN%%", "push_api": "http://127.0.0.1:1988/v1/push" } } ================================================ FILE: config/alarm.json ================================================ { "log_level": "debug", "http": { "enabled": true, "listen": "0.0.0.0:9912" }, "redis": { "addr": "%%REDIS%%", "maxIdle": 5, "highQueues": [ "event:p0", "event:p1", "event:p2" ], "lowQueues": [ "event:p3", "event:p4", "event:p5", "event:p6" ], "userIMQueue": "/queue/user/im", "userSmsQueue": "/queue/user/sms", "userMailQueue": "/queue/user/mail" }, "api": { "im": "http://127.0.0.1:10086/wechat", "sms": "http://127.0.0.1:10086/sms", "mail": "http://127.0.0.1:10086/mail", "dashboard": "http://127.0.0.1:8081", "plus_api":"http://127.0.0.1:8080", "plus_api_token": "%%PLUS_API_DEFAULT_TOKEN%%" }, "falcon_portal": { "addr": "%%MYSQL%%/alarms?charset=utf8&loc=Local", "idle": 10, "max": 100 }, "worker": { "im": 10, "sms": 10, "mail": 50 }, "housekeeper": { "event_retention_days": 7, "event_delete_batch": 100 } } ================================================ FILE: config/api.json ================================================ { "log_level": "debug", "db": { "falcon_portal": "%%MYSQL%%/falcon_portal?charset=utf8&parseTime=True&loc=Local", "graph": "%%MYSQL%%/graph?charset=utf8&parseTime=True&loc=Local", "uic": "%%MYSQL%%/uic?charset=utf8&parseTime=True&loc=Local", "dashboard": "%%MYSQL%%/dashboard?charset=utf8&parseTime=True&loc=Local", "alarms": "%%MYSQL%%/alarms?charset=utf8&parseTime=True&loc=Local", "db_bug": true }, "graphs": { "cluster": { "graph-00": "%%GRAPH_RPC%%" }, "max_conns": 100, "max_idle": 100, "conn_timeout": 1000, "call_timeout": 5000, "numberOfReplicas": 500 }, "metric_list_file": "./api/data/metric", "web_port": "%%PLUS_API_HTTP%%", "access_control": true, "signup_disable": false, "salt": "", "skip_auth": false, "default_token": "%%PLUS_API_DEFAULT_TOKEN%%", "gen_doc": false, "gen_doc_path": "doc/module.html" } ================================================ FILE: config/confgen.sh ================================================ #!/bin/bash confs=( '%%AGENT_HTTP%%=0.0.0.0:1988' '%%AGGREGATOR_HTTP%%=0.0.0.0:6055' '%%GRAPH_HTTP%%=0.0.0.0:6071' '%%GRAPH_RPC%%=0.0.0.0:6070' '%%HBS_HTTP%%=0.0.0.0:6031' '%%HBS_RPC%%=0.0.0.0:6030' '%%JUDGE_HTTP%%=0.0.0.0:6081' '%%JUDGE_RPC%%=0.0.0.0:6080' '%%NODATA_HTTP%%=0.0.0.0:6090' '%%TRANSFER_HTTP%%=0.0.0.0:6060' '%%TRANSFER_RPC%%=0.0.0.0:8433' '%%REDIS%%=127.0.0.1:6379' '%%MYSQL%%=root:@tcp(127.0.0.1:3306)' '%%PLUS_API_DEFAULT_TOKEN%%=default-token-used-in-server-side' '%%PLUS_API_HTTP%%=0.0.0.0:8080' '%%AGENT_HOSTNAME%%=' ) configurer() { for i in "${confs[@]}" do search="${i%%=*}" replace="${i##*=}" uname=`uname` if [ "$uname" == "Darwin" ] ; then # Note the "" and -e after -i, needed in OS X find ./out/*/config/*.json -type f -exec sed -i .tpl -e "s/${search}/${replace}/g" {} \; else find ./out/*/config/*.json -type f -exec sed -i "s/${search}/${replace}/g" {} \; fi done } configurer ================================================ FILE: config/falcon2p8s.json ================================================ { "log_level": "debug", "concurrent": 100, "http": { "listen": "0.0.0.0:9090" }, "rpc": { "listen": "0.0.0.0:8080" } } ================================================ FILE: config/gateway.json ================================================ { "debug": true, "minStep": 30, "http": { "enabled": true, "listen": "0.0.0.0:16060" }, "rpc": { "enabled": true, "listen": "0.0.0.0:18433" }, "socket": { "enabled": true, "listen": "0.0.0.0:14444", "timeout": 3600 }, "judge": { "enabled": false, "batch": 200, "connTimeout": 1000, "callTimeout": 5000, "maxConns": 32, "maxIdle": 32, "replicas": 500, "cluster": { "judge-00" : "%%JUDGE_RPC%%" } }, "graph": { "enabled": false, "batch": 200, "connTimeout": 1000, "callTimeout": 5000, "maxConns": 32, "maxIdle": 32, "replicas": 500, "cluster": { "graph-00" : "%%GRAPH_RPC%%" } }, "tsdb": { "enabled": false, "batch": 200, "connTimeout": 1000, "callTimeout": 5000, "maxConns": 32, "maxIdle": 32, "retry": 3, "address": "127.0.0.1:8088" }, "transfer": { "enabled": true, "batch": 200, "connTimeout": 1000, "callTimeout": 5000, "maxConns": 32, "maxIdle": 32, "retry": 3, "cluster": { "t1": "%%TRANSFER_RPC%%" } }, "influxdb": { "enabled": false, "batch": 200, "retry": 3, "maxConns": 32, "username": "admin", "password": "123456", "precision": "s", "db": "foo", "address": "http://127.0.0.1:8086", "timeout": 5000 } } ================================================ FILE: config/graph.json ================================================ { "debug": false, "http": { "enabled": true, "listen": "%%GRAPH_HTTP%%" }, "rpc": { "enabled": true, "listen": "%%GRAPH_RPC%%" }, "rrd": { "storage": "./data/6070" }, "db": { "dsn": "%%MYSQL%%/graph?loc=Local&parseTime=true", "maxIdle": 4 }, "callTimeout": 5000, "ioWorkerNum": 64, "migrate": { "enabled": false, "concurrency": 2, "replicas": 500, "cluster": { "graph-00" : "127.0.0.1:6070" } } } ================================================ FILE: config/hbs.json ================================================ { "debug": true, "database": "%%MYSQL%%/falcon_portal?loc=Local&parseTime=true", "hosts": "", "maxConns": 20, "maxIdle": 15, "listen": ":6030", "trustable": [""], "http": { "enabled": true, "listen": "%%HBS_HTTP%%" } } ================================================ FILE: config/judge.json ================================================ { "debug": true, "debugHost": "nil", "remain": 11, "http": { "enabled": true, "listen": "%%JUDGE_HTTP%%" }, "rpc": { "enabled": true, "listen": "%%JUDGE_RPC%%" }, "hbs": { "servers": ["%%HBS_RPC%%"], "timeout": 300, "interval": 60 }, "alarm": { "enabled": true, "minInterval": 300, "queuePattern": "event:p%v", "redis": { "dsn": "%%REDIS%%", "maxIdle": 5, "connTimeout": 5000, "readTimeout": 5000, "writeTimeout": 5000 } } } ================================================ FILE: config/nodata.json ================================================ { "debug": true, "http": { "enabled": true, "listen": "%%NODATA_HTTP%%" }, "plus_api":{ "connectTimeout": 500, "requestTimeout": 2000, "addr": "http://127.0.0.1:8080", "token": "default-token-used-in-server-side" }, "config": { "enabled": true, "dsn": "%%MYSQL%%/falcon_portal?loc=Local&parseTime=true&wait_timeout=604800", "maxIdle": 4 }, "collector":{ "enabled": true, "batch": 200, "concurrent": 10 }, "sender":{ "enabled": true, "connectTimeout": 500, "requestTimeout": 2000, "transferAddr": "%%TRANSFER_HTTP%%", "batch": 500 } } ================================================ FILE: config/transfer.json ================================================ { "debug": true, "minStep": 30, "http": { "enabled": true, "listen": "%%TRANSFER_HTTP%%" }, "rpc": { "enabled": true, "listen": "%%TRANSFER_RPC%%" }, "socket": { "enabled": true, "listen": "0.0.0.0:4444", "timeout": 3600 }, "judge": { "enabled": true, "batch": 200, "connTimeout": 1000, "callTimeout": 5000, "maxConns": 32, "maxIdle": 32, "replicas": 500, "cluster": { "judge-00" : "%%JUDGE_RPC%%" } }, "graph": { "enabled": true, "batch": 200, "connTimeout": 1000, "callTimeout": 5000, "maxConns": 32, "maxIdle": 32, "replicas": 500, "cluster": { "graph-00" : "%%GRAPH_RPC%%" } }, "tsdb": { "enabled": false, "batch": 200, "connTimeout": 1000, "callTimeout": 5000, "maxConns": 32, "maxIdle": 32, "retry": 3, "address": "127.0.0.1:8088" }, "transfer": { "enabled": false, "batch": 200, "connTimeout": 1000, "callTimeout": 5000, "maxConns": 32, "maxIdle": 32, "retry": 3, "cluster": { "t1": "127.0.0.1:8433" } }, "influxdb": { "enabled": false, "batch": 200, "retry": 3, "maxConns": 32, "username": "admin", "password": "123456", "precision": "s", "db": "foo", "address": "http://127.0.0.1:8086", "timeout": 5000 }, "p8s_relay": { "enabled": false, "batch": 200, "connTimeout": 1000, "callTimeout": 5000, "maxConns": 32, "maxIdle": 32, "replicas": 500, "notSyncMetrics": [ "gpu.", "snmp." ], "cluster": { "p8s-relay-00" : "192.168.1.1:8080", "p8s-relay-01" : "192.168.1.2:8080" } } } ================================================ FILE: docker/README.md ================================================ ## Running open-falcon container `the latest version in docker hub is v0.3` ##### 1. Start mysql and init the mysql table before the first running ``` ## start mysql in container docker run -itd \ --name falcon-mysql \ -v /home/work/mysql-data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=test123456 \ -p 3306:3306 \ mysql:5.7 ## init mysql table before the first running cd /tmp && \ git clone --depth=1 https://github.com/open-falcon/falcon-plus.git && \ cd /tmp/falcon-plus/ && \ for x in `ls ./scripts/mysql/db_schema/*.sql`; do echo init mysql table $x ...; docker exec -i falcon-mysql mysql -uroot -ptest123456 < $x; done rm -rf /tmp/falcon-plus/ ``` ##### 2. Start redis in container ``` docker run --name falcon-redis -p6379:6379 -d redis:4-alpine3.8 ``` ##### 3. Start falcon-plus modules in one container ``` ## pull images from hub.docker.com/openfalcon docker pull openfalcon/falcon-plus:v0.3 ## run falcon-plus container docker run -itd --name falcon-plus \ --link=falcon-mysql:db.falcon \ --link=falcon-redis:redis.falcon \ -p 8433:8433 \ -p 8080:8080 \ -e MYSQL_PORT=root:test123456@tcp\(db.falcon:3306\) \ -e REDIS_PORT=redis.falcon:6379 \ -v /home/work/open-falcon/data:/open-falcon/data \ -v /home/work/open-falcon/logs:/open-falcon/logs \ openfalcon/falcon-plus:v0.3 ## start falcon backend modules, such as graph,api,etc. docker exec falcon-plus sh ctrl.sh start \ graph hbs judge transfer nodata aggregator agent gateway api alarm ## or you can just start/stop/restart specific module as: docker exec falcon-plus sh ctrl.sh start/stop/restart xxx ## check status of backend modules docker exec falcon-plus ./open-falcon check ## or you can check logs at /home/work/open-falcon/logs/ in your host ls -l /home/work/open-falcon/logs/ ``` ##### 4. Start falcon-dashboard in container ``` docker run -itd --name falcon-dashboard \ -p 8081:8081 \ --link=falcon-mysql:db.falcon \ --link=falcon-plus:api.falcon \ -e API_ADDR=http://api.falcon:8080/api/v1 \ -e PORTAL_DB_HOST=db.falcon \ -e PORTAL_DB_PORT=3306 \ -e PORTAL_DB_USER=root \ -e PORTAL_DB_PASS=test123456 \ -e PORTAL_DB_NAME=falcon_portal \ -e ALARM_DB_HOST=db.falcon \ -e ALARM_DB_PORT=3306 \ -e ALARM_DB_USER=root \ -e ALARM_DB_PASS=test123456 \ -e ALARM_DB_NAME=alarms \ -w /open-falcon/dashboard openfalcon/falcon-dashboard:v0.2.1 \ './control startfg' ``` ##### 5. Start falcon-agent in container ``` sudo docker run -d --restart always --name falcon-agent \ -e NUX_ROOTFS=/rootfs \ -v /:/rootfs:ro \ openfalcon/falcon-plus:v0.3 \ ./agent/bin/falcon-agent -c /open-falcon/agent/config/cfg.json ``` ---- ## Building open-falcon images from source code ##### Building falcon-plus ``` cd /tmp && \ git clone https://github.com/open-falcon/falcon-plus.git && \ cd /tmp/falcon-plus/ && \ docker build -t falcon-plus:v0.3 . ``` ##### Building falcon-dashboard ``` cd /tmp && \ git clone https://github.com/open-falcon/dashboard.git && \ cd /tmp/dashboard/ && \ docker build -t falcon-dashboard:v0.2.1 . ``` ================================================ FILE: docker/confgen4docker.sh ================================================ #!/bin/bash confs=( '%%AGENT_HTTP%%=0.0.0.0:1988' '%%AGGREGATOR_HTTP%%=0.0.0.0:6055' '%%GRAPH_HTTP%%=0.0.0.0:6071' '%%GRAPH_RPC%%=0.0.0.0:6070' '%%HBS_HTTP%%=0.0.0.0:6031' '%%HBS_RPC%%=0.0.0.0:6030' '%%JUDGE_HTTP%%=0.0.0.0:6081' '%%JUDGE_RPC%%=0.0.0.0:6080' '%%NODATA_HTTP%%=0.0.0.0:6090' '%%TRANSFER_HTTP%%=0.0.0.0:6060' '%%TRANSFER_RPC%%=0.0.0.0:8433' '%%PLUS_API_DEFAULT_TOKEN%%=default-token-used-in-server-side' '%%PLUS_API_HTTP%%=0.0.0.0:8080' '%%AGENT_HOSTNAME%%=' ) configurer() { for i in "${confs[@]}" do search="${i%%=*}" replace="${i##*=}" uname=`uname` if [ "$uname" == "Darwin" ] ; then # Note the "" and -e after -i, needed in OS X find ./out/*/config/*.json -type f -exec sed -i .tpl -e "s/${search}/${replace}/g" {} \; else find ./out/*/config/*.json -type f -exec sed -i "s/${search}/${replace}/g" {} \; fi done } configurer ================================================ FILE: docker/ctrl.sh ================================================ #!/bin/sh DOCKER_DIR=/open-falcon of_bin=$DOCKER_DIR/open-falcon DOCKER_HOST_IP=$(route -n | awk '/UG[ \t]/{print $2}') # Search $1 and replace with $2 or $3(defualt) replace() { replacement=$2 if [ -z "$replacement" ]; then replacement=$3 fi find $DOCKER_DIR/*/config/*.json -type f -exec sed -i "s/$1/$replacement/g" {} \; } replace "%%MYSQL%%" "$MYSQL_PORT" "$DOCKER_HOST_IP:3306" replace "%%REDIS%%" "$REDIS_PORT" "$DOCKER_HOST_IP:6379" replace "%%AGGREGATOR_HTTP%%" "$AGGREGATOR_HTTP" "0.0.0.0:6055" replace "%%GRAPH_HTTP%%" "$GRAPH_HTTP" "0.0.0.0:6071" replace "%%GRAPH_RPC%%" "$GRAPH_RPC" "0.0.0.0:6070" replace "%%HBS_HTTP%%" "$HBS_HTTP" "0.0.0.0:6031" replace "%%HBS_RPC%%" "$HBS_RPC" "0.0.0.0:6030" replace "%%JUDGE_HTTP%%" "$JUDGE_HTTP" "0.0.0.0:6081" replace "%%JUDGE_RPC%%" "$JUDGE_RPC" "0.0.0.0:6080" replace "%%NODATA_HTTP%%" "$NODATA_HTTP" "0.0.0.0:6090" replace "%%TRANSFER_HTTP%%" "$TRANSFER_HTTP" "0.0.0.0:6060" replace "%%TRANSFER_RPC%%" "$TRANSFER_RPC" "0.0.0.0:8433" replace "%%PLUS_API_HTTP%%" "$PLUS_API_HTTP" "0.0.0.0:8080" replace "%%AGENT_HOSTNAME%%" "$AGENT_HOSTNAME" "" #use absolute path of metric_list_file in docker TAB=$'\t'; sed -i "s|.*metric_list_file.*|${TAB}\"metric_list_file\": \"$DOCKER_DIR/api/data/metric\",|g" $DOCKER_DIR/api/config/*.json; action=$1 module_name=$2 case $action in run) $DOCKER_DIR/"$module_name"/bin/falcon-"$module_name" -c /open-falcon/"$module_name"/config/cfg.json ;; *) supervisorctl $* ;; esac ================================================ FILE: docker/k8s-cluster/Dockerfile.tpl ================================================ FROM alpine:3.7 LABEL maintainer tabsp@qq.com USER root ENV FALCON_DIR=/open-falcon # agent RUN apk add --no-cache ca-certificates git curl # alarm ADD https://github.com/golang/go/raw/master/lib/time/zoneinfo.zip /usr/local/go/lib/time/zoneinfo.zip COPY build/%%MODULE_NAME%% ${FALCON_DIR}/%%MODULE_NAME%% WORKDIR ${FALCON_DIR} CMD ["/open-falcon/%%MODULE_NAME%%/bin/falcon-%%MODULE_NAME%%", "-c", "/open-falcon/%%MODULE_NAME%%/config/cfg.json"] ================================================ FILE: docker/k8s-cluster/README.md ================================================ ## 分布式部署 open-falcon 到 k8s 集群 ### 构建 克隆源码: ```shell git clone https://github.com/open-falcon/falcon-plus.git && cd falcon-plus ``` 编译源码并构建 Docker 镜像 ```shell ./docker/k8s-cluster/build.sh ``` ### 部署 注意点: 1. graph 为有状态组件,部署方式为每个节点一个 Deployment,同时 replica 设置为 1 2. 所有配置文件使用挂载目录的方式持久化,可以改为 ConfigMap 管理配置 3. 镜像可以使用构建脚本自己构建后推送到自己的私仓使用(推荐),或者直接使用我构建好的,仓库地址在 docker/k8s-cluster/build.sh 查看或修改 ================================================ FILE: docker/k8s-cluster/build.sh ================================================ #!/bin/bash MODULES=( 'agent' 'aggregator' 'alarm' 'api' 'gateway' 'graph' 'hbs' 'judge' 'nodata' 'transfer' ) DOCKER_REGISTRY=registry.cn-hangzhou.aliyuncs.com/open-falcon VERSION=v0.3 clean() { echo "clean..." if [ -d "build" ]; then rm -rf build/ fi mkdir build } build() { echo "build source..." if [ `uname -m` == "aarch64" ]; then BASE_IMAGE=jimmytinsley/makegcc-golang else BASE_IMAGE=openfalcon/makegcc-golang:1.10-alpine fi docker run -it --rm \ --name build \ -v "$(pwd)":"/go/src/github.com/open-falcon/falcon-plus" \ -w "/go/src/github.com/open-falcon/falcon-plus" \ $BASE_IMAGE \ docker/k8s-cluster/init.sh } buildDockerImages() { echo "build docker images..." for i in "${MODULES[@]}"; do echo "build $i" awk -v module="$i" '{ gsub(/%%MODULE_NAME%%/, module); print $0 }' docker/k8s-cluster/Dockerfile.tpl > docker/k8s-cluster/Dockerfile docker build -f docker/k8s-cluster/Dockerfile -t $DOCKER_REGISTRY/$i:$VERSION . rm docker/k8s-cluster/Dockerfile done } clean build buildDockerImages ================================================ FILE: docker/k8s-cluster/init.sh ================================================ #!/bin/sh apk add --no-cache ca-certificates git bash \ && make all \ && make pack4docker \ && tar -zxf open-falcon-v*.tar.gz -C build \ && rm open-falcon-v*.tar.gz ================================================ FILE: docker/k8s-cluster/modules/falcon-agent.yaml ================================================ apiVersion: v1 kind: Service metadata: namespace: open-falcon name: falcon-agent labels: app: open-falcon spec: type: ClusterIP ports: - name: http port: 1988 selector: name: falcon-agent --- apiVersion: extensions/v1beta1 kind: Deployment metadata: namespace: open-falcon name: falcon-agent labels: app: open-falcon spec: replicas: 1 template: metadata: labels: name: falcon-agent spec: containers: - name: falcon-agent image: registry.cn-hangzhou.aliyuncs.com/open-falcon/agent:v0.3 imagePullPolicy: IfNotPresent ports: - containerPort: 1988 name: http protocol: TCP volumeMounts: - mountPath: /open-falcon/agent/config name: falcon-agent-config - mountPath: /etc/localtime name: tz-config volumes: - flexVolume: driver: alicloud/nas options: path: /open-falcon/falcon-agent/config server: xxx.cn-hangzhou.nas.aliyuncs.com vers: "4.0" name: falcon-agent-config - hostPath: path: /etc/localtime type: '' name: tz-config ================================================ FILE: docker/k8s-cluster/modules/falcon-aggregator.yaml ================================================ apiVersion: v1 kind: Service metadata: namespace: open-falcon name: falcon-aggregator labels: app: open-falcon spec: type: ClusterIP ports: - name: http port: 6055 selector: name: falcon-aggregator --- apiVersion: extensions/v1beta1 kind: Deployment metadata: namespace: open-falcon name: falcon-aggregator labels: app: open-falcon spec: replicas: 1 template: metadata: labels: name: falcon-aggregator spec: containers: - name: falcon-aggregator image: registry.cn-hangzhou.aliyuncs.com/open-falcon/aggregator:v0.3 imagePullPolicy: IfNotPresent ports: - containerPort: 6055 name: http protocol: TCP volumeMounts: - mountPath: /open-falcon/aggregator/config name: falcon-aggregator-config - mountPath: /etc/localtime name: tz-config volumes: - flexVolume: driver: alicloud/nas options: path: /open-falcon/falcon-aggregator/config server: xxx.cn-hangzhou.nas.aliyuncs.com vers: "4.0" name: falcon-aggregator-config - hostPath: path: /etc/localtime type: '' name: tz-config ================================================ FILE: docker/k8s-cluster/modules/falcon-alarm.yaml ================================================ apiVersion: v1 kind: Service metadata: namespace: open-falcon name: falcon-alarm labels: app: open-falcon spec: type: ClusterIP ports: - name: http port: 9912 selector: name: falcon-alarm --- apiVersion: extensions/v1beta1 kind: Deployment metadata: namespace: open-falcon name: falcon-alarm labels: app: open-falcon spec: replicas: 1 template: metadata: labels: name: falcon-alarm spec: containers: - name: falcon-alarm image: registry.cn-hangzhou.aliyuncs.com/open-falcon/alarm:v0.3 imagePullPolicy: IfNotPresent ports: - containerPort: 9912 name: http protocol: TCP volumeMounts: - mountPath: /open-falcon/alarm/config name: falcon-alarm-config - mountPath: /etc/localtime name: tz-config volumes: - flexVolume: driver: alicloud/nas options: path: /open-falcon/falcon-alarm/config server: xxx.cn-hangzhou.nas.aliyuncs.com vers: "4.0" name: falcon-alarm-config - hostPath: path: /etc/localtime type: '' name: tz-config ================================================ FILE: docker/k8s-cluster/modules/falcon-api.yaml ================================================ apiVersion: v1 kind: Service metadata: namespace: open-falcon name: falcon-api labels: app: open-falcon spec: type: ClusterIP ports: - name: http port: 8080 selector: name: falcon-api --- apiVersion: extensions/v1beta1 kind: Deployment metadata: namespace: open-falcon name: falcon-api labels: app: open-falcon spec: replicas: 1 template: metadata: labels: name: falcon-api spec: containers: - name: falcon-api image: registry.cn-hangzhou.aliyuncs.com/open-falcon/api:v0.3 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 name: http protocol: TCP volumeMounts: - mountPath: /open-falcon/api/config name: falcon-api-config - mountPath: /etc/localtime name: tz-config volumes: - flexVolume: driver: alicloud/nas options: path: /open-falcon/falcon-api/config server: xxx.cn-hangzhou.nas.aliyuncs.com vers: "4.0" name: falcon-api-config - hostPath: path: /etc/localtime type: '' name: tz-config ================================================ FILE: docker/k8s-cluster/modules/falcon-dashboard.yaml ================================================ apiVersion: v1 kind: Service metadata: namespace: open-falcon name: falcon-dashboard labels: app: open-falcon spec: type: ClusterIP ports: - name: http port: 8081 selector: name: falcon-dashboard --- apiVersion: extensions/v1beta1 kind: Deployment metadata: namespace: open-falcon name: falcon-dashboard labels: app: open-falcon spec: replicas: 1 template: metadata: labels: name: falcon-dashboard spec: containers: - name: falcon-dashboard image: openfalcon/falcon-dashboard:v0.2.1 command: ["sh","-c","cd /open-falcon/dashboard && ./control startfg"] imagePullPolicy: IfNotPresent ports: - containerPort: 8081 env: - name: API_ADDR value: http://falcon-api:8080/api/v1 - name: PORTAL_DB_HOST value: 127.0.0.1 - name: PORTAL_DB_PORT value: "3306" - name: PORTAL_DB_USER value: root - name: PORTAL_DB_PASS value: xxx - name: PORTAL_DB_NAME value: falcon_portal - name: ALARM_DB_HOST value: 127.0.0.1 - name: ALARM_DB_PORT value: "3306" - name: ALARM_DB_USER value: root - name: ALARM_DB_PASS value: root - name: ALARM_DB_NAME value: alarms volumeMounts: - mountPath: /etc/localtime name: tz-config volumes: - hostPath: path: /etc/localtime type: '' name: tz-config ================================================ FILE: docker/k8s-cluster/modules/falcon-graph-01.yaml ================================================ apiVersion: v1 kind: Service metadata: namespace: open-falcon name: falcon-graph-01 labels: app: open-falcon spec: type: ClusterIP ports: - name: rpc port: 6070 - name: http port: 6071 selector: name: falcon-graph-01 --- apiVersion: extensions/v1beta1 kind: Deployment metadata: namespace: open-falcon name: falcon-graph-01 labels: app: open-falcon spec: replicas: 1 template: metadata: labels: name: falcon-graph-01 spec: containers: - name: falcon-graph-01 image: registry.cn-hangzhou.aliyuncs.com/open-falcon/graph:v0.3 imagePullPolicy: IfNotPresent ports: - containerPort: 6070 name: rpc protocol: TCP - containerPort: 6071 name: http protocol: TCP volumeMounts: - mountPath: /open-falcon/graph/config name: falcon-graph-config - mountPath: /open-falcon/graph/data name: falcon-graph-data - mountPath: /etc/localtime name: tz-config volumes: - flexVolume: driver: alicloud/nas options: path: /open-falcon/falcon-graph/01/config server: xxx.cn-hangzhou.nas.aliyuncs.com vers: "4.0" name: falcon-graph-config - flexVolume: driver: alicloud/nas options: path: /open-falcon/falcon-graph/01/data server: xxx.cn-hangzhou.nas.aliyuncs.com vers: "4.0" name: falcon-graph-data - hostPath: path: /etc/localtime type: '' name: tz-config ================================================ FILE: docker/k8s-cluster/modules/falcon-hbs.yaml ================================================ apiVersion: v1 kind: Service metadata: namespace: open-falcon name: falcon-hbs labels: app: open-falcon spec: type: ClusterIP ports: - name: rpc port: 6030 - name: http port: 6031 selector: name: falcon-hbs --- apiVersion: extensions/v1beta1 kind: Deployment metadata: namespace: open-falcon name: falcon-hbs labels: app: open-falcon spec: replicas: 1 template: metadata: labels: name: falcon-hbs spec: containers: - name: falcon-hbs image: registry.cn-hangzhou.aliyuncs.com/open-falcon/hbs:v0.3 imagePullPolicy: IfNotPresent ports: - containerPort: 6030 name: rpc protocol: TCP - containerPort: 6031 name: http protocol: TCP volumeMounts: - mountPath: /open-falcon/hbs/config name: falcon-hbs-config - mountPath: /etc/localtime name: tz-config volumes: - flexVolume: driver: alicloud/nas options: path: /open-falcon/falcon-hbs/config server: xxx.cn-hangzhou.nas.aliyuncs.com vers: "4.0" name: falcon-hbs-config - hostPath: path: /etc/localtime type: '' name: tz-config ================================================ FILE: docker/k8s-cluster/modules/falcon-judge.yaml ================================================ apiVersion: v1 kind: Service metadata: namespace: open-falcon name: falcon-judge labels: app: open-falcon spec: type: ClusterIP ports: - name: rpc port: 6080 - name: http port: 6081 selector: name: falcon-judge --- apiVersion: extensions/v1beta1 kind: Deployment metadata: namespace: open-falcon name: falcon-judge labels: app: open-falcon spec: replicas: 1 template: metadata: labels: name: falcon-judge spec: containers: - name: falcon-judge image: registry.cn-hangzhou.aliyuncs.com/open-falcon/judge:v0.3 imagePullPolicy: IfNotPresent ports: - containerPort: 6080 name: rpc protocol: TCP - containerPort: 6081 name: http protocol: TCP volumeMounts: - mountPath: /open-falcon/judge/config name: falcon-judge-config - mountPath: /etc/localtime name: tz-config volumes: - flexVolume: driver: alicloud/nas options: path: /open-falcon/falcon-judge/config server: xxx.cn-hangzhou.nas.aliyuncs.com vers: "4.0" name: falcon-judge-config - hostPath: path: /etc/localtime type: '' name: tz-config ================================================ FILE: docker/k8s-cluster/modules/falcon-nodata.yaml ================================================ apiVersion: v1 kind: Service metadata: namespace: open-falcon name: falcon-nodata labels: app: open-falcon spec: type: ClusterIP ports: - name: http port: 6090 selector: name: falcon-nodata --- apiVersion: extensions/v1beta1 kind: Deployment metadata: namespace: open-falcon name: falcon-nodata labels: app: open-falcon spec: replicas: 1 template: metadata: labels: name: falcon-nodata spec: containers: - name: falcon-nodata image: registry.cn-hangzhou.aliyuncs.com/open-falcon/nodata:v0.3 imagePullPolicy: IfNotPresent ports: - containerPort: 6090 name: http protocol: TCP volumeMounts: - mountPath: /open-falcon/nodata/config name: falcon-nodata-config - mountPath: /etc/localtime name: tz-config volumes: - flexVolume: driver: alicloud/nas options: path: /open-falcon/falcon-nodata/config server: xxx.cn-hangzhou.nas.aliyuncs.com vers: "4.0" name: falcon-nodata-config - hostPath: path: /etc/localtime type: '' name: tz-config ================================================ FILE: docker/k8s-cluster/modules/falcon-transfer.yaml ================================================ apiVersion: v1 kind: Service metadata: namespace: open-falcon name: falcon-transfer labels: app: open-falcon spec: type: ClusterIP ports: - name: http port: 6060 - name: rpc port: 8433 selector: name: falcon-transfer --- apiVersion: extensions/v1beta1 kind: Deployment metadata: namespace: open-falcon name: falcon-transfer labels: app: open-falcon spec: replicas: 1 template: metadata: labels: name: falcon-transfer spec: containers: - name: falcon-transfer image: registry.cn-hangzhou.aliyuncs.com/open-falcon/transfer:v0.3 imagePullPolicy: IfNotPresent ports: - containerPort: 6060 name: http protocol: TCP - containerPort: 8433 name: rpc protocol: TCP volumeMounts: - mountPath: /open-falcon/transfer/config name: falcon-transfer-config - mountPath: /etc/localtime name: tz-config volumes: - flexVolume: driver: alicloud/nas options: path: /open-falcon/falcon-transfer/config server: xxx.cn-hangzhou.nas.aliyuncs.com vers: "4.0" name: falcon-transfer-config - hostPath: path: /etc/localtime type: '' name: tz-config ================================================ FILE: docker/k8s-example/README.md ================================================ ## Running open-falcon in kubernetes work on kubernetes 1.14 , the `kubectl version` like: ``` Client Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.0", GitCommit:"641856db18352033a0d96dbc99153fa3b27298e5", GitTreeState:"clean", BuildDate:"2019-03-25T15:53:57Z", GoVersion:"go1.12.1", Compiler:"gc", Platform:"linux/amd64"} Server Version: version.Info{Major:"1", Minor:"14", GitVersion:"v1.14.0", GitCommit:"641856db18352033a0d96dbc99153fa3b27298e5", GitTreeState:"clean", BuildDate:"2019-03-25T15:45:25Z", GoVersion:"go1.12.1", Compiler:"gc", Platform:"linux/amd64"} ``` ##### 1. Start mysql in k8s and init the mysql table before the first running if mysql is already in k8s you can break this step ``` kubectl apply -f mysql.yaml ``` init mysql table before the first running ``` sh init_mysql_data.sh ``` ##### 2. Start redis in k8s if redis is already in k8s you can also break this step ``` kubectl apply -f redis.yaml ``` ##### 3. Start falcon-plus modules in one pod ``` kubectl apply -f openfalcon-plus.yaml ``` ##### 4. Start falcon-dashboard in k8s ``` kubectl apply -f openfalcon-dashboard.yaml ``` ##### 5. browse the dashboard view ``` [tyhall51@192-168-10-21 k8s-example]$ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 443/TCP 105d mysql NodePort 10.110.20.201 3306:30535/TCP 25m open-falcon NodePort 10.97.12.125 8433:31952/TCP,8080:31957/TCP 53s open-falcon-dashboard NodePort 10.96.119.231 8081:30191/TCP 3s redis ClusterIP 10.98.212.126 6379/TCP 32m ``` get **open-falcon-dashboard** service localhost port **30191** , then can visit `http://192.168.10.21:30191` in webrowser 。 [mailto](mailto:studyoo@foxmail.com) ================================================ FILE: docker/k8s-example/init_mysql_data.sh ================================================ #!/bin/sh mysql_pod=$(kubectl get pods | grep mysql | awk '{print $1}') cd /tmp && \ git clone --depth=1 https://github.com/open-falcon/falcon-plus && \ cd /tmp/falcon-plus/ && \ for x in `ls ./scripts/mysql/db_schema/*.sql`; do echo init mysql table $x ...; kubectl exec -it $mysql_pod -- mysql -uroot -p123456 < $x; done rm -rf /tmp/falcon-plus/ ================================================ FILE: docker/k8s-example/mysql.yaml ================================================ apiVersion: v1 kind: Service metadata: name: mysql labels: app: db spec: type: NodePort ports: - port: 3306 targetPort: mysqlport selector: app: db name: mysql --- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: mysql spec: replicas: 1 template: metadata: labels: app: db name: mysql spec: containers: - name: mysql image: mysql:5.7 imagePullPolicy: IfNotPresent env: - name: TZ value: "Asia/Shanghai" - name: MYSQL_ROOT_PASSWORD value: "123456" ports: - containerPort: 3306 name: mysqlport volumeMounts: - name: mysqldata subPath: mysql_data mountPath: /var/lib/mysql volumes: - name: mysqldata emptyDir: {} ================================================ FILE: docker/k8s-example/openfalcon-dashboard.yaml ================================================ apiVersion: v1 kind: Service metadata: name: open-falcon-dashboard labels: app: monitor spec: type: NodePort ports: - name: web port: 8081 selector: name: open-falcon-dashboard --- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: open-falcon-dashboard labels: app: monitor spec: replicas: 1 template: metadata: labels: name: open-falcon-dashboard spec: containers: - name: open-falcon-dashboard image: openfalcon/falcon-dashboard:v0.2.1 command: ["sh","-c","cd /open-falcon/dashboard && ./control startfg"] imagePullPolicy: IfNotPresent ports: - containerPort: 8081 env: - name: API_ADDR value: http://open-falcon:8080/api/v1 - name: PORTAL_DB_HOST value: mysql - name: PORTAL_DB_PORT value: "3306" - name: PORTAL_DB_USER value: root - name: PORTAL_DB_PASS value: 1qazxsw2 - name: PORTAL_DB_NAME value: falcon_portal - name: ALARM_DB_HOST value: mysql - name: ALARM_DB_PORT value: "3306" - name: ALARM_DB_USER value: root - name: ALARM_DB_PASS value: 1qazxsw2 - name: ALARM_DB_NAME value: alarms ================================================ FILE: docker/k8s-example/openfalcon-plus.yaml ================================================ apiVersion: v1 kind: ConfigMap metadata: name: openfalcon-configmap data: entrypoint.sh: |- #!/bin/bash /bin/sh -c 'sleep 10 && sh ctrl.sh start graph hbs judge transfer nodata aggregator gateway api alarm' & /usr/bin/supervisord -c /etc/supervisord.conf agent.json: |- { "debug": true, "hostname": "", "ip": "", "plugin": { "enabled": false, "dir": "./plugin", "git": "https://github.com/open-falcon/plugin.git", "logs": "./logs" }, "heartbeat": { "enabled": true, "addr": "open-falcon:6030", "interval": 60, "timeout": 1000 }, "transfer": { "enabled": true, "addrs": [ "open-falcon:8433" ], "interval": 60, "timeout": 1000 }, "http": { "enabled": true, "listen": ":1988", "backdoor": false }, "collector": { "ifacePrefix": ["eth", "em"], "mountPoint": [] }, "default_tags": { }, "ignore": { "sys.disk.rw": true, "df.bytes.free": true, "df.bytes.total": true, "df.bytes.used": true, "df.inodes.total": true, "df.inodes.free": true, "df.inodes.used": true, "mem.memtotal": true, "mem.memused": true, "mem.memfree": true, "mem.swaptotal": true, "mem.swapused": true, "mem.swapfree": true, "df.statistics.total": true, "df.statistics.used": true } } --- apiVersion: v1 kind: Service metadata: name: open-falcon labels: app: monitor spec: type: NodePort ports: - name: tcp port: 8433 - name: web port: 8080 selector: name: open-falcon --- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: open-falcon labels: app: monitor spec: replicas: 1 template: metadata: labels: name: open-falcon spec: containers: - name: open-falcon image: openfalcon/falcon-plus:v0.3 workingDir: /open-falcon command: - /bin/entrypoint.sh imagePullPolicy: IfNotPresent ports: - containerPort: 8433 - containerPort: 8080 env: - name: MYSQL_PORT value: root:123456@tcp(mysql:3306) - name: REDIS_PORT value: redis:6379 volumeMounts: - name: open-falcon-data mountPath: /open-falcon/data - name: configmap-volume mountPath: /bin/entrypoint.sh readOnly: true subPath: entrypoint.sh volumes: - name: open-falcon-data emptyDir: {} - name: configmap-volume configMap: defaultMode: 0700 name: openfalcon-configmap --- apiVersion: v1 kind: ServiceAccount metadata: name: falcon-plus --- apiVersion: apps/v1 kind: DaemonSet metadata: labels: k8s-app: falcon-agent kubernetes.io/cluster-service: 'true' version: v1 name: falcon-agent spec: revisionHistoryLimit: 10 selector: matchLabels: k8s-app: falcon-agent kubernetes.io/cluster-service: 'true' version: v1 template: metadata: creationTimestamp: null labels: k8s-app: falcon-agent kubernetes.io/cluster-service: 'true' version: v1 spec: containers: - args: - '-c' - /open-falcon/config/agent.json command: - ./agent/bin/falcon-agent env: - name: GIN_MODE value: release - name: NUX_ROOTFS value: /rootfs - name: FALCON_ENDPOINT valueFrom: fieldRef: apiVersion: v1 fieldPath: spec.nodeName image: 'openfalcon/falcon-plus:v0.3' workingDir: /open-falcon imagePullPolicy: IfNotPresent name: falcon-agent resources: limits: cpu: 200m memory: 200Mi requests: cpu: 200m memory: 200Mi terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /rootfs name: rootfs readOnly: true - mountPath: /open-falcon/config name: configmap-volume readOnly: true dnsPolicy: ClusterFirst restartPolicy: Always schedulerName: default-scheduler securityContext: {} serviceAccount: falcon-plus serviceAccountName: falcon-plus terminationGracePeriodSeconds: 30 volumes: - hostPath: path: / type: '' name: rootfs - name: configmap-volume configMap: defaultMode: 0700 name: openfalcon-configmap updateStrategy: rollingUpdate: maxUnavailable: 1 type: RollingUpdate ================================================ FILE: docker/k8s-example/redis.yaml ================================================ apiVersion: v1 kind: Service metadata: name: redis labels: app: db spec: ports: - port: 6379 selector: app: db name: redis --- apiVersion: extensions/v1beta1 kind: Deployment metadata: name: redis spec: replicas: 1 template: metadata: labels: app: db name: redis spec: containers: - image: redis:alpine name: redis livenessProbe: tcpSocket: port: 6379 ports: - containerPort: 6379 name: redis ================================================ FILE: docker/mysql-init/Dockerfile ================================================ from alpine:3.5 env MYSQL_HOST=mysql \ MYSQL_USER=root \ MYSQL_PASSWORD=test123456 run apk add --no-cache mysql-client git copy init_mysql_data.sh / cmd ["/init_mysql_data.sh"] ================================================ FILE: docker/mysql-init/init_mysql_data.sh ================================================ #!/bin/sh Host=${MYSQL_HOST} User=${MYSQL_USER} Password=${MYSQL_PASSWORD} cd /tmp && \ git clone --depth=1 https://github.com/open-falcon/falcon-plus && \ cd /tmp/falcon-plus/ && \ for x in `ls ./scripts/mysql/db_schema/*.sql`; do echo init mysql table $x ...; mysql -h${Host} -u${User} -p${Password} < $x; done rm -rf /tmp/falcon-plus/ ================================================ FILE: docker/supervisord.conf ================================================ [supervisord] childlogdir = /open-falcon/logs/ logfile = /open-falcon/logs/supervisord.log pidfile = /var/run/supervisord.pid nodaemon = true directory = /open-falcon [unix_http_server] file = /var/run/supervisor.sock chmod = 0777 chown= nobody:nogroup [rpcinterface:supervisor] supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface [supervisorctl] serverurl = unix:///var/run/supervisor.sock [program:graph] user = root directory = /open-falcon/%(program_name)s command = /open-falcon/%(program_name)s/bin/falcon-%(program_name)s -c /open-falcon/%(program_name)s/config/cfg.json stdout_logfile = /open-falcon/logs/%(program_name)s.log stderr_logfile = /open-falcon/logs/%(program_name)s.err autostart=false [program:hbs] user = root directory = /open-falcon/%(program_name)s command = /open-falcon/%(program_name)s/bin/falcon-%(program_name)s -c /open-falcon/%(program_name)s/config/cfg.json stdout_logfile = /open-falcon/logs/%(program_name)s.log stderr_logfile = /open-falcon/logs/%(program_name)s.err autostart=false [program:judge] user = root directory = /open-falcon/%(program_name)s command = /open-falcon/%(program_name)s/bin/falcon-%(program_name)s -c /open-falcon/%(program_name)s/config/cfg.json stdout_logfile = /open-falcon/logs/%(program_name)s.log stderr_logfile = /open-falcon/logs/%(program_name)s.err autostart=false [program:transfer] user = root directory = /open-falcon/%(program_name)s command = /open-falcon/%(program_name)s/bin/falcon-%(program_name)s -c /open-falcon/%(program_name)s/config/cfg.json stdout_logfile = /open-falcon/logs/%(program_name)s.log stderr_logfile = /open-falcon/logs/%(program_name)s.err autostart=false [program:nodata] user = root directory = /open-falcon/%(program_name)s command = /open-falcon/%(program_name)s/bin/falcon-%(program_name)s -c /open-falcon/%(program_name)s/config/cfg.json stdout_logfile = /open-falcon/logs/%(program_name)s.log stderr_logfile = /open-falcon/logs/%(program_name)s.err autostart=false [program:aggregator] user = root directory = /open-falcon/%(program_name)s command = /open-falcon/%(program_name)s/bin/falcon-%(program_name)s -c /open-falcon/%(program_name)s/config/cfg.json stdout_logfile = /open-falcon/logs/%(program_name)s.log stderr_logfile = /open-falcon/logs/%(program_name)s.err autostart=false [program:agent] user = root directory = /open-falcon/%(program_name)s command = /open-falcon/%(program_name)s/bin/falcon-%(program_name)s -c /open-falcon/%(program_name)s/config/cfg.json stdout_logfile = /open-falcon/logs/%(program_name)s.log stderr_logfile = /open-falcon/logs/%(program_name)s.err autostart=false [program:gateway] user = root directory = /open-falcon/%(program_name)s command = /open-falcon/%(program_name)s/bin/falcon-%(program_name)s -c /open-falcon/%(program_name)s/config/cfg.json stdout_logfile = /open-falcon/logs/%(program_name)s.log stderr_logfile = /open-falcon/logs/%(program_name)s.err autostart=false [program:api] user = root directory = /open-falcon/%(program_name)s command = /open-falcon/%(program_name)s/bin/falcon-%(program_name)s -c /open-falcon/%(program_name)s/config/cfg.json stdout_logfile = /open-falcon/logs/%(program_name)s.log stderr_logfile = /open-falcon/logs/%(program_name)s.err autostart=false [program:alarm] user = root directory = /open-falcon/%(program_name)s command = /open-falcon/%(program_name)s/bin/falcon-%(program_name)s -c /open-falcon/%(program_name)s/config/cfg.json stdout_logfile = /open-falcon/logs/%(program_name)s.log stderr_logfile = /open-falcon/logs/%(program_name)s.err autostart=false ================================================ FILE: docker-compose.yml ================================================ version: '3.5' services: mysql: container_name: falcon-mysql image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: root volumes: - ./scripts/mysql/db_schema:/docker-entrypoint-initdb.d/ - mysql-data:/var/lib/mysql redis: container_name: falcon-redis image: redis:4-alpine3.8 hbs: &falcon container_name: falcon-hbs build: context: ./ args: MODULE: hbs dockerfile: Dockerfile.module image: openfalcon/falcon-hbs:dev environment: MYSQL_PORT: root:root@tcp\(falcon-mysql:3306\) REDIS_PORT: falcon-redis:6379 AGGREGATOR_HTTP: falcon-aggregator:6055 GRAPH_HTTP: falcon-graph:6071 GRAPH_RPC: falcon-graph:6070 HBS_HTTP: falcon-hbs:6031 HBS_RPC: falcon-hbs:6030 JUDGE_HTTP: falcon-judge:6081 JUDGE_RPC: falcon-judge:6080 NODATA_HTTP: falcon-nodata:6090 TRANSFER_HTTP: falcon-transfer:6060 TRANSFER_RPC: falcon-transfer:8433 PLUS_API_HTTP: falcon-api:8080 AGENT_HOSTNAME: docker-agent depends_on: - mysql - redis command: "sh ctrl.sh run hbs" agent: <<: *falcon build: context: ./ args: MODULE: agent dockerfile: Dockerfile.module image: openfalcon/falcon-agent:dev container_name: falcon-agent depends_on: - hbs - transfer command: "sh ctrl.sh run agent" aggregator: <<: *falcon build: context: ./ args: MODULE: aggregator dockerfile: Dockerfile.module image: openfalcon/falcon-aggregator:dev container_name: falcon-aggregator command: "sh ctrl.sh run aggregator" nodata: <<: *falcon build: context: ./ args: MODULE: nodata dockerfile: Dockerfile.module image: openfalcon/falcon-nodata:dev container_name: falcon-nodata command: "sh ctrl.sh run nodata" api: <<: *falcon build: context: ./ args: MODULE: api dockerfile: Dockerfile.module image: openfalcon/falcon-api:dev container_name: falcon-api command: "sh ctrl.sh run api" ports: - 8080:8080 alarm: <<: *falcon build: context: ./ args: MODULE: alarm dockerfile: Dockerfile.module image: openfalcon/falcon-alarm:dev container_name: falcon-alarm command: "sh ctrl.sh run alarm" transfer: <<: *falcon build: context: ./ args: MODULE: transfer dockerfile: Dockerfile.module image: openfalcon/falcon-transfer:dev container_name: falcon-transfer depends_on: - graph command: "sh ctrl.sh run transfer" judge: <<: *falcon build: context: ./ args: MODULE: judge dockerfile: Dockerfile.module image: openfalcon/falcon-judge:dev container_name: falcon-judge command: "sh ctrl.sh run judge" graph: <<: *falcon build: context: ./ args: MODULE: graph dockerfile: Dockerfile.module image: openfalcon/falcon-graph:dev container_name: falcon-graph volumes: - graph-data:/open-falcon/data command: "sh ctrl.sh run graph" dashboard: container_name: falcon-dashboard image: openfalcon/falcon-dashboard:v0.2.1 entrypoint: ./control startfg environment: API_ADDR: http://falcon-api:8080/api/v1 PORTAL_DB_HOST: mysql PORTAL_DB_PORT: 3306 PORTAL_DB_USER: root PORTAL_DB_PASS: root PORTAL_DB_NAME: falcon_portal ALARM_DB_HOST: mysql ALARM_DB_PORT: 3306 ALARM_DB_USER: root ALARM_DB_PASS: root ALARM_DB_NAME: alarms working_dir: /open-falcon/dashboard ports: - 8081:8081 volumes: mysql-data: graph-data: ================================================ FILE: docker_test.sh ================================================ #!/bin/bash export DB_USER=root export DB_PASSWORD=test123456 export DB_HOST=127.0.0.1 export DB_PORT=13306 export REDIS_HOST=127.0.0.1 export REDIS_PORT=16379 export API_PORT=18080 export API_HOST=127.0.0.1 docker rm -f falcon-mysql falcon-redis falcon-plus &> /dev/null if [[ `uname -m` == "aarch64" ]]; then docker run --name falcon-mysql -e MYSQL_ROOT_PASSWORD=$DB_PASSWORD -p $DB_PORT:3306 -d mariadb:10.3 else docker run --name falcon-mysql -e MYSQL_ROOT_PASSWORD=$DB_PASSWORD -p $DB_PORT:3306 -d mysql:5.7 fi docker run --name falcon-redis -p $REDIS_PORT:6379 -d redis:4-alpine3.8 echo "waiting mysql start..." sleep 15 for x in `ls ./scripts/mysql/db_schema/*.sql`; do echo "- - -" $x ... mysql -h $DB_HOST -P$DB_PORT -u$DB_USER -p$DB_PASSWORD < $x done commit_id=`git rev-parse --short HEAD` image_tag="falcon-plus:$commit_id" #build docker image from source code if [[ `uname -m` == "aarch64" ]]; then docker build -t $image_tag -f Dockerfile_arm64 . else docker build -t $image_tag . fi ## run falcon-plus container docker run -itd --name falcon-plus \ --link=falcon-mysql:db.falcon \ --link=falcon-redis:redis.falcon \ -p 18433:8433 \ -p 18080:8080 \ -e MYSQL_PORT=$DB_USER:$DB_PASSWORD@tcp\(db.falcon:3306\) \ -e REDIS_PORT=redis.falcon:6379 \ $image_tag sleep 15 ## start falcon backend modules, such as graph,api,etc. docker exec falcon-plus sh ctrl.sh start \ graph hbs judge transfer nodata aggregator agent gateway api alarm echo "sleep 15s waiting for falcon-plus process ready..." sleep 15 make test ================================================ FILE: docs/LICENSE.md ================================================ The MIT License (MIT) Copyright (c) [year] [fullname] Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: docs/Makefile ================================================ SRC = $(wildcard lib/*/*.js) HTML = $(wildcard lib/*/*.html) TEMPLATES = $(HTML:.html=.js) LESS = $(wildcard lib/*/*.less) CSS = $(LESS:.less=.css) build: components $(SRC) $(TEMPLATES) $(CSS) @component build --verbose --out . --name assets components: component.json @component install %.js: %.html @component convert $< %.css: %.less @lessc $< $@ clean: rm -fr build components $(TEMPLATES) .PHONY: clean ================================================ FILE: docs/README.md ================================================ ## The "What ?" and the "Why ?" **Carte** is a simple Jekyll based documentation website for APIs. It is designed as a boilerplate to build your own documentation and is heavily inspired from [Swagger](http://swagger.wordnik.com/) and [I/O docs](http://www.mashery.com/product/io-docs). Fork it, add specifications for your APIs calls and customize the theme. Go ahead, see if we care. We built **Carte** because the existing options (Swagger and the likes) were trying to do too much and did not match our needs: 1. Most of our API calls are sending JSON objects, as opposed to a series of parameters, 1. Being able to query the real API is nice, but running anything but `GET` calls can get tricky ("What do you mean I deleted my stuff? I was just trying out the API calls!"), 1. Overall, setting up a separate server for what really requires a good static documentation seemed overkill. The real value of **Carte** is its structure for describing APIs, not its underlying technical stack (or lack-thereof). In a nutshell; **we built a static template for your API documentation, feel free to re-use it**. ## Install It' Jekyll god dammit: 1. Clone this repository on your local, 1. [Install Jekyll](https://github.com/mojombo/jekyll/wiki/install), 1. Go at the root of the repository and run ```jekyll serve --watch```, 1. Go to http://localhost:4000, 1. [Great success! High five!](http://www.youtube.com/watch?v=wWWyJwHQ-4E) ## How to... ### Adding a new API call You can add a new API call by simply adding a new post in the `_posts` folder. Jekyll by default forces you to specify a date in the file path: it makes us sad pandas too, but you'll have to stick to this format. You can use dates to control the order in which API calls are displayed in the interface. Each API call can define a few values in its YAML header: Variable | Mandatory | Default | Description --- | --- | --- | --- ``title`` | Y | - | A short description of what that calls does. ``path`` | N | - | The URL for the API call, including potential parameters. ``type`` | N | - | Set it to `PUT`, `GET`, `POST`, `DELETE` or nothing (for parts of your documentation that do not relate to an actual API call). A typical header: ``` --- path: '/stuff/:id' title: 'Delete a thing' type: 'DELETE' layout: nil --- ``` We then describe the request and response (or whatever else you wish to talk about) in the body of our post. Check the placeholders present in the `_posts` folder to get an idea of what it can look like. ### Grouping calls Adding a category to your YAML header will allows you to group methods in the navigation. It is particularly helpful as you start having a lot of methods and need to organize them. For example: ``` --- category: Stuff path: '/stuff/:id' title: 'Delete a thing' type: 'DELETE' layout: nil --- ``` ### Edit the design The default UI is mostly described through the `css/style.css` file and a couple short jQuery scripts in the `/_layouts/default.html` layout. Hack it to oblivion. ================================================ FILE: docs/_config.yml ================================================ --- exclude: ['README.markdown'] permalink: ':title' safe: false title: 'Falcon+ API' project_name: 'Falcon+' ================================================ FILE: docs/_includes/nav.html ================================================

{{ site.title }}

================================================ FILE: docs/_layouts/default.html ================================================ {{ site.title }} {{ content }} ================================================ FILE: docs/_posts/2017-01-01-authentication.md ================================================ --- title: 'Auth Session' apiurl: '/api/v1/user/auth_session' type: 'GET' layout: default --- 透过Session检查去判定使用者可否存取资源 ### RequestHeader 透过RequestHeader 的 Apitoken做验证 ```"RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1" }``` ### Response Session 为有效 ```Status: 200``` ```{"message":"session is vaild!"}``` For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/2017-01-01-response-status-codes.md ================================================ --- title: 'Response status codes' layout: default --- ### Success * `POST`, `GET`, `PUT`, `DELETE` returns `200` on success, * 当参数使用不正确的时候会回覆 `400` ### 参考 return code 请参考 [status.go](https://golang.org/src/net/http/status.go) ================================================ FILE: docs/_posts/Admin/2017-01-01-admin_change_role.md ================================================ --- category: Admin apiurl: '/api/v1/admin/change_user_role' title: "Change User's role" type: 'PUT' sample_doc: 'admin.html' layout: default --- * [Session](#/authentication) Required * `Admin` usage * admin: * accept option: * yes * no ### Request ```{"user_id": 14, "admin": "yes"}``` ### Response ```Status: 200``` ```{"message":"user role update sccuessful, affect row: 1"}``` ================================================ FILE: docs/_posts/Admin/2017-01-01-admin_change_user_passwd.md ================================================ --- category: Admin apiurl: '/api/v1/admin/change_user_passwd' title: "Change User's Password" type: 'PUT' sample_doc: 'admin.html' layout: default --- * [Session](#/authentication) Required * `Admin` usage ### Request ```{"user_id": 14, "password": "newpasswd"}``` ### Response ```Status: 200``` ```{"message":"password updated!"}``` ================================================ FILE: docs/_posts/Admin/2017-01-01-admin_delete_user.md ================================================ --- category: Admin apiurl: '/api/v1/admin/delete_user' title: 'Delete User' type: 'DELETE' sample_doc: 'admin.html' layout: default --- * [Session](#/authentication) Required * `Admin` usage ### Request ```{"user_id": 31}``` ### Response ```Status: 200``` ```{"message":"user 31 has been delete, affect row: 1"}``` ================================================ FILE: docs/_posts/Admin/2017-12-07-admin_login.md ================================================ --- category: Admin apiurl: '/api/v1/admin/login' title: 'Admin Login' type: 'POST' sample_doc: 'admin.html' layout: default --- SSO 登入 * [Session](#/authentication) Required * `Admin` usage ### Request ```{ "name": "test2", }``` ### Response ```Status: 200``` ```{ "sig": "9d791331c0ea11e690c5001500c6ca5a", "name": "test2", "admin": false }``` For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/Aggregator/2017-01-01-aggreator_create.md ================================================ --- category: Aggregator apiurl: '/api/v1/aggregator' title: "Create Aggregator to a HostGroup" type: 'POST' sample_doc: 'aggregator.html' layout: default --- * [Session](#/authentication) Required * numerator: 分子 * denominator: 分母 * step: 汇报周期(秒为单位) ### Request ```{ "tags": "", "step": 60, "numerator": "$(cpu.idle)", "metric": "test.idle", "hostgroup_id": 343, "endpoint": "testenp", "denominator": "2" }``` ### Response ```Status: 200``` ```{ "id": 16, "grp_id": 343, "numerator": "$(cpu.idle)", "denominator": "2", "endpoint": "testenp", "metric": "test.idle", "tags": "", "ds_type": "GAUGE", "step": 60, "creator": "root" }``` ================================================ FILE: docs/_posts/Aggregator/2017-01-01-aggreator_delete.md ================================================ --- category: Aggregator apiurl: '/api/v1/aggregator/16' title: "Delete Aggregator" type: 'DELETE' sample_doc: 'aggregator.html' layout: default --- * [Session](#/authentication) Required ### Response ```Status: 200``` ```{"message":"aggregator:16 is deleted"}``` ================================================ FILE: docs/_posts/Aggregator/2017-01-01-aggreator_of_hostgroup.md ================================================ --- category: Aggregator apiurl: '/api/v1/hostgroup/#{hostgroup_id}/aggregators' title: "Get Aggregator List of HostGroup" type: 'GET' sample_doc: 'aggregator.html' layout: default --- * [Session](#/authentication) Required * ex. /api/v1/hostgroup/343/aggregators * numerator: 分子 * denominator: 分母 * step: 汇报周期(秒为单位) ### Response ```Status: 200``` ```{ "hostgroup": "test_group", "aggregators": [ { "id": 13, "grp_id": 343, "numerator": "$(cpu.idle)", "denominator": "2", "endpoint": "testenp", "metric": "test.idle", "tags": "", "ds_type": "GAUGE", "step": 60, "creator": "root" }, { "id": 14, "grp_id": 343, "numerator": "$(cpu.idle)", "denominator": "2", "endpoint": "testenp", "metric": "test.idle", "tags": "", "ds_type": "GAUGE", "step": 60, "creator": "root" }] }``` ================================================ FILE: docs/_posts/Aggregator/2017-01-01-aggreator_update.md ================================================ --- category: Aggregator apiurl: '/api/v1/aggregators' title: "Update Aggregator" type: 'PUT' sample_doc: 'aggregator.html' layout: default --- * [Session](#/authentication) Required * numerator: 分子 * denominator: 分母 * step: 汇报周期(秒为单位) ### Request ```{ "tags": "", "step": 60, "numerator": "$(cpu.idle)", "metric": "test.idle", "id": 16, "endpoint": "testenp", "denominator": "$#" }``` ### Response ```Status: 200``` ```{ "id": 16, "grp_id": 343, "numerator": "$(cpu.idle)", "denominator": "$#", "endpoint": "testenp", "metric": "test.idle", "tags": "", "ds_type": "GAUGE", "step": 60, "creator": "root" }``` ================================================ FILE: docs/_posts/Aggregator/2017-01-01-get_aggreator_by_id.md ================================================ --- category: Aggregator apiurl: '/api/v1/aggregators' title: "Get Aggregator Info by id" type: 'GET' sample_doc: 'aggregator.html' layout: default --- * [Session](#/authentication) Required ### Request ```{ "tags": "", "step": 60, "numerator": "$(cpu.idle)", "metric": "test.idle", "hostgroup_id": 343, "endpoint": "testenp", "denominator": "2" }``` ### Response ```Status: 200``` ```{ "id": 16, "grp_id": 343, "numerator": "$(cpu.idle)", "denominator": "2", "endpoint": "testenp", "metric": "test.idle", "tags": "", "ds_type": "GAUGE", "step": 60, "creator": "root" }``` ================================================ FILE: docs/_posts/Alarm/2017-01-01-alarm_eventcases_get_by_id.md ================================================ --- category: Alarm apiurl: '/api/v1/alarm/eventcases' title: 'Get EventCases by id' type: 'GET' sample_doc: 'alarm.html' layout: default --- * [Session](#/authentication) Required ### Request Content-type: application/x-www-form-urlencoded ```event_id=s_165_cef145900bf4e2a4a0db8b85762b9cdb ``` ### Response ```Status: 200``` ``` [ { "closed_at": null, "closed_note": "", "cond": "0 != 66", "current_step": 3, "endpoint": "agent2", "expression_id": 0, "func": "all(#1)", "id": "s_165_cef145900bf4e2a4a0db8b85762b9cdb", "metric": "cpu.idle", "note": "\u5a13\ue103\u2502\u935b\u5a45\ue11f\u9477\ue044\u5aca\u93c7\u5b58\u67ca", "priority": 0, "process_note": 56603, "process_status": "ignored", "status": "PROBLEM", "step": 300, "strategy_id": 165, "template_id": 45, "timestamp": "2017-03-23T15:51:11+08:00", "tpl_creator": "root", "update_at": "2016-06-23T05:00:00+08:00", "user_modified": 0 } ] ``` For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/Alarm/2017-01-01-alarm_eventcases_list.md ================================================ --- category: Alarm apiurl: '/api/v1/alarm/eventcases' title: 'EventCases List' type: 'POST' sample_doc: 'alarm.html' layout: default --- * [Session](#/authentication) Required ### Request ``` { "endTime": 1480521600, "limit": 10, "process_status": "ignored,unresolved", "startTime": 1466956800, "status": "PROBLEM", "endpoints": ["agent4"], "strategy_id": 46, "template_id": 126 } ``` ### Response ```Status: 200``` ``` { "closed_at": null, "closed_note": "", "cond": "48.33759590792839 > 40", "current_step": 1, "endpoint": "agent4", "expression_id": 0, "func": "all(#3)", "id": "s_46_1ac45122afb893adc02fbd30154ac303", "metric": "cpu.iowait", "note": "CPU I/O wait\u74d2\u5470\u7e4340", "priority": 1, "process_note": 16907, "process_status": "ignored", "status": "PROBLEM", "step": 1, "strategy_id": 46, "template_id": 126, "timestamp": "2016-08-01T06:25:00+08:00", "tpl_creator": "root", "update_at": "2016-08-01T06:25:00+08:00", "user_modified": 0 } ] ``` For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/Alarm/2017-01-01-alarm_eventnote_create.md ================================================ --- category: Alarm apiurl: '/api/v1/alarm/event_note' title: 'Create Event Note' type: 'POST' sample_doc: 'alarm.html' layout: default --- * [Session](#/authentication) Required ### Request ``` { "event_id": "s_165_cef145900bf4e2a4a0db8b85762b9cdb", "note": "test note", "status": "comment" } ``` ### Response ```Status: 200``` ``` { "id": "s_165_cef145900bf4e2a4a0db8b85762b9cdb", "message": "add note to s_165_cef145900bf4e2a4a0db8b85762b9cdb successfuled" } ``` For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/Alarm/2017-01-01-alarm_eventnote_get.md ================================================ --- category: Alarm apiurl: '/api/v1/alarm/event_note' title: 'Get Event Note by id or time range' type: 'GET' sample_doc: 'alarm.html' layout: default --- * [Session](#/authentication) Required ### Request Content-type: application/x-www-form-urlencoded ```endTime=1466697600&startTime=1466611200``` or ```event_id=s_165_cef145900bf4e2a4a0db8b85762b9cdb``` ### Response ```Status: 200``` ``` [ { "case_id": "", "event_caseId": "s_165_cef145900bf4e2a4a0db8b85762b9cdb", "note": "test", "status": "ignored", "timestamp": "2016-06-23T05:39:09+08:00", "user": "root" }, { "case_id": "", "event_caseId": "s_165_9d223f126e7ecb3477cd6806f1ee9656", "note": "Ignored by user", "status": "ignored", "timestamp": "2016-06-23T05:38:56+08:00", "user": "root" } ] ``` For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/Alarm/2017-01-01-alarm_events_create.md ================================================ --- category: Alarm apiurl: '/api/v1/alarm/events' title: 'Create Events' type: 'POST' sample_doc: 'alarm.html' layout: default --- * [Session](#/authentication) Required ### Request Content-type: application/x-www-form-urlencoded Key|Value ---|--- endTime|1466628960 event_id|s_165_cef145900bf4e2a4a0db8b85762b9cdb startTime|1466611200 ### Response ```Status: 200``` ``` [ { "cond": "10.649350649350648 != 66", "event_caseId": "s_165_cef145900bf4e2a4a0db8b85762b9cdb", "id": 635166, "status": 0, "step": 0, "timestamp": "2016-06-23T04:55:00+08:00" }, { "cond": "13.486005089058525 != 66", "event_caseId": "s_165_cef145900bf4e2a4a0db8b85762b9cdb", "id": 635149, "status": 0, "step": 0, "timestamp": "2016-06-23T04:50:00+08:00" } ] ``` For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/DashboardGraph/2017-01-01-dashboard_graph_create.md ================================================ --- category: DashboardGraph apiurl: '/api/v1/dashboard/graph' title: 'Create User' type: 'POST' sample_doc: 'dashboard.html' layout: default --- * [Session](#/authentication) Required ### Request ``` { "screen_id": 953, "title": "laiwei-test-graph1", "endpoints": ["laiweiofficemac"], "counters": ["value/name=pfc.push.ms","value/name=pfc.push.size"], "timespan": 1800, "graph_type": "h", "method": "AVG", "position": 0 } ``` ### Response ```Status: 200``` ```{"message":"ok"}``` For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/DashboardGraph/2017-01-01-dashboard_graph_create_tmpgraph.md ================================================ --- category: DashboardGraph apiurl: '/api/v1/dashboard/tmpgraph' title: 'Create a tmpgraph' type: 'POST' sample_doc: 'dashboard.html' layout: default --- * [Session](#/authentication) Required ### Request ``` {"endpoints":["e1", "e2"], "counters":["c1", "c2"]} ``` ### Response ```Status: 200``` ``` { "ck": "68c07419dbd7ac65977c97d05d99440d", "counters": "c1|c2", "endpoints": "e1|e2", "id": 365195 } ``` For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/DashboardGraph/2017-01-01-dashboard_graph_delete.md ================================================ --- category: DashboardGraph apiurl: '/api/v1/dashboard/graph/:id' title: 'Delete a DashboardGraph' type: 'DELETE' sample_doc: 'dashboard.html' layout: default --- * [Session](#/authentication) Required ### Response ```Status: 200``` ```{"message":"ok"}``` For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/DashboardGraph/2017-01-01-dashboard_graph_get.md ================================================ --- category: DashboardGraph apiurl: '/api/v1/dashboard/graph/:id' title: 'Get DashboardGraph info by id' type: 'GET' sample_doc: 'dashboard.html' layout: default --- * [Session](#/authentication) Required ### Response ```Status: 200``` ``` { "counters":["value/name=pfc.push.ms", "value/name=pfc.push.size"], "endpoints":["laiweiofficemac"], "falcon_tags":"", "graph_id":4626, "graph_type":"h", "method":"", "position":4626, "screen_id":953, "timespan":3600, "title":"test" }``` For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/DashboardGraph/2017-01-01-dashboard_graph_get_tmpgraph_by_id.md ================================================ --- category: DashboardGraph apiurl: '/api/v1/dashboard/tmpgraph/:id' title: 'Get a tmpgraph by id' type: 'GET' sample_doc: 'dashboard.html' layout: default --- * [Session](#/authentication) Required ### Response ```Status: 200``` ```{"counters":["agent.alive"],"endpoints":["laiweiofficemac"]}``` For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/DashboardGraph/2017-01-01-dashboard_graph_update.md ================================================ --- category: DashboardGraph apiurl: '/api/v1/dashboard/graph/:id' title: 'Update a DashboardGraph' type: 'PUT' sample_doc: 'dashboard.html' layout: default --- * [Session](#/authentication) Required ### Request ``` { "counters": ["value/name=pfc.push.ms","value/name=pfc.push.size", "agent.alive"], "falcon_tags": "srv=falcon" } ``` ### Response ```Status: 200``` ```{"message":"ok"}``` For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/DashboardGraph/2017-01-01-dashboard_graphs_gets_by_screenid.md ================================================ --- category: DashboardGraph apiurl: '/api/v1/dashboard/graphs/screen/:screen_id' title: 'Gets graphs by screen id' type: 'GET' sample_doc: 'dashboard.html' layout: default --- * [Session](#/authentication) Required ### Response ```Status: 200``` ``` [ { "counters": [ "value/name=pfc.push.ms" ], "endpoints": [ "laiweiofficemac" ], "falcon_tags": "", "graph_id": 4640, "graph_type": "h", "method": "", "position": 0, "screen_id": 991, "timespan": 3600, "title": "dddd" }, { "counters": [ "aaa" ], "endpoints": [ "xxx" ], "falcon_tags": "", "graph_id": 4641, "graph_type": "h", "method": "SUM", "position": 0, "screen_id": 991, "timespan": 3600, "title": "dddd" } ] ``` For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/DashboardScreen/2017-01-01-dashboard_screen_create.md ================================================ --- category: DashboardScreen apiurl: '/api/v1/dashboard/screen' title: 'Create a DashboardScreen' type: 'POST' sample_doc: 'dashboard.html' layout: default --- * [Session](#/authentication) Required ### Request Content-type: application/x-www-form-urlencoded ```name=laiwei-sceen1&pid=0``` ### Response ```Status: 200``` ```{"name":"laiwei-sceen1","pid":0,"screen_id":961} ``` For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/DashboardScreen/2017-01-01-dashboard_screen_delete.md ================================================ --- category: DashboardScreen apiurl: '/api/v1/dashboard/screen/:screen_id' title: 'Delete a DashboardScreen' type: 'DELETE' sample_doc: 'dashboard.html' layout: default --- * [Session](#/authentication) Required ### Response ```Status: 200``` ```{"message":"ok"} ``` For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/DashboardScreen/2017-01-01-dashboard_screen_get_by_id.md ================================================ --- category: DashboardScreen apiurl: '/api/v1/dashboard/screen/:screen_id' title: 'Get a DashboardScreen by id' type: 'GET' sample_doc: 'dashboard.html' layout: default --- * [Session](#/authentication) Required ### Response ```Status: 200``` ```{"id":961,"pid":0,"name":"laiwei-sceen1"} ``` For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/DashboardScreen/2017-01-01-dashboard_screen_gets_all.md ================================================ --- category: DashboardScreen apiurl: '/api/v1/dashboard/screens' title: 'Gets all DashboardScreens' type: 'GET' sample_doc: 'dashboard.html' layout: default --- * [Session](#/authentication) Required ### Request Content-type: application/x-www-form-urlencoded * params: * limit: 【选填】查询最大数据量,默认值:500,如:limit=10 只查询最多10条数据 ### Response ```Status: 200``` ``` [ { "id": 952, "name": "a1", "pid": 0 }, { "id": 953, "name": "aa1", "pid": 952 }, { "id": 968, "name": "laiwei-screen2", "pid": 1 }, { "id": 972, "name": "laiwei-sceen1", "pid": 0 }, { "id": 991, "name": "xnew", "pid": 972 }, { "id": 993, "name": "clone3", "pid": 972 }, { "id": 995, "name": "op", "pid": 0 } ] ``` For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/DashboardScreen/2017-01-01-dashboard_screen_gets_by_pid.md ================================================ --- category: DashboardScreen apiurl: '/api/v1/dashboard/screens/pid/:screen_pid' title: 'Gets DashboardScreens by pid' type: 'GET' sample_doc: 'dashboard.html' layout: default --- * [Session](#/authentication) Required ### Response ```Status: 200``` ``` [ { "id": 952, "name": "a1", "pid": 0 }, { "id": 961, "name": "laiwei-sceen1", "pid": 0 } ] ``` For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/DashboardScreen/2017-01-01-dashboard_screen_update.md ================================================ --- category: DashboardScreen apiurl: '/api/v1/dashboard/screen/:screen_id' title: 'Update a DashboardScreen' type: 'PUT' sample_doc: 'dashboard.html' layout: default --- * [Session](#/authentication) Required ### Request Content-type: application/x-www-form-urlencoded ```name=laiwei-sceen1&pid=0``` ### Response ```Status: 200``` ```{"message":"ok"} ``` For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/Expression/2017-01-01-expression_create.md ================================================ --- category: Expression apiurl: '/api/v1/expression' title: "Create Expression" type: 'POST' sample_doc: 'expression.html' layout: default --- * [Session](#/authentication) Required ### Request ```{ "right_value": "0", "priority": 2, "pause": 0, "op": "==", "note": "this is a test exp", "max_step": 3, "func": "all(#3)", "expression": "each(metric=agent.alive endpoint=docker-agent)", "action": { "url": "http://localhost:1234/callback", "uic": [ "test" ], "callback": 1, "before_callback_sms": 1, "before_callback_mail": 0, "after_callback_sms": 1, "after_callback_mail": 0 } }``` ### Response ```Status: 200``` ```{"message":"expression created"}``` ================================================ FILE: docs/_posts/Expression/2017-01-01-expression_delete.md ================================================ --- category: Expression apiurl: '/api/v1/expression/#{expression_id}' title: "Delete Expression" type: 'DELETE' sample_doc: 'expression.html' layout: default --- * [Session](#/authentication) Required * ex. /api/v1/expression/5 ### Response ```Status: 200``` ```{"message":"expression:5 has been deleted"}``` ================================================ FILE: docs/_posts/Expression/2017-01-01-expression_info_by_id.md ================================================ --- category: Expression apiurl: '/api/v1/expression/#{expression_id}' title: "Get Expression Info by id" type: 'GET' sample_doc: 'expression.html' layout: default --- * [Session](#/authentication) Required ex. /api/v1/expression/5 ### Response ```Status: 200``` ```{ "action": { "id": 5, "uic": "taipei", "url": "", "callback": 0, "before_callback_sms": 0, "before_callback_mail": 0, "after_callback_sms": 0, "after_callback_mail": 0 }, "expression": { "id": 5, "expression": "each(metric=agent.alive endpoint=docker-agent)", "func": "all(#3)", "op": "==", "right_value": "0", "max_step": 3, "priority": 2, "note": "this is a test exp", "action_id": 177, "create_user": "root", "pause": 1 } }``` ================================================ FILE: docs/_posts/Expression/2017-01-01-expression_list.md ================================================ --- category: Expression apiurl: '/api/v1/expression' title: "Expression List" type: 'GET' sample_doc: 'expression.html' layout: default --- * [Session](#/authentication) Required ### Response ```Status: 200``` ```[ { "id": 2, "expression": "each(metric=? xx=yy)", "func": "all(#3)", "op": "==", "right_value": "0", "max_step": 3, "priority": 0, "note": "", "action_id": 18, "create_user": "root", "pause": 0 }, { "id": 3, "expression": "each(metric=ss.close.wait endpoint=docker-A)", "func": "all(#1)", "op": "!=", "right_value": "0", "max_step": 1, "priority": 4, "note": "boss docker-A 连接数大于10", "action_id": 91, "create_user": "root", "pause": 0 }, { "id": 4, "expression": "each(metric=agent.alive endpoint=docker-agent)", "func": "all(#3)", "op": "==", "right_value": "0", "max_step": 3, "priority": 2, "note": "this is a test exp", "action_id": 176, "create_user": "root", "pause": 1 } ]``` ================================================ FILE: docs/_posts/Expression/2017-01-01-expression_update.md ================================================ --- category: Expression apiurl: '/api/v1/expression' title: "Update Expression" type: 'PUT' sample_doc: 'expression.html' layout: default --- * [Session](#/authentication) Required ### Request ```{ "right_value": "0", "priority": 2, "pause": 1, "op": "==", "note": "this is a test exp", "max_step": 3, "id": 5, "func": "all(#3)", "expression": "each(metric=agent.alive endpoint=docker-agent)", "action": { "url": "http://localhost:1234/callback", "uic": [ "test", "test2" ], "callback": 0, "before_callback_sms": 1, "before_callback_mail": 0, "after_callback_sms": 1, "after_callback_mail": 0 } }``` ### Response ```Status: 200``` ```{"message":"expression:5 has been updated"}``` ================================================ FILE: docs/_posts/Graph/2017-01-01-endpoint_counter.md ================================================ --- category: Graph apiurl: '/api/v1/graph/endpoint_counter' title: "Get Counter of Endpoint" type: 'GET' sample_doc: 'graph.html' layout: default --- * [Session](#/authentication) Required * params: * eid: endpoint id list * metricQuery: 查询counter参数【选填】。如:metricQuery=device=sda * page: 【选填】分页查询的页码,默认值:1,如: page=2 表示第2页 * limit: 【选填】分页查询的页大小,默认值:500,如:limit=10 表示每页10条数据 * q: 使用 regex 查询字符 * option 参数 ### Response ```Status: 200``` ```[ "disk.io.avgqu-sz/device=sda", "disk.io.ios_in_progress/device=sda", "disk.io.msec_read/device=sda", "disk.io.read_requests/device=sda", ... ]``` ================================================ FILE: docs/_posts/Graph/2017-01-01-endpoints.md ================================================ --- category: Graph apiurl: '/api/v1/graph/endpoint' title: "Endpoint List" type: 'GET' sample_doc: 'graph.html' layout: default --- * [Session](#/authentication) Required * params: * q: 使用 regex 查询字符 * option 参数 * page: 【选填】分页查询的页码,默认值:1,如: page=2 表示第2页 * limit: 【选填】分页查询的页大小,默认值:500,如:limit=10 表示每页10条数据 ### Response ```Status: 200``` ```[ { "endpoint": "docker-agent", "id": 7 }, { "endpoint": "docker-task", "id": 6 }, { "endpoint": "graph", "id": 3 }, { "endpoint": "nodata", "id": 920 }, { "endpoint": "task", "id": 5 } ]``` ================================================ FILE: docs/_posts/Graph/2017-01-01-grafana.md ================================================ --- category: Graph apiurl: '/v1/grafana/render' title: "Grafan query" type: 'POST' layout: default --- * target: grafana query查询串 (type: []string) * 支援多组查询条件. * ex. ["{host-A}#cpu#idel", "{1.1.1.1,2.2.2.2,3.3.3.3}#cpu#idle"] * 為了支援ip & 一些实做的限制. 所以将 "." 制换成 "#" * {}# 后面代入的的counter 会作為查询counter的依据. 可以支援regex match. 例如 #.+cpu.+ 会将所有包含cpu字眼的counter一并查询返回数据画图 * 有时想要找特定的counter可以善用regex语法 "^" or "$" 去限定字串的范围 ex. ["{host-A}#^cpu#idel$"] * 这边保留很大的弹性, 有特殊需求的可以自行修改判断逻辑 * from: start time (unix time) * until: end time (unix time) * step: 查询graph时, 指定step interval * default: 60 * ConsolFun: 取样 -> ["AVERAGE", "MAX", "MIN"] * default: "AVERAGE" ### Response ```Status: 200``` ```[ { "endpoint": "host-A", "counter": "cpu.idle", "dstype": "GAUGE", "step": 60, "Values": [ { "timestamp": 1506698040, "value": 55.934343 }, { "timestamp": 1506698100, "value": 44.656489 } ] } ]``` ================================================ FILE: docs/_posts/Graph/2017-01-01-graph_histroy.md ================================================ --- category: Graph apiurl: '/api/v1/graph/history' title: "Graph History" type: 'POST' sample_doc: 'graph.html' layout: default --- * [Session](#/authentication) Required * dashobard 画图资料 * consol_fun: * AVERAGE * MAX * MIN ### Request ```{ "step": 60, "start_time": 1481854596, "hostnames": [ "docker-a", "docker-b", "docker-c" ], "end_time": 1481858193, "counters": [ "cpu.idle", "cpu.iowait" ], "consol_fun": "AVERAGE" }``` ### Response ```Status: 200``` ```[ { "endpoint": "docker-a", "counter": "cpu.idle", "dstype": "GAUGE", "step": 60, "Values": [ { "timestamp": 1481854620, "value": 98.154506 }, { "timestamp": 1481854680, "value": 97.864161 }, { "timestamp": 1481854740, "value": 97.521368 }, { "timestamp": 1481854800, "value": 97.587247 }, { "timestamp": 1481854860, "value": 97.440273 }, { "timestamp": 1481854920, "value": 97.914006 }, { "timestamp": 1481854980, "value": 97.223409 }, { "timestamp": 1481855040, "value": 98.029135 }, { "timestamp": 1481855100, "value": 97.614991 }, { "timestamp": 1481855160, "value": 97.565143 }, { "timestamp": 1481855220, "value": 97.070064 }, { "timestamp": 1481855280, "value": 98.726115 }, { "timestamp": 1481855340, "value": 98.720137 }, { "timestamp": 1481855400, "value": 98.205128 }, { "timestamp": 1481855460, "value": 97.70017 }, { "timestamp": 1481855520, "value": 97.780623 }, { "timestamp": 1481855580, "value": 97.379725 }, { "timestamp": 1481855640, "value": 98.034188 }, { "timestamp": 1481855700, "value": 98.246364 }, { "timestamp": 1481855760, "value": 98.372591 }, { "timestamp": 1481855820, "value": 98.152921 }, { "timestamp": 1481855880, "value": 97.914006 }, { "timestamp": 1481855940, "value": 95.592048 }, { "timestamp": 1481856000, "value": 94.11512 }, { "timestamp": 1481856060, "value": 97.596567 }, { "timestamp": 1481856120, "value": 97.501077 }, { "timestamp": 1481856180, "value": 96.374622 }, { "timestamp": 1481856240, "value": 89.570815 }, { "timestamp": 1481856300, "value": 96.410035 }, { "timestamp": 1481856360, "value": 97.567222 }, { "timestamp": 1481856420, "value": 97.25204 }, { "timestamp": 1481856480, "value": 95.356836 }, { "timestamp": 1481856540, "value": 97.330508 }, { "timestamp": 1481856600, "value": 96.999571 }, { "timestamp": 1481856660, "value": 97.278912 }, { "timestamp": 1481856720, "value": 97.229327 }, { "timestamp": 1481856780, "value": 97.212693 }, { "timestamp": 1481856840, "value": 96.503198 }, { "timestamp": 1481856900, "value": 96.790757 }, { "timestamp": 1481856960, "value": 98.121264 }, { "timestamp": 1481857020, "value": 98.550725 }, { "timestamp": 1481857080, "value": 97.548387 }, { "timestamp": 1481857140, "value": 98.466127 }, { "timestamp": 1481857200, "value": 97.9006 }, { "timestamp": 1481857260, "value": 97.985426 }, { "timestamp": 1481857320, "value": 97.357204 }, { "timestamp": 1481857380, "value": 97.086547 }, { "timestamp": 1481857440, "value": 98.770144 }, { "timestamp": 1481857500, "value": 97.727273 }, { "timestamp": 1481857560, "value": 98.595147 }, { "timestamp": 1481857620, "value": 97.867804 }, { "timestamp": 1481857680, "value": 98.128456 }, { "timestamp": 1481857740, "value": 97.886729 }, { "timestamp": 1481857800, "value": 95.969453 }, { "timestamp": 1481857860, "value": 97.134303 }, { "timestamp": 1481857920, "value": 98.033348 }, { "timestamp": 1481857980, "value": 96.511628 }, { "timestamp": 1481858040, "value": 96.522112 }, { "timestamp": 1481858100, "value": 97.49043 }, { "timestamp": 1481858160, "value": 96.958012 } ] }, { "endpoint": "docker-a", "counter": "cpu.iowait", "dstype": "GAUGE", "step": 60, "Values": [ { "timestamp": 1481854620, "value": 0.815451 }, { "timestamp": 1481854680, "value": 0.598035 }, { "timestamp": 1481854740, "value": 1.239316 }, { "timestamp": 1481854800, "value": 0.775528 }, { "timestamp": 1481854860, "value": 0.895904 }, { "timestamp": 1481854920, "value": 0.893997 }, { "timestamp": 1481854980, "value": 0.811619 }, { "timestamp": 1481855040, "value": 0.728363 }, { "timestamp": 1481855100, "value": 0.425894 }, { "timestamp": 1481855160, "value": 0.768902 }, { "timestamp": 1481855220, "value": 1.443737 }, { "timestamp": 1481855280, "value": 0.29724 }, { "timestamp": 1481855340, "value": 0.213311 }, { "timestamp": 1481855400, "value": 0.512821 }, { "timestamp": 1481855460, "value": 1.022147 }, { "timestamp": 1481855520, "value": 0.810926 }, { "timestamp": 1481855580, "value": 0.515464 }, { "timestamp": 1481855640, "value": 0.555556 }, { "timestamp": 1481855700, "value": 0.470488 }, { "timestamp": 1481855760, "value": 0.428266 }, { "timestamp": 1481855820, "value": 0.386598 }, { "timestamp": 1481855880, "value": 0.63857 }, { "timestamp": 1481855940, "value": 0.432152 }, { "timestamp": 1481856000, "value": 0.730241 }, { "timestamp": 1481856060, "value": 0.643777 }, { "timestamp": 1481856120, "value": 0.603188 }, { "timestamp": 1481856180, "value": 1.035822 }, { "timestamp": 1481856240, "value": 8.927039 }, { "timestamp": 1481856300, "value": 0.605536 }, { "timestamp": 1481856360, "value": 0.341443 }, { "timestamp": 1481856420, "value": 0.343495 }, { "timestamp": 1481856480, "value": 0.601892 }, { "timestamp": 1481856540, "value": 0.466102 }, { "timestamp": 1481856600, "value": 0.557222 }, { "timestamp": 1481856660, "value": 0.382653 }, { "timestamp": 1481856720, "value": 0.554135 }, { "timestamp": 1481856780, "value": 0.428816 }, { "timestamp": 1481856840, "value": 1.151386 }, { "timestamp": 1481856900, "value": 0.556269 }, { "timestamp": 1481856960, "value": 0.469684 }, { "timestamp": 1481857020, "value": 0.29838 }, { "timestamp": 1481857080, "value": 0.903226 }, { "timestamp": 1481857140, "value": 0.426076 }, { "timestamp": 1481857200, "value": 0.771208 }, { "timestamp": 1481857260, "value": 1.071582 }, { "timestamp": 1481857320, "value": 1.278772 }, { "timestamp": 1481857380, "value": 0.642674 }, { "timestamp": 1481857440, "value": 0.212044 }, { "timestamp": 1481857500, "value": 0.686106 }, { "timestamp": 1481857560, "value": 0.425713 }, { "timestamp": 1481857620, "value": 0.810235 }, { "timestamp": 1481857680, "value": 0.765632 }, { "timestamp": 1481857740, "value": 0.380389 }, { "timestamp": 1481857800, "value": 0.296988 }, { "timestamp": 1481857860, "value": 0.855432 }, { "timestamp": 1481857920, "value": 0.470286 }, { "timestamp": 1481857980, "value": 1.248923 }, { "timestamp": 1481858040, "value": 1.631602 }, { "timestamp": 1481858100, "value": 1.531263 }, { "timestamp": 1481858160, "value": 0.599829 } ] }, { "endpoint": "docker-b", "counter": "cpu.idle", "dstype": "GAUGE", "step": 60, "Values": [ { "timestamp": 1481854620, "value": 93.811775 }, { "timestamp": 1481854680, "value": 94.150538 }, { "timestamp": 1481854740, "value": 94.991438 }, { "timestamp": 1481854800, "value": 93.287435 }, { "timestamp": 1481854860, "value": 96.642584 }, { "timestamp": 1481854920, "value": 98.207426 }, { "timestamp": 1481854980, "value": 94.801875 }, { "timestamp": 1481855040, "value": 97.827939 }, { "timestamp": 1481855100, "value": 94.439692 }, { "timestamp": 1481855160, "value": 98.292787 }, { "timestamp": 1481855220, "value": 95.027624 }, { "timestamp": 1481855280, "value": 98.218074 }, { "timestamp": 1481855340, "value": 97.402044 }, { "timestamp": 1481855400, "value": 94.368601 }, { "timestamp": 1481855460, "value": 94.772631 }, { "timestamp": 1481855520, "value": 93.992331 }, { "timestamp": 1481855580, "value": 94.939446 }, { "timestamp": 1481855640, "value": 97.780623 }, { "timestamp": 1481855700, "value": 97.860505 }, { "timestamp": 1481855760, "value": 92.765411 }, { "timestamp": 1481855820, "value": 98.029979 }, { "timestamp": 1481855880, "value": 94.523502 }, { "timestamp": 1481855940, "value": 94.102564 }, { "timestamp": 1481856000, "value": 94.96587 }, { "timestamp": 1481856060, "value": 94.382979 }, { "timestamp": 1481856120, "value": 93.336181 }, { "timestamp": 1481856180, "value": 97.988875 }, { "timestamp": 1481856240, "value": 94.401709 }, { "timestamp": 1481856300, "value": 94.619983 }, { "timestamp": 1481856360, "value": 94.916702 }, { "timestamp": 1481856420, "value": 94.089733 }, { "timestamp": 1481856480, "value": 94.475375 }, { "timestamp": 1481856540, "value": 93.576017 }, { "timestamp": 1481856600, "value": 94.010195 }, { "timestamp": 1481856660, "value": 94.137783 }, { "timestamp": 1481856720, "value": 95.264505 }, { "timestamp": 1481856780, "value": 96.879008 }, { "timestamp": 1481856840, "value": 96.38759 }, { "timestamp": 1481856900, "value": 93.830334 }, { "timestamp": 1481856960, "value": 96.282051 }, { "timestamp": 1481857020, "value": 94.173093 }, { "timestamp": 1481857080, "value": 95.382642 }, { "timestamp": 1481857140, "value": 94.107452 }, { "timestamp": 1481857200, "value": 93.611584 }, { "timestamp": 1481857260, "value": 97.0538 }, { "timestamp": 1481857320, "value": 94.404101 }, { "timestamp": 1481857380, "value": 94.449189 }, { "timestamp": 1481857440, "value": 98.286938 }, { "timestamp": 1481857500, "value": 93.720632 }, { "timestamp": 1481857560, "value": 93.669803 }, { "timestamp": 1481857620, "value": 93.865294 }, { "timestamp": 1481857680, "value": 94.498934 }, { "timestamp": 1481857740, "value": 94.610778 }, { "timestamp": 1481857800, "value": 93.929029 }, { "timestamp": 1481857860, "value": 97.827939 }, { "timestamp": 1481857920, "value": 97.76824 }, { "timestamp": 1481857980, "value": 91.079014 }, { "timestamp": 1481858040, "value": 97.854998 }, { "timestamp": 1481858100, "value": 93.399482 }, { "timestamp": 1481858160, "value": 94.014536 } ] }, { "endpoint": "docker-b", "counter": "cpu.iowait", "dstype": "GAUGE", "step": 60, "Values": [ { "timestamp": 1481854620, "value": 0.171895 }, { "timestamp": 1481854680, "value": 0.645161 }, { "timestamp": 1481854740, "value": 0.47089 }, { "timestamp": 1481854800, "value": 0.731497 }, { "timestamp": 1481854860, "value": 0.594985 }, { "timestamp": 1481854920, "value": 0.256082 }, { "timestamp": 1481854980, "value": 0.340861 }, { "timestamp": 1481855040, "value": 0.255537 }, { "timestamp": 1481855100, "value": 0.684346 }, { "timestamp": 1481855160, "value": 0.384123 }, { "timestamp": 1481855220, "value": 0.084998 }, { "timestamp": 1481855280, "value": 0.466695 }, { "timestamp": 1481855340, "value": 1.192504 }, { "timestamp": 1481855400, "value": 0.511945 }, { "timestamp": 1481855460, "value": 0.594985 }, { "timestamp": 1481855520, "value": 0.383468 }, { "timestamp": 1481855580, "value": 1.038062 }, { "timestamp": 1481855640, "value": 0.981647 }, { "timestamp": 1481855700, "value": 0.599059 }, { "timestamp": 1481855760, "value": 0.770548 }, { "timestamp": 1481855820, "value": 0.428266 }, { "timestamp": 1481855880, "value": 0.301854 }, { "timestamp": 1481855940, "value": 0.598291 }, { "timestamp": 1481856000, "value": 0.853242 }, { "timestamp": 1481856060, "value": 0.723404 }, { "timestamp": 1481856120, "value": 1.025203 }, { "timestamp": 1481856180, "value": 0.470689 }, { "timestamp": 1481856240, "value": 0.213675 }, { "timestamp": 1481856300, "value": 0.768574 }, { "timestamp": 1481856360, "value": 0.256301 }, { "timestamp": 1481856420, "value": 0.388266 }, { "timestamp": 1481856480, "value": 0.342612 }, { "timestamp": 1481856540, "value": 0.813704 }, { "timestamp": 1481856600, "value": 0.594732 }, { "timestamp": 1481856660, "value": 0.684638 }, { "timestamp": 1481856720, "value": 1.535836 }, { "timestamp": 1481856780, "value": 0.25652 }, { "timestamp": 1481856840, "value": 0.38249 }, { "timestamp": 1481856900, "value": 1.028278 }, { "timestamp": 1481856960, "value": 1.025641 }, { "timestamp": 1481857020, "value": 0.642674 }, { "timestamp": 1481857080, "value": 0.726806 }, { "timestamp": 1481857140, "value": 0.649913 }, { "timestamp": 1481857200, "value": 0.809199 }, { "timestamp": 1481857260, "value": 0.256191 }, { "timestamp": 1481857320, "value": 0.512601 }, { "timestamp": 1481857380, "value": 0.59778 }, { "timestamp": 1481857440, "value": 0.342612 }, { "timestamp": 1481857500, "value": 1.19607 }, { "timestamp": 1481857560, "value": 0.983747 }, { "timestamp": 1481857620, "value": 0.900901 }, { "timestamp": 1481857680, "value": 0.639659 }, { "timestamp": 1481857740, "value": 0.641574 }, { "timestamp": 1481857800, "value": 0.598546 }, { "timestamp": 1481857860, "value": 0.425894 }, { "timestamp": 1481857920, "value": 0.729614 }, { "timestamp": 1481857980, "value": 0.339847 }, { "timestamp": 1481858040, "value": 0.686401 }, { "timestamp": 1481858100, "value": 0.560828 }, { "timestamp": 1481858160, "value": 0.51304 } ] }, { "endpoint": "docker-c", "counter": "cpu.idle", "dstype": "", "step": 0, "Values": [] }, { "endpoint": "docker-c", "counter": "cpu.iowait", "dstype": "", "step": 0, "Values": [] } ]``` ================================================ FILE: docs/_posts/Host/2017-01-01-host_maintain.md ================================================ --- category: Host apiurl: '/api/v1/host/maintain' title: "Set host maintain by ids or hostnames" type: 'POST' sample_doc: 'host.html' layout: default --- * [Session](#/authentication) Required ### Request ``` { "ids": [1,2,3,4], "maintain_begin": 1497951907, "maintain_end": 1497951907 } ``` or ``` { "hosts": ["host.a","host.b"], "maintain_begin": 1497951907, "maintain_end": 1497951907 } ``` ### Response ```Status: 200``` ```{ "message": "Through: hosts, Affect row: 2" }``` ================================================ FILE: docs/_posts/Host/2017-01-01-host_related_hostgroup.md ================================================ --- category: Host apiurl: '/api/v1/host/#{host_id}/hostgroup' title: "Get related HostGorup of Host" type: 'GET' sample_doc: 'host.html' layout: default --- * [Session](#/authentication) Required * ex. /api/v1/host/1647/hostgroup * grp_name: hostgroup name ### Response ```Status: 200``` ```[ { "id": 78, "grp_name": "tplB", "create_user": "userA" }, { "id": 145, "grp_name": "Owl_Default_Group", "create_user": "userA" } ]``` ================================================ FILE: docs/_posts/Host/2017-01-01-host_related_template.md ================================================ --- category: Host apiurl: '/api/v1/host/#{host_id}/template' title: "Get bind Template List of Host" type: 'GET' sample_doc: 'host.html' layout: default --- * [Session](#/authentication) Required * ex. /api/v1/host/1647/template * tpl_name: template name ### Response ```Status: 200``` ```[ { "id": 125, "tpl_name": "tplA", "parent_id": 0, "action_id": 99, "create_user": "root" }, { "id": 142, "tpl_name": "tplB", "parent_id": 0, "action_id": 111, "create_user": "root" }, { "id": 180, "tpl_name": "tplC", "parent_id": 0, "action_id": 142, "create_user": "root" } ]``` ================================================ FILE: docs/_posts/Host/2017-01-01-host_reset.md ================================================ --- category: Host apiurl: '/api/v1/host/maintain' title: "Reset host maintain by ids or hostnames" type: 'DELETE' sample_doc: 'host.html' layout: default --- * [Session](#/authentication) Required ### Request ```{"ids": [1,2,3,4]}``` or ```{"hosts": ["host.a","host.b"]}``` ### Response ```Status: 200``` ```{ "message": "Through: hosts, Affect row: 2" }``` ================================================ FILE: docs/_posts/HostGroup/2017-01-01-hostgroup_add_host.md ================================================ --- category: HostGroup apiurl: '/api/v1/hostgroup/host' title: "Add Hosts to HostGroup" type: 'POST' sample_doc: 'hostgroup.html' layout: default --- * [Session](#/authentication) Required * Hosts 每次会覆盖该HostGroup内现有的Host List * 如果使用者不是 Admin 只能对创建的hostgroup做操作 ### Request ```{ "hosts": [ "testhostgroup", "agent_test" ], "hostgroup_id": 343 }``` ### Response ```Status: 200``` ```{"message":"[9312 9313] bind to hostgroup: 343"}``` ================================================ FILE: docs/_posts/HostGroup/2017-01-01-hostgroup_create.md ================================================ --- category: HostGroup apiurl: '/api/v1/hostgroup' title: "Create HostGroup" type: 'POST' sample_doc: 'hostgroup.html' layout: default --- * [Session](#/authentication) Required ### Request ```{"name":"testhostgroup"}``` ### Response ```Status: 200``` ```{ "id": 343, "grp_name": "testhostgroup", "create_user": "root" }``` ================================================ FILE: docs/_posts/HostGroup/2017-01-01-hostgroup_delete.md ================================================ --- category: HostGroup apiurl: '/api/v1/hostgroup/#{hostgroup_id}' title: "Delete HostGroup" type: 'DELETE' sample_doc: 'hostgroup.html' layout: default --- * [Session](#/authentication) Required ex. /api/v1/hostgroup/343 * 如果使用者不是 Admin 只能对创建的hostgroup做操作 ### Response ```Status: 200``` ```{"message":"hostgroup:343 has been deleted"}``` ================================================ FILE: docs/_posts/HostGroup/2017-01-01-hostgroup_get_info_by_id.md ================================================ --- category: HostGroup apiurl: '/api/v1/hostgroup/#{hostgroup_id}' title: "Get HostGroup info by id" type: 'GET' sample_doc: 'hostgroup.html' layout: default --- * [Session](#/authentication) Required * ex. /api/v1/hostgroup/343 ### Response ```Status: 200``` ```{ "hostgroup": { "id": 343, "grp_name": "testhostgroup", "create_user": "root" }, "hosts": [ { "id": 9313, "hostname": "agent_test", "ip": "", "agent_version": "", "plugin_version": "", "maintain_begin": 0, "maintain_end": 0 } ] }``` ================================================ FILE: docs/_posts/HostGroup/2017-01-01-hostgroup_list.md ================================================ --- category: HostGroup apiurl: '/api/v1/hostgroup' title: "HostGroup List" type: 'GET' sample_doc: 'hostgroup.html' layout: default --- * [Session](#/authentication) Required ### Response ```Status: 200``` ```[ { "id": 3, "grp_name": "docker-A", "create_user": "user-A" }, { "id": 5, "grp_name": "docker-T", "create_user": "user-B" }, { "id": 8, "grp_name": "docker-F", "create_user": "root" } ]``` ================================================ FILE: docs/_posts/HostGroup/2017-01-01-hostgroup_template_bind.md ================================================ --- category: HostGroup apiurl: '/api/v1/hostgroup/template' title: "Bind A Template to HostGroup" type: 'POST' sample_doc: 'hostgroup.html' layout: default --- * [Session](#/authentication) Required ### Request ```{ "tpl_id": 5, "grp_id": 3 }``` ### Response ```Status: 200``` ```{"grp_id":3,"tpl_id":5,"bind_user":2}``` ================================================ FILE: docs/_posts/HostGroup/2017-01-01-hostgroup_template_list.md ================================================ --- category: HostGroup apiurl: '/api/v1/hostgroup/#{hostgroup_id}/template' title: "Get Template List of HostGroup" type: 'GET' sample_doc: 'hostgroup.html' layout: default --- * [Session](#/authentication) Required * ex. /api/v1/hostgroup/3/template ### Response ```Status: 200``` ```{ "hostgroup": { "id": 3, "grp_name": "hostgroupA", "create_user": "root" }, "templates": [ { "id": 5, "tpl_name": "TplA", "parent_id": 0, "action_id": 12, "create_user": "root" }, { "id": 91, "tpl_name": "TplB", "parent_id": 0, "action_id": 59, "create_user": "userA" }, { "id": 94, "tpl_name": "TplB", "parent_id": 0, "action_id": 62, "create_user": "userA" }, { "id": 103, "tpl_name": "TplC", "parent_id": 0, "action_id": 74, "create_user": "root" }, { "id": 104, "tpl_name": "TplD", "parent_id": 0, "action_id": 75, "create_user": "root" }, { "id": 105, "tpl_name": "TplE", "parent_id": 0, "action_id": 76, "create_user": "root" }, { "id": 116, "tpl_name": "TplG", "parent_id": 0, "action_id": 87, "create_user": "root" }, { "id": 125, "tpl_name": "TplH", "parent_id": 0, "action_id": 99, "create_user": "root" }, { "id": 126, "tpl_name": "http", "parent_id": 0, "action_id": 100, "create_user": "root" }, { "id": 127, "tpl_name": "TplJ", "parent_id": 0, "action_id": 101, "create_user": "root" } ] }``` ================================================ FILE: docs/_posts/HostGroup/2017-01-01-hostgroup_template_unbind.md ================================================ --- category: HostGroup apiurl: '/api/v1/hostgroup/template' title: "Unbind A Template of A HostGroup" type: 'PUT' sample_doc: 'hostgroup.html' layout: default --- * [Session](#/authentication) Required ### Request ```{ "tpl_id": 5, "grp_id": 3 }``` ### Response ```Status: 200``` ```{"message":"template: 5 is unbind of HostGroup: 3"}``` ================================================ FILE: docs/_posts/HostGroup/2017-01-01-hostgroup_unbind_host.md ================================================ --- category: HostGroup apiurl: '/api/v1/hostgroup/host' title: "Unbind a Host on HostGroup" type: 'PUT' sample_doc: 'hostgroup.html' layout: default --- * [Session](#/authentication) Required * 如果使用者不是 Admin 只能对创建的hostgroup做操作 ### Request ```{ "hostgroup_id": 343, "host_id": 9312 }``` ### Response ```Status: 200``` ```{"message":"unbind host:9312 of hostgroup: 343"}``` ================================================ FILE: docs/_posts/HostGroup/2017-01-01-hostgroup_update.md ================================================ --- category: HostGroup apiurl: '/api/v1/hostgroup/update/#{hostgroup_id}' title: "Update HostGroup info by id" type: 'PUT' sample_doc: 'hostgroup.html' layout: default --- * [Session](#/authentication) Required * ex. /api/v1/hostgroup ### Request ```{ "id" : 343, "grp_name": "test1" }``` ### Response ```Status: 200``` ```{ "message":"hostgroup profile updated" }``` ================================================ FILE: docs/_posts/HostGroup/2017-08-22-hostgroup_update_partial_hosts.md ================================================ --- category: HostGroup apiurl: '/api/v1/hostgroup/#{hostgroup_id}/host' title: "Update partial hosts in HostGroup" type: 'PATCH' sample_doc: 'hostgroup.html' layout: default --- * [Session](#/authentication) Required * 如果使用者不是 Admin 只能对创建的 HostGroup 做操作 * ex. /api/v1/hostgroup/1/host ### Request ```{ "hosts": [ "host01", "host02" ], "action": "add" }``` ### Response ```Status: 200``` ```{ "message": "[host01, host02] bind to hostgroup: test, [] have been exist" }``` ### Request ```{ "hosts": [ "host01", "host02" ], "action": "remove" }``` ### Response ```Status: 200``` ```{ "message": "[host01, host02] unbind to hostgroup: test" }``` ================================================ FILE: docs/_posts/NoData/2017-01-01-nodata_create.md ================================================ --- category: NoData apiurl: '/api/v1/nodata/' title: "Create Nodata" type: 'POST' sample_doc: 'nodata.html' layout: default --- * [Session](#/authentication) Required ### Request ```{ "tags": "", "step": 60, "obj_type": "host", "obj": "docker-agent", "name": "testnodata", "mock": -1, "metric": "test.metric", "dstype": "GAUGE" }``` ### Response ```Status: 200``` ```{ "id": 4, "name": "testnodata", "obj": "docker-agent", "obj_type": "host", "metric": "test.metric", "tags": "", "dstype": "GAUGE", "step": 60, "mock": -1, "creator": "root" }``` ================================================ FILE: docs/_posts/NoData/2017-01-01-nodata_delete.md ================================================ --- category: NoData apiurl: '/api/v1/nodata/#{nodata_id}' title: "Delete Nodata" type: 'DELETE' sample_doc: 'nodata.html' layout: default --- * [Session](#/authentication) Required * ex. /api/v1/nodata/4 ### Response ```Status: 200``` ```{"message":"mockcfg:4 is deleted"}``` ================================================ FILE: docs/_posts/NoData/2017-01-01-nodata_info_by_id.md ================================================ --- category: NoData apiurl: '/api/v1/nodata/#{nodata_id}' title: "Get Nodata Info by id" type: 'GET' sample_doc: 'nodata.html' layout: default --- * [Session](#/authentication) Required * ex. /api/v1/nodata/2 ### Response ```Status: 200``` ```{ "id": 2, "name": "owl_nodate", "obj": "docker-agent", "obj_type": "host", "metric": "test.metric", "tags": "", "dstype": "GAUGE", "step": 60, "mock": -2, "creator": "root" }``` ================================================ FILE: docs/_posts/NoData/2017-01-01-nodata_list.md ================================================ --- category: NoData apiurl: '/api/v1/nodata' title: "Nodata List" type: 'GET' sample_doc: 'nodata.html' layout: default --- * [Session](#/authentication) Required ### Response ```Status: 200``` ```[ { "id": 2, "name": "owl_nodate", "obj": "docker-agent", "obj_type": "host", "metric": "test.metric", "tags": "", "dstype": "GAUGE", "step": 60, "mock": -2, "creator": "root" } ]``` ================================================ FILE: docs/_posts/NoData/2017-01-01-nodata_update.md ================================================ --- category: NoData apiurl: '/api/v1/nodata/' title: "Update Nodata" type: 'PUT' sample_doc: 'nodata.html' layout: default --- * [Session](#/authentication) Required ### Request ```{ "tags": "", "step": 60, "obj_type": "host", "obj": "docker-agent", "mock": -2, "metric": "test.metric", "id": 4, "dstype": "GAUGE" }``` ### Response ```Status: 200``` ```{ "id": 0, "name": "", "obj": "docker-agent", "obj_type": "host", "metric": "test.metric", "tags": "", "dstype": "GAUGE", "step": 60, "mock": -2, "creator": "" }``` ================================================ FILE: docs/_posts/Plugin/2017-01-01-plugin_create.md ================================================ --- category: Plugin apiurl: '/api/v1/plugin' title: "Create A Plugin of HostGroup" type: 'POST' sample_doc: 'plugin.html' layout: default --- * [Session](#/authentication) Required * grp_id: hostgroup id ### Request ```{ "hostgroup_id": 343, "dir_path": "testpath" }``` ### Response ```Status: 200``` ```{ "id": 1501, "grp_id": 343, "dir": "testpath", "create_user": "root" }``` ================================================ FILE: docs/_posts/Plugin/2017-01-01-plugin_delete.md ================================================ --- category: Plugin apiurl: '/api/v1/plugin/#{plugin_id}' title: "Delete Plugin" type: 'DELETE' sample_doc: 'plugin.html' layout: default --- * [Session](#/authentication) Required * ex. /api/v1/plugin/1501 ### Response ```Status: 200``` ```{"message":"plugin:1501 is deleted"}``` ================================================ FILE: docs/_posts/Plugin/2017-01-01-plugin_info_by_id.md ================================================ --- category: Plugin apiurl: '/api/v1/hostgroup/#{hostgroup_id}/plugins' title: "Get Plugin List of HostGroup" type: 'GET' sample_doc: 'plugin.html' layout: default --- * [Session](#/authentication) Required * ex. /api/v1/hostgroup/343/plugins * grp_id: hostgroup id ### Response ```Status: 200``` ```[ { "id": 1499, "grp_id": 343, "dir": "testpath", "create_user": "root" }, { "id": 1501, "grp_id": 343, "dir": "testpath", "create_user": "root" } ]``` ================================================ FILE: docs/_posts/Strategy/2017-01-01-metric_tmplist.md ================================================ --- category: Metric apiurl: '/api/v1/metric/default_list' title: "Get Default Builtin Metric List" type: 'GET' sample_doc: 'template.html' layout: default --- * [Session](#/authentication) Required * Metric Suggestion for create strategy * base on `./data/metric` file ### Response ```Status: 200``` ```[ "cpu.busy", "cpu.cnt", "cpu.guest", "cpu.idle", "cpu.iowait", "cpu.irq", "cpu.nice", "cpu.softirq", "cpu.steal", "cpu.system", "cpu.user", "df.bytes.free", "df.bytes.free.percent" .... ]``` ================================================ FILE: docs/_posts/Strategy/2017-01-01-strategy_create.md ================================================ --- category: Strategy apiurl: '/api/v1/strategy' title: "Create Strategy" type: 'POST' sample_doc: 'template.html' layout: default --- * [Session](#/authentication) Required ### Request ```{ "tpl_id": 221, "tags": "", "run_end": "24:00", "run_begin": "00:00", "right_value": "1", "priority": 1, "op": "==", "note": "this is a test", "metric": "agent.alive", "max_step": 3, "func": "all(#3)" }``` ### Response ```Status: 200``` ``` { "id": 2, "tpl_id": 221, "tags": "", "run_end": "24:00", "run_begin": "00:00", "right_value": "1", "priority": 1, "op": "==", "note": "this is a test", "metric": "agent.alive", "max_step": 3, "func": "all(#3)" } ``` ================================================ FILE: docs/_posts/Strategy/2017-01-01-strategy_delete.md ================================================ --- category: Strategy apiurl: '/api/v1/strategy/#{strategy_id}' title: "Delete Strategy" type: 'DELETE' sample_doc: 'template.html' layout: default --- * [Session](#/authentication) Required * ex. /api/v1/strategy/904 ### Response ```Status: 200``` ```{"message":"strategy:904 has been deleted"}``` ================================================ FILE: docs/_posts/Strategy/2017-01-01-strategy_info_by_id.md ================================================ --- category: Strategy apiurl: '/api/v1/strategy/#{strategy_id}' title: "Get Strategy info by id" type: 'GET' sample_doc: 'template.html' layout: default --- * [Session](#/authentication) Required * ex. /api/v1/strategy/904 ### Response ```Status: 200``` ```{ "id": 904, "metric": "agent.alive", "tags": "", "max_step": 3, "priority": 1, "func": "all(#3)", "op": "==", "right_value": "1", "note": "this is a test", "run_begin": "00:00", "run_end": "24:00", "tpl_id": 221 }``` ================================================ FILE: docs/_posts/Strategy/2017-01-01-strategy_list.md ================================================ --- category: Strategy apiurl: '/api/v1/strategy' title: "Get Strategy List" type: 'GET' sample_doc: 'template.html' layout: default --- * [Session](#/authentication) Required ### Response ```Status: 200``` ```[ { "id": 893, "metric": "process.num", "tags": "name=redis", "max_step": 3, "priority": 2, "func": "all(#2)", "op": "<", "right_value": "1", "note": "Redis异常", "run_begin": "", "run_end": "", "tpl_id": 221 }, { "id": 894, "metric": "process.num", "tags": "name=smtp", "max_step": 3, "priority": 2, "func": "all(#3)", "op": "<", "right_value": "1", "note": "Smtp异常", "run_begin": "", "run_end": "", "tpl_id": 221 }, { "id": 895, "metric": "process.num", "tags": "cmdline=logger", "max_step": 3, "priority": 3, "func": "all(#5)", "op": "<", "right_value": "2", "note": "logger异常", "run_begin": "", "run_end": "", "tpl_id": 221 }, ]``` ================================================ FILE: docs/_posts/Strategy/2017-01-01-strategy_update.md ================================================ --- category: Strategy apiurl: '/api/v1/strategy' title: "Update Strategy" type: 'PUT' sample_doc: 'template.html' layout: default --- * [Session](#/authentication) Required ### Request ```{ "tags": "", "run_end": "", "run_begin": "", "right_value": "1", "priority": 2, "op": "==", "note": "this is a test", "metric": "agent.alive", "max_step": 3, "id": 904, "func": "all(#3)" }``` ### Response ```Status: 200``` ```{"message":"stragtegy:904 has been updated"}``` ================================================ FILE: docs/_posts/Team/2017-01-01-team_create.md ================================================ --- category: Team apiurl: '/api/v1/team' title: "Team Create" type: 'POST' sample_doc: 'team.html' layout: default --- 新增使用者群組 * [Session](#/authentication) Required * users: 属於该群组的user id list * resume: team的描述 ### Request ```{"team_name": "ateamname","resume": "i'm descript", "users": [1]}``` ### Response ```Status: 200``` ```{"message":"team created! Afftect row: 1, Affect refer: 1"}``` ================================================ FILE: docs/_posts/Team/2017-01-01-team_delete_by_id.md ================================================ --- category: Team apiurl: '/api/v1/team/#{team_id}' title: "Delete Team By Id" type: 'DELETE' sample_doc: 'team.html' layout: default --- 新增使用者群組 * [Session](#/authentication) Required * ex. /api/v1/team/107 * 除Admin外, 使用者只能更新自己创建的team ### Response ```Status: 200``` ```{"message":"team 107 is deleted. Affect row: 1 / refer delete: 4"}``` ================================================ FILE: docs/_posts/Team/2017-01-01-team_info_by_id.md ================================================ --- category: Team apiurl: '/api/v1/team/t/#{team_id}' title: "Get Team Info By Id" type: 'GET' sample_doc: 'team.html' layout: default --- * [Session](#/authentication) Required * ex. /api/v1/team/t/107 ### Response ```Status: 200``` ```{ "id": 107, "name": "ateamname", "resume": "i'm descript", "creator": 1, "users": [ { "id": 4, "name": "test1", "cnname": "翱鶚Test", "email": "root123@cepave.com", "phone": "99999999999", "im": "44955834958", "qq": "904394234239", "role": 0 }, { "id": 7, "name": "cepave1", "cnname": "", "email": "", "phone": "", "im": "", "qq": "904394234239", "role": 0 } ] }``` ================================================ FILE: docs/_posts/Team/2017-01-01-team_info_by_name.md ================================================ --- category: Team apiurl: '/api/v1/team/name/#{team_name}' title: "Get Team Info by name" type: 'GET' sample_doc: 'team.html' layout: default --- * [Session](#/authentication) Required * ex. /api/v1/team/name/plus-dev ### Response ```Status: 200``` ``` { "creator": 6, "creator_name": "", "id": 10, "name": "plus-dev", "resume": "test intro", "users": [ { "cnname": "laiwei", "email": "laiwei@xxx.com", "id": 1, "im": "yyyyx", "name": "laiwei1", "phone": "15011518472", "qq": "3805112124444455", "role": 2 } ] }``` ================================================ FILE: docs/_posts/Team/2017-01-01-team_list.md ================================================ --- category: Team apiurl: '/api/v1/team' title: "Team List" type: 'GET' sample_doc: 'team.html' layout: default --- * [Session](#/authentication) Required * q: 使用 regex 查询字符, 查询team name * option 参数 ### Request ```q=a.+``` ### Response ```Status: 200``` ```[ { "id": 1, "name": "a", "resume": "", "creator": 1 }, { "id": 5, "name": "atestteam", "resume": "i'm test", "creator": 16 }, { "id": 107, "name": "ateamname", "resume": "i'm descript", "creator": 1 } ]``` ================================================ FILE: docs/_posts/Team/2017-01-01-team_update.md ================================================ --- category: Team apiurl: '/api/v1/team' title: "Team Update" type: 'PUT' sample_doc: 'team.html' layout: default --- 更新使用者群組 * [Session](#/authentication) Required * users: 属於该群组的user id list * resume: team的描述 * name: team的名字 * 除Admin外, 使用者只能更新自己创建的team ### Request ```{ "team_id": 107, "name": "new_name", "resume": "i'm descript update", "users": [4,5,6,7] }``` ### Response ```Status: 200``` ```{"message":"team updated!"}``` ================================================ FILE: docs/_posts/Team/2018-11-19-add-user-to-team.md ================================================ --- category: Team apiurl: '/api/v1/team/user' title: "Add users to team" type: 'POST' sample_doc: '' layout: default --- 添加用户到某个组 * [Session](#/authentication) Required * users: 待添加到 team 中的用户名列表 * team_id: 目标 team 的 team_id ### Request ```{ "team_id": 107, "users": ["root", "test1"] }``` ### Response ```Status: 200``` ```{"message":"add successful"}``` ================================================ FILE: docs/_posts/Template/2017-01-01-tpl_action_create.md ================================================ --- category: Template apiurl: '/api/v1/template/action' title: "Create Template Action" type: 'POST' sample_doc: 'template.html' layout: default --- Create Action to a Template * [Session](#/authentication) Required * params: * url: callback url * uic: 需要通知的使用者群组(name) * callback: enable/disable ### Request ```{ "url": "", "uic": "test,tt2", "tpl_id": 225, "callback": 1, "before_callback_sms": 0, "before_callback_mail": 0, "after_callback_sms": 0, "after_callback_mail": 0 }``` ### Response ```Status: 200``` ```{"message":"template created"}``` ================================================ FILE: docs/_posts/Template/2017-01-01-tpl_action_update.md ================================================ --- category: Template apiurl: '/api/v1/template/action' title: "Update Template Action" type: 'PUT' sample_doc: 'template.html' layout: default --- Update Action * [Session](#/authentication) Required * params: * url: callback url * uic: 需要通知的使用者群组(name) * callback: enable/disable ### Request ```{ "url": "", "uic": "test,tt2,tt3", "id": 175, "callback": 1, "before_callback_sms": 0, "before_callback_mail": 0, "after_callback_sms": 0, "after_callback_mail": 0 }``` ### Response ```Status: 200``` ```{"message":"action is updated, row affected: 1"}``` ================================================ FILE: docs/_posts/Template/2017-01-01-tpl_create.md ================================================ --- category: Template apiurl: '/api/v1/template' title: "Create Template" type: 'POST' sample_doc: 'template.html' layout: default --- * [Session](#/authentication) Required * parent_id: 继承现有Template ### Request ```{"parent_id":0,"name":"AtmpForTesting"}``` ### Response ```Status: 200``` ```{ "id": 2, "parent_id": 0, "tpl_name": "AtmpForTesting", "action_id": 0, "create_user": "root" }``` ================================================ FILE: docs/_posts/Template/2017-01-01-tpl_delete.md ================================================ --- category: Template apiurl: '/api/v1/template/#{template_id}' title: "Delete Template" type: 'DELETE' sample_doc: 'template.html' layout: default --- Delete a Template * [Session](#/authentication) Required * ex. /api/v1/template/225 ### Response ```Status: 200``` ```{"message":"template 225 has been deleted"}``` ================================================ FILE: docs/_posts/Template/2017-01-01-tpl_hgp_list.md ================================================ --- category: Template apiurl: '/api/v1/template/#{template_id}/hostgroup' title: "Get hostgroups list by id" type: 'GET' sample_doc: 'template.html' layout: default --- * [Session](#/authentication) Required * ex. /api/v1/template/178/hostgroup ### Response ```Status: 200``` ```{ "hostgroups": [{ "id":33, "grp_name":"HostGroup", "create_user":"root" } ], "template": { "id": 178, "tpl_name": "TemplateA", "parent_id": 0, "action_id": 141, "create_user": "root" } }``` ================================================ FILE: docs/_posts/Template/2017-01-01-tpl_info_by_id.md ================================================ --- category: Template apiurl: '/api/v1/template/#{template_id}' title: "Get Template Info by id" type: 'GET' sample_doc: 'template.html' layout: default --- * [Session](#/authentication) Required * ex. /api/v1/template/178 ### Response ```Status: 200``` ```{ "action": { "id": 141, "uic": "admin,mm1", "url": "", "callback": 0, "before_callback_sms": 0, "before_callback_mail": 0, "after_callback_sms": 0, "after_callback_mail": 0 }, "stratges": [ { "id": 686, "metric": "xxx.check", "tags": "name=xxx", "max_step": 3, "priority": 2, "func": "all(#2)", "op": "<", "right_value": "1", "note": "xxx服务异常", "run_begin": "", "run_end": "", "tpl_id": 178 }, { "id": 687, "metric": "xxx.sync", "tags": "", "max_step": 3, "priority": 2, "func": "all(#3)", "op": "!=", "right_value": "0", "note": "XXX同步异常", "run_begin": "", "run_end": "", "tpl_id": 178 }, { "id": 688, "metric": "bbb.check.mq", "tags": "", "max_step": 3, "priority": 2, "func": "all(#3)", "op": "==", "right_value": "1", "note": "bbb连接MQ异常", "run_begin": "", "run_end": "", "tpl_id": 178 }, { "id": 793, "metric": "aaa.proc.num", "tags": "", "max_step": 3, "priority": 2, "func": "all(#3)", "op": "==", "right_value": "1", "note": "aaaa 进程大于5", "run_begin": "", "run_end": "", "tpl_id": 178 } ], "template": { "id": 178, "tpl_name": "TemplateA", "parent_id": 0, "action_id": 141, "create_user": "root" } }``` ================================================ FILE: docs/_posts/Template/2017-01-01-tpl_list.md ================================================ --- category: Template apiurl: '/api/v1/template' title: "Template List" type: 'GET' sample_doc: 'template.html' layout: default --- Template List * [Session](#/authentication) Required ### Response ```Status: 200``` ```[ { "id": 1, "tpl_name": "cpu.board", "parent_id": 0, "action_id": 5, "create_user": "usera" }, { "id": 2, "tpl_name": "traffic checking", "parent_id": 0, "action_id": 6, "create_user": "userb" }, { "id": 3, "tpl_name": "cputest", "parent_id": 0, "action_id": 7, "create_user": "userc" }, { "id": 5, "tpl_name": "all metrics base", "parent_id": 0, "action_id": 12, "create_user": "root" } ]``` ================================================ FILE: docs/_posts/Template/2017-01-01-tpl_update.md ================================================ --- category: Template apiurl: '/api/v1/template/' title: "Update Template" type: 'PUT' sample_doc: 'template.html' layout: default --- * [Session](#/authentication) Required * parent_id: 继承现有Template ### Request ```{ "tpl_id": 225, "parent_id": 0, "name": "AtmpForTesting2" }``` ### Response ```Status: 200``` ```{"message":"template updated"}``` ================================================ FILE: docs/_posts/User/2017-01-01-user_change_password.md ================================================ --- category: User apiurl: '/api/v1/user/cgpasswd' title: 'Change Password' type: 'PUT' sample_doc: 'user.html' layout: default --- * [Session](#/authentication) Required ### Request ```{ "new_password": "test1", "old_password": "test1" }``` ### Response ```Status: 200``` ```{"message":"password updated!"}``` ================================================ FILE: docs/_posts/User/2017-01-01-user_create.md ================================================ --- category: User apiurl: '/api/v1/user/create' title: 'Create User' type: 'POST' sample_doc: 'user.html' layout: default --- * [Session](#/authentication) Required ### Request ```{"name": "test","password": "test", "email":"xxx@xxx.com", "cnname": "翱鹗"}``` ### Response ```Status: 200``` ```{ "name": "owltester", "password": "mypassword", "cnname": "翱鹗", "email": "root123@cepave.com", "im": "44955834958", "phone": "99999999999", "qq": "904394234239" }``` For more example, see the [user](/doc/user.html). For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/User/2017-01-01-user_current.md ================================================ --- category: User apiurl: '/api/v1/user/current' title: 'Current User info' type: 'GET' sample_doc: 'user.html' layout: default --- * [Session](#/authentication) Required * 当前使用者资讯 ### Response ```Status: 200``` ```{ "id": 2, "name": "root", "cnname": "", "email": "", "phone": "", "im": "", "qq": "", "role": 2 }``` For more example, see the [user](/doc/user.html). For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/User/2017-01-01-user_get_info_by_id.md ================================================ --- category: User apiurl: '/api/v1/user/u/#{user_id}' title: 'Get User info by id' type: 'GET' sample_doc: 'user.html' layout: default --- * [Session](#/authentication) Required * `Admin` usage * ex. /api/v1/user/u/4 ### Response ```Status: 200``` ```{ "id": 4, "name": "userA", "cnname": "tear", "email": "", "phone": "", "im": "", "qq": "", "role": 0 }``` For more example, see the [user](/doc/user.html). For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/User/2017-01-01-user_get_info_by_name.md ================================================ --- category: User apiurl: '/api/v1/user/name/#{user_name}' title: 'Get User info by name' type: 'GET' sample_doc: 'user.html' layout: default --- * [Session](#/authentication) Required * `Admin` usage * ex. /api/v1/user/name/laiwei ### Response ```Status: 200``` ``` { "cnname": "laiwei8", "email": "laiwei8@xx", "id": 8, "im": "", "name": "laiwei8", "phone": "", "qq": "", "role": 0 }``` For more example, see the [user](/doc/user.html). For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/User/2017-01-01-user_get_teams.md ================================================ --- category: User apiurl: '/api/v1/user/u/:uid/teams' title: 'Get user teams' type: 'GET' sample_doc: 'user.html' layout: default --- * [Session](#/authentication) Required * ex. /api/v1/user/u/4/teams ### Response ```Status: 200``` ```{"teams": [{ "id":3, "name":"root", "resume":"", "creator":5}, {"id":32, "name":"testteam", "resume":"test22", "creator":5 }] } ``` For more example, see the [user](/doc/user.html). For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/User/2017-01-01-user_is_in_teams.md ================================================ --- category: User apiurl: '/api/v1/user/u/:uid/in_teams' title: 'Check user in teams or not' type: 'GET' sample_doc: 'user.html' layout: default --- * [Session](#/authentication) Required * ex. /api/v1/user/u/4/in_teams?team_names=team1,team4 ### Request Content-type: application/x-www-form-urlencoded ```team_names=team1,team2``` ### Response ```Status: 200``` ```{"message":"true"} ``` For more example, see the [user](/doc/user.html). For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/User/2017-01-01-user_list.md ================================================ --- category: User apiurl: '/api/v1/user/users' title: 'User List' type: 'GET' sample_doc: 'user.html' layout: default --- * [Session](#/authentication) Required ### Response ```Status: 200``` ```[ { "id": 1, "name": "root", "cnname": "", "email": "", "phone": "", "im": "", "qq": "904394234239", "role": 2 }, { "id": 32, "name": "owltester", "cnname": "翱鶚", "email": "root123@cepave.com", "phone": "99999999999", "im": "44955834958", "qq": "904394234239", "role": 0 } ]``` For more example, see the [user](/doc/user.html). For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/User/2017-01-01-user_login.md ================================================ --- category: User apiurl: '/api/v1/user/login' title: 'Login' type: 'POST' sample_doc: 'user.html' layout: default --- 使用者登入 ### Request ```{ "name": "test2", "password": "test2" }``` ### Response ```Status: 200``` ```{ "sig": "9d791331c0ea11e690c5001500c6ca5a", "name": "test2", "admin": false }``` For more example, see the [user](/doc/user.html). For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/User/2017-01-01-user_logout.md ================================================ --- category: User apiurl: '/api/v1/user/logout' title: 'Logout' type: 'GET' sample_doc: 'user.html' layout: default --- 使用者登出 * [Session](#/authentication) Required ### Response Sends back a collection of things. ```Status: 200``` ```{"message":"logout successful"}``` For more example, see the [user](/doc/user.html). For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/User/2017-01-01-user_update.md ================================================ --- category: User apiurl: '/api/v1/user/update' title: 'Update User' type: 'PUT' sample_doc: 'user.html' layout: default --- 更新使用者 * [Session](#/authentication) Required ### Request ```{ "cnname": "翱鶚Test", "email": "root123@cepave.com", "im": "44955834958", "phone": "99999999999", "qq": "904394234239" }``` ### Response ```Status: 200``` ```{"message":"user info updated"}``` For more example, see the [user](/doc/user.html). For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/_posts/User/2019-04-14-update-specific-user.md ================================================ --- category: User apiurl: '/api/v1/user/u/:uid' title: 'Update Specific User' type: 'PUT' sample_doc: 'user.html' layout: default --- 更新使用者 * [Session](#/authentication) Required ### Request ```{ "cnname": "翱鶚Test", "email": "root123@cepave.com", "im": "44955834958", "phone": "99999999999", "qq": "904394234239" }``` ### Response ```Status: 200``` ```{"message":"user info updated"}``` For more example, see the [user](/doc/user.html). For errors responses, see the [response status codes documentation](#/response-status-codes). ================================================ FILE: docs/assets.css ================================================ /*! normalize.css v2.1.0 | MIT License | git.io/normalize */ /* ========================================================================== HTML5 display definitions ========================================================================== */ /** * Correct `block` display not defined in IE 8/9. */ article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary { display: block; } /** * Correct `inline-block` display not defined in IE 8/9. */ audio, canvas, video { display: inline-block; } /** * Prevent modern browsers from displaying `audio` without controls. * Remove excess height in iOS 5 devices. */ audio:not([controls]) { display: none; height: 0; } /** * Address styling not present in IE 8/9. */ [hidden] { display: none; } /* ========================================================================== Base ========================================================================== */ /** * 1. Set default font family to sans-serif. * 2. Prevent iOS text size adjust after orientation change, without disabling * user zoom. */ html { font-family: sans-serif; /* 1 */ -webkit-text-size-adjust: 100%; /* 2 */ -ms-text-size-adjust: 100%; /* 2 */ } /** * Remove default margin. */ body { margin: 0; } /* ========================================================================== Links ========================================================================== */ /** * Address `outline` inconsistency between Chrome and other browsers. */ a:focus { outline: thin dotted; } /** * Improve readability when focused and also mouse hovered in all browsers. */ a:active, a:hover { outline: 0; } /* ========================================================================== Typography ========================================================================== */ /** * Address variable `h1` font-size and margin within `section` and `article` * contexts in Firefox 4+, Safari 5, and Chrome. */ h1 { font-size: 2em; margin: 0.67em 0; } /** * Address styling not present in IE 8/9, Safari 5, and Chrome. */ abbr[title] { border-bottom: 1px dotted; } /** * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. */ b, strong { font-weight: bold; } /** * Address styling not present in Safari 5 and Chrome. */ dfn { font-style: italic; } /** * Address differences between Firefox and other browsers. */ hr { -moz-box-sizing: content-box; box-sizing: content-box; height: 0; } /** * Address styling not present in IE 8/9. */ mark { background: #ff0; color: #000; } /** * Correct font family set oddly in Safari 5 and Chrome. */ code, kbd, pre, samp { font-family: monospace, serif; font-size: 1em; } /** * Improve readability of pre-formatted text in all browsers. */ pre { white-space: pre-wrap; } /** * Set consistent quote types. */ q { quotes: "\201C" "\201D" "\2018" "\2019"; } /** * Address inconsistent and variable font size in all browsers. */ small { font-size: 80%; } /** * Prevent `sub` and `sup` affecting `line-height` in all browsers. */ sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sup { top: -0.5em; } sub { bottom: -0.25em; } /* ========================================================================== Embedded content ========================================================================== */ /** * Remove border when inside `a` element in IE 8/9. */ img { border: 0; } /** * Correct overflow displayed oddly in IE 9. */ svg:not(:root) { overflow: hidden; } /* ========================================================================== Figures ========================================================================== */ /** * Address margin not present in IE 8/9 and Safari 5. */ figure { margin: 0; } /* ========================================================================== Forms ========================================================================== */ /** * Define consistent border, margin, and padding. */ fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; } /** * 1. Correct `color` not being inherited in IE 8/9. * 2. Remove padding so people aren't caught out if they zero out fieldsets. */ legend { border: 0; /* 1 */ padding: 0; /* 2 */ } /** * 1. Correct font family not being inherited in all browsers. * 2. Correct font size not being inherited in all browsers. * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. */ button, input, select, textarea { font-family: inherit; /* 1 */ font-size: 100%; /* 2 */ margin: 0; /* 3 */ } /** * Address Firefox 4+ setting `line-height` on `input` using `!important` in * the UA stylesheet. */ button, input { line-height: normal; } /** * Address inconsistent `text-transform` inheritance for `button` and `select`. * All other form control elements do not inherit `text-transform` values. * Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. * Correct `select` style inheritance in Firefox 4+ and Opera. */ button, select { text-transform: none; } /** * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` * and `video` controls. * 2. Correct inability to style clickable `input` types in iOS. * 3. Improve usability and consistency of cursor style between image-type * `input` and others. */ button, html input[type="button"], /* 1 */ input[type="reset"], input[type="submit"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ } /** * Re-set default cursor for disabled elements. */ button[disabled], html input[disabled] { cursor: default; } /** * 1. Address box sizing set to `content-box` in IE 8/9. * 2. Remove excess padding in IE 8/9. */ input[type="checkbox"], input[type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ } /** * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome * (include `-moz` to future-proof). */ input[type="search"] { -webkit-appearance: textfield; /* 1 */ -moz-box-sizing: content-box; -webkit-box-sizing: content-box; /* 2 */ box-sizing: content-box; } /** * Remove inner padding and search cancel button in Safari 5 and Chrome * on OS X. */ input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; } /** * Remove inner padding and border in Firefox 4+. */ button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; } /** * 1. Remove default vertical scrollbar in IE 8/9. * 2. Improve readability and alignment in all browsers. */ textarea { overflow: auto; /* 1 */ vertical-align: top; /* 2 */ } /* ========================================================================== Tables ========================================================================== */ /** * Remove most spacing between table cells. */ table { border-collapse: collapse; border-spacing: 0; } /* GENERAL */ html, body { height: 100%; } body { background: #fff; } body, input, textarea { color: #191919; font: 12px/120% 'Open Sans', Arial, sans-serif; } a { color: #119bdf; text-decoration: none; } a:hover { color: #29aeef; text-decoration: underline; } h1, h2, h3, h4, p, ul, code { margin: 0 0 20px; } code { font-family: 'Monaco', monospace, sans-serif; } /* SIDEBAR */ #sidebar { background: #191919; color: #fff; float: left; overflow: auto; max-width: 400px; /*margin-top: 54px;*/ height: 100%; } #sidebar h1 { background: #111; font-size: 14px; margin: 0; padding: 20px; text-transform: uppercase; } #sidebar h2 { color: #888; font-size: 12px; margin: 0; } #sidebar ul { list-style: none; margin: 0; padding: 0; } #sidebar ul#links { padding: 20px; } #sidebar ul ul { padding-left: 20px; } #sidebar ul li a { color: #fff; display: block; padding: 0 0 15px; } #sidebar ul li a:active, #sidebar ul li a.active { text-decoration: underline; } #sidebar input { background: #111; border: 0; border-radius: 2px; -moz-border-radius: 2px; -webkit-border-radius: 2px; box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2); -moz-box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.2); -webkit-box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.2); color: #ddd; margin-bottom: 20px; padding: 5px 10px; } #sidebar input:active, #sidebar input:focus { border-color: #ccc; box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.1); -moz-box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); -webkit-box-shadow: inset 0 1px 5px rgba(0, 0, 0, 0.1); outline: none; } /* References */ #content { float:left; padding: 20px; max-width: 700px; overflow: auto; height: 100%; } #content .control { cursor: pointer; font-size: 12px; margin-left: 15px; } #content article { clear: both; margin: 15px 0; } #content article > a { background: #333; border-radius: 2px; -moz-border-radius: 2px; -webkit-border-radius: 2px; cursor: pointer; display: block; padding: 15px; } #content article > a:hover { background: #222; text-decoration: none; } #content a h2 { color: #fff; font-size: 14px; font-weight: normal; margin: 0; } #content a h2 code { float: right; font-size: 12px; } #content a h2 code b { border-radius: 2px; -moz-border-radius: 2px; -webkit-border-radius: 2px; color: #fff; font-weight: normal; padding: 3px 6px; } /* Default */ #content article { border-color: #e2e7ea; } #content article a h2 code { color: #657e8b; } #content article a h2 code b { background: #657e8b; text-transform: uppercase; } /* GET */ #content article.GET a h2 code { color: #119bdf; } #content article.GET a h2 code b { background: #119bdf; } /* POST */ #content article.POST a h2 code { color: #52ce0e; } #content article.POST a h2 code b { background: #52ce0e; } /* PUT */ #content article.PUT a h2 code { color: #e08f10; } #content article.PUT a h2 code b { background: #e08f10; } /* DELETE */ #content article.DELETE a h2 code { color: #e02a10; } #content article.DELETE a h2 code b { background: #e02a10; } /* Reference's body */ #content h3 { } #content .body { border-top: 1px solid #eef1f2; display: block; padding: 15px 15px 0; } #content .body code { border: 1px solid #e2e7ea; background: #eef1f2; border-radius: 2px; -moz-border-radius: 2px; -webkit-border-radius: 2px; color: #546974; padding: 0 1px; } #content .body p > code { display: block; padding: 15px; white-space: pre; } table{ border-collapse: collapse; border-spacing: 1; border:2px solid #ff0000; } th{ border:2px solid #000000; } td{ border:1px solid #000000; } ================================================ FILE: docs/assets.js ================================================ /** * hasOwnProperty. */ var has = Object.prototype.hasOwnProperty; /** * Require the given path. * * @param {String} path * @return {Object} exports * @api public */ function require(path, parent, orig) { var resolved = require.resolve(path); // lookup failed if (null == resolved) { orig = orig || path; parent = parent || 'root'; var err = new Error('Failed to require "' + orig + '" from "' + parent + '"'); err.path = orig; err.parent = parent; err.require = true; throw err; } var module = require.modules[resolved]; // perform real require() // by invoking the module's // registered function if (!module.exports) { module.exports = {}; module.client = module.component = true; module.call(this, module.exports, require.relative(resolved), module); } return module.exports; } /** * Registered modules. */ require.modules = {}; /** * Registered aliases. */ require.aliases = {}; /** * Resolve `path`. * * Lookup: * * - PATH/index.js * - PATH.js * - PATH * * @param {String} path * @return {String} path or null * @api private */ require.resolve = function(path) { var index = path + '/index.js'; var paths = [ path, path + '.js', path + '.json', path + '/index.js', path + '/index.json' ]; for (var i = 0; i < paths.length; i++) { var path = paths[i]; if (has.call(require.modules, path)) return path; } if (has.call(require.aliases, index)) { return require.aliases[index]; } }; /** * Normalize `path` relative to the current path. * * @param {String} curr * @param {String} path * @return {String} * @api private */ require.normalize = function(curr, path) { var segs = []; if ('.' != path.charAt(0)) return path; curr = curr.split('/'); path = path.split('/'); for (var i = 0; i < path.length; ++i) { if ('..' == path[i]) { curr.pop(); } else if ('.' != path[i] && '' != path[i]) { segs.push(path[i]); } } return curr.concat(segs).join('/'); }; /** * Register module at `path` with callback `definition`. * * @param {String} path * @param {Function} definition * @api private */ require.register = function(path, definition) { require.modules[path] = definition; }; /** * Alias a module definition. * * @param {String} from * @param {String} to * @api private */ require.alias = function(from, to) { if (!has.call(require.modules, from)) { throw new Error('Failed to alias "' + from + '", it does not exist'); } require.aliases[to] = from; }; /** * Return a require function relative to the `parent` path. * * @param {String} parent * @return {Function} * @api private */ require.relative = function(parent) { var p = require.normalize(parent, '..'); /** * lastIndexOf helper. */ function lastIndexOf(arr, obj) { var i = arr.length; while (i--) { if (arr[i] === obj) return i; } return -1; } /** * The relative require() itself. */ function localRequire(path) { var resolved = localRequire.resolve(path); return require(resolved, parent, path); } /** * Resolve relative to the parent. */ localRequire.resolve = function(path) { // resolve deps by returning // the dep in the nearest "deps" // directory if ('.' != path.charAt(0)) { var segs = parent.split('/'); var i = lastIndexOf(segs, 'deps') + 1; if (!i) i = 0; path = segs.slice(0, i + 1).join('/') + '/deps/' + path; return path; } return require.normalize(p, path); }; /** * Check if module is defined at `path`. */ localRequire.exists = function(path) { return has.call(require.modules, localRequire.resolve(path)); }; return localRequire; }; require.register("component-jquery/index.js", function(exports, require, module){ /*! * jQuery JavaScript Library v1.7.3pre * http://jquery.com/ * * Copyright 2011, John Resig * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * Includes Sizzle.js * http://sizzlejs.com/ * Copyright 2011, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * * Date: Thu May 3 11:06:50 2012 -0700 */ (function( window, undefined ) { // Use the correct document accordingly with window argument (sandbox) var document = window.document, navigator = window.navigator, location = window.location; var jQuery = (function() { // Define a local copy of jQuery var jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' return new jQuery.fn.init( selector, context, rootjQuery ); }, // Map over jQuery in case of overwrite _jQuery = window.jQuery, // Map over the $ in case of overwrite _$ = window.$, // A central reference to the root jQuery(document) rootjQuery, // A simple way to check for HTML strings or ID strings // Prioritize #id over to avoid XSS via location.hash (#9521) quickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, // Check if a string has a non-whitespace character in it rnotwhite = /\S/, // Used for trimming whitespace trimLeft = /^\s+/, trimRight = /\s+$/, // Match a standalone tag rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/, // JSON RegExp rvalidchars = /^[\],:{}\s]*$/, rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, // Useragent RegExp rwebkit = /(webkit)[ \/]([\w.]+)/, ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/, rmsie = /(msie) ([\w.]+)/, rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/, // Matches dashed string for camelizing rdashAlpha = /-([a-z]|[0-9])/ig, rmsPrefix = /^-ms-/, // Used by jQuery.camelCase as callback to replace() fcamelCase = function( all, letter ) { return ( letter + "" ).toUpperCase(); }, // Keep a UserAgent string for use with jQuery.browser userAgent = navigator.userAgent, // For matching the engine and version of the browser browserMatch, // The deferred used on DOM ready readyList, // The ready event handler DOMContentLoaded, // Save a reference to some core methods toString = Object.prototype.toString, hasOwn = Object.prototype.hasOwnProperty, push = Array.prototype.push, slice = Array.prototype.slice, trim = String.prototype.trim, indexOf = Array.prototype.indexOf, // [[Class]] -> type pairs class2type = {}; jQuery.fn = jQuery.prototype = { constructor: jQuery, init: function( selector, context, rootjQuery ) { var match, elem, ret, doc; // Handle $(""), $(null), or $(undefined) if ( !selector ) { return this; } // Handle $(DOMElement) if ( selector.nodeType ) { this.context = this[0] = selector; this.length = 1; return this; } // The body element only exists once, optimize finding it if ( selector === "body" && !context && document.body ) { this.context = document; this[0] = document.body; this.selector = selector; this.length = 1; return this; } // Handle HTML strings if ( typeof selector === "string" ) { // Are we dealing with HTML string or an ID? if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { // Assume that strings that start and end with <> are HTML and skip the regex check match = [ null, selector, null ]; } else { match = quickExpr.exec( selector ); } // Verify a match, and that no context was specified for #id if ( match && (match[1] || !context) ) { // HANDLE: $(html) -> $(array) if ( match[1] ) { context = context instanceof jQuery ? context[0] : context; doc = ( context ? context.ownerDocument || context : document ); // If a single string is passed in and it's a single tag // just do a createElement and skip the rest ret = rsingleTag.exec( selector ); if ( ret ) { if ( jQuery.isPlainObject( context ) ) { selector = [ document.createElement( ret[1] ) ]; jQuery.fn.attr.call( selector, context, true ); } else { selector = [ doc.createElement( ret[1] ) ]; } } else { ret = jQuery.buildFragment( [ match[1] ], [ doc ] ); selector = ( ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment ).childNodes; } return jQuery.merge( this, selector ); // HANDLE: $("#id") } else { elem = document.getElementById( match[2] ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 if ( elem && elem.parentNode ) { // Handle the case where IE and Opera return items // by name instead of ID if ( elem.id !== match[2] ) { return rootjQuery.find( selector ); } // Otherwise, we inject the element directly into the jQuery object this.length = 1; this[0] = elem; } this.context = document; this.selector = selector; return this; } // HANDLE: $(expr, $(...)) } else if ( !context || context.jquery ) { return ( context || rootjQuery ).find( selector ); // HANDLE: $(expr, context) // (which is just equivalent to: $(context).find(expr) } else { return this.constructor( context ).find( selector ); } // HANDLE: $(function) // Shortcut for document ready } else if ( jQuery.isFunction( selector ) ) { return rootjQuery.ready( selector ); } if ( selector.selector !== undefined ) { this.selector = selector.selector; this.context = selector.context; } return jQuery.makeArray( selector, this ); }, // Start with an empty selector selector: "", // The current version of jQuery being used jquery: "1.7.3pre", // The default length of a jQuery object is 0 length: 0, // The number of elements contained in the matched element set size: function() { return this.length; }, toArray: function() { return slice.call( this, 0 ); }, // Get the Nth element in the matched element set OR // Get the whole matched element set as a clean array get: function( num ) { return num == null ? // Return a 'clean' array this.toArray() : // Return just the object ( num < 0 ? this[ this.length + num ] : this[ num ] ); }, // Take an array of elements and push it onto the stack // (returning the new matched element set) pushStack: function( elems, name, selector ) { // Build a new jQuery matched element set var ret = this.constructor(); if ( jQuery.isArray( elems ) ) { push.apply( ret, elems ); } else { jQuery.merge( ret, elems ); } // Add the old object onto the stack (as a reference) ret.prevObject = this; ret.context = this.context; if ( name === "find" ) { ret.selector = this.selector + ( this.selector ? " " : "" ) + selector; } else if ( name ) { ret.selector = this.selector + "." + name + "(" + selector + ")"; } // Return the newly-formed element set return ret; }, // Execute a callback for every element in the matched set. // (You can seed the arguments with an array of args, but this is // only used internally.) each: function( callback, args ) { return jQuery.each( this, callback, args ); }, ready: function( fn ) { // Attach the listeners jQuery.bindReady(); // Add the callback readyList.add( fn ); return this; }, eq: function( i ) { i = +i; return i === -1 ? this.slice( i ) : this.slice( i, i + 1 ); }, first: function() { return this.eq( 0 ); }, last: function() { return this.eq( -1 ); }, slice: function() { return this.pushStack( slice.apply( this, arguments ), "slice", slice.call(arguments).join(",") ); }, map: function( callback ) { return this.pushStack( jQuery.map(this, function( elem, i ) { return callback.call( elem, i, elem ); })); }, end: function() { return this.prevObject || this.constructor(null); }, // For internal use only. // Behaves like an Array's method, not like a jQuery method. push: push, sort: [].sort, splice: [].splice }; // Give the init function the jQuery prototype for later instantiation jQuery.fn.init.prototype = jQuery.fn; jQuery.extend = jQuery.fn.extend = function() { var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false; // Handle a deep copy situation if ( typeof target === "boolean" ) { deep = target; target = arguments[1] || {}; // skip the boolean and the target i = 2; } // Handle case when target is a string or something (possible in deep copy) if ( typeof target !== "object" && !jQuery.isFunction(target) ) { target = {}; } // extend jQuery itself if only one argument is passed if ( length === i ) { target = this; --i; } for ( ; i < length; i++ ) { // Only deal with non-null/undefined values if ( (options = arguments[ i ]) != null ) { // Extend the base object for ( name in options ) { src = target[ name ]; copy = options[ name ]; // Prevent never-ending loop if ( target === copy ) { continue; } // Recurse if we're merging plain objects or arrays if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { if ( copyIsArray ) { copyIsArray = false; clone = src && jQuery.isArray(src) ? src : []; } else { clone = src && jQuery.isPlainObject(src) ? src : {}; } // Never move original objects, clone them target[ name ] = jQuery.extend( deep, clone, copy ); // Don't bring in undefined values } else if ( copy !== undefined ) { target[ name ] = copy; } } } } // Return the modified object return target; }; jQuery.extend({ noConflict: function( deep ) { if ( window.$ === jQuery ) { window.$ = _$; } if ( deep && window.jQuery === jQuery ) { window.jQuery = _jQuery; } return jQuery; }, // Is the DOM ready to be used? Set to true once it occurs. isReady: false, // A counter to track how many items to wait for before // the ready event fires. See #6781 readyWait: 1, // Hold (or release) the ready event holdReady: function( hold ) { if ( hold ) { jQuery.readyWait++; } else { jQuery.ready( true ); } }, // Handle when the DOM is ready ready: function( wait ) { // Either a released hold or an DOMready/load event and not yet ready if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). if ( !document.body ) { return setTimeout( jQuery.ready, 1 ); } // Remember that the DOM is ready jQuery.isReady = true; // If a normal DOM Ready event fired, decrement, and wait if need be if ( wait !== true && --jQuery.readyWait > 0 ) { return; } // If there are functions bound, to execute readyList.fireWith( document, [ jQuery ] ); // Trigger any bound ready events if ( jQuery.fn.trigger ) { jQuery( document ).trigger( "ready" ).off( "ready" ); } } }, bindReady: function() { if ( readyList ) { return; } readyList = jQuery.Callbacks( "once memory" ); // Catch cases where $(document).ready() is called after the // browser event has already occurred. if ( document.readyState === "complete" ) { // Handle it asynchronously to allow scripts the opportunity to delay ready return setTimeout( jQuery.ready, 1 ); } // Mozilla, Opera and webkit nightlies currently support this event if ( document.addEventListener ) { // Use the handy event callback document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); // A fallback to window.onload, that will always work window.addEventListener( "load", jQuery.ready, false ); // If IE event model is used } else if ( document.attachEvent ) { // ensure firing before onload, // maybe late but safe also for iframes document.attachEvent( "onreadystatechange", DOMContentLoaded ); // A fallback to window.onload, that will always work window.attachEvent( "onload", jQuery.ready ); // If IE and not a frame // continually check to see if the document is ready var toplevel = false; try { toplevel = window.frameElement == null; } catch(e) {} if ( document.documentElement.doScroll && toplevel ) { doScrollCheck(); } } }, // See test/unit/core.js for details concerning isFunction. // Since version 1.3, DOM methods and functions like alert // aren't supported. They return false on IE (#2968). isFunction: function( obj ) { return jQuery.type(obj) === "function"; }, isArray: Array.isArray || function( obj ) { return jQuery.type(obj) === "array"; }, isWindow: function( obj ) { return obj != null && obj == obj.window; }, isNumeric: function( obj ) { return !isNaN( parseFloat(obj) ) && isFinite( obj ); }, type: function( obj ) { return obj == null ? String( obj ) : class2type[ toString.call(obj) ] || "object"; }, isPlainObject: function( obj ) { // Must be an Object. // Because of IE, we also have to check the presence of the constructor property. // Make sure that DOM nodes and window objects don't pass through, as well if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { return false; } try { // Not own constructor property must be Object if ( obj.constructor && !hasOwn.call(obj, "constructor") && !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { return false; } } catch ( e ) { // IE8,9 Will throw exceptions on certain host objects #9897 return false; } // Own properties are enumerated firstly, so to speed up, // if last one is own, then all properties are own. var key; for ( key in obj ) {} return key === undefined || hasOwn.call( obj, key ); }, isEmptyObject: function( obj ) { for ( var name in obj ) { return false; } return true; }, error: function( msg ) { throw new Error( msg ); }, parseJSON: function( data ) { if ( typeof data !== "string" || !data ) { return null; } // Make sure leading/trailing whitespace is removed (IE can't handle it) data = jQuery.trim( data ); // Attempt to parse using the native JSON parser first if ( window.JSON && window.JSON.parse ) { return window.JSON.parse( data ); } // Make sure the incoming data is actual JSON // Logic borrowed from http://json.org/json2.js if ( rvalidchars.test( data.replace( rvalidescape, "@" ) .replace( rvalidtokens, "]" ) .replace( rvalidbraces, "")) ) { return ( new Function( "return " + data ) )(); } jQuery.error( "Invalid JSON: " + data ); }, // Cross-browser xml parsing parseXML: function( data ) { if ( typeof data !== "string" || !data ) { return null; } var xml, tmp; try { if ( window.DOMParser ) { // Standard tmp = new DOMParser(); xml = tmp.parseFromString( data , "text/xml" ); } else { // IE xml = new ActiveXObject( "Microsoft.XMLDOM" ); xml.async = "false"; xml.loadXML( data ); } } catch( e ) { xml = undefined; } if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { jQuery.error( "Invalid XML: " + data ); } return xml; }, noop: function() {}, // Evaluates a script in a global context // Workarounds based on findings by Jim Driscoll // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context globalEval: function( data ) { if ( data && rnotwhite.test( data ) ) { // We use execScript on Internet Explorer // We use an anonymous function so that context is window // rather than jQuery in Firefox ( window.execScript || function( data ) { window[ "eval" ].call( window, data ); } )( data ); } }, // Convert dashed to camelCase; used by the css and data modules // Microsoft forgot to hump their vendor prefix (#9572) camelCase: function( string ) { return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); }, nodeName: function( elem, name ) { return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); }, // args is for internal usage only each: function( object, callback, args ) { var name, i = 0, length = object.length, isObj = length === undefined || jQuery.isFunction( object ); if ( args ) { if ( isObj ) { for ( name in object ) { if ( callback.apply( object[ name ], args ) === false ) { break; } } } else { for ( ; i < length; ) { if ( callback.apply( object[ i++ ], args ) === false ) { break; } } } // A special, fast, case for the most common use of each } else { if ( isObj ) { for ( name in object ) { if ( callback.call( object[ name ], name, object[ name ] ) === false ) { break; } } } else { for ( ; i < length; ) { if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { break; } } } } return object; }, // Use native String.trim function wherever possible trim: trim ? function( text ) { return text == null ? "" : trim.call( text ); } : // Otherwise use our own trimming functionality function( text ) { return text == null ? "" : text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); }, // results is for internal usage only makeArray: function( array, results ) { var ret = results || []; if ( array != null ) { // The window, strings (and functions) also have 'length' // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 var type = jQuery.type( array ); if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { push.call( ret, array ); } else { jQuery.merge( ret, array ); } } return ret; }, inArray: function( elem, array, i ) { var len; if ( array ) { if ( indexOf ) { return indexOf.call( array, elem, i ); } len = array.length; i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; for ( ; i < len; i++ ) { // Skip accessing in sparse arrays if ( i in array && array[ i ] === elem ) { return i; } } } return -1; }, merge: function( first, second ) { var i = first.length, j = 0; if ( typeof second.length === "number" ) { for ( var l = second.length; j < l; j++ ) { first[ i++ ] = second[ j ]; } } else { while ( second[j] !== undefined ) { first[ i++ ] = second[ j++ ]; } } first.length = i; return first; }, grep: function( elems, callback, inv ) { var ret = [], retVal; inv = !!inv; // Go through the array, only saving the items // that pass the validator function for ( var i = 0, length = elems.length; i < length; i++ ) { retVal = !!callback( elems[ i ], i ); if ( inv !== retVal ) { ret.push( elems[ i ] ); } } return ret; }, // arg is for internal usage only map: function( elems, callback, arg ) { var value, key, ret = [], i = 0, length = elems.length, // jquery objects are treated as arrays isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; // Go through the array, translating each of the items to their if ( isArray ) { for ( ; i < length; i++ ) { value = callback( elems[ i ], i, arg ); if ( value != null ) { ret[ ret.length ] = value; } } // Go through every key on the object, } else { for ( key in elems ) { value = callback( elems[ key ], key, arg ); if ( value != null ) { ret[ ret.length ] = value; } } } // Flatten any nested arrays return ret.concat.apply( [], ret ); }, // A global GUID counter for objects guid: 1, // Bind a function to a context, optionally partially applying any // arguments. proxy: function( fn, context ) { if ( typeof context === "string" ) { var tmp = fn[ context ]; context = fn; fn = tmp; } // Quick check to determine if target is callable, in the spec // this throws a TypeError, but we will just return undefined. if ( !jQuery.isFunction( fn ) ) { return undefined; } // Simulated bind var args = slice.call( arguments, 2 ), proxy = function() { return fn.apply( context, args.concat( slice.call( arguments ) ) ); }; // Set the guid of unique handler to the same of original handler, so it can be removed proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; return proxy; }, // Multifunctional method to get and set values of a collection // The value/s can optionally be executed if it's a function access: function( elems, fn, key, value, chainable, emptyGet, pass ) { var exec, bulk = key == null, i = 0, length = elems.length; // Sets many values if ( key && typeof key === "object" ) { for ( i in key ) { jQuery.access( elems, fn, i, key[i], 1, emptyGet, value ); } chainable = 1; // Sets one value } else if ( value !== undefined ) { // Optionally, function values get executed if exec is true exec = pass === undefined && jQuery.isFunction( value ); if ( bulk ) { // Bulk operations only iterate when executing function values if ( exec ) { exec = fn; fn = function( elem, key, value ) { return exec.call( jQuery( elem ), value ); }; // Otherwise they run against the entire set } else { fn.call( elems, value ); fn = null; } } if ( fn ) { for (; i < length; i++ ) { fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); } } chainable = 1; } return chainable ? elems : // Gets bulk ? fn.call( elems ) : length ? fn( elems[0], key ) : emptyGet; }, now: function() { return ( new Date() ).getTime(); }, // Use of jQuery.browser is frowned upon. // More details: http://docs.jquery.com/Utilities/jQuery.browser uaMatch: function( ua ) { ua = ua.toLowerCase(); var match = rwebkit.exec( ua ) || ropera.exec( ua ) || rmsie.exec( ua ) || ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || []; return { browser: match[1] || "", version: match[2] || "0" }; }, sub: function() { function jQuerySub( selector, context ) { return new jQuerySub.fn.init( selector, context ); } jQuery.extend( true, jQuerySub, this ); jQuerySub.superclass = this; jQuerySub.fn = jQuerySub.prototype = this(); jQuerySub.fn.constructor = jQuerySub; jQuerySub.sub = this.sub; jQuerySub.fn.init = function init( selector, context ) { if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { context = jQuerySub( context ); } return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); }; jQuerySub.fn.init.prototype = jQuerySub.fn; var rootjQuerySub = jQuerySub(document); return jQuerySub; }, browser: {} }); // Populate the class2type map jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { class2type[ "[object " + name + "]" ] = name.toLowerCase(); }); browserMatch = jQuery.uaMatch( userAgent ); if ( browserMatch.browser ) { jQuery.browser[ browserMatch.browser ] = true; jQuery.browser.version = browserMatch.version; } // Deprecated, use jQuery.browser.webkit instead if ( jQuery.browser.webkit ) { jQuery.browser.safari = true; } // IE doesn't match non-breaking spaces with \s if ( rnotwhite.test( "\xA0" ) ) { trimLeft = /^[\s\xA0]+/; trimRight = /[\s\xA0]+$/; } // All jQuery objects should point back to these rootjQuery = jQuery(document); // Cleanup functions for the document ready method if ( document.addEventListener ) { DOMContentLoaded = function() { document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); jQuery.ready(); }; } else if ( document.attachEvent ) { DOMContentLoaded = function() { // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). if ( document.readyState === "complete" ) { document.detachEvent( "onreadystatechange", DOMContentLoaded ); jQuery.ready(); } }; } // The DOM ready check for Internet Explorer function doScrollCheck() { if ( jQuery.isReady ) { return; } try { // If IE is used, use the trick by Diego Perini // http://javascript.nwbox.com/IEContentLoaded/ document.documentElement.doScroll("left"); } catch(e) { setTimeout( doScrollCheck, 1 ); return; } // and execute any waiting functions jQuery.ready(); } return jQuery; })(); // String to Object flags format cache var flagsCache = {}; // Convert String-formatted flags into Object-formatted ones and store in cache function createFlags( flags ) { var object = flagsCache[ flags ] = {}, i, length; flags = flags.split( /\s+/ ); for ( i = 0, length = flags.length; i < length; i++ ) { object[ flags[i] ] = true; } return object; } /* * Create a callback list using the following parameters: * * flags: an optional list of space-separated flags that will change how * the callback list behaves * * By default a callback list will act like an event callback list and can be * "fired" multiple times. * * Possible flags: * * once: will ensure the callback list can only be fired once (like a Deferred) * * memory: will keep track of previous values and will call any callback added * after the list has been fired right away with the latest "memorized" * values (like a Deferred) * * unique: will ensure a callback can only be added once (no duplicate in the list) * * stopOnFalse: interrupt callings when a callback returns false * */ jQuery.Callbacks = function( flags ) { // Convert flags from String-formatted to Object-formatted // (we check in cache first) flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {}; var // Actual callback list list = [], // Stack of fire calls for repeatable lists stack = [], // Last fire value (for non-forgettable lists) memory, // Flag to know if list was already fired fired, // Flag to know if list is currently firing firing, // First callback to fire (used internally by add and fireWith) firingStart, // End of the loop when firing firingLength, // Index of currently firing callback (modified by remove if needed) firingIndex, // Add one or several callbacks to the list add = function( args ) { var i, length, elem, type, actual; for ( i = 0, length = args.length; i < length; i++ ) { elem = args[ i ]; type = jQuery.type( elem ); if ( type === "array" ) { // Inspect recursively add( elem ); } else if ( type === "function" ) { // Add if not in unique mode and callback is not in if ( !flags.unique || !self.has( elem ) ) { list.push( elem ); } } } }, // Fire callbacks fire = function( context, args ) { args = args || []; memory = !flags.memory || [ context, args ]; fired = true; firing = true; firingIndex = firingStart || 0; firingStart = 0; firingLength = list.length; for ( ; list && firingIndex < firingLength; firingIndex++ ) { if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) { memory = true; // Mark as halted break; } } firing = false; if ( list ) { if ( !flags.once ) { if ( stack && stack.length ) { memory = stack.shift(); self.fireWith( memory[ 0 ], memory[ 1 ] ); } } else if ( memory === true ) { self.disable(); } else { list = []; } } }, // Actual Callbacks object self = { // Add a callback or a collection of callbacks to the list add: function() { if ( list ) { var length = list.length; add( arguments ); // Do we need to add the callbacks to the // current firing batch? if ( firing ) { firingLength = list.length; // With memory, if we're not firing then // we should call right away, unless previous // firing was halted (stopOnFalse) } else if ( memory && memory !== true ) { firingStart = length; fire( memory[ 0 ], memory[ 1 ] ); } } return this; }, // Remove a callback from the list remove: function() { if ( list ) { var args = arguments, argIndex = 0, argLength = args.length; for ( ; argIndex < argLength ; argIndex++ ) { for ( var i = 0; i < list.length; i++ ) { if ( args[ argIndex ] === list[ i ] ) { // Handle firingIndex and firingLength if ( firing ) { if ( i <= firingLength ) { firingLength--; if ( i <= firingIndex ) { firingIndex--; } } } // Remove the element list.splice( i--, 1 ); // If we have some unicity property then // we only need to do this once if ( flags.unique ) { break; } } } } } return this; }, // Control if a given callback is in the list has: function( fn ) { if ( list ) { var i = 0, length = list.length; for ( ; i < length; i++ ) { if ( fn === list[ i ] ) { return true; } } } return false; }, // Remove all callbacks from the list empty: function() { list = []; return this; }, // Have the list do nothing anymore disable: function() { list = stack = memory = undefined; return this; }, // Is it disabled? disabled: function() { return !list; }, // Lock the list in its current state lock: function() { stack = undefined; if ( !memory || memory === true ) { self.disable(); } return this; }, // Is it locked? locked: function() { return !stack; }, // Call all callbacks with the given context and arguments fireWith: function( context, args ) { if ( stack ) { if ( firing ) { if ( !flags.once ) { stack.push( [ context, args ] ); } } else if ( !( flags.once && memory ) ) { fire( context, args ); } } return this; }, // Call all the callbacks with the given arguments fire: function() { self.fireWith( this, arguments ); return this; }, // To know if the callbacks have already been called at least once fired: function() { return !!fired; } }; return self; }; var // Static reference to slice sliceDeferred = [].slice; jQuery.extend({ Deferred: function( func ) { var doneList = jQuery.Callbacks( "once memory" ), failList = jQuery.Callbacks( "once memory" ), progressList = jQuery.Callbacks( "memory" ), state = "pending", lists = { resolve: doneList, reject: failList, notify: progressList }, promise = { done: doneList.add, fail: failList.add, progress: progressList.add, state: function() { return state; }, // Deprecated isResolved: doneList.fired, isRejected: failList.fired, then: function( doneCallbacks, failCallbacks, progressCallbacks ) { deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks ); return this; }, always: function() { deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments ); return this; }, pipe: function( fnDone, fnFail, fnProgress ) { return jQuery.Deferred(function( newDefer ) { jQuery.each( { done: [ fnDone, "resolve" ], fail: [ fnFail, "reject" ], progress: [ fnProgress, "notify" ] }, function( handler, data ) { var fn = data[ 0 ], action = data[ 1 ], returned; if ( jQuery.isFunction( fn ) ) { deferred[ handler ](function() { returned = fn.apply( this, arguments ); if ( returned && jQuery.isFunction( returned.promise ) ) { returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify ); } else { newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); } }); } else { deferred[ handler ]( newDefer[ action ] ); } }); }).promise(); }, // Get a promise for this deferred // If obj is provided, the promise aspect is added to the object promise: function( obj ) { if ( obj == null ) { obj = promise; } else { for ( var key in promise ) { obj[ key ] = promise[ key ]; } } return obj; } }, deferred = promise.promise({}), key; for ( key in lists ) { deferred[ key ] = lists[ key ].fire; deferred[ key + "With" ] = lists[ key ].fireWith; } // Handle state deferred.done( function() { state = "resolved"; }, failList.disable, progressList.lock ).fail( function() { state = "rejected"; }, doneList.disable, progressList.lock ); // Call given func if any if ( func ) { func.call( deferred, deferred ); } // All done! return deferred; }, // Deferred helper when: function( firstParam ) { var args = sliceDeferred.call( arguments, 0 ), i = 0, length = args.length, pValues = new Array( length ), count = length, pCount = length, deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ? firstParam : jQuery.Deferred(), promise = deferred.promise(); function resolveFunc( i ) { return function( value ) { args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; if ( !( --count ) ) { deferred.resolveWith( deferred, args ); } }; } function progressFunc( i ) { return function( value ) { pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value; deferred.notifyWith( promise, pValues ); }; } if ( length > 1 ) { for ( ; i < length; i++ ) { if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) { args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) ); } else { --count; } } if ( !count ) { deferred.resolveWith( deferred, args ); } } else if ( deferred !== firstParam ) { deferred.resolveWith( deferred, length ? [ firstParam ] : [] ); } return promise; } }); jQuery.support = (function() { var support, all, a, select, opt, input, fragment, tds, events, eventName, i, isSupported, div = document.createElement( "div" ), documentElement = document.documentElement; // Preliminary tests div.setAttribute("className", "t"); div.innerHTML = "
a"; all = div.getElementsByTagName( "*" ); a = div.getElementsByTagName( "a" )[ 0 ]; // Can't get basic test support if ( !all || !all.length || !a ) { return {}; } // First batch of supports tests select = document.createElement( "select" ); opt = select.appendChild( document.createElement("option") ); input = div.getElementsByTagName( "input" )[ 0 ]; support = { // IE strips leading whitespace when .innerHTML is used leadingWhitespace: ( div.firstChild.nodeType === 3 ), // Make sure that tbody elements aren't automatically inserted // IE will insert them into empty tables tbody: !div.getElementsByTagName("tbody").length, // Make sure that link elements get serialized correctly by innerHTML // This requires a wrapper element in IE htmlSerialize: !!div.getElementsByTagName("link").length, // Get the style information from getAttribute // (IE uses .cssText instead) style: /top/.test( a.getAttribute("style") ), // Make sure that URLs aren't manipulated // (IE normalizes it by default) hrefNormalized: ( a.getAttribute("href") === "/a" ), // Make sure that element opacity exists // (IE uses filter instead) // Use a regex to work around a WebKit issue. See #5145 opacity: /^0.55/.test( a.style.opacity ), // Verify style float existence // (IE uses styleFloat instead of cssFloat) cssFloat: !!a.style.cssFloat, // Make sure that if no value is specified for a checkbox // that it defaults to "on". // (WebKit defaults to "" instead) checkOn: ( input.value === "on" ), // Make sure that a selected-by-default option has a working selected property. // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) optSelected: opt.selected, // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) getSetAttribute: div.className !== "t", // Tests for enctype support on a form(#6743) enctype: !!document.createElement("form").enctype, // Makes sure cloning an html5 element does not cause problems // Where outerHTML is undefined, this still works html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>", // Will be defined later submitBubbles: true, changeBubbles: true, focusinBubbles: false, deleteExpando: true, noCloneEvent: true, inlineBlockNeedsLayout: false, shrinkWrapBlocks: false, reliableMarginRight: true, pixelMargin: true }; // jQuery.boxModel DEPRECATED in 1.3, use jQuery.support.boxModel instead jQuery.boxModel = support.boxModel = (document.compatMode === "CSS1Compat"); // Make sure checked status is properly cloned input.checked = true; support.noCloneChecked = input.cloneNode( true ).checked; // Make sure that the options inside disabled selects aren't marked as disabled // (WebKit marks them as disabled) select.disabled = true; support.optDisabled = !opt.disabled; // Test to see if it's possible to delete an expando from an element // Fails in Internet Explorer try { delete div.test; } catch( e ) { support.deleteExpando = false; } if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { div.attachEvent( "onclick", function() { // Cloning a node shouldn't copy over any // bound event handlers (IE does this) support.noCloneEvent = false; }); div.cloneNode( true ).fireEvent( "onclick" ); } // Check if a radio maintains its value // after being appended to the DOM input = document.createElement("input"); input.value = "t"; input.setAttribute("type", "radio"); support.radioValue = input.value === "t"; input.setAttribute("checked", "checked"); // #11217 - WebKit loses check when the name is after the checked attribute input.setAttribute( "name", "t" ); div.appendChild( input ); fragment = document.createDocumentFragment(); fragment.appendChild( div.lastChild ); // WebKit doesn't clone checked state correctly in fragments support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; // Check if a disconnected checkbox will retain its checked // value of true after appended to the DOM (IE6/7) support.appendChecked = input.checked; fragment.removeChild( input ); fragment.appendChild( div ); // Technique from Juriy Zaytsev // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/ // We only care about the case where non-standard event systems // are used, namely in IE. Short-circuiting here helps us to // avoid an eval call (in setAttribute) which can cause CSP // to go haywire. See: https://developer.mozilla.org/en/Security/CSP if ( div.attachEvent ) { for ( i in { submit: 1, change: 1, focusin: 1 }) { eventName = "on" + i; isSupported = ( eventName in div ); if ( !isSupported ) { div.setAttribute( eventName, "return;" ); isSupported = ( typeof div[ eventName ] === "function" ); } support[ i + "Bubbles" ] = isSupported; } } fragment.removeChild( div ); // Null elements to avoid leaks in IE fragment = select = opt = div = input = null; // Run tests that need a body at doc ready jQuery(function() { var container, outer, inner, table, td, offsetSupport, marginDiv, conMarginTop, style, html, positionTopLeftWidthHeight, paddingMarginBorderVisibility, paddingMarginBorder, body = document.getElementsByTagName("body")[0]; if ( !body ) { // Return for frameset docs that don't have a body return; } conMarginTop = 1; paddingMarginBorder = "padding:0;margin:0;border:"; positionTopLeftWidthHeight = "position:absolute;top:0;left:0;width:1px;height:1px;"; paddingMarginBorderVisibility = paddingMarginBorder + "0;visibility:hidden;"; style = "style='" + positionTopLeftWidthHeight + paddingMarginBorder + "5px solid #000;"; html = "
" + "" + "
"; container = document.createElement("div"); container.style.cssText = paddingMarginBorderVisibility + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px"; body.insertBefore( container, body.firstChild ); // Construct the test element div = document.createElement("div"); container.appendChild( div ); // Check if table cells still have offsetWidth/Height when they are set // to display:none and there are still other visible table cells in a // table row; if so, offsetWidth/Height are not reliable for use when // determining if an element has been hidden directly using // display:none (it is still safe to use offsets if a parent element is // hidden; don safety goggles and see bug #4512 for more information). // (only IE 8 fails this test) div.innerHTML = "
t
"; tds = div.getElementsByTagName( "td" ); isSupported = ( tds[ 0 ].offsetHeight === 0 ); tds[ 0 ].style.display = ""; tds[ 1 ].style.display = "none"; // Check if empty table cells still have offsetWidth/Height // (IE <= 8 fail this test) support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); // Check if div with explicit width and no margin-right incorrectly // gets computed margin-right based on width of container. For more // info see bug #3333 // Fails in WebKit before Feb 2011 nightlies // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right if ( window.getComputedStyle ) { div.innerHTML = ""; marginDiv = document.createElement( "div" ); marginDiv.style.width = "0"; marginDiv.style.marginRight = "0"; div.style.width = "2px"; div.appendChild( marginDiv ); support.reliableMarginRight = ( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0; } if ( typeof div.style.zoom !== "undefined" ) { // Check if natively block-level elements act like inline-block // elements when setting their display to 'inline' and giving // them layout // (IE < 8 does this) div.innerHTML = ""; div.style.width = div.style.padding = "1px"; div.style.border = 0; div.style.overflow = "hidden"; div.style.display = "inline"; div.style.zoom = 1; support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); // Check if elements with layout shrink-wrap their children // (IE 6 does this) div.style.display = "block"; div.style.overflow = "visible"; div.innerHTML = "
"; support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); } div.style.cssText = positionTopLeftWidthHeight + paddingMarginBorderVisibility; div.innerHTML = html; outer = div.firstChild; inner = outer.firstChild; td = outer.nextSibling.firstChild.firstChild; offsetSupport = { doesNotAddBorder: ( inner.offsetTop !== 5 ), doesAddBorderForTableAndCells: ( td.offsetTop === 5 ) }; inner.style.position = "fixed"; inner.style.top = "20px"; // safari subtracts parent border width here which is 5px offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 ); inner.style.position = inner.style.top = ""; outer.style.overflow = "hidden"; outer.style.position = "relative"; offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 ); offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop ); if ( window.getComputedStyle ) { div.style.marginTop = "1%"; support.pixelMargin = ( window.getComputedStyle( div, null ) || { marginTop: 0 } ).marginTop !== "1%"; } if ( typeof container.style.zoom !== "undefined" ) { container.style.zoom = 1; } body.removeChild( container ); marginDiv = div = container = null; jQuery.extend( support, offsetSupport ); }); return support; })(); var rbrace = /^(?:\{.*\}|\[.*\])$/, rmultiDash = /([A-Z])/g; jQuery.extend({ cache: {}, // Please use with caution uuid: 0, // Unique for each copy of jQuery on the page // Non-digits removed to match rinlinejQuery expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), // The following elements throw uncatchable exceptions if you // attempt to add expando properties to them. noData: { "embed": true, // Ban all objects except for Flash (which handle expandos) "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", "applet": true }, hasData: function( elem ) { elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; return !!elem && !isEmptyDataObject( elem ); }, data: function( elem, name, data, pvt /* Internal Use Only */ ) { if ( !jQuery.acceptData( elem ) ) { return; } var privateCache, thisCache, ret, internalKey = jQuery.expando, getByName = typeof name === "string", // We have to handle DOM nodes and JS objects differently because IE6-7 // can't GC object references properly across the DOM-JS boundary isNode = elem.nodeType, // Only DOM nodes need the global jQuery cache; JS object data is // attached directly to the object so GC can occur automatically cache = isNode ? jQuery.cache : elem, // Only defining an ID for JS objects if its cache already exists allows // the code to shortcut on the same path as a DOM node with no cache id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey, isEvents = name === "events"; // Avoid doing any more work than we need to when trying to get data on an // object that has no data at all if ( (!id || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && getByName && data === undefined ) { return; } if ( !id ) { // Only DOM nodes need a new unique ID for each element since their data // ends up in the global cache if ( isNode ) { elem[ internalKey ] = id = ++jQuery.uuid; } else { id = internalKey; } } if ( !cache[ id ] ) { cache[ id ] = {}; // Avoids exposing jQuery metadata on plain JS objects when the object // is serialized using JSON.stringify if ( !isNode ) { cache[ id ].toJSON = jQuery.noop; } } // An object can be passed to jQuery.data instead of a key/value pair; this gets // shallow copied over onto the existing cache if ( typeof name === "object" || typeof name === "function" ) { if ( pvt ) { cache[ id ] = jQuery.extend( cache[ id ], name ); } else { cache[ id ].data = jQuery.extend( cache[ id ].data, name ); } } privateCache = thisCache = cache[ id ]; // jQuery data() is stored in a separate object inside the object's internal data // cache in order to avoid key collisions between internal data and user-defined // data. if ( !pvt ) { if ( !thisCache.data ) { thisCache.data = {}; } thisCache = thisCache.data; } if ( data !== undefined ) { thisCache[ jQuery.camelCase( name ) ] = data; } // Users should not attempt to inspect the internal events object using jQuery.data, // it is undocumented and subject to change. But does anyone listen? No. if ( isEvents && !thisCache[ name ] ) { return privateCache.events; } // Check for both converted-to-camel and non-converted data property names // If a data property was specified if ( getByName ) { // First Try to find as-is property data ret = thisCache[ name ]; // Test for null|undefined property data if ( ret == null ) { // Try to find the camelCased property ret = thisCache[ jQuery.camelCase( name ) ]; } } else { ret = thisCache; } return ret; }, removeData: function( elem, name, pvt /* Internal Use Only */ ) { if ( !jQuery.acceptData( elem ) ) { return; } var thisCache, i, l, // Reference to internal data cache key internalKey = jQuery.expando, isNode = elem.nodeType, // See jQuery.data for more information cache = isNode ? jQuery.cache : elem, // See jQuery.data for more information id = isNode ? elem[ internalKey ] : internalKey; // If there is already no cache entry for this object, there is no // purpose in continuing if ( !cache[ id ] ) { return; } if ( name ) { thisCache = pvt ? cache[ id ] : cache[ id ].data; if ( thisCache ) { // Support array or space separated string names for data keys if ( !jQuery.isArray( name ) ) { // try the string as a key before any manipulation if ( name in thisCache ) { name = [ name ]; } else { // split the camel cased version by spaces unless a key with the spaces exists name = jQuery.camelCase( name ); if ( name in thisCache ) { name = [ name ]; } else { name = name.split( " " ); } } } for ( i = 0, l = name.length; i < l; i++ ) { delete thisCache[ name[i] ]; } // If there is no data left in the cache, we want to continue // and let the cache object itself get destroyed if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { return; } } } // See jQuery.data for more information if ( !pvt ) { delete cache[ id ].data; // Don't destroy the parent cache unless the internal data object // had been the only thing left in it if ( !isEmptyDataObject(cache[ id ]) ) { return; } } // Browsers that fail expando deletion also refuse to delete expandos on // the window, but it will allow it on all other JS objects; other browsers // don't care // Ensure that `cache` is not a window object #10080 if ( jQuery.support.deleteExpando || !cache.setInterval ) { delete cache[ id ]; } else { cache[ id ] = null; } // We destroyed the cache and need to eliminate the expando on the node to avoid // false lookups in the cache for entries that no longer exist if ( isNode ) { // IE does not allow us to delete expando properties from nodes, // nor does it have a removeAttribute function on Document nodes; // we must handle all of these cases if ( jQuery.support.deleteExpando ) { delete elem[ internalKey ]; } else if ( elem.removeAttribute ) { elem.removeAttribute( internalKey ); } else { elem[ internalKey ] = null; } } }, // For internal use only. _data: function( elem, name, data ) { return jQuery.data( elem, name, data, true ); }, // A method for determining if a DOM node can handle the data expando acceptData: function( elem ) { if ( elem.nodeName ) { var match = jQuery.noData[ elem.nodeName.toLowerCase() ]; if ( match ) { return !(match === true || elem.getAttribute("classid") !== match); } } return true; } }); jQuery.fn.extend({ data: function( key, value ) { var parts, part, attr, name, l, elem = this[0], i = 0, data = null; // Gets all values if ( key === undefined ) { if ( this.length ) { data = jQuery.data( elem ); if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { attr = elem.attributes; for ( l = attr.length; i < l; i++ ) { name = attr[i].name; if ( name.indexOf( "data-" ) === 0 ) { name = jQuery.camelCase( name.substring(5) ); dataAttr( elem, name, data[ name ] ); } } jQuery._data( elem, "parsedAttrs", true ); } } return data; } // Sets multiple values if ( typeof key === "object" ) { return this.each(function() { jQuery.data( this, key ); }); } parts = key.split( ".", 2 ); parts[1] = parts[1] ? "." + parts[1] : ""; part = parts[1] + "!"; return jQuery.access( this, function( value ) { if ( value === undefined ) { data = this.triggerHandler( "getData" + part, [ parts[0] ] ); // Try to fetch any internally stored data first if ( data === undefined && elem ) { data = jQuery.data( elem, key ); data = dataAttr( elem, key, data ); } return data === undefined && parts[1] ? this.data( parts[0] ) : data; } parts[1] = value; this.each(function() { var self = jQuery( this ); self.triggerHandler( "setData" + part, parts ); jQuery.data( this, key, value ); self.triggerHandler( "changeData" + part, parts ); }); }, null, value, arguments.length > 1, null, false ); }, removeData: function( key ) { return this.each(function() { jQuery.removeData( this, key ); }); } }); function dataAttr( elem, key, data ) { // If nothing was found internally, try to fetch any // data from the HTML5 data-* attribute if ( data === undefined && elem.nodeType === 1 ) { var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); data = elem.getAttribute( name ); if ( typeof data === "string" ) { try { data = data === "true" ? true : data === "false" ? false : data === "null" ? null : jQuery.isNumeric( data ) ? +data : rbrace.test( data ) ? jQuery.parseJSON( data ) : data; } catch( e ) {} // Make sure we set the data so it isn't changed later jQuery.data( elem, key, data ); } else { data = undefined; } } return data; } // checks a cache object for emptiness function isEmptyDataObject( obj ) { for ( var name in obj ) { // if the public data object is empty, the private is still empty if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { continue; } if ( name !== "toJSON" ) { return false; } } return true; } function handleQueueMarkDefer( elem, type, src ) { var deferDataKey = type + "defer", queueDataKey = type + "queue", markDataKey = type + "mark", defer = jQuery._data( elem, deferDataKey ); if ( defer && ( src === "queue" || !jQuery._data(elem, queueDataKey) ) && ( src === "mark" || !jQuery._data(elem, markDataKey) ) ) { // Give room for hard-coded callbacks to fire first // and eventually mark/queue something else on the element setTimeout( function() { if ( !jQuery._data( elem, queueDataKey ) && !jQuery._data( elem, markDataKey ) ) { jQuery.removeData( elem, deferDataKey, true ); defer.fire(); } }, 0 ); } } jQuery.extend({ _mark: function( elem, type ) { if ( elem ) { type = ( type || "fx" ) + "mark"; jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 ); } }, _unmark: function( force, elem, type ) { if ( force !== true ) { type = elem; elem = force; force = false; } if ( elem ) { type = type || "fx"; var key = type + "mark", count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 ); if ( count ) { jQuery._data( elem, key, count ); } else { jQuery.removeData( elem, key, true ); handleQueueMarkDefer( elem, type, "mark" ); } } }, queue: function( elem, type, data ) { var q; if ( elem ) { type = ( type || "fx" ) + "queue"; q = jQuery._data( elem, type ); // Speed up dequeue by getting out quickly if this is just a lookup if ( data ) { if ( !q || jQuery.isArray(data) ) { q = jQuery._data( elem, type, jQuery.makeArray(data) ); } else { q.push( data ); } } return q || []; } }, dequeue: function( elem, type ) { type = type || "fx"; var queue = jQuery.queue( elem, type ), fn = queue.shift(), hooks = {}; // If the fx queue is dequeued, always remove the progress sentinel if ( fn === "inprogress" ) { fn = queue.shift(); } if ( fn ) { // Add a progress sentinel to prevent the fx queue from being // automatically dequeued if ( type === "fx" ) { queue.unshift( "inprogress" ); } jQuery._data( elem, type + ".run", hooks ); fn.call( elem, function() { jQuery.dequeue( elem, type ); }, hooks ); } if ( !queue.length ) { jQuery.removeData( elem, type + "queue " + type + ".run", true ); handleQueueMarkDefer( elem, type, "queue" ); } } }); jQuery.fn.extend({ queue: function( type, data ) { var setter = 2; if ( typeof type !== "string" ) { data = type; type = "fx"; setter--; } if ( arguments.length < setter ) { return jQuery.queue( this[0], type ); } return data === undefined ? this : this.each(function() { var queue = jQuery.queue( this, type, data ); if ( type === "fx" && queue[0] !== "inprogress" ) { jQuery.dequeue( this, type ); } }); }, dequeue: function( type ) { return this.each(function() { jQuery.dequeue( this, type ); }); }, // Based off of the plugin by Clint Helfers, with permission. // http://blindsignals.com/index.php/2009/07/jquery-delay/ delay: function( time, type ) { time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; type = type || "fx"; return this.queue( type, function( next, hooks ) { var timeout = setTimeout( next, time ); hooks.stop = function() { clearTimeout( timeout ); }; }); }, clearQueue: function( type ) { return this.queue( type || "fx", [] ); }, // Get a promise resolved when queues of a certain type // are emptied (fx is the type by default) promise: function( type, object ) { if ( typeof type !== "string" ) { object = type; type = undefined; } type = type || "fx"; var defer = jQuery.Deferred(), elements = this, i = elements.length, count = 1, deferDataKey = type + "defer", queueDataKey = type + "queue", markDataKey = type + "mark", tmp; function resolve() { if ( !( --count ) ) { defer.resolveWith( elements, [ elements ] ); } } while( i-- ) { if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) || ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) || jQuery.data( elements[ i ], markDataKey, undefined, true ) ) && jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) { count++; tmp.add( resolve ); } } resolve(); return defer.promise( object ); } }); var rclass = /[\n\t\r]/g, rspace = /\s+/, rreturn = /\r/g, rtype = /^(?:button|input)$/i, rfocusable = /^(?:button|input|object|select|textarea)$/i, rclickable = /^a(?:rea)?$/i, rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, getSetAttribute = jQuery.support.getSetAttribute, nodeHook, boolHook, fixSpecified; jQuery.fn.extend({ attr: function( name, value ) { return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); }, removeAttr: function( name ) { return this.each(function() { jQuery.removeAttr( this, name ); }); }, prop: function( name, value ) { return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); }, removeProp: function( name ) { name = jQuery.propFix[ name ] || name; return this.each(function() { // try/catch handles cases where IE balks (such as removing a property on window) try { this[ name ] = undefined; delete this[ name ]; } catch( e ) {} }); }, addClass: function( value ) { var classNames, i, l, elem, setClass, c, cl; if ( jQuery.isFunction( value ) ) { return this.each(function( j ) { jQuery( this ).addClass( value.call(this, j, this.className) ); }); } if ( value && typeof value === "string" ) { classNames = value.split( rspace ); for ( i = 0, l = this.length; i < l; i++ ) { elem = this[ i ]; if ( elem.nodeType === 1 ) { if ( !elem.className && classNames.length === 1 ) { elem.className = value; } else { setClass = " " + elem.className + " "; for ( c = 0, cl = classNames.length; c < cl; c++ ) { if ( !~setClass.indexOf( " " + classNames[ c ] + " " ) ) { setClass += classNames[ c ] + " "; } } elem.className = jQuery.trim( setClass ); } } } } return this; }, removeClass: function( value ) { var classNames, i, l, elem, className, c, cl; if ( jQuery.isFunction( value ) ) { return this.each(function( j ) { jQuery( this ).removeClass( value.call(this, j, this.className) ); }); } if ( (value && typeof value === "string") || value === undefined ) { classNames = ( value || "" ).split( rspace ); for ( i = 0, l = this.length; i < l; i++ ) { elem = this[ i ]; if ( elem.nodeType === 1 && elem.className ) { if ( value ) { className = (" " + elem.className + " ").replace( rclass, " " ); for ( c = 0, cl = classNames.length; c < cl; c++ ) { className = className.replace(" " + classNames[ c ] + " ", " "); } elem.className = jQuery.trim( className ); } else { elem.className = ""; } } } } return this; }, toggleClass: function( value, stateVal ) { var type = typeof value, isBool = typeof stateVal === "boolean"; if ( jQuery.isFunction( value ) ) { return this.each(function( i ) { jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); }); } return this.each(function() { if ( type === "string" ) { // toggle individual class names var className, i = 0, self = jQuery( this ), state = stateVal, classNames = value.split( rspace ); while ( (className = classNames[ i++ ]) ) { // check each className given, space seperated list state = isBool ? state : !self.hasClass( className ); self[ state ? "addClass" : "removeClass" ]( className ); } } else if ( type === "undefined" || type === "boolean" ) { if ( this.className ) { // store className if set jQuery._data( this, "__className__", this.className ); } // toggle whole className this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; } }); }, hasClass: function( selector ) { var className = " " + selector + " ", i = 0, l = this.length; for ( ; i < l; i++ ) { if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) { return true; } } return false; }, val: function( value ) { var hooks, ret, isFunction, elem = this[0]; if ( !arguments.length ) { if ( elem ) { hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { return ret; } ret = elem.value; return typeof ret === "string" ? // handle most common string cases ret.replace(rreturn, "") : // handle cases where value is null/undef or number ret == null ? "" : ret; } return; } isFunction = jQuery.isFunction( value ); return this.each(function( i ) { var self = jQuery(this), val; if ( this.nodeType !== 1 ) { return; } if ( isFunction ) { val = value.call( this, i, self.val() ); } else { val = value; } // Treat null/undefined as ""; convert numbers to string if ( val == null ) { val = ""; } else if ( typeof val === "number" ) { val += ""; } else if ( jQuery.isArray( val ) ) { val = jQuery.map(val, function ( value ) { return value == null ? "" : value + ""; }); } hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; // If set returns undefined, fall back to normal setting if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { this.value = val; } }); } }); jQuery.extend({ valHooks: { option: { get: function( elem ) { // attributes.value is undefined in Blackberry 4.7 but // uses .value. See #6932 var val = elem.attributes.value; return !val || val.specified ? elem.value : elem.text; } }, select: { get: function( elem ) { var value, i, max, option, index = elem.selectedIndex, values = [], options = elem.options, one = elem.type === "select-one"; // Nothing was selected if ( index < 0 ) { return null; } // Loop through all the selected options i = one ? index : 0; max = one ? index + 1 : options.length; for ( ; i < max; i++ ) { option = options[ i ]; // Don't return options that are disabled or in a disabled optgroup if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { // Get the specific value for the option value = jQuery( option ).val(); // We don't need an array for one selects if ( one ) { return value; } // Multi-Selects return an array values.push( value ); } } // Fixes Bug #2551 -- select.val() broken in IE after form.reset() if ( one && !values.length && options.length ) { return jQuery( options[ index ] ).val(); } return values; }, set: function( elem, value ) { var values = jQuery.makeArray( value ); jQuery(elem).find("option").each(function() { this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; }); if ( !values.length ) { elem.selectedIndex = -1; } return values; } } }, attrFn: { val: true, css: true, html: true, text: true, data: true, width: true, height: true, offset: true }, attr: function( elem, name, value, pass ) { var ret, hooks, notxml, nType = elem.nodeType; // don't get/set attributes on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return; } if ( pass && name in jQuery.attrFn ) { return jQuery( elem )[ name ]( value ); } // Fallback to prop when attributes are not supported if ( typeof elem.getAttribute === "undefined" ) { return jQuery.prop( elem, name, value ); } notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); // All attributes are lowercase // Grab necessary hook if one is defined if ( notxml ) { name = name.toLowerCase(); hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); } if ( value !== undefined ) { if ( value === null ) { jQuery.removeAttr( elem, name ); return; } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { return ret; } else { elem.setAttribute( name, "" + value ); return value; } } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { return ret; } else { ret = elem.getAttribute( name ); // Non-existent attributes return null, we normalize to undefined return ret === null ? undefined : ret; } }, removeAttr: function( elem, value ) { var propName, attrNames, name, l, isBool, i = 0; if ( value && elem.nodeType === 1 ) { attrNames = value.toLowerCase().split( rspace ); l = attrNames.length; for ( ; i < l; i++ ) { name = attrNames[ i ]; if ( name ) { propName = jQuery.propFix[ name ] || name; isBool = rboolean.test( name ); // See #9699 for explanation of this approach (setting first, then removal) // Do not do this for boolean attributes (see #10870) if ( !isBool ) { jQuery.attr( elem, name, "" ); } elem.removeAttribute( getSetAttribute ? name : propName ); // Set corresponding property to false for boolean attributes if ( isBool && propName in elem ) { elem[ propName ] = false; } } } } }, attrHooks: { type: { set: function( elem, value ) { // We can't allow the type property to be changed (since it causes problems in IE) if ( rtype.test( elem.nodeName ) && elem.parentNode ) { jQuery.error( "type property can't be changed" ); } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { // Setting the type on a radio button after the value resets the value in IE6-9 // Reset value to it's default in case type is set after value // This is for element creation var val = elem.value; elem.setAttribute( "type", value ); if ( val ) { elem.value = val; } return value; } } }, // Use the value property for back compat // Use the nodeHook for button elements in IE6/7 (#1954) value: { get: function( elem, name ) { if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { return nodeHook.get( elem, name ); } return name in elem ? elem.value : null; }, set: function( elem, value, name ) { if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { return nodeHook.set( elem, value, name ); } // Does not return so that setAttribute is also used elem.value = value; } } }, propFix: { tabindex: "tabIndex", readonly: "readOnly", "for": "htmlFor", "class": "className", maxlength: "maxLength", cellspacing: "cellSpacing", cellpadding: "cellPadding", rowspan: "rowSpan", colspan: "colSpan", usemap: "useMap", frameborder: "frameBorder", contenteditable: "contentEditable" }, prop: function( elem, name, value ) { var ret, hooks, notxml, nType = elem.nodeType; // don't get/set properties on text, comment and attribute nodes if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { return; } notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); if ( notxml ) { // Fix name and attach hooks name = jQuery.propFix[ name ] || name; hooks = jQuery.propHooks[ name ]; } if ( value !== undefined ) { if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { return ret; } else { return ( elem[ name ] = value ); } } else { if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { return ret; } else { return elem[ name ]; } } }, propHooks: { tabIndex: { get: function( elem ) { // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ var attributeNode = elem.getAttributeNode("tabindex"); return attributeNode && attributeNode.specified ? parseInt( attributeNode.value, 10 ) : rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? 0 : undefined; } } } }); // Add the tabIndex propHook to attrHooks for back-compat (different case is intentional) jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex; // Hook for boolean attributes boolHook = { get: function( elem, name ) { // Align boolean attributes with corresponding properties // Fall back to attribute presence where some booleans are not supported var attrNode, property = jQuery.prop( elem, name ); return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ? name.toLowerCase() : undefined; }, set: function( elem, value, name ) { var propName; if ( value === false ) { // Remove boolean attributes when set to false jQuery.removeAttr( elem, name ); } else { // value is true since we know at this point it's type boolean and not false // Set boolean attributes to the same name and set the DOM property propName = jQuery.propFix[ name ] || name; if ( propName in elem ) { // Only set the IDL specifically if it already exists on the element elem[ propName ] = true; } elem.setAttribute( name, name.toLowerCase() ); } return name; } }; // IE6/7 do not support getting/setting some attributes with get/setAttribute if ( !getSetAttribute ) { fixSpecified = { name: true, id: true, coords: true }; // Use this for any attribute in IE6/7 // This fixes almost every IE6/7 issue nodeHook = jQuery.valHooks.button = { get: function( elem, name ) { var ret; ret = elem.getAttributeNode( name ); return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ? ret.nodeValue : undefined; }, set: function( elem, value, name ) { // Set the existing or create a new attribute node var ret = elem.getAttributeNode( name ); if ( !ret ) { ret = document.createAttribute( name ); elem.setAttributeNode( ret ); } return ( ret.nodeValue = value + "" ); } }; // Apply the nodeHook to tabindex jQuery.attrHooks.tabindex.set = nodeHook.set; // Set width and height to auto instead of 0 on empty string( Bug #8150 ) // This is for removals jQuery.each([ "width", "height" ], function( i, name ) { jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { set: function( elem, value ) { if ( value === "" ) { elem.setAttribute( name, "auto" ); return value; } } }); }); // Set contenteditable to false on removals(#10429) // Setting to empty string throws an error as an invalid value jQuery.attrHooks.contenteditable = { get: nodeHook.get, set: function( elem, value, name ) { if ( value === "" ) { value = "false"; } nodeHook.set( elem, value, name ); } }; } // Some attributes require a special call on IE if ( !jQuery.support.hrefNormalized ) { jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { get: function( elem ) { var ret = elem.getAttribute( name, 2 ); return ret === null ? undefined : ret; } }); }); } if ( !jQuery.support.style ) { jQuery.attrHooks.style = { get: function( elem ) { // Return undefined in the case of empty string // Normalize to lowercase since IE uppercases css property names return elem.style.cssText.toLowerCase() || undefined; }, set: function( elem, value ) { return ( elem.style.cssText = "" + value ); } }; } // Safari mis-reports the default selected property of an option // Accessing the parent's selectedIndex property fixes it if ( !jQuery.support.optSelected ) { jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { get: function( elem ) { var parent = elem.parentNode; if ( parent ) { parent.selectedIndex; // Make sure that it also works with optgroups, see #5701 if ( parent.parentNode ) { parent.parentNode.selectedIndex; } } return null; } }); } // IE6/7 call enctype encoding if ( !jQuery.support.enctype ) { jQuery.propFix.enctype = "encoding"; } // Radios and checkboxes getter/setter if ( !jQuery.support.checkOn ) { jQuery.each([ "radio", "checkbox" ], function() { jQuery.valHooks[ this ] = { get: function( elem ) { // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified return elem.getAttribute("value") === null ? "on" : elem.value; } }; }); } jQuery.each([ "radio", "checkbox" ], function() { jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { set: function( elem, value ) { if ( jQuery.isArray( value ) ) { return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); } } }); }); var rformElems = /^(?:textarea|input|select)$/i, rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/, rhoverHack = /(?:^|\s)hover(\.\S+)?\b/, rkeyEvent = /^key/, rmouseEvent = /^(?:mouse|contextmenu)|click/, rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/, quickParse = function( selector ) { var quick = rquickIs.exec( selector ); if ( quick ) { // 0 1 2 3 // [ _, tag, id, class ] quick[1] = ( quick[1] || "" ).toLowerCase(); quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" ); } return quick; }, quickIs = function( elem, m ) { var attrs = elem.attributes || {}; return ( (!m[1] || elem.nodeName.toLowerCase() === m[1]) && (!m[2] || (attrs.id || {}).value === m[2]) && (!m[3] || m[3].test( (attrs[ "class" ] || {}).value )) ); }, hoverHack = function( events ) { return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" ); }; /* * Helper functions for managing events -- not part of the public interface. * Props to Dean Edwards' addEvent library for many of the ideas. */ jQuery.event = { add: function( elem, types, handler, data, selector ) { var elemData, eventHandle, events, t, tns, type, namespaces, handleObj, handleObjIn, quick, handlers, special; // Don't attach events to noData or text/comment nodes (allow plain objects tho) if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) { return; } // Caller can pass in an object of custom data in lieu of the handler if ( handler.handler ) { handleObjIn = handler; handler = handleObjIn.handler; selector = handleObjIn.selector; } // Make sure that the handler has a unique ID, used to find/remove it later if ( !handler.guid ) { handler.guid = jQuery.guid++; } // Init the element's event structure and main handler, if this is the first events = elemData.events; if ( !events ) { elemData.events = events = {}; } eventHandle = elemData.handle; if ( !eventHandle ) { elemData.handle = eventHandle = function( e ) { // Discard the second event of a jQuery.event.trigger() and // when an event is called after a page has unloaded return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : undefined; }; // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events eventHandle.elem = elem; } // Handle multiple events separated by a space // jQuery(...).bind("mouseover mouseout", fn); types = jQuery.trim( hoverHack(types) ).split( " " ); for ( t = 0; t < types.length; t++ ) { tns = rtypenamespace.exec( types[t] ) || []; type = tns[1]; namespaces = ( tns[2] || "" ).split( "." ).sort(); // If event changes its type, use the special event handlers for the changed type special = jQuery.event.special[ type ] || {}; // If selector defined, determine special event api type, otherwise given type type = ( selector ? special.delegateType : special.bindType ) || type; // Update special based on newly reset type special = jQuery.event.special[ type ] || {}; // handleObj is passed to all event handlers handleObj = jQuery.extend({ type: type, origType: tns[1], data: data, handler: handler, guid: handler.guid, selector: selector, quick: selector && quickParse( selector ), namespace: namespaces.join(".") }, handleObjIn ); // Init the event handler queue if we're the first handlers = events[ type ]; if ( !handlers ) { handlers = events[ type ] = []; handlers.delegateCount = 0; // Only use addEventListener/attachEvent if the special events handler returns false if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { // Bind the global event handler to the element if ( elem.addEventListener ) { elem.addEventListener( type, eventHandle, false ); } else if ( elem.attachEvent ) { elem.attachEvent( "on" + type, eventHandle ); } } } if ( special.add ) { special.add.call( elem, handleObj ); if ( !handleObj.handler.guid ) { handleObj.handler.guid = handler.guid; } } // Add to the element's handler list, delegates in front if ( selector ) { handlers.splice( handlers.delegateCount++, 0, handleObj ); } else { handlers.push( handleObj ); } // Keep track of which events have ever been used, for event optimization jQuery.event.global[ type ] = true; } // Nullify elem to prevent memory leaks in IE elem = null; }, global: {}, // Detach an event or set of events from an element remove: function( elem, types, handler, selector, mappedTypes ) { var elemData = jQuery.hasData( elem ) && jQuery._data( elem ), t, tns, type, origType, namespaces, origCount, j, events, special, handle, eventType, handleObj; if ( !elemData || !(events = elemData.events) ) { return; } // Once for each type.namespace in types; type may be omitted types = jQuery.trim( hoverHack( types || "" ) ).split(" "); for ( t = 0; t < types.length; t++ ) { tns = rtypenamespace.exec( types[t] ) || []; type = origType = tns[1]; namespaces = tns[2]; // Unbind all events (on this namespace, if provided) for the element if ( !type ) { for ( type in events ) { jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); } continue; } special = jQuery.event.special[ type ] || {}; type = ( selector? special.delegateType : special.bindType ) || type; eventType = events[ type ] || []; origCount = eventType.length; namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null; // Remove matching events for ( j = 0; j < eventType.length; j++ ) { handleObj = eventType[ j ]; if ( ( mappedTypes || origType === handleObj.origType ) && ( !handler || handler.guid === handleObj.guid ) && ( !namespaces || namespaces.test( handleObj.namespace ) ) && ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { eventType.splice( j--, 1 ); if ( handleObj.selector ) { eventType.delegateCount--; } if ( special.remove ) { special.remove.call( elem, handleObj ); } } } // Remove generic event handler if we removed something and no more handlers exist // (avoids potential for endless recursion during removal of special event handlers) if ( eventType.length === 0 && origCount !== eventType.length ) { if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) { jQuery.removeEvent( elem, type, elemData.handle ); } delete events[ type ]; } } // Remove the expando if it's no longer used if ( jQuery.isEmptyObject( events ) ) { handle = elemData.handle; if ( handle ) { handle.elem = null; } // removeData also checks for emptiness and clears the expando if empty // so use it instead of delete jQuery.removeData( elem, [ "events", "handle" ], true ); } }, // Events that are safe to short-circuit if no handlers are attached. // Native DOM events should not be added, they may have inline handlers. customEvent: { "getData": true, "setData": true, "changeData": true }, trigger: function( event, data, elem, onlyHandlers ) { // Don't do events on text and comment nodes if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) { return; } // Event object or event type var type = event.type || event, namespaces = [], cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType; // focus/blur morphs to focusin/out; ensure we're not firing them right now if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { return; } if ( type.indexOf( "!" ) >= 0 ) { // Exclusive events trigger only for the exact event (no namespaces) type = type.slice(0, -1); exclusive = true; } if ( type.indexOf( "." ) >= 0 ) { // Namespaced trigger; create a regexp to match event type in handle() namespaces = type.split("."); type = namespaces.shift(); namespaces.sort(); } if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { // No jQuery handlers for this event type, and it can't have inline handlers return; } // Caller can pass in an Event, Object, or just an event type string event = typeof event === "object" ? // jQuery.Event object event[ jQuery.expando ] ? event : // Object literal new jQuery.Event( type, event ) : // Just the event type (string) new jQuery.Event( type ); event.type = type; event.isTrigger = true; event.exclusive = exclusive; event.namespace = namespaces.join( "." ); event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null; ontype = type.indexOf( ":" ) < 0 ? "on" + type : ""; // Handle a global trigger if ( !elem ) { // TODO: Stop taunting the data cache; remove global events and always attach to document cache = jQuery.cache; for ( i in cache ) { if ( cache[ i ].events && cache[ i ].events[ type ] ) { jQuery.event.trigger( event, data, cache[ i ].handle.elem, true ); } } return; } // Clean up the event in case it is being reused event.result = undefined; if ( !event.target ) { event.target = elem; } // Clone any incoming data and prepend the event, creating the handler arg list data = data != null ? jQuery.makeArray( data ) : []; data.unshift( event ); // Allow special events to draw outside the lines special = jQuery.event.special[ type ] || {}; if ( special.trigger && special.trigger.apply( elem, data ) === false ) { return; } // Determine event propagation path in advance, per W3C events spec (#9951) // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) eventPath = [[ elem, special.bindType || type ]]; if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { bubbleType = special.delegateType || type; cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode; old = null; for ( ; cur; cur = cur.parentNode ) { eventPath.push([ cur, bubbleType ]); old = cur; } // Only add window if we got to document (e.g., not plain obj or detached DOM) if ( old && old === elem.ownerDocument ) { eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]); } } // Fire handlers on the event path for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) { cur = eventPath[i][0]; event.type = eventPath[i][1]; handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); if ( handle ) { handle.apply( cur, data ); } // Note that this is a bare JS function and not a jQuery handler handle = ontype && cur[ ontype ]; if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) { event.preventDefault(); } } event.type = type; // If nobody prevented the default action, do it now if ( !onlyHandlers && !event.isDefaultPrevented() ) { if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { // Call a native DOM method on the target with the same name name as the event. // Can't use an .isFunction() check here because IE6/7 fails that test. // Don't do default actions on window, that's where global variables be (#6170) // IE<9 dies on focus/blur to hidden element (#1486) if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) { // Don't re-trigger an onFOO event when we call its FOO() method old = elem[ ontype ]; if ( old ) { elem[ ontype ] = null; } // Prevent re-triggering of the same event, since we already bubbled it above jQuery.event.triggered = type; elem[ type ](); jQuery.event.triggered = undefined; if ( old ) { elem[ ontype ] = old; } } } } return event.result; }, dispatch: function( event ) { // Make a writable jQuery.Event from the native event object event = jQuery.event.fix( event || window.event ); var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []), delegateCount = handlers.delegateCount, args = [].slice.call( arguments, 0 ), run_all = !event.exclusive && !event.namespace, special = jQuery.event.special[ event.type ] || {}, handlerQueue = [], i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related; // Use the fix-ed jQuery.Event rather than the (read-only) native event args[0] = event; event.delegateTarget = this; // Call the preDispatch hook for the mapped type, and let it bail if desired if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { return; } // Determine handlers that should run if there are delegated events // Avoid non-left-click bubbling in Firefox (#3861) if ( delegateCount && !(event.button && event.type === "click") ) { // Pregenerate a single jQuery object for reuse with .is() jqcur = jQuery(this); jqcur.context = this.ownerDocument || this; for ( cur = event.target; cur != this; cur = cur.parentNode || this ) { // Don't process events on disabled elements (#6911, #8165) if ( cur.disabled !== true ) { selMatch = {}; matches = []; jqcur[0] = cur; for ( i = 0; i < delegateCount; i++ ) { handleObj = handlers[ i ]; sel = handleObj.selector; if ( selMatch[ sel ] === undefined ) { selMatch[ sel ] = ( handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel ) ); } if ( selMatch[ sel ] ) { matches.push( handleObj ); } } if ( matches.length ) { handlerQueue.push({ elem: cur, matches: matches }); } } } } // Add the remaining (directly-bound) handlers if ( handlers.length > delegateCount ) { handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) }); } // Run delegates first; they may want to stop propagation beneath us for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) { matched = handlerQueue[ i ]; event.currentTarget = matched.elem; for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) { handleObj = matched.matches[ j ]; // Triggered event must either 1) be non-exclusive and have no namespace, or // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) { event.data = handleObj.data; event.handleObj = handleObj; ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) .apply( matched.elem, args ); if ( ret !== undefined ) { event.result = ret; if ( ret === false ) { event.preventDefault(); event.stopPropagation(); } } } } } // Call the postDispatch hook for the mapped type if ( special.postDispatch ) { special.postDispatch.call( this, event ); } return event.result; }, // Includes some event props shared by KeyEvent and MouseEvent // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 *** props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), fixHooks: {}, keyHooks: { props: "char charCode key keyCode".split(" "), filter: function( event, original ) { // Add which for key events if ( event.which == null ) { event.which = original.charCode != null ? original.charCode : original.keyCode; } return event; } }, mouseHooks: { props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), filter: function( event, original ) { var eventDoc, doc, body, button = original.button, fromElement = original.fromElement; // Calculate pageX/Y if missing and clientX/Y available if ( event.pageX == null && original.clientX != null ) { eventDoc = event.target.ownerDocument || document; doc = eventDoc.documentElement; body = eventDoc.body; event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); } // Add relatedTarget, if necessary if ( !event.relatedTarget && fromElement ) { event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; } // Add which for click: 1 === left; 2 === middle; 3 === right // Note: button is not normalized, so don't use it if ( !event.which && button !== undefined ) { event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); } return event; } }, fix: function( event ) { if ( event[ jQuery.expando ] ) { return event; } // Create a writable copy of the event object and normalize some properties var i, prop, originalEvent = event, fixHook = jQuery.event.fixHooks[ event.type ] || {}, copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; event = jQuery.Event( originalEvent ); for ( i = copy.length; i; ) { prop = copy[ --i ]; event[ prop ] = originalEvent[ prop ]; } // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2) if ( !event.target ) { event.target = originalEvent.srcElement || document; } // Target should not be a text node (#504, Safari) if ( event.target.nodeType === 3 ) { event.target = event.target.parentNode; } // For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8) if ( event.metaKey === undefined ) { event.metaKey = event.ctrlKey; } return fixHook.filter? fixHook.filter( event, originalEvent ) : event; }, special: { ready: { // Make sure the ready event is setup setup: jQuery.bindReady }, load: { // Prevent triggered image.load events from bubbling to window.load noBubble: true }, focus: { delegateType: "focusin" }, blur: { delegateType: "focusout" }, beforeunload: { setup: function( data, namespaces, eventHandle ) { // We only want to do this special case on windows if ( jQuery.isWindow( this ) ) { this.onbeforeunload = eventHandle; } }, teardown: function( namespaces, eventHandle ) { if ( this.onbeforeunload === eventHandle ) { this.onbeforeunload = null; } } } }, simulate: function( type, elem, event, bubble ) { // Piggyback on a donor event to simulate a different one. // Fake originalEvent to avoid donor's stopPropagation, but if the // simulated event prevents default then we do the same on the donor. var e = jQuery.extend( new jQuery.Event(), event, { type: type, isSimulated: true, originalEvent: {} } ); if ( bubble ) { jQuery.event.trigger( e, null, elem ); } else { jQuery.event.dispatch.call( elem, e ); } if ( e.isDefaultPrevented() ) { event.preventDefault(); } } }; // Some plugins are using, but it's undocumented/deprecated and will be removed. // The 1.7 special event interface should provide all the hooks needed now. jQuery.event.handle = jQuery.event.dispatch; jQuery.removeEvent = document.removeEventListener ? function( elem, type, handle ) { if ( elem.removeEventListener ) { elem.removeEventListener( type, handle, false ); } } : function( elem, type, handle ) { if ( elem.detachEvent ) { elem.detachEvent( "on" + type, handle ); } }; jQuery.Event = function( src, props ) { // Allow instantiation without the 'new' keyword if ( !(this instanceof jQuery.Event) ) { return new jQuery.Event( src, props ); } // Event object if ( src && src.type ) { this.originalEvent = src; this.type = src.type; // Events bubbling up the document may have been marked as prevented // by a handler lower down the tree; reflect the correct value. this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; // Event type } else { this.type = src; } // Put explicitly provided properties onto the event object if ( props ) { jQuery.extend( this, props ); } // Create a timestamp if incoming event doesn't have one this.timeStamp = src && src.timeStamp || jQuery.now(); // Mark it as fixed this[ jQuery.expando ] = true; }; function returnFalse() { return false; } function returnTrue() { return true; } // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html jQuery.Event.prototype = { preventDefault: function() { this.isDefaultPrevented = returnTrue; var e = this.originalEvent; if ( !e ) { return; } // if preventDefault exists run it on the original event if ( e.preventDefault ) { e.preventDefault(); // otherwise set the returnValue property of the original event to false (IE) } else { e.returnValue = false; } }, stopPropagation: function() { this.isPropagationStopped = returnTrue; var e = this.originalEvent; if ( !e ) { return; } // if stopPropagation exists run it on the original event if ( e.stopPropagation ) { e.stopPropagation(); } // otherwise set the cancelBubble property of the original event to true (IE) e.cancelBubble = true; }, stopImmediatePropagation: function() { this.isImmediatePropagationStopped = returnTrue; this.stopPropagation(); }, isDefaultPrevented: returnFalse, isPropagationStopped: returnFalse, isImmediatePropagationStopped: returnFalse }; // Create mouseenter/leave events using mouseover/out and event-time checks jQuery.each({ mouseenter: "mouseover", mouseleave: "mouseout" }, function( orig, fix ) { jQuery.event.special[ orig ] = { delegateType: fix, bindType: fix, handle: function( event ) { var target = this, related = event.relatedTarget, handleObj = event.handleObj, selector = handleObj.selector, ret; // For mousenter/leave call the handler if related is outside the target. // NB: No relatedTarget if the mouse left/entered the browser window if ( !related || (related !== target && !jQuery.contains( target, related )) ) { event.type = handleObj.origType; ret = handleObj.handler.apply( this, arguments ); event.type = fix; } return ret; } }; }); // IE submit delegation if ( !jQuery.support.submitBubbles ) { jQuery.event.special.submit = { setup: function() { // Only need this for delegated form submit events if ( jQuery.nodeName( this, "form" ) ) { return false; } // Lazy-add a submit handler when a descendant form may potentially be submitted jQuery.event.add( this, "click._submit keypress._submit", function( e ) { // Node name check avoids a VML-related crash in IE (#9807) var elem = e.target, form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; if ( form && !form._submit_attached ) { jQuery.event.add( form, "submit._submit", function( event ) { event._submit_bubble = true; }); form._submit_attached = true; } }); // return undefined since we don't need an event listener }, postDispatch: function( event ) { // If form was submitted by the user, bubble the event up the tree if ( event._submit_bubble ) { delete event._submit_bubble; if ( this.parentNode && !event.isTrigger ) { jQuery.event.simulate( "submit", this.parentNode, event, true ); } } }, teardown: function() { // Only need this for delegated form submit events if ( jQuery.nodeName( this, "form" ) ) { return false; } // Remove delegated handlers; cleanData eventually reaps submit handlers attached above jQuery.event.remove( this, "._submit" ); } }; } // IE change delegation and checkbox/radio fix if ( !jQuery.support.changeBubbles ) { jQuery.event.special.change = { setup: function() { if ( rformElems.test( this.nodeName ) ) { // IE doesn't fire change on a check/radio until blur; trigger it on click // after a propertychange. Eat the blur-change in special.change.handle. // This still fires onchange a second time for check/radio after blur. if ( this.type === "checkbox" || this.type === "radio" ) { jQuery.event.add( this, "propertychange._change", function( event ) { if ( event.originalEvent.propertyName === "checked" ) { this._just_changed = true; } }); jQuery.event.add( this, "click._change", function( event ) { if ( this._just_changed && !event.isTrigger ) { this._just_changed = false; jQuery.event.simulate( "change", this, event, true ); } }); } return false; } // Delegated event; lazy-add a change handler on descendant inputs jQuery.event.add( this, "beforeactivate._change", function( e ) { var elem = e.target; if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) { jQuery.event.add( elem, "change._change", function( event ) { if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { jQuery.event.simulate( "change", this.parentNode, event, true ); } }); elem._change_attached = true; } }); }, handle: function( event ) { var elem = event.target; // Swallow native change events from checkbox/radio, we already triggered them above if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { return event.handleObj.handler.apply( this, arguments ); } }, teardown: function() { jQuery.event.remove( this, "._change" ); return rformElems.test( this.nodeName ); } }; } // Create "bubbling" focus and blur events if ( !jQuery.support.focusinBubbles ) { jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { // Attach a single capturing handler while someone wants focusin/focusout var attaches = 0, handler = function( event ) { jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); }; jQuery.event.special[ fix ] = { setup: function() { if ( attaches++ === 0 ) { document.addEventListener( orig, handler, true ); } }, teardown: function() { if ( --attaches === 0 ) { document.removeEventListener( orig, handler, true ); } } }; }); } jQuery.fn.extend({ on: function( types, selector, data, fn, /*INTERNAL*/ one ) { var origFn, type; // Types can be a map of types/handlers if ( typeof types === "object" ) { // ( types-Object, selector, data ) if ( typeof selector !== "string" ) { // && selector != null // ( types-Object, data ) data = data || selector; selector = undefined; } for ( type in types ) { this.on( type, selector, data, types[ type ], one ); } return this; } if ( data == null && fn == null ) { // ( types, fn ) fn = selector; data = selector = undefined; } else if ( fn == null ) { if ( typeof selector === "string" ) { // ( types, selector, fn ) fn = data; data = undefined; } else { // ( types, data, fn ) fn = data; data = selector; selector = undefined; } } if ( fn === false ) { fn = returnFalse; } else if ( !fn ) { return this; } if ( one === 1 ) { origFn = fn; fn = function( event ) { // Can use an empty set, since event contains the info jQuery().off( event ); return origFn.apply( this, arguments ); }; // Use same guid so caller can remove using origFn fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); } return this.each( function() { jQuery.event.add( this, types, fn, data, selector ); }); }, one: function( types, selector, data, fn ) { return this.on( types, selector, data, fn, 1 ); }, off: function( types, selector, fn ) { if ( types && types.preventDefault && types.handleObj ) { // ( event ) dispatched jQuery.Event var handleObj = types.handleObj; jQuery( types.delegateTarget ).off( handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, handleObj.selector, handleObj.handler ); return this; } if ( typeof types === "object" ) { // ( types-object [, selector] ) for ( var type in types ) { this.off( type, selector, types[ type ] ); } return this; } if ( selector === false || typeof selector === "function" ) { // ( types [, fn] ) fn = selector; selector = undefined; } if ( fn === false ) { fn = returnFalse; } return this.each(function() { jQuery.event.remove( this, types, fn, selector ); }); }, bind: function( types, data, fn ) { return this.on( types, null, data, fn ); }, unbind: function( types, fn ) { return this.off( types, null, fn ); }, live: function( types, data, fn ) { jQuery( this.context ).on( types, this.selector, data, fn ); return this; }, die: function( types, fn ) { jQuery( this.context ).off( types, this.selector || "**", fn ); return this; }, delegate: function( selector, types, data, fn ) { return this.on( types, selector, data, fn ); }, undelegate: function( selector, types, fn ) { // ( namespace ) or ( selector, types [, fn] ) return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn ); }, trigger: function( type, data ) { return this.each(function() { jQuery.event.trigger( type, data, this ); }); }, triggerHandler: function( type, data ) { if ( this[0] ) { return jQuery.event.trigger( type, data, this[0], true ); } }, toggle: function( fn ) { // Save reference to arguments for access in closure var args = arguments, guid = fn.guid || jQuery.guid++, i = 0, toggler = function( event ) { // Figure out which function to execute var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); // Make sure that clicks stop event.preventDefault(); // and execute the function return args[ lastToggle ].apply( this, arguments ) || false; }; // link all the functions, so any of them can unbind this click handler toggler.guid = guid; while ( i < args.length ) { args[ i++ ].guid = guid; } return this.click( toggler ); }, hover: function( fnOver, fnOut ) { return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); } }); jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { // Handle event binding jQuery.fn[ name ] = function( data, fn ) { if ( fn == null ) { fn = data; data = null; } return arguments.length > 0 ? this.on( name, null, data, fn ) : this.trigger( name ); }; if ( jQuery.attrFn ) { jQuery.attrFn[ name ] = true; } if ( rkeyEvent.test( name ) ) { jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks; } if ( rmouseEvent.test( name ) ) { jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; } }); /*! * Sizzle CSS Selector Engine * Copyright 2011, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * More information: http://sizzlejs.com/ */ (function(){ var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, expando = "sizcache" + (Math.random() + '').replace('.', ''), done = 0, toString = Object.prototype.toString, hasDuplicate = false, baseHasDuplicate = true, rBackslash = /\\/g, rNonWord = /\W/; // Here we check if the JavaScript engine is using some sort of // optimization where it does not always call our comparision // function. If that is the case, discard the hasDuplicate value. // Thus far that includes Google Chrome. [0, 0].sort(function() { baseHasDuplicate = false; return 0; }); var Sizzle = function( selector, context, results, seed ) { results = results || []; context = context || document; var origContext = context; if ( context.nodeType !== 1 && context.nodeType !== 9 ) { return []; } if ( !selector || typeof selector !== "string" ) { return results; } var m, set, checkSet, extra, ret, cur, pop, i, prune = true, contextXML = Sizzle.isXML( context ), parts = [], soFar = selector; // Reset the position of the chunker regexp (start from head) do { chunker.exec( "" ); m = chunker.exec( soFar ); if ( m ) { soFar = m[3]; parts.push( m[1] ); if ( m[2] ) { extra = m[3]; break; } } } while ( m ); if ( parts.length > 1 && origPOS.exec( selector ) ) { if ( parts.length === 2 && Expr.relative[ parts[0] ] ) { set = posProcess( parts[0] + parts[1], context, seed ); } else { set = Expr.relative[ parts[0] ] ? [ context ] : Sizzle( parts.shift(), context ); while ( parts.length ) { selector = parts.shift(); if ( Expr.relative[ selector ] ) { selector += parts.shift(); } set = posProcess( selector, set, seed ); } } } else { // Take a shortcut and set the context if the root selector is an ID // (but not if it'll be faster if the inner selector is an ID) if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML && Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) { ret = Sizzle.find( parts.shift(), context, contextXML ); context = ret.expr ? Sizzle.filter( ret.expr, ret.set )[0] : ret.set[0]; } if ( context ) { ret = seed ? { expr: parts.pop(), set: makeArray(seed) } : Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML ); set = ret.expr ? Sizzle.filter( ret.expr, ret.set ) : ret.set; if ( parts.length > 0 ) { checkSet = makeArray( set ); } else { prune = false; } while ( parts.length ) { cur = parts.pop(); pop = cur; if ( !Expr.relative[ cur ] ) { cur = ""; } else { pop = parts.pop(); } if ( pop == null ) { pop = context; } Expr.relative[ cur ]( checkSet, pop, contextXML ); } } else { checkSet = parts = []; } } if ( !checkSet ) { checkSet = set; } if ( !checkSet ) { Sizzle.error( cur || selector ); } if ( toString.call(checkSet) === "[object Array]" ) { if ( !prune ) { results.push.apply( results, checkSet ); } else if ( context && context.nodeType === 1 ) { for ( i = 0; checkSet[i] != null; i++ ) { if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) { results.push( set[i] ); } } } else { for ( i = 0; checkSet[i] != null; i++ ) { if ( checkSet[i] && checkSet[i].nodeType === 1 ) { results.push( set[i] ); } } } } else { makeArray( checkSet, results ); } if ( extra ) { Sizzle( extra, origContext, results, seed ); Sizzle.uniqueSort( results ); } return results; }; Sizzle.uniqueSort = function( results ) { if ( sortOrder ) { hasDuplicate = baseHasDuplicate; results.sort( sortOrder ); if ( hasDuplicate ) { for ( var i = 1; i < results.length; i++ ) { if ( results[i] === results[ i - 1 ] ) { results.splice( i--, 1 ); } } } } return results; }; Sizzle.matches = function( expr, set ) { return Sizzle( expr, null, null, set ); }; Sizzle.matchesSelector = function( node, expr ) { return Sizzle( expr, null, null, [node] ).length > 0; }; Sizzle.find = function( expr, context, isXML ) { var set, i, len, match, type, left; if ( !expr ) { return []; } for ( i = 0, len = Expr.order.length; i < len; i++ ) { type = Expr.order[i]; if ( (match = Expr.leftMatch[ type ].exec( expr )) ) { left = match[1]; match.splice( 1, 1 ); if ( left.substr( left.length - 1 ) !== "\\" ) { match[1] = (match[1] || "").replace( rBackslash, "" ); set = Expr.find[ type ]( match, context, isXML ); if ( set != null ) { expr = expr.replace( Expr.match[ type ], "" ); break; } } } } if ( !set ) { set = typeof context.getElementsByTagName !== "undefined" ? context.getElementsByTagName( "*" ) : []; } return { set: set, expr: expr }; }; Sizzle.filter = function( expr, set, inplace, not ) { var match, anyFound, type, found, item, filter, left, i, pass, old = expr, result = [], curLoop = set, isXMLFilter = set && set[0] && Sizzle.isXML( set[0] ); while ( expr && set.length ) { for ( type in Expr.filter ) { if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) { filter = Expr.filter[ type ]; left = match[1]; anyFound = false; match.splice(1,1); if ( left.substr( left.length - 1 ) === "\\" ) { continue; } if ( curLoop === result ) { result = []; } if ( Expr.preFilter[ type ] ) { match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter ); if ( !match ) { anyFound = found = true; } else if ( match === true ) { continue; } } if ( match ) { for ( i = 0; (item = curLoop[i]) != null; i++ ) { if ( item ) { found = filter( item, match, i, curLoop ); pass = not ^ found; if ( inplace && found != null ) { if ( pass ) { anyFound = true; } else { curLoop[i] = false; } } else if ( pass ) { result.push( item ); anyFound = true; } } } } if ( found !== undefined ) { if ( !inplace ) { curLoop = result; } expr = expr.replace( Expr.match[ type ], "" ); if ( !anyFound ) { return []; } break; } } } // Improper expression if ( expr === old ) { if ( anyFound == null ) { Sizzle.error( expr ); } else { break; } } old = expr; } return curLoop; }; Sizzle.error = function( msg ) { throw new Error( "Syntax error, unrecognized expression: " + msg ); }; /** * Utility function for retreiving the text value of an array of DOM nodes * @param {Array|Element} elem */ var getText = Sizzle.getText = function( elem ) { var i, node, nodeType = elem.nodeType, ret = ""; if ( nodeType ) { if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { // Use textContent for elements // innerText usage removed for consistency of new lines (see #11153) if ( typeof elem.textContent === "string" ) { return elem.textContent; } else { // Traverse it's children for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { ret += getText( elem ); } } } else if ( nodeType === 3 || nodeType === 4 ) { return elem.nodeValue; } } else { // If no nodeType, this is expected to be an array for ( i = 0; (node = elem[i]); i++ ) { // Do not traverse comment nodes if ( node.nodeType !== 8 ) { ret += getText( node ); } } } return ret; }; var Expr = Sizzle.selectors = { order: [ "ID", "NAME", "TAG" ], match: { ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/, NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/, ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/, TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/, CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/, POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/, PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/ }, leftMatch: {}, attrMap: { "class": "className", "for": "htmlFor" }, attrHandle: { href: function( elem ) { return elem.getAttribute( "href" ); }, type: function( elem ) { return elem.getAttribute( "type" ); } }, relative: { "+": function(checkSet, part){ var isPartStr = typeof part === "string", isTag = isPartStr && !rNonWord.test( part ), isPartStrNotTag = isPartStr && !isTag; if ( isTag ) { part = part.toLowerCase(); } for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) { if ( (elem = checkSet[i]) ) { while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {} checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ? elem || false : elem === part; } } if ( isPartStrNotTag ) { Sizzle.filter( part, checkSet, true ); } }, ">": function( checkSet, part ) { var elem, isPartStr = typeof part === "string", i = 0, l = checkSet.length; if ( isPartStr && !rNonWord.test( part ) ) { part = part.toLowerCase(); for ( ; i < l; i++ ) { elem = checkSet[i]; if ( elem ) { var parent = elem.parentNode; checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false; } } } else { for ( ; i < l; i++ ) { elem = checkSet[i]; if ( elem ) { checkSet[i] = isPartStr ? elem.parentNode : elem.parentNode === part; } } if ( isPartStr ) { Sizzle.filter( part, checkSet, true ); } } }, "": function(checkSet, part, isXML){ var nodeCheck, doneName = done++, checkFn = dirCheck; if ( typeof part === "string" && !rNonWord.test( part ) ) { part = part.toLowerCase(); nodeCheck = part; checkFn = dirNodeCheck; } checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML ); }, "~": function( checkSet, part, isXML ) { var nodeCheck, doneName = done++, checkFn = dirCheck; if ( typeof part === "string" && !rNonWord.test( part ) ) { part = part.toLowerCase(); nodeCheck = part; checkFn = dirNodeCheck; } checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML ); } }, find: { ID: function( match, context, isXML ) { if ( typeof context.getElementById !== "undefined" && !isXML ) { var m = context.getElementById(match[1]); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 return m && m.parentNode ? [m] : []; } }, NAME: function( match, context ) { if ( typeof context.getElementsByName !== "undefined" ) { var ret = [], results = context.getElementsByName( match[1] ); for ( var i = 0, l = results.length; i < l; i++ ) { if ( results[i].getAttribute("name") === match[1] ) { ret.push( results[i] ); } } return ret.length === 0 ? null : ret; } }, TAG: function( match, context ) { if ( typeof context.getElementsByTagName !== "undefined" ) { return context.getElementsByTagName( match[1] ); } } }, preFilter: { CLASS: function( match, curLoop, inplace, result, not, isXML ) { match = " " + match[1].replace( rBackslash, "" ) + " "; if ( isXML ) { return match; } for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) { if ( elem ) { if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) { if ( !inplace ) { result.push( elem ); } } else if ( inplace ) { curLoop[i] = false; } } } return false; }, ID: function( match ) { return match[1].replace( rBackslash, "" ); }, TAG: function( match, curLoop ) { return match[1].replace( rBackslash, "" ).toLowerCase(); }, CHILD: function( match ) { if ( match[1] === "nth" ) { if ( !match[2] ) { Sizzle.error( match[0] ); } match[2] = match[2].replace(/^\+|\s*/g, ''); // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6' var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec( match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" || !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]); // calculate the numbers (first)n+(last) including if they are negative match[2] = (test[1] + (test[2] || 1)) - 0; match[3] = test[3] - 0; } else if ( match[2] ) { Sizzle.error( match[0] ); } // TODO: Move to normal caching system match[0] = done++; return match; }, ATTR: function( match, curLoop, inplace, result, not, isXML ) { var name = match[1] = match[1].replace( rBackslash, "" ); if ( !isXML && Expr.attrMap[name] ) { match[1] = Expr.attrMap[name]; } // Handle if an un-quoted value was used match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" ); if ( match[2] === "~=" ) { match[4] = " " + match[4] + " "; } return match; }, PSEUDO: function( match, curLoop, inplace, result, not ) { if ( match[1] === "not" ) { // If we're dealing with a complex expression, or a simple one if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) { match[3] = Sizzle(match[3], null, null, curLoop); } else { var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not); if ( !inplace ) { result.push.apply( result, ret ); } return false; } } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) { return true; } return match; }, POS: function( match ) { match.unshift( true ); return match; } }, filters: { enabled: function( elem ) { return elem.disabled === false && elem.type !== "hidden"; }, disabled: function( elem ) { return elem.disabled === true; }, checked: function( elem ) { return elem.checked === true; }, selected: function( elem ) { // Accessing this property makes selected-by-default // options in Safari work properly if ( elem.parentNode ) { elem.parentNode.selectedIndex; } return elem.selected === true; }, parent: function( elem ) { return !!elem.firstChild; }, empty: function( elem ) { return !elem.firstChild; }, has: function( elem, i, match ) { return !!Sizzle( match[3], elem ).length; }, header: function( elem ) { return (/h\d/i).test( elem.nodeName ); }, text: function( elem ) { var attr = elem.getAttribute( "type" ), type = elem.type; // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) // use getAttribute instead to test this case return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null ); }, radio: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type; }, checkbox: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type; }, file: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "file" === elem.type; }, password: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "password" === elem.type; }, submit: function( elem ) { var name = elem.nodeName.toLowerCase(); return (name === "input" || name === "button") && "submit" === elem.type; }, image: function( elem ) { return elem.nodeName.toLowerCase() === "input" && "image" === elem.type; }, reset: function( elem ) { var name = elem.nodeName.toLowerCase(); return (name === "input" || name === "button") && "reset" === elem.type; }, button: function( elem ) { var name = elem.nodeName.toLowerCase(); return name === "input" && "button" === elem.type || name === "button"; }, input: function( elem ) { return (/input|select|textarea|button/i).test( elem.nodeName ); }, focus: function( elem ) { return elem === elem.ownerDocument.activeElement; } }, setFilters: { first: function( elem, i ) { return i === 0; }, last: function( elem, i, match, array ) { return i === array.length - 1; }, even: function( elem, i ) { return i % 2 === 0; }, odd: function( elem, i ) { return i % 2 === 1; }, lt: function( elem, i, match ) { return i < match[3] - 0; }, gt: function( elem, i, match ) { return i > match[3] - 0; }, nth: function( elem, i, match ) { return match[3] - 0 === i; }, eq: function( elem, i, match ) { return match[3] - 0 === i; } }, filter: { PSEUDO: function( elem, match, i, array ) { var name = match[1], filter = Expr.filters[ name ]; if ( filter ) { return filter( elem, i, match, array ); } else if ( name === "contains" ) { return (elem.textContent || elem.innerText || getText([ elem ]) || "").indexOf(match[3]) >= 0; } else if ( name === "not" ) { var not = match[3]; for ( var j = 0, l = not.length; j < l; j++ ) { if ( not[j] === elem ) { return false; } } return true; } else { Sizzle.error( name ); } }, CHILD: function( elem, match ) { var first, last, doneName, parent, cache, count, diff, type = match[1], node = elem; switch ( type ) { case "only": case "first": while ( (node = node.previousSibling) ) { if ( node.nodeType === 1 ) { return false; } } if ( type === "first" ) { return true; } node = elem; /* falls through */ case "last": while ( (node = node.nextSibling) ) { if ( node.nodeType === 1 ) { return false; } } return true; case "nth": first = match[2]; last = match[3]; if ( first === 1 && last === 0 ) { return true; } doneName = match[0]; parent = elem.parentNode; if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) { count = 0; for ( node = parent.firstChild; node; node = node.nextSibling ) { if ( node.nodeType === 1 ) { node.nodeIndex = ++count; } } parent[ expando ] = doneName; } diff = elem.nodeIndex - last; if ( first === 0 ) { return diff === 0; } else { return ( diff % first === 0 && diff / first >= 0 ); } } }, ID: function( elem, match ) { return elem.nodeType === 1 && elem.getAttribute("id") === match; }, TAG: function( elem, match ) { return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match; }, CLASS: function( elem, match ) { return (" " + (elem.className || elem.getAttribute("class")) + " ") .indexOf( match ) > -1; }, ATTR: function( elem, match ) { var name = match[1], result = Sizzle.attr ? Sizzle.attr( elem, name ) : Expr.attrHandle[ name ] ? Expr.attrHandle[ name ]( elem ) : elem[ name ] != null ? elem[ name ] : elem.getAttribute( name ), value = result + "", type = match[2], check = match[4]; return result == null ? type === "!=" : !type && Sizzle.attr ? result != null : type === "=" ? value === check : type === "*=" ? value.indexOf(check) >= 0 : type === "~=" ? (" " + value + " ").indexOf(check) >= 0 : !check ? value && result !== false : type === "!=" ? value !== check : type === "^=" ? value.indexOf(check) === 0 : type === "$=" ? value.substr(value.length - check.length) === check : type === "|=" ? value === check || value.substr(0, check.length + 1) === check + "-" : false; }, POS: function( elem, match, i, array ) { var name = match[2], filter = Expr.setFilters[ name ]; if ( filter ) { return filter( elem, i, match, array ); } } } }; var origPOS = Expr.match.POS, fescape = function(all, num){ return "\\" + (num - 0 + 1); }; for ( var type in Expr.match ) { Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) ); Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) ); } // Expose origPOS // "global" as in regardless of relation to brackets/parens Expr.match.globalPOS = origPOS; var makeArray = function( array, results ) { array = Array.prototype.slice.call( array, 0 ); if ( results ) { results.push.apply( results, array ); return results; } return array; }; // Perform a simple check to determine if the browser is capable of // converting a NodeList to an array using builtin methods. // Also verifies that the returned array holds DOM nodes // (which is not the case in the Blackberry browser) try { Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType; // Provide a fallback method if it does not work } catch( e ) { makeArray = function( array, results ) { var i = 0, ret = results || []; if ( toString.call(array) === "[object Array]" ) { Array.prototype.push.apply( ret, array ); } else { if ( typeof array.length === "number" ) { for ( var l = array.length; i < l; i++ ) { ret.push( array[i] ); } } else { for ( ; array[i]; i++ ) { ret.push( array[i] ); } } } return ret; }; } var sortOrder, siblingCheck; if ( document.documentElement.compareDocumentPosition ) { sortOrder = function( a, b ) { if ( a === b ) { hasDuplicate = true; return 0; } if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) { return a.compareDocumentPosition ? -1 : 1; } return a.compareDocumentPosition(b) & 4 ? -1 : 1; }; } else { sortOrder = function( a, b ) { // The nodes are identical, we can exit early if ( a === b ) { hasDuplicate = true; return 0; // Fallback to using sourceIndex (in IE) if it's available on both nodes } else if ( a.sourceIndex && b.sourceIndex ) { return a.sourceIndex - b.sourceIndex; } var al, bl, ap = [], bp = [], aup = a.parentNode, bup = b.parentNode, cur = aup; // If the nodes are siblings (or identical) we can do a quick check if ( aup === bup ) { return siblingCheck( a, b ); // If no parents were found then the nodes are disconnected } else if ( !aup ) { return -1; } else if ( !bup ) { return 1; } // Otherwise they're somewhere else in the tree so we need // to build up a full list of the parentNodes for comparison while ( cur ) { ap.unshift( cur ); cur = cur.parentNode; } cur = bup; while ( cur ) { bp.unshift( cur ); cur = cur.parentNode; } al = ap.length; bl = bp.length; // Start walking down the tree looking for a discrepancy for ( var i = 0; i < al && i < bl; i++ ) { if ( ap[i] !== bp[i] ) { return siblingCheck( ap[i], bp[i] ); } } // We ended someplace up the tree so do a sibling check return i === al ? siblingCheck( a, bp[i], -1 ) : siblingCheck( ap[i], b, 1 ); }; siblingCheck = function( a, b, ret ) { if ( a === b ) { return ret; } var cur = a.nextSibling; while ( cur ) { if ( cur === b ) { return -1; } cur = cur.nextSibling; } return 1; }; } // Check to see if the browser returns elements by name when // querying by getElementById (and provide a workaround) (function(){ // We're going to inject a fake input element with a specified name var form = document.createElement("div"), id = "script" + (new Date()).getTime(), root = document.documentElement; form.innerHTML = ""; // Inject it into the root element, check its status, and remove it quickly root.insertBefore( form, root.firstChild ); // The workaround has to do additional checks after a getElementById // Which slows things down for other browsers (hence the branching) if ( document.getElementById( id ) ) { Expr.find.ID = function( match, context, isXML ) { if ( typeof context.getElementById !== "undefined" && !isXML ) { var m = context.getElementById(match[1]); return m ? m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ? [m] : undefined : []; } }; Expr.filter.ID = function( elem, match ) { var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); return elem.nodeType === 1 && node && node.nodeValue === match; }; } root.removeChild( form ); // release memory in IE root = form = null; })(); (function(){ // Check to see if the browser returns only elements // when doing getElementsByTagName("*") // Create a fake element var div = document.createElement("div"); div.appendChild( document.createComment("") ); // Make sure no comments are found if ( div.getElementsByTagName("*").length > 0 ) { Expr.find.TAG = function( match, context ) { var results = context.getElementsByTagName( match[1] ); // Filter out possible comments if ( match[1] === "*" ) { var tmp = []; for ( var i = 0; results[i]; i++ ) { if ( results[i].nodeType === 1 ) { tmp.push( results[i] ); } } results = tmp; } return results; }; } // Check to see if an attribute returns normalized href attributes div.innerHTML = ""; if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" && div.firstChild.getAttribute("href") !== "#" ) { Expr.attrHandle.href = function( elem ) { return elem.getAttribute( "href", 2 ); }; } // release memory in IE div = null; })(); if ( document.querySelectorAll ) { (function(){ var oldSizzle = Sizzle, div = document.createElement("div"), id = "__sizzle__"; div.innerHTML = "

"; // Safari can't handle uppercase or unicode characters when // in quirks mode. if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) { return; } Sizzle = function( query, context, extra, seed ) { context = context || document; // Only use querySelectorAll on non-XML documents // (ID selectors don't work in non-HTML documents) if ( !seed && !Sizzle.isXML(context) ) { // See if we find a selector to speed up var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query ); if ( match && (context.nodeType === 1 || context.nodeType === 9) ) { // Speed-up: Sizzle("TAG") if ( match[1] ) { return makeArray( context.getElementsByTagName( query ), extra ); // Speed-up: Sizzle(".CLASS") } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) { return makeArray( context.getElementsByClassName( match[2] ), extra ); } } if ( context.nodeType === 9 ) { // Speed-up: Sizzle("body") // The body element only exists once, optimize finding it if ( query === "body" && context.body ) { return makeArray( [ context.body ], extra ); // Speed-up: Sizzle("#ID") } else if ( match && match[3] ) { var elem = context.getElementById( match[3] ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 if ( elem && elem.parentNode ) { // Handle the case where IE and Opera return items // by name instead of ID if ( elem.id === match[3] ) { return makeArray( [ elem ], extra ); } } else { return makeArray( [], extra ); } } try { return makeArray( context.querySelectorAll(query), extra ); } catch(qsaError) {} // qSA works strangely on Element-rooted queries // We can work around this by specifying an extra ID on the root // and working up from there (Thanks to Andrew Dupont for the technique) // IE 8 doesn't work on object elements } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { var oldContext = context, old = context.getAttribute( "id" ), nid = old || id, hasParent = context.parentNode, relativeHierarchySelector = /^\s*[+~]/.test( query ); if ( !old ) { context.setAttribute( "id", nid ); } else { nid = nid.replace( /'/g, "\\$&" ); } if ( relativeHierarchySelector && hasParent ) { context = context.parentNode; } try { if ( !relativeHierarchySelector || hasParent ) { return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra ); } } catch(pseudoError) { } finally { if ( !old ) { oldContext.removeAttribute( "id" ); } } } } return oldSizzle(query, context, extra, seed); }; for ( var prop in oldSizzle ) { Sizzle[ prop ] = oldSizzle[ prop ]; } // release memory in IE div = null; })(); } (function(){ var html = document.documentElement, matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector; if ( matches ) { // Check to see if it's possible to do matchesSelector // on a disconnected node (IE 9 fails this) var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ), pseudoWorks = false; try { // This should fail with an exception // Gecko does not error, returns false instead matches.call( document.documentElement, "[test!='']:sizzle" ); } catch( pseudoError ) { pseudoWorks = true; } Sizzle.matchesSelector = function( node, expr ) { // Make sure that attribute selectors are quoted expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']"); if ( !Sizzle.isXML( node ) ) { try { if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) { var ret = matches.call( node, expr ); // IE 9's matchesSelector returns false on disconnected nodes if ( ret || !disconnectedMatch || // As well, disconnected nodes are said to be in a document // fragment in IE 9, so check for that node.document && node.document.nodeType !== 11 ) { return ret; } } } catch(e) {} } return Sizzle(expr, null, null, [node]).length > 0; }; } })(); (function(){ var div = document.createElement("div"); div.innerHTML = "
"; // Opera can't find a second classname (in 9.6) // Also, make sure that getElementsByClassName actually exists if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) { return; } // Safari caches class attributes, doesn't catch changes (in 3.2) div.lastChild.className = "e"; if ( div.getElementsByClassName("e").length === 1 ) { return; } Expr.order.splice(1, 0, "CLASS"); Expr.find.CLASS = function( match, context, isXML ) { if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) { return context.getElementsByClassName(match[1]); } }; // release memory in IE div = null; })(); function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { var match = false; elem = elem[dir]; while ( elem ) { if ( elem[ expando ] === doneName ) { match = checkSet[elem.sizset]; break; } if ( elem.nodeType === 1 && !isXML ){ elem[ expando ] = doneName; elem.sizset = i; } if ( elem.nodeName.toLowerCase() === cur ) { match = elem; break; } elem = elem[dir]; } checkSet[i] = match; } } } function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) { for ( var i = 0, l = checkSet.length; i < l; i++ ) { var elem = checkSet[i]; if ( elem ) { var match = false; elem = elem[dir]; while ( elem ) { if ( elem[ expando ] === doneName ) { match = checkSet[elem.sizset]; break; } if ( elem.nodeType === 1 ) { if ( !isXML ) { elem[ expando ] = doneName; elem.sizset = i; } if ( typeof cur !== "string" ) { if ( elem === cur ) { match = true; break; } } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) { match = elem; break; } } elem = elem[dir]; } checkSet[i] = match; } } } if ( document.documentElement.contains ) { Sizzle.contains = function( a, b ) { return a !== b && (a.contains ? a.contains(b) : true); }; } else if ( document.documentElement.compareDocumentPosition ) { Sizzle.contains = function( a, b ) { return !!(a.compareDocumentPosition(b) & 16); }; } else { Sizzle.contains = function() { return false; }; } Sizzle.isXML = function( elem ) { // documentElement is verified for cases where it doesn't yet exist // (such as loading iframes in IE - #4833) var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement; return documentElement ? documentElement.nodeName !== "HTML" : false; }; var posProcess = function( selector, context, seed ) { var match, tmpSet = [], later = "", root = context.nodeType ? [context] : context; // Position selectors must be done after the filter // And so must :not(positional) so we move all PSEUDOs to the end while ( (match = Expr.match.PSEUDO.exec( selector )) ) { later += match[0]; selector = selector.replace( Expr.match.PSEUDO, "" ); } selector = Expr.relative[selector] ? selector + "*" : selector; for ( var i = 0, l = root.length; i < l; i++ ) { Sizzle( selector, root[i], tmpSet, seed ); } return Sizzle.filter( later, tmpSet ); }; // EXPOSE // Override sizzle attribute retrieval Sizzle.attr = jQuery.attr; Sizzle.selectors.attrMap = {}; jQuery.find = Sizzle; jQuery.expr = Sizzle.selectors; jQuery.expr[":"] = jQuery.expr.filters; jQuery.unique = Sizzle.uniqueSort; jQuery.text = Sizzle.getText; jQuery.isXMLDoc = Sizzle.isXML; jQuery.contains = Sizzle.contains; })(); var runtil = /Until$/, rparentsprev = /^(?:parents|prevUntil|prevAll)/, // Note: This RegExp should be improved, or likely pulled from Sizzle rmultiselector = /,/, isSimple = /^.[^:#\[\.,]*$/, slice = Array.prototype.slice, POS = jQuery.expr.match.globalPOS, // methods guaranteed to produce a unique set when starting from a unique set guaranteedUnique = { children: true, contents: true, next: true, prev: true }; jQuery.fn.extend({ find: function( selector ) { var self = this, i, l; if ( typeof selector !== "string" ) { return jQuery( selector ).filter(function() { for ( i = 0, l = self.length; i < l; i++ ) { if ( jQuery.contains( self[ i ], this ) ) { return true; } } }); } var ret = this.pushStack( "", "find", selector ), length, n, r; for ( i = 0, l = this.length; i < l; i++ ) { length = ret.length; jQuery.find( selector, this[i], ret ); if ( i > 0 ) { // Make sure that the results are unique for ( n = length; n < ret.length; n++ ) { for ( r = 0; r < length; r++ ) { if ( ret[r] === ret[n] ) { ret.splice(n--, 1); break; } } } } } return ret; }, has: function( target ) { var targets = jQuery( target ); return this.filter(function() { for ( var i = 0, l = targets.length; i < l; i++ ) { if ( jQuery.contains( this, targets[i] ) ) { return true; } } }); }, not: function( selector ) { return this.pushStack( winnow(this, selector, false), "not", selector); }, filter: function( selector ) { return this.pushStack( winnow(this, selector, true), "filter", selector ); }, is: function( selector ) { return !!selector && ( typeof selector === "string" ? // If this is a positional selector, check membership in the returned set // so $("p:first").is("p:last") won't return true for a doc with two "p". POS.test( selector ) ? jQuery( selector, this.context ).index( this[0] ) >= 0 : jQuery.filter( selector, this ).length > 0 : this.filter( selector ).length > 0 ); }, closest: function( selectors, context ) { var ret = [], i, l, cur = this[0]; // Array (deprecated as of jQuery 1.7) if ( jQuery.isArray( selectors ) ) { var level = 1; while ( cur && cur.ownerDocument && cur !== context ) { for ( i = 0; i < selectors.length; i++ ) { if ( jQuery( cur ).is( selectors[ i ] ) ) { ret.push({ selector: selectors[ i ], elem: cur, level: level }); } } cur = cur.parentNode; level++; } return ret; } // String var pos = POS.test( selectors ) || typeof selectors !== "string" ? jQuery( selectors, context || this.context ) : 0; for ( i = 0, l = this.length; i < l; i++ ) { cur = this[i]; while ( cur ) { if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { ret.push( cur ); break; } else { cur = cur.parentNode; if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) { break; } } } } ret = ret.length > 1 ? jQuery.unique( ret ) : ret; return this.pushStack( ret, "closest", selectors ); }, // Determine the position of an element within // the matched set of elements index: function( elem ) { // No argument, return index in parent if ( !elem ) { return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; } // index in selector if ( typeof elem === "string" ) { return jQuery.inArray( this[0], jQuery( elem ) ); } // Locate the position of the desired element return jQuery.inArray( // If it receives a jQuery object, the first element is used elem.jquery ? elem[0] : elem, this ); }, add: function( selector, context ) { var set = typeof selector === "string" ? jQuery( selector, context ) : jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), all = jQuery.merge( this.get(), set ); return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? all : jQuery.unique( all ) ); }, andSelf: function() { return this.add( this.prevObject ); } }); // A painfully simple check to see if an element is disconnected // from a document (should be improved, where feasible). function isDisconnected( node ) { return !node || !node.parentNode || node.parentNode.nodeType === 11; } jQuery.each({ parent: function( elem ) { var parent = elem.parentNode; return parent && parent.nodeType !== 11 ? parent : null; }, parents: function( elem ) { return jQuery.dir( elem, "parentNode" ); }, parentsUntil: function( elem, i, until ) { return jQuery.dir( elem, "parentNode", until ); }, next: function( elem ) { return jQuery.nth( elem, 2, "nextSibling" ); }, prev: function( elem ) { return jQuery.nth( elem, 2, "previousSibling" ); }, nextAll: function( elem ) { return jQuery.dir( elem, "nextSibling" ); }, prevAll: function( elem ) { return jQuery.dir( elem, "previousSibling" ); }, nextUntil: function( elem, i, until ) { return jQuery.dir( elem, "nextSibling", until ); }, prevUntil: function( elem, i, until ) { return jQuery.dir( elem, "previousSibling", until ); }, siblings: function( elem ) { return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); }, children: function( elem ) { return jQuery.sibling( elem.firstChild ); }, contents: function( elem ) { return jQuery.nodeName( elem, "iframe" ) ? elem.contentDocument || elem.contentWindow.document : jQuery.makeArray( elem.childNodes ); } }, function( name, fn ) { jQuery.fn[ name ] = function( until, selector ) { var ret = jQuery.map( this, fn, until ); if ( !runtil.test( name ) ) { selector = until; } if ( selector && typeof selector === "string" ) { ret = jQuery.filter( selector, ret ); } ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) { ret = ret.reverse(); } return this.pushStack( ret, name, slice.call( arguments ).join(",") ); }; }); jQuery.extend({ filter: function( expr, elems, not ) { if ( not ) { expr = ":not(" + expr + ")"; } return elems.length === 1 ? jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : jQuery.find.matches(expr, elems); }, dir: function( elem, dir, until ) { var matched = [], cur = elem[ dir ]; while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { if ( cur.nodeType === 1 ) { matched.push( cur ); } cur = cur[dir]; } return matched; }, nth: function( cur, result, dir, elem ) { result = result || 1; var num = 0; for ( ; cur; cur = cur[dir] ) { if ( cur.nodeType === 1 && ++num === result ) { break; } } return cur; }, sibling: function( n, elem ) { var r = []; for ( ; n; n = n.nextSibling ) { if ( n.nodeType === 1 && n !== elem ) { r.push( n ); } } return r; } }); // Implement the identical functionality for filter and not function winnow( elements, qualifier, keep ) { // Can't pass null or undefined to indexOf in Firefox 4 // Set to 0 to skip string check qualifier = qualifier || 0; if ( jQuery.isFunction( qualifier ) ) { return jQuery.grep(elements, function( elem, i ) { var retVal = !!qualifier.call( elem, i, elem ); return retVal === keep; }); } else if ( qualifier.nodeType ) { return jQuery.grep(elements, function( elem, i ) { return ( elem === qualifier ) === keep; }); } else if ( typeof qualifier === "string" ) { var filtered = jQuery.grep(elements, function( elem ) { return elem.nodeType === 1; }); if ( isSimple.test( qualifier ) ) { return jQuery.filter(qualifier, filtered, !keep); } else { qualifier = jQuery.filter( qualifier, filtered ); } } return jQuery.grep(elements, function( elem, i ) { return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; }); } function createSafeFragment( document ) { var list = nodeNames.split( "|" ), safeFrag = document.createDocumentFragment(); if ( safeFrag.createElement ) { while ( list.length ) { safeFrag.createElement( list.pop() ); } } return safeFrag; } var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g, rleadingWhitespace = /^\s+/, rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig, rtagName = /<([\w:]+)/, rtbody = /]", "i"), // checked="checked" or checked rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, rscriptType = /\/(java|ecma)script/i, rcleanScript = /^\s*", "" ], legend: [ 1, "
", "
" ], thead: [ 1, "", "
" ], tr: [ 2, "", "
" ], td: [ 3, "", "
" ], col: [ 2, "", "
" ], area: [ 1, "", "" ], _default: [ 0, "", "" ] }, safeFragment = createSafeFragment( document ); wrapMap.optgroup = wrapMap.option; wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; wrapMap.th = wrapMap.td; // IE can't serialize and

Request Headers

Key Value
Apitoken {"sig": "25ae3f6cdb1711e79997005056a6aba2", "name": "root"}
Content-Type application/x-www-form-urlencoded

Post Form

Key Value
name qfeng

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"sig":"05434ff8db0311e7afde005056a6aba2","name":"qfeng","admin":true}

Request Headers

Key Value
Apitoken {"sig": "25ae3f6cdb1711e79997005056a6aba2", "name": "root"}
Content-Type application/x-www-form-urlencoded

Post Form

Key Value
name daye

Response Code

400

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"error":"no such user"}

Request Headers

Key Value
Apitoken {"sig": "05434ff8db0311e7afde005056a6aba2", "name": "qfeng"}
Content-Type application/x-www-form-urlencoded

Post Form

Key Value
name qfeng

Response Code

400

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"error":"API_USER not admin, no permissions can do this"}

Request Headers

Key Value
Apitoken {"sig": "25ae3f6cdb1711e79997005056a6aba2", "name": "root"}
Content-Type application/json

Request Body

{"admin": "yes", "user_id": 12}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"message":"user role update sccuessful, affect row: 0"}

Request Headers

Key Value
Apitoken {"sig": "25ae3f6cdb1711e79997005056a6aba2", "name": "root"}
Content-Type application/json

Request Body

{"admin": "no", "user_id": 12}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"message":"user role update sccuessful, affect row: 1"}

Request Headers

Key Value
Apitoken {"sig": "25ae3f6cdb1711e79997005056a6aba2", "name": "root"}
Content-Type application/json

Request Body

{"password": "lalala", "user_id": 12}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"message":"password updated!"}

Request Headers

Key Value
Apitoken {"sig": "25ae3f6cdb1711e79997005056a6aba2", "name": "root"}
Content-Type application/json

Request Body

{"user_id": 12}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"message":"user 12 has been delete, affect row: 1"}


================================================ FILE: docs/doc/admin.html.json ================================================ { "ApiSpecs": [ { "HttpVerb": "POST", "Path": "/api/v1/admin/login", "Calls": [ { "Id": 0, "CurrentPath": "/api/v1/admin/login", "MethodType": "POST", "PostForm": { "name": "qfeng" }, "RequestHeader": { "Apitoken": "{\"sig\": \"25ae3f6cdb1711e79997005056a6aba2\", \"name\": \"root\"}", "Content-Type": " application/x-www-form-urlencoded\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"sig\":\"05434ff8db0311e7afde005056a6aba2\",\"name\":\"qfeng\",\"admin\":true}", "ResponseCode": 200 }, { "Id": 1, "CurrentPath": "/api/v1/admin/login", "MethodType": "POST", "PostForm": { "name": "daye" }, "RequestHeader": { "Apitoken": "{\"sig\": \"25ae3f6cdb1711e79997005056a6aba2\", \"name\": \"root\"}", "Content-Type": " application/x-www-form-urlencoded\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"error\":\"no such user\"}", "ResponseCode": 400 }, { "Id": 2, "CurrentPath": "/api/v1/admin/login", "MethodType": "POST", "PostForm": { "name": "qfeng" }, "RequestHeader": { "Apitoken": "{\"sig\": \"05434ff8db0311e7afde005056a6aba2\", \"name\": \"qfeng\"}", "Content-Type": " application/x-www-form-urlencoded\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"error\":\"API_USER not admin, no permissions can do this\"}", "ResponseCode": 400 } ] }, { "HttpVerb": "PUT", "Path": "/api/v1/admin/change_user_role", "Calls": [ { "Id": 3, "CurrentPath": "/api/v1/admin/change_user_role", "MethodType": "PUT", "PostForm": null, "RequestHeader": { "Apitoken": "{\"sig\": \"25ae3f6cdb1711e79997005056a6aba2\", \"name\": \"root\"}", "Content-Type": " application/json\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"admin\": \"yes\", \"user_id\": 12}", "ResponseBody": "{\"message\":\"user role update sccuessful, affect row: 0\"}", "ResponseCode": 200 }, { "Id": 4, "CurrentPath": "/api/v1/admin/change_user_role", "MethodType": "PUT", "PostForm": null, "RequestHeader": { "Apitoken": "{\"sig\": \"25ae3f6cdb1711e79997005056a6aba2\", \"name\": \"root\"}", "Content-Type": " application/json\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"admin\": \"no\", \"user_id\": 12}", "ResponseBody": "{\"message\":\"user role update sccuessful, affect row: 1\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "PUT", "Path": "/api/v1/admin/change_user_passwd", "Calls": [ { "Id": 5, "CurrentPath": "/api/v1/admin/change_user_passwd", "MethodType": "PUT", "PostForm": null, "RequestHeader": { "Apitoken": "{\"sig\": \"25ae3f6cdb1711e79997005056a6aba2\", \"name\": \"root\"}", "Content-Type": " application/json\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"password\": \"lalala\", \"user_id\": 12}", "ResponseBody": "{\"message\":\"password updated!\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "DELETE", "Path": "/api/v1/admin/delete_user", "Calls": [ { "Id": 6, "CurrentPath": "/api/v1/admin/delete_user", "MethodType": "DELETE", "PostForm": null, "RequestHeader": { "Apitoken": "{\"sig\": \"25ae3f6cdb1711e79997005056a6aba2\", \"name\": \"root\"}", "Content-Type": " application/json\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"user_id\": 12}", "ResponseBody": "{\"message\":\"user 12 has been delete, affect row: 1\"}", "ResponseCode": 200 } ] } ] } ================================================ FILE: docs/doc/aggregator.html ================================================ API Documentation

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
Content-Type application/json
X-Forwarded-For 127.0.0.1

Request Body

{"tags":"","step":60,"numerator":"$(cpu.idle)","metric":"test.idle","hostgroup_id":343,"endpoint":"testenp","denominator":"2"}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"id":16,"grp_id":343,"numerator":"$(cpu.idle)","denominator":"2","endpoint":"testenp","metric":"test.idle","tags":"","ds_type":"GAUGE","step":60,"creator":"root"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"id":13,"grp_id":343,"numerator":"$(cpu.idle)","denominator":"2","endpoint":"testenp","metric":"test.idle","tags":"","ds_type":"GAUGE","step":60,"creator":"root"},{"id":14,"grp_id":343,"numerator":"$(cpu.idle)","denominator":"2","endpoint":"testenp","metric":"test.idle","tags":"","ds_type":"GAUGE","step":60,"creator":"root"},{"id":15,"grp_id":343,"numerator":"$(cpu.idle)","denominator":"2","endpoint":"testenp","metric":"test.idle","tags":"","ds_type":"GAUGE","step":60,"creator":"root"},{"id":16,"grp_id":343,"numerator":"$(cpu.idle)","denominator":"2","endpoint":"testenp","metric":"test.idle","tags":"","ds_type":"GAUGE","step":60,"creator":"root"}]

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
Content-Type application/json
X-Forwarded-For 127.0.0.1

Request Body

{"tags":"","step":60,"numerator":"$(cpu.idle)","metric":"test.idle","id":16,"endpoint":"testenp","denominator":"$#"}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"id":16,"grp_id":343,"numerator":"$(cpu.idle)","denominator":"$#","endpoint":"testenp","metric":"test.idle","tags":"","ds_type":"GAUGE","step":60,"creator":"root"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"id":16,"grp_id":343,"numerator":"$(cpu.idle)","denominator":"$#","endpoint":"testenp","metric":"test.idle","tags":"","ds_type":"GAUGE","step":60,"creator":"root"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"message":"aggregator:16 is deleted"}


================================================ FILE: docs/doc/aggregator.html.json ================================================ { "ApiSpecs": [ { "HttpVerb": "POST", "Path": "/api/v1/aggregator", "Calls": [ { "Id": 0, "CurrentPath": "/api/v1/aggregator", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"tags\":\"\",\"step\":60,\"numerator\":\"$(cpu.idle)\",\"metric\":\"test.idle\",\"hostgroup_id\":343,\"endpoint\":\"testenp\",\"denominator\":\"2\"}", "ResponseBody": "{\"id\":16,\"grp_id\":343,\"numerator\":\"$(cpu.idle)\",\"denominator\":\"2\",\"endpoint\":\"testenp\",\"metric\":\"test.idle\",\"tags\":\"\",\"ds_type\":\"GAUGE\",\"step\":60,\"creator\":\"root\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/hostgroup/343/aggregators", "Calls": [ { "Id": 1, "CurrentPath": "/api/v1/hostgroup/343/aggregators", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"hostgroup\": \"test_group\", \"aggregators\": [{\"id\":13,\"grp_id\":343,\"numerator\":\"$(cpu.idle)\",\"denominator\":\"2\",\"endpoint\":\"testenp\",\"metric\":\"test.idle\",\"tags\":\"\",\"ds_type\":\"GAUGE\",\"step\":60,\"creator\":\"root\"},{\"id\":14,\"grp_id\":343,\"numerator\":\"$(cpu.idle)\",\"denominator\":\"2\",\"endpoint\":\"testenp\",\"metric\":\"test.idle\",\"tags\":\"\",\"ds_type\":\"GAUGE\",\"step\":60,\"creator\":\"root\"},{\"id\":15,\"grp_id\":343,\"numerator\":\"$(cpu.idle)\",\"denominator\":\"2\",\"endpoint\":\"testenp\",\"metric\":\"test.idle\",\"tags\":\"\",\"ds_type\":\"GAUGE\",\"step\":60,\"creator\":\"root\"},{\"id\":16,\"grp_id\":343,\"numerator\":\"$(cpu.idle)\",\"denominator\":\"2\",\"endpoint\":\"testenp\",\"metric\":\"test.idle\",\"tags\":\"\",\"ds_type\":\"GAUGE\",\"step\":60,\"creator\":\"root\"}]}", "ResponseCode": 200 } ] }, { "HttpVerb": "PUT", "Path": "/api/v1/aggregator", "Calls": [ { "Id": 2, "CurrentPath": "/api/v1/aggregator", "MethodType": "PUT", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"tags\":\"\",\"step\":60,\"numerator\":\"$(cpu.idle)\",\"metric\":\"test.idle\",\"id\":16,\"endpoint\":\"testenp\",\"denominator\":\"$#\"}", "ResponseBody": "{\"id\":16,\"grp_id\":343,\"numerator\":\"$(cpu.idle)\",\"denominator\":\"$#\",\"endpoint\":\"testenp\",\"metric\":\"test.idle\",\"tags\":\"\",\"ds_type\":\"GAUGE\",\"step\":60,\"creator\":\"root\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/aggregator/16", "Calls": [ { "Id": 3, "CurrentPath": "/api/v1/aggregator/16", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"id\":16,\"grp_id\":343,\"numerator\":\"$(cpu.idle)\",\"denominator\":\"$#\",\"endpoint\":\"testenp\",\"metric\":\"test.idle\",\"tags\":\"\",\"ds_type\":\"GAUGE\",\"step\":60,\"creator\":\"root\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "DELETE", "Path": "/api/v1/aggregator/16", "Calls": [ { "Id": 4, "CurrentPath": "/api/v1/aggregator/16", "MethodType": "DELETE", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"message\":\"aggregator:16 is deleted\"}", "ResponseCode": 200 } ] } ] } ================================================ FILE: docs/doc/alarm.html ================================================ API Documentation

Request Headers

Key Value
Apitoken {"name": "root", "sig": "233fdb00f99811e68a5c001500c6ca5a"}
Content-Type application/json

Request Body

			{
	      "startTime": 1466956800,
	    	"endTime": 1480521600,
	    	"status": "PROBLEM",
	    	"process_status": "ignored,unresolved",
	    	"limit": 10
	    }

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"id":"s_46_1ac45122afb893adc02fbd30154ac303","endpoint":"agent4","metric":"cpu.iowait","func":"all(#3)","cond":"48.33759590792839 \u003e 40","note":"CPU I/O wait超过40","step":1,"current_step":1,"priority":1,"status":"PROBLEM","timestamp":"2016-08-01T06:25:00+08:00","update_at":"2016-08-01T06:25:00+08:00","closed_at":null,"closed_note":"","user_modified":0,"tpl_creator":"root","expression_id":0,"strategy_id":46,"template_id":126,"process_note":16907,"process_status":"ignored"},{"id":"s_50_6438ac68b30e2712fb8f00d894c46e21","endpoint":"agent5","metric":"cpu.idle","func":"avg(#3)","cond":"95.16331658291456 \u003c= 98","note":"cpu空闲值报警","step":1,"current_step":1,"priority":3,"status":"PROBLEM","timestamp":"2016-07-03T16:13:00+08:00","update_at":"2016-07-03T16:13:00+08:00","closed_at":null,"closed_note":"","user_modified":0,"tpl_creator":"root","expression_id":0,"strategy_id":50,"template_id":53,"process_note":1181,"process_status":"ignored"}]

Request Headers

Key Value
Apitoken {"name": "root", "sig": "233fdb00f99811e68a5c001500c6ca5a"}
Content-Type application/json

Request Body

			{
	      "startTime": 1466956800,
	    	"endTime": 1480521600,
	    	"status": "PROBLEM,OK",
	    	"process_status": "ignored,unresolved",
	    	"limit": 10
	    }

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"id":"s_322_00c5f5c87a71bd4c686c0a4a0544b719","endpoint":"agent8","metric":"cpu.iowait","func":"avg(#3)","cond":"0 \u003e 40","note":"CPU I/O wait超过40","step":1,"current_step":1,"priority":1,"status":"OK","timestamp":"2016-11-30T20:10:00+08:00","update_at":"2016-11-30T20:10:00+08:00","closed_at":null,"closed_note":"","user_modified":0,"tpl_creator":"root","expression_id":0,"strategy_id":322,"template_id":125,"process_note":0,"process_status":"unresolved"},{"id":"s_322_00a9b9f9f859d8436f9b643ea5a1fb5e","endpoint":"agent6","metric":"cpu.iowait","func":"avg(#3)","cond":"0 \u003e 40","note":"CPU I/O wait超过40","step":1,"current_step":1,"priority":1,"status":"OK","timestamp":"2016-11-14T22:16:00+08:00","update_at":"2016-11-14T22:16:00+08:00","closed_at":null,"closed_note":"","user_modified":0,"tpl_creator":"root","expression_id":0,"strategy_id":322,"template_id":140,"process_note":0,"process_status":"unresolved"},{"id":"s_322_00ba3072006a8ba863108d4b3f9c1c51","endpoint":"agent7","metric":"cpu.iowait","func":"avg(#3)","cond":"0.0695615485072203 \u003e 40","note":"CPU I/O wait超过40","step":1,"current_step":1,"priority":1,"status":"OK","timestamp":"2016-11-14T20:43:00+08:00","update_at":"2016-11-14T20:43:00+08:00","closed_at":null,"closed_note":"","user_modified":0,"tpl_creator":"root","expression_id":0,"strategy_id":322,"template_id":125,"process_note":0,"process_status":"unresolved"},{"id":"s_322_002e499f3b56420fdea506c887e51799","endpoint":"agent3","metric":"cpu.iowait","func":"avg(#3)","cond":"30.76679150609009 \u003e 40","note":"CPU I/O wait超过40","step":1,"current_step":1,"priority":1,"status":"OK","timestamp":"2016-11-07T04:28:00+08:00","update_at":"2016-11-07T04:28:00+08:00","closed_at":null,"closed_note":"","user_modified":0,"tpl_creator":"root","expression_id":0,"strategy_id":322,"template_id":125,"process_note":0,"process_status":"unresolved"},{"id":"s_322_00cc81434a0e277b57254a89a839a47b","endpoint":"agent9","metric":"cpu.iowait","func":"avg(#3)","cond":"0.041876046901172526 \u003e 40","note":"CPU I/O wait超过40","step":1,"current_step":1,"priority":1,"status":"OK","timestamp":"2016-10-28T10:37:00+08:00","update_at":"2016-10-28T10:37:00+08:00","closed_at":null,"closed_note":"","user_modified":0,"tpl_creator":"root","expression_id":0,"strategy_id":322,"template_id":125,"process_note":0,"process_status":"unresolved"},{"id":"s_322_001da6a5f95d83387cdfecc37ac70c24","endpoint":"agent2","metric":"cpu.iowait","func":"avg(#3)","cond":"34.40479690409319 \u003e 40","note":"CPU I/O wait超过40","step":1,"current_step":1,"priority":1,"status":"OK","timestamp":"2016-10-27T15:37:00+08:00","update_at":"2016-10-27T15:37:00+08:00","closed_at":null,"closed_note":"","user_modified":0,"tpl_creator":"root","expression_id":0,"strategy_id":322,"template_id":125,"process_note":0,"process_status":"unresolved"},{"id":"s_46_1ac45122afb893adc02fbd30154ac303","endpoint":"agent4","metric":"cpu.iowait","func":"all(#3)","cond":"48.33759590792839 \u003e 40","note":"CPU I/O wait超过40","step":1,"current_step":1,"priority":1,"status":"PROBLEM","timestamp":"2016-08-01T06:25:00+08:00","update_at":"2016-08-01T06:25:00+08:00","closed_at":null,"closed_note":"","user_modified":0,"tpl_creator":"root","expression_id":0,"strategy_id":46,"template_id":126,"process_note":16907,"process_status":"ignored"},{"id":"s_191_ddd09333257b2e92e1941860ee86ab15","endpoint":"agent1","metric":"cpu.idle","func":"all(#3)","cond":"11.813186813186814 \u003c 10","note":"cpu.idle小于10%","step":1,"current_step":1,"priority":3,"status":"OK","timestamp":"2016-07-06T09:13:00+08:00","update_at":"2016-07-06T09:13:00+08:00","closed_at":null,"closed_note":"","user_modified":0,"tpl_creator":"root","expression_id":0,"strategy_id":191,"template_id":42,"process_note":0,"process_status":"unresolved"},{"id":"s_50_6438ac68b30e2712fb8f00d894c46e21","endpoint":"agent5","metric":"cpu.idle","func":"avg(#3)","cond":"95.16331658291456 \u003c= 98","note":"cpu空闲值报警","step":1,"current_step":1,"priority":3,"status":"PROBLEM","timestamp":"2016-07-03T16:13:00+08:00","update_at":"2016-07-03T16:13:00+08:00","closed_at":null,"closed_note":"","user_modified":0,"tpl_creator":"root","expression_id":0,"strategy_id":50,"template_id":53,"process_note":1181,"process_status":"ignored"}]

Request Headers

Key Value
Apitoken {"name": "root", "sig": "233fdb00f99811e68a5c001500c6ca5a"}
Content-Type application/json

Request Body

			{
	      "startTime": 1466956800,
	      "endTime": 1480521600,
	      "status": "PROBLEM",
	      "process_status": "unresolved",
	      "limit": 10
	    }

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[]

Request Headers

Key Value
Apitoken {"name": "root", "sig": "233fdb00f99811e68a5c001500c6ca5a"}
Content-Type application/json

Request Body

			{
	      "startTime": 1466956800,
	      "endTime": 1480521600,
	      "process_status": "unresolved",
	      "limit": 1
	    }

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"id":"s_322_00c5f5c87a71bd4c686c0a4a0544b719","endpoint":"agent8","metric":"cpu.iowait","func":"avg(#3)","cond":"0 \u003e 40","note":"CPU I/O wait超过40","step":1,"current_step":1,"priority":1,"status":"OK","timestamp":"2016-11-30T20:10:00+08:00","update_at":"2016-11-30T20:10:00+08:00","closed_at":null,"closed_note":"","user_modified":0,"tpl_creator":"root","expression_id":0,"strategy_id":322,"template_id":125,"process_note":0,"process_status":"unresolved"}]

Request Headers

Key Value
Apitoken {"name": "root", "sig": "233fdb00f99811e68a5c001500c6ca5a"}
Content-Type application/json

Request Body

			{
	      "startTime": 1477584000,
	      "endTime": 1477670400,
	      "process_status": "unresolved",
	      "limit": 10
	    }

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"id":"s_322_00cc81434a0e277b57254a89a839a47b","endpoint":"agent9","metric":"cpu.iowait","func":"avg(#3)","cond":"0.041876046901172526 \u003e 40","note":"CPU I/O wait超过40","step":1,"current_step":1,"priority":1,"status":"OK","timestamp":"2016-10-28T10:37:00+08:00","update_at":"2016-10-28T10:37:00+08:00","closed_at":null,"closed_note":"","user_modified":0,"tpl_creator":"root","expression_id":0,"strategy_id":322,"template_id":125,"process_note":0,"process_status":"unresolved"}]

Request Headers

Key Value
Apitoken {"name": "root", "sig": "233fdb00f99811e68a5c001500c6ca5a"}
Content-Type application/json

Request Body

			{
	      "startTime": 1466956800,
	      "endTime": 1480521600,
	      "process_status": "unresolved",
				"page": 0,
	      "limit": 1
	    }

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"id":"s_322_00c5f5c87a71bd4c686c0a4a0544b719","endpoint":"agent8","metric":"cpu.iowait","func":"avg(#3)","cond":"0 \u003e 40","note":"CPU I/O wait超过40","step":1,"current_step":1,"priority":1,"status":"OK","timestamp":"2016-11-30T20:10:00+08:00","update_at":"2016-11-30T20:10:00+08:00","closed_at":null,"closed_note":"","user_modified":0,"tpl_creator":"root","expression_id":0,"strategy_id":322,"template_id":125,"process_note":0,"process_status":"unresolved"}]

Request Headers

Key Value
Apitoken {"name": "root", "sig": "233fdb00f99811e68a5c001500c6ca5a"}
Content-Type application/json

Request Body

			{
	      "startTime": 1466956800,
	      "endTime": 1480521600,
	      "process_status": "unresolved",
				"page": 1,
	      "limit": 1
	    }

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"id":"s_322_00a9b9f9f859d8436f9b643ea5a1fb5e","endpoint":"agent6","metric":"cpu.iowait","func":"avg(#3)","cond":"0 \u003e 40","note":"CPU I/O wait超过40","step":1,"current_step":1,"priority":1,"status":"OK","timestamp":"2016-11-14T22:16:00+08:00","update_at":"2016-11-14T22:16:00+08:00","closed_at":null,"closed_note":"","user_modified":0,"tpl_creator":"root","expression_id":0,"strategy_id":322,"template_id":140,"process_note":0,"process_status":"unresolved"}]

Request Headers

Key Value
Apitoken {"name": "root", "sig": "233fdb00f99811e68a5c001500c6ca5a"}

URL Params

Key Value
endTime 1466697600
startTime 1466611200

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test","case_id":"","status":"ignored","timestamp":"2016-06-23T05:39:09+08:00","user":"root"},{"event_caseId":"s_165_9d223f126e7ecb3477cd6806f1ee9656","note":"Ignored by user","case_id":"","status":"ignored","timestamp":"2016-06-23T05:38:56+08:00","user":"root"}]

Request Headers

Key Value
Apitoken {"name": "root", "sig": "233fdb00f99811e68a5c001500c6ca5a"}

URL Params

Key Value
event_id s_165_cef145900bf4e2a4a0db8b85762b9cdb

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-23T15:50:29+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"a000001","status":"ignored","timestamp":"2017-03-23T15:50:29+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-23T15:50:06+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"a000001","status":"ignored","timestamp":"2017-03-23T15:50:06+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-23T15:48:07+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"a000001","status":"ignored","timestamp":"2017-03-23T15:48:07+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-23T15:47:24+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"a000001","status":"ignored","timestamp":"2017-03-23T15:47:24+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-23T15:45:04+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"a000001","status":"ignored","timestamp":"2017-03-23T15:45:04+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-23T15:43:26+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"a000001","status":"ignored","timestamp":"2017-03-23T15:43:26+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-23T15:42:02+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"a000001","status":"ignored","timestamp":"2017-03-23T15:42:02+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-23T15:41:14+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"a000001","status":"ignored","timestamp":"2017-03-23T15:41:14+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"a000001","status":"ignored","timestamp":"2017-03-23T15:41:02+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-23T15:41:01+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-23T15:39:49+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"a000001","status":"ignored","timestamp":"2017-03-23T15:39:49+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-23T15:37:50+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"a000001","status":"ignored","timestamp":"2017-03-23T15:37:50+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-23T15:36:34+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"a000001","status":"ignored","timestamp":"2017-03-23T15:36:34+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-23T15:33:50+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"a000001","status":"ignored","timestamp":"2017-03-23T15:33:50+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-23T15:32:52+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"a000001","status":"ignored","timestamp":"2017-03-23T15:32:52+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-23T15:18:12+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"a000001","status":"ignored","timestamp":"2017-03-23T15:18:12+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-22T20:34:15+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"ignored","timestamp":"2017-03-22T20:34:15+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-22T20:30:51+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"ignored","timestamp":"2017-03-22T20:30:51+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-22T20:30:03+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"ignored","timestamp":"2017-03-22T20:30:03+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-22T20:30:03+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"ignored","timestamp":"2017-03-22T20:30:03+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-22T20:29:44+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"ignored","timestamp":"2017-03-22T20:29:44+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-22T20:20:42+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"ignored","timestamp":"2017-03-22T20:20:42+08:00","user":"root"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-22T18:58:41+08:00","user":"owl"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"ignored","timestamp":"2017-03-22T18:58:41+08:00","user":"owl"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-22T18:58:04+08:00","user":"owl"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"ignored","timestamp":"2017-03-22T18:58:04+08:00","user":"owl"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-22T18:56:35+08:00","user":"owl"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"ignored","timestamp":"2017-03-22T18:56:35+08:00","user":"owl"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"comment","timestamp":"2017-03-22T18:56:25+08:00","user":"owl"},{"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","note":"test note","case_id":"","status":"ignored","timestamp":"2017-03-22T18:56:25+08:00","user":"owl"}]

Request Headers

Key Value
Apitoken {"name": "root", "sig": "233fdb00f99811e68a5c001500c6ca5a"}
Content-Type application/json

Request Body

			{
				"event_id": "s_165_cef145900bf4e2a4a0db8b85762b9cdb",
				"note": "test note",
				"status": "comment"
			}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"id":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","message":"add note to s_165_cef145900bf4e2a4a0db8b85762b9cdb successfuled"}

Request Headers

Key Value
Apitoken {"name": "root", "sig": "233fdb00f99811e68a5c001500c6ca5a"}
Content-Type application/json

Request Body

			{
				"event_id": "s_165_cef145900bf4e2a4a0db8b85762b9cdb",
				"note": "test note",
				"status": "ignored",
				"case_id": "a000001"
			}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"id":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","message":"add note to s_165_cef145900bf4e2a4a0db8b85762b9cdb successfuled"}

Request Headers

Key Value
Apitoken {"name": "root", "sig": "233fdb00f99811e68a5c001500c6ca5a"}

URL Params

Key Value
event_id s_165_cef145900bf4e2a4a0db8b85762b9cdb

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"id":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","endpoint":"agent2","metric":"cpu.idle","func":"all(#1)","cond":"0 != 66","note":"測試告警自動更新","step":300,"current_step":3,"priority":0,"status":"PROBLEM","timestamp":"2017-03-23T15:51:11+08:00","update_at":"2016-06-23T05:00:00+08:00","closed_at":null,"closed_note":"","user_modified":0,"tpl_creator":"root","expression_id":0,"strategy_id":165,"template_id":45,"process_note":56603,"process_status":"ignored"}]

Request Headers

Key Value
Apitoken {"name": "root", "sig": "233fdb00f99811e68a5c001500c6ca5a"}
Content-Type application/x-www-form-urlencoded

Post Form

Key Value
endTime 1466628960
event_id s_165_cef145900bf4e2a4a0db8b85762b9cdb
startTime 1466611200

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"id":635166,"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","step":0,"cond":"10.649350649350648 != 66","status":0,"timestamp":"2016-06-23T04:55:00+08:00"},{"id":635149,"event_caseId":"s_165_cef145900bf4e2a4a0db8b85762b9cdb","step":0,"cond":"13.486005089058525 != 66","status":0,"timestamp":"2016-06-23T04:50:00+08:00"}]

Request Headers

Key Value
Apitoken {"name": "root", "sig": "233fdb00f99811e68a5c001500c6ca5a"}
Content-Type application/x-www-form-urlencoded

Post Form

Key Value
event_id s_322_00f5a68989281d30fbbb647194a09230
limit 2
status 1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"id":2283581,"event_caseId":"s_322_00f5a68989281d30fbbb647194a09230","step":0,"cond":"0 \u003e 40","status":1,"timestamp":"2016-12-08T02:10:00+08:00"},{"id":2229288,"event_caseId":"s_322_00f5a68989281d30fbbb647194a09230","step":0,"cond":"0.8756834205893638 \u003e 40","status":1,"timestamp":"2016-12-02T15:43:00+08:00"}]

Request Headers

Key Value
Apitoken {"name": "root", "sig": "233fdb00f99811e68a5c001500c6ca5a"}
Content-Type application/x-www-form-urlencoded

Post Form

Key Value
event_id s_322_00f5a68989281d30fbbb647194a09230
limit 1
page 0

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"id":2283581,"event_caseId":"s_322_00f5a68989281d30fbbb647194a09230","step":0,"cond":"0 \u003e 40","status":1,"timestamp":"2016-12-08T02:10:00+08:00"}]

Request Headers

Key Value
Apitoken {"name": "root", "sig": "233fdb00f99811e68a5c001500c6ca5a"}
Content-Type application/x-www-form-urlencoded

Post Form

Key Value
event_id s_322_00f5a68989281d30fbbb647194a09230
limit 1
page 1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"id":2283566,"event_caseId":"s_322_00f5a68989281d30fbbb647194a09230","step":0,"cond":"2.5609807127182493e+17 \u003e 40","status":0,"timestamp":"2016-12-08T02:07:00+08:00"}]


================================================ FILE: docs/doc/alarm.html.json ================================================ { "ApiSpecs": [ { "HttpVerb": "POST", "Path": "/api/v1/alarm/eventcases", "Calls": [ { "Id": 0, "CurrentPath": "/api/v1/alarm/eventcases", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\": \"root\", \"sig\": \"233fdb00f99811e68a5c001500c6ca5a\"}", "Content-Type": " application/json\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "\n\t\t\t{\n\t \"startTime\": 1466956800,\n\t \t\"endTime\": 1480521600,\n\t \t\"status\": \"PROBLEM\",\n\t \t\"process_status\": \"ignored,unresolved\",\n\t \t\"limit\": 10\n\t }", "ResponseBody": "[{\"id\":\"s_46_1ac45122afb893adc02fbd30154ac303\",\"endpoint\":\"agent4\",\"metric\":\"cpu.iowait\",\"func\":\"all(#3)\",\"cond\":\"48.33759590792839 \\u003e 40\",\"note\":\"CPU I/O wait超过40\",\"step\":1,\"current_step\":1,\"priority\":1,\"status\":\"PROBLEM\",\"timestamp\":\"2016-08-01T06:25:00+08:00\",\"update_at\":\"2016-08-01T06:25:00+08:00\",\"closed_at\":null,\"closed_note\":\"\",\"user_modified\":0,\"tpl_creator\":\"root\",\"expression_id\":0,\"strategy_id\":46,\"template_id\":126,\"process_note\":16907,\"process_status\":\"ignored\"},{\"id\":\"s_50_6438ac68b30e2712fb8f00d894c46e21\",\"endpoint\":\"agent5\",\"metric\":\"cpu.idle\",\"func\":\"avg(#3)\",\"cond\":\"95.16331658291456 \\u003c= 98\",\"note\":\"cpu空闲值报警\",\"step\":1,\"current_step\":1,\"priority\":3,\"status\":\"PROBLEM\",\"timestamp\":\"2016-07-03T16:13:00+08:00\",\"update_at\":\"2016-07-03T16:13:00+08:00\",\"closed_at\":null,\"closed_note\":\"\",\"user_modified\":0,\"tpl_creator\":\"root\",\"expression_id\":0,\"strategy_id\":50,\"template_id\":53,\"process_note\":1181,\"process_status\":\"ignored\"}]", "ResponseCode": 200 }, { "Id": 1, "CurrentPath": "/api/v1/alarm/eventcases", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\": \"root\", \"sig\": \"233fdb00f99811e68a5c001500c6ca5a\"}", "Content-Type": " application/json\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "\n\t\t\t{\n\t \"startTime\": 1466956800,\n\t \t\"endTime\": 1480521600,\n\t \t\"status\": \"PROBLEM,OK\",\n\t \t\"process_status\": \"ignored,unresolved\",\n\t \t\"limit\": 10\n\t }", "ResponseBody": "[{\"id\":\"s_322_00c5f5c87a71bd4c686c0a4a0544b719\",\"endpoint\":\"agent8\",\"metric\":\"cpu.iowait\",\"func\":\"avg(#3)\",\"cond\":\"0 \\u003e 40\",\"note\":\"CPU I/O wait超过40\",\"step\":1,\"current_step\":1,\"priority\":1,\"status\":\"OK\",\"timestamp\":\"2016-11-30T20:10:00+08:00\",\"update_at\":\"2016-11-30T20:10:00+08:00\",\"closed_at\":null,\"closed_note\":\"\",\"user_modified\":0,\"tpl_creator\":\"root\",\"expression_id\":0,\"strategy_id\":322,\"template_id\":125,\"process_note\":0,\"process_status\":\"unresolved\"},{\"id\":\"s_322_00a9b9f9f859d8436f9b643ea5a1fb5e\",\"endpoint\":\"agent6\",\"metric\":\"cpu.iowait\",\"func\":\"avg(#3)\",\"cond\":\"0 \\u003e 40\",\"note\":\"CPU I/O wait超过40\",\"step\":1,\"current_step\":1,\"priority\":1,\"status\":\"OK\",\"timestamp\":\"2016-11-14T22:16:00+08:00\",\"update_at\":\"2016-11-14T22:16:00+08:00\",\"closed_at\":null,\"closed_note\":\"\",\"user_modified\":0,\"tpl_creator\":\"root\",\"expression_id\":0,\"strategy_id\":322,\"template_id\":140,\"process_note\":0,\"process_status\":\"unresolved\"},{\"id\":\"s_322_00ba3072006a8ba863108d4b3f9c1c51\",\"endpoint\":\"agent7\",\"metric\":\"cpu.iowait\",\"func\":\"avg(#3)\",\"cond\":\"0.0695615485072203 \\u003e 40\",\"note\":\"CPU I/O wait超过40\",\"step\":1,\"current_step\":1,\"priority\":1,\"status\":\"OK\",\"timestamp\":\"2016-11-14T20:43:00+08:00\",\"update_at\":\"2016-11-14T20:43:00+08:00\",\"closed_at\":null,\"closed_note\":\"\",\"user_modified\":0,\"tpl_creator\":\"root\",\"expression_id\":0,\"strategy_id\":322,\"template_id\":125,\"process_note\":0,\"process_status\":\"unresolved\"},{\"id\":\"s_322_002e499f3b56420fdea506c887e51799\",\"endpoint\":\"agent3\",\"metric\":\"cpu.iowait\",\"func\":\"avg(#3)\",\"cond\":\"30.76679150609009 \\u003e 40\",\"note\":\"CPU I/O wait超过40\",\"step\":1,\"current_step\":1,\"priority\":1,\"status\":\"OK\",\"timestamp\":\"2016-11-07T04:28:00+08:00\",\"update_at\":\"2016-11-07T04:28:00+08:00\",\"closed_at\":null,\"closed_note\":\"\",\"user_modified\":0,\"tpl_creator\":\"root\",\"expression_id\":0,\"strategy_id\":322,\"template_id\":125,\"process_note\":0,\"process_status\":\"unresolved\"},{\"id\":\"s_322_00cc81434a0e277b57254a89a839a47b\",\"endpoint\":\"agent9\",\"metric\":\"cpu.iowait\",\"func\":\"avg(#3)\",\"cond\":\"0.041876046901172526 \\u003e 40\",\"note\":\"CPU I/O wait超过40\",\"step\":1,\"current_step\":1,\"priority\":1,\"status\":\"OK\",\"timestamp\":\"2016-10-28T10:37:00+08:00\",\"update_at\":\"2016-10-28T10:37:00+08:00\",\"closed_at\":null,\"closed_note\":\"\",\"user_modified\":0,\"tpl_creator\":\"root\",\"expression_id\":0,\"strategy_id\":322,\"template_id\":125,\"process_note\":0,\"process_status\":\"unresolved\"},{\"id\":\"s_322_001da6a5f95d83387cdfecc37ac70c24\",\"endpoint\":\"agent2\",\"metric\":\"cpu.iowait\",\"func\":\"avg(#3)\",\"cond\":\"34.40479690409319 \\u003e 40\",\"note\":\"CPU I/O wait超过40\",\"step\":1,\"current_step\":1,\"priority\":1,\"status\":\"OK\",\"timestamp\":\"2016-10-27T15:37:00+08:00\",\"update_at\":\"2016-10-27T15:37:00+08:00\",\"closed_at\":null,\"closed_note\":\"\",\"user_modified\":0,\"tpl_creator\":\"root\",\"expression_id\":0,\"strategy_id\":322,\"template_id\":125,\"process_note\":0,\"process_status\":\"unresolved\"},{\"id\":\"s_46_1ac45122afb893adc02fbd30154ac303\",\"endpoint\":\"agent4\",\"metric\":\"cpu.iowait\",\"func\":\"all(#3)\",\"cond\":\"48.33759590792839 \\u003e 40\",\"note\":\"CPU I/O wait超过40\",\"step\":1,\"current_step\":1,\"priority\":1,\"status\":\"PROBLEM\",\"timestamp\":\"2016-08-01T06:25:00+08:00\",\"update_at\":\"2016-08-01T06:25:00+08:00\",\"closed_at\":null,\"closed_note\":\"\",\"user_modified\":0,\"tpl_creator\":\"root\",\"expression_id\":0,\"strategy_id\":46,\"template_id\":126,\"process_note\":16907,\"process_status\":\"ignored\"},{\"id\":\"s_191_ddd09333257b2e92e1941860ee86ab15\",\"endpoint\":\"agent1\",\"metric\":\"cpu.idle\",\"func\":\"all(#3)\",\"cond\":\"11.813186813186814 \\u003c 10\",\"note\":\"cpu.idle小于10%\",\"step\":1,\"current_step\":1,\"priority\":3,\"status\":\"OK\",\"timestamp\":\"2016-07-06T09:13:00+08:00\",\"update_at\":\"2016-07-06T09:13:00+08:00\",\"closed_at\":null,\"closed_note\":\"\",\"user_modified\":0,\"tpl_creator\":\"root\",\"expression_id\":0,\"strategy_id\":191,\"template_id\":42,\"process_note\":0,\"process_status\":\"unresolved\"},{\"id\":\"s_50_6438ac68b30e2712fb8f00d894c46e21\",\"endpoint\":\"agent5\",\"metric\":\"cpu.idle\",\"func\":\"avg(#3)\",\"cond\":\"95.16331658291456 \\u003c= 98\",\"note\":\"cpu空闲值报警\",\"step\":1,\"current_step\":1,\"priority\":3,\"status\":\"PROBLEM\",\"timestamp\":\"2016-07-03T16:13:00+08:00\",\"update_at\":\"2016-07-03T16:13:00+08:00\",\"closed_at\":null,\"closed_note\":\"\",\"user_modified\":0,\"tpl_creator\":\"root\",\"expression_id\":0,\"strategy_id\":50,\"template_id\":53,\"process_note\":1181,\"process_status\":\"ignored\"}]", "ResponseCode": 200 }, { "Id": 2, "CurrentPath": "/api/v1/alarm/eventcases", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\": \"root\", \"sig\": \"233fdb00f99811e68a5c001500c6ca5a\"}", "Content-Type": " application/json\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "\n\t\t\t{\n\t \"startTime\": 1466956800,\n\t \"endTime\": 1480521600,\n\t \"status\": \"PROBLEM\",\n\t \"process_status\": \"unresolved\",\n\t \"limit\": 10\n\t }", "ResponseBody": "[]", "ResponseCode": 200 }, { "Id": 3, "CurrentPath": "/api/v1/alarm/eventcases", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\": \"root\", \"sig\": \"233fdb00f99811e68a5c001500c6ca5a\"}", "Content-Type": " application/json\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "\n\t\t\t{\n\t \"startTime\": 1466956800,\n\t \"endTime\": 1480521600,\n\t \"process_status\": \"unresolved\",\n\t \"limit\": 1\n\t }", "ResponseBody": "[{\"id\":\"s_322_00c5f5c87a71bd4c686c0a4a0544b719\",\"endpoint\":\"agent8\",\"metric\":\"cpu.iowait\",\"func\":\"avg(#3)\",\"cond\":\"0 \\u003e 40\",\"note\":\"CPU I/O wait超过40\",\"step\":1,\"current_step\":1,\"priority\":1,\"status\":\"OK\",\"timestamp\":\"2016-11-30T20:10:00+08:00\",\"update_at\":\"2016-11-30T20:10:00+08:00\",\"closed_at\":null,\"closed_note\":\"\",\"user_modified\":0,\"tpl_creator\":\"root\",\"expression_id\":0,\"strategy_id\":322,\"template_id\":125,\"process_note\":0,\"process_status\":\"unresolved\"}]", "ResponseCode": 200 }, { "Id": 4, "CurrentPath": "/api/v1/alarm/eventcases", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\": \"root\", \"sig\": \"233fdb00f99811e68a5c001500c6ca5a\"}", "Content-Type": " application/json\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "\n\t\t\t{\n\t \"startTime\": 1477584000,\n\t \"endTime\": 1477670400,\n\t \"process_status\": \"unresolved\",\n\t \"limit\": 10\n\t }", "ResponseBody": "[{\"id\":\"s_322_00cc81434a0e277b57254a89a839a47b\",\"endpoint\":\"agent9\",\"metric\":\"cpu.iowait\",\"func\":\"avg(#3)\",\"cond\":\"0.041876046901172526 \\u003e 40\",\"note\":\"CPU I/O wait超过40\",\"step\":1,\"current_step\":1,\"priority\":1,\"status\":\"OK\",\"timestamp\":\"2016-10-28T10:37:00+08:00\",\"update_at\":\"2016-10-28T10:37:00+08:00\",\"closed_at\":null,\"closed_note\":\"\",\"user_modified\":0,\"tpl_creator\":\"root\",\"expression_id\":0,\"strategy_id\":322,\"template_id\":125,\"process_note\":0,\"process_status\":\"unresolved\"}]", "ResponseCode": 200 }, { "Id": 5, "CurrentPath": "/api/v1/alarm/eventcases", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\": \"root\", \"sig\": \"233fdb00f99811e68a5c001500c6ca5a\"}", "Content-Type": " application/json\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "\n\t\t\t{\n\t \"startTime\": 1466956800,\n\t \"endTime\": 1480521600,\n\t \"process_status\": \"unresolved\",\n\t\t\t\t\"page\": 0,\n\t \"limit\": 1\n\t }", "ResponseBody": "[{\"id\":\"s_322_00c5f5c87a71bd4c686c0a4a0544b719\",\"endpoint\":\"agent8\",\"metric\":\"cpu.iowait\",\"func\":\"avg(#3)\",\"cond\":\"0 \\u003e 40\",\"note\":\"CPU I/O wait超过40\",\"step\":1,\"current_step\":1,\"priority\":1,\"status\":\"OK\",\"timestamp\":\"2016-11-30T20:10:00+08:00\",\"update_at\":\"2016-11-30T20:10:00+08:00\",\"closed_at\":null,\"closed_note\":\"\",\"user_modified\":0,\"tpl_creator\":\"root\",\"expression_id\":0,\"strategy_id\":322,\"template_id\":125,\"process_note\":0,\"process_status\":\"unresolved\"}]", "ResponseCode": 200 }, { "Id": 6, "CurrentPath": "/api/v1/alarm/eventcases", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\": \"root\", \"sig\": \"233fdb00f99811e68a5c001500c6ca5a\"}", "Content-Type": " application/json\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "\n\t\t\t{\n\t \"startTime\": 1466956800,\n\t \"endTime\": 1480521600,\n\t \"process_status\": \"unresolved\",\n\t\t\t\t\"page\": 1,\n\t \"limit\": 1\n\t }", "ResponseBody": "[{\"id\":\"s_322_00a9b9f9f859d8436f9b643ea5a1fb5e\",\"endpoint\":\"agent6\",\"metric\":\"cpu.iowait\",\"func\":\"avg(#3)\",\"cond\":\"0 \\u003e 40\",\"note\":\"CPU I/O wait超过40\",\"step\":1,\"current_step\":1,\"priority\":1,\"status\":\"OK\",\"timestamp\":\"2016-11-14T22:16:00+08:00\",\"update_at\":\"2016-11-14T22:16:00+08:00\",\"closed_at\":null,\"closed_note\":\"\",\"user_modified\":0,\"tpl_creator\":\"root\",\"expression_id\":0,\"strategy_id\":322,\"template_id\":140,\"process_note\":0,\"process_status\":\"unresolved\"}]", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/alarm/event_note", "Calls": [ { "Id": 7, "CurrentPath": "/api/v1/alarm/event_note", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\": \"root\", \"sig\": \"233fdb00f99811e68a5c001500c6ca5a\"}" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": { "endTime": "1466697600", "startTime": "1466611200" }, "RequestBody": "", "ResponseBody": "[{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test\",\"case_id\":\"\",\"status\":\"ignored\",\"timestamp\":\"2016-06-23T05:39:09+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_9d223f126e7ecb3477cd6806f1ee9656\",\"note\":\"Ignored by user\",\"case_id\":\"\",\"status\":\"ignored\",\"timestamp\":\"2016-06-23T05:38:56+08:00\",\"user\":\"root\"}]", "ResponseCode": 200 }, { "Id": 8, "CurrentPath": "/api/v1/alarm/event_note", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\": \"root\", \"sig\": \"233fdb00f99811e68a5c001500c6ca5a\"}" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": { "event_id": "s_165_cef145900bf4e2a4a0db8b85762b9cdb" }, "RequestBody": "", "ResponseBody": "[{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-23T15:50:29+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"a000001\",\"status\":\"ignored\",\"timestamp\":\"2017-03-23T15:50:29+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-23T15:50:06+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"a000001\",\"status\":\"ignored\",\"timestamp\":\"2017-03-23T15:50:06+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-23T15:48:07+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"a000001\",\"status\":\"ignored\",\"timestamp\":\"2017-03-23T15:48:07+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-23T15:47:24+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"a000001\",\"status\":\"ignored\",\"timestamp\":\"2017-03-23T15:47:24+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-23T15:45:04+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"a000001\",\"status\":\"ignored\",\"timestamp\":\"2017-03-23T15:45:04+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-23T15:43:26+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"a000001\",\"status\":\"ignored\",\"timestamp\":\"2017-03-23T15:43:26+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-23T15:42:02+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"a000001\",\"status\":\"ignored\",\"timestamp\":\"2017-03-23T15:42:02+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-23T15:41:14+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"a000001\",\"status\":\"ignored\",\"timestamp\":\"2017-03-23T15:41:14+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"a000001\",\"status\":\"ignored\",\"timestamp\":\"2017-03-23T15:41:02+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-23T15:41:01+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-23T15:39:49+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"a000001\",\"status\":\"ignored\",\"timestamp\":\"2017-03-23T15:39:49+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-23T15:37:50+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"a000001\",\"status\":\"ignored\",\"timestamp\":\"2017-03-23T15:37:50+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-23T15:36:34+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"a000001\",\"status\":\"ignored\",\"timestamp\":\"2017-03-23T15:36:34+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-23T15:33:50+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"a000001\",\"status\":\"ignored\",\"timestamp\":\"2017-03-23T15:33:50+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-23T15:32:52+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"a000001\",\"status\":\"ignored\",\"timestamp\":\"2017-03-23T15:32:52+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-23T15:18:12+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"a000001\",\"status\":\"ignored\",\"timestamp\":\"2017-03-23T15:18:12+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-22T20:34:15+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"ignored\",\"timestamp\":\"2017-03-22T20:34:15+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-22T20:30:51+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"ignored\",\"timestamp\":\"2017-03-22T20:30:51+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-22T20:30:03+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"ignored\",\"timestamp\":\"2017-03-22T20:30:03+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-22T20:30:03+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"ignored\",\"timestamp\":\"2017-03-22T20:30:03+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-22T20:29:44+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"ignored\",\"timestamp\":\"2017-03-22T20:29:44+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-22T20:20:42+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"ignored\",\"timestamp\":\"2017-03-22T20:20:42+08:00\",\"user\":\"root\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-22T18:58:41+08:00\",\"user\":\"owl\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"ignored\",\"timestamp\":\"2017-03-22T18:58:41+08:00\",\"user\":\"owl\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-22T18:58:04+08:00\",\"user\":\"owl\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"ignored\",\"timestamp\":\"2017-03-22T18:58:04+08:00\",\"user\":\"owl\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-22T18:56:35+08:00\",\"user\":\"owl\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"ignored\",\"timestamp\":\"2017-03-22T18:56:35+08:00\",\"user\":\"owl\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"comment\",\"timestamp\":\"2017-03-22T18:56:25+08:00\",\"user\":\"owl\"},{\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"note\":\"test note\",\"case_id\":\"\",\"status\":\"ignored\",\"timestamp\":\"2017-03-22T18:56:25+08:00\",\"user\":\"owl\"}]", "ResponseCode": 200 } ] }, { "HttpVerb": "POST", "Path": "/api/v1/alarm/event_note", "Calls": [ { "Id": 9, "CurrentPath": "/api/v1/alarm/event_note", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\": \"root\", \"sig\": \"233fdb00f99811e68a5c001500c6ca5a\"}", "Content-Type": " application/json\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "\n\t\t\t{\n\t\t\t\t\"event_id\": \"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\n\t\t\t\t\"note\": \"test note\",\n\t\t\t\t\"status\": \"comment\"\n\t\t\t}", "ResponseBody": "{\"id\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"message\":\"add note to s_165_cef145900bf4e2a4a0db8b85762b9cdb successfuled\"}", "ResponseCode": 200 }, { "Id": 10, "CurrentPath": "/api/v1/alarm/event_note", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\": \"root\", \"sig\": \"233fdb00f99811e68a5c001500c6ca5a\"}", "Content-Type": " application/json\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "\n\t\t\t{\n\t\t\t\t\"event_id\": \"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\n\t\t\t\t\"note\": \"test note\",\n\t\t\t\t\"status\": \"ignored\",\n\t\t\t\t\"case_id\": \"a000001\"\n\t\t\t}", "ResponseBody": "{\"id\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"message\":\"add note to s_165_cef145900bf4e2a4a0db8b85762b9cdb successfuled\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/alarm/eventcases", "Calls": [ { "Id": 11, "CurrentPath": "/api/v1/alarm/eventcases", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\": \"root\", \"sig\": \"233fdb00f99811e68a5c001500c6ca5a\"}" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": { "event_id": "s_165_cef145900bf4e2a4a0db8b85762b9cdb" }, "RequestBody": "", "ResponseBody": "[{\"id\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"endpoint\":\"agent2\",\"metric\":\"cpu.idle\",\"func\":\"all(#1)\",\"cond\":\"0 != 66\",\"note\":\"測試告警自動更新\",\"step\":300,\"current_step\":3,\"priority\":0,\"status\":\"PROBLEM\",\"timestamp\":\"2017-03-23T15:51:11+08:00\",\"update_at\":\"2016-06-23T05:00:00+08:00\",\"closed_at\":null,\"closed_note\":\"\",\"user_modified\":0,\"tpl_creator\":\"root\",\"expression_id\":0,\"strategy_id\":165,\"template_id\":45,\"process_note\":56603,\"process_status\":\"ignored\"}]", "ResponseCode": 200 } ] }, { "HttpVerb": "POST", "Path": "/api/v1/alarm/events", "Calls": [ { "Id": 12, "CurrentPath": "/api/v1/alarm/events", "MethodType": "POST", "PostForm": { "endTime": "1466628960", "event_id": "s_165_cef145900bf4e2a4a0db8b85762b9cdb", "startTime": "1466611200" }, "RequestHeader": { "Apitoken": "{\"name\": \"root\", \"sig\": \"233fdb00f99811e68a5c001500c6ca5a\"}", "Content-Type": " application/x-www-form-urlencoded\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "[{\"id\":635166,\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"step\":0,\"cond\":\"10.649350649350648 != 66\",\"status\":0,\"timestamp\":\"2016-06-23T04:55:00+08:00\"},{\"id\":635149,\"event_caseId\":\"s_165_cef145900bf4e2a4a0db8b85762b9cdb\",\"step\":0,\"cond\":\"13.486005089058525 != 66\",\"status\":0,\"timestamp\":\"2016-06-23T04:50:00+08:00\"}]", "ResponseCode": 200 }, { "Id": 13, "CurrentPath": "/api/v1/alarm/events", "MethodType": "POST", "PostForm": { "event_id": "s_322_00f5a68989281d30fbbb647194a09230", "limit": "2", "status": "1" }, "RequestHeader": { "Apitoken": "{\"name\": \"root\", \"sig\": \"233fdb00f99811e68a5c001500c6ca5a\"}", "Content-Type": " application/x-www-form-urlencoded\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "[{\"id\":2283581,\"event_caseId\":\"s_322_00f5a68989281d30fbbb647194a09230\",\"step\":0,\"cond\":\"0 \\u003e 40\",\"status\":1,\"timestamp\":\"2016-12-08T02:10:00+08:00\"},{\"id\":2229288,\"event_caseId\":\"s_322_00f5a68989281d30fbbb647194a09230\",\"step\":0,\"cond\":\"0.8756834205893638 \\u003e 40\",\"status\":1,\"timestamp\":\"2016-12-02T15:43:00+08:00\"}]", "ResponseCode": 200 }, { "Id": 14, "CurrentPath": "/api/v1/alarm/events", "MethodType": "POST", "PostForm": { "event_id": "s_322_00f5a68989281d30fbbb647194a09230", "limit": "1", "page": "0" }, "RequestHeader": { "Apitoken": "{\"name\": \"root\", \"sig\": \"233fdb00f99811e68a5c001500c6ca5a\"}", "Content-Type": " application/x-www-form-urlencoded\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "[{\"id\":2283581,\"event_caseId\":\"s_322_00f5a68989281d30fbbb647194a09230\",\"step\":0,\"cond\":\"0 \\u003e 40\",\"status\":1,\"timestamp\":\"2016-12-08T02:10:00+08:00\"}]", "ResponseCode": 200 }, { "Id": 15, "CurrentPath": "/api/v1/alarm/events", "MethodType": "POST", "PostForm": { "event_id": "s_322_00f5a68989281d30fbbb647194a09230", "limit": "1", "page": "1" }, "RequestHeader": { "Apitoken": "{\"name\": \"root\", \"sig\": \"233fdb00f99811e68a5c001500c6ca5a\"}", "Content-Type": " application/x-www-form-urlencoded\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "[{\"id\":2283566,\"event_caseId\":\"s_322_00f5a68989281d30fbbb647194a09230\",\"step\":0,\"cond\":\"2.5609807127182493e+17 \\u003e 40\",\"status\":0,\"timestamp\":\"2016-12-08T02:07:00+08:00\"}]", "ResponseCode": 200 } ] } ] } ================================================ FILE: docs/doc/expression.html ================================================ API Documentation

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
Content-Type application/json
X-Forwarded-For 127.0.0.1

Request Body

{"right_value":"0","priority":2,"pause":0,"op":"==","note":"this is a test exp","max_step":3,"func":"all(#3)","expression":"each(metric=agent.alive endpoint=docker-agent)","action":{"url":"http://localhost:1234/callback","uic":["test"],"callback":1,"before_callback_sms":1,"before_callback_mail":0,"after_callback_sms":1,"after_callback_mail":0}}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"message":"expression created"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
Content-Type application/json
X-Forwarded-For 127.0.0.1

Request Body

{"right_value":"0","priority":2,"pause":1,"op":"==","note":"this is a test exp","max_step":3,"id":5,"func":"all(#3)","expression":"each(metric=agent.alive endpoint=docker-agent)","action":{"url":"http://localhost:1234/callback","uic":["test","test2"],"callback":0,"before_callback_sms":1,"before_callback_mail":0,"after_callback_sms":1,"after_callback_mail":0}}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"message":"expression:5 has been updated"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"action":{"id":5,"uic":"taipei","url":"","callback":0,"before_callback_sms":0,"before_callback_mail":0,"after_callback_sms":0,"after_callback_mail":0},"expression":{"id":5,"expression":"each(metric=agent.alive endpoint=docker-agent)","func":"all(#3)","op":"==","right_value":"0","max_step":3,"priority":2,"note":"this is a test exp","action_id":177,"create_user":"root","pause":1}}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"message":"expression:5 has been deleted"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"id":2,"expression":"each(metric=? xx=yy)","func":"all(#3)","op":"==","right_value":"0","max_step":3,"priority":0,"note":"","action_id":18,"create_user":"root","pause":0},{"id":3,"expression":"each(metric=ss.close.wait endpoint=docker-A)","func":"all(#1)","op":"!=","right_value":"0","max_step":1,"priority":4,"note":"boss docker-A 连接数大于10","action_id":91,"create_user":"root","pause":0},{"id":4,"expression":"each(metric=agent.alive endpoint=docker-agent)","func":"all(#3)","op":"==","right_value":"0","max_step":3,"priority":2,"note":"this is a test exp","action_id":176,"create_user":"root","pause":1}]

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

URL Params

Key Value
limit 2
page 1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"id":2,"expression":"each(metric=? xx=yy)","func":"all(#3)","op":"==","right_value":"0","max_step":3,"priority":0,"note":"","action_id":18,"create_user":"root","pause":0},{"id":3,"expression":"each(metric=ss.close.wait endpoint=docker-A)","func":"all(#1)","op":"!=","right_value":"0","max_step":1,"priority":4,"note":"boss docker-A 连接数大于10","action_id":91,"create_user":"root","pause":0}]


================================================ FILE: docs/doc/expression.html.json ================================================ { "ApiSpecs": [ { "HttpVerb": "POST", "Path": "/api/v1/expression", "Calls": [ { "Id": 0, "CurrentPath": "/api/v1/expression", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"right_value\":\"0\",\"priority\":2,\"pause\":0,\"op\":\"==\",\"note\":\"this is a test exp\",\"max_step\":3,\"func\":\"all(#3)\",\"expression\":\"each(metric=agent.alive endpoint=docker-agent)\",\"action\":{\"url\":\"http://localhost:1234/callback\",\"uic\":[\"test\"],\"callback\":1,\"before_callback_sms\":1,\"before_callback_mail\":0,\"after_callback_sms\":1,\"after_callback_mail\":0}}", "ResponseBody": "{\"message\":\"expression created\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "PUT", "Path": "/api/v1/expression", "Calls": [ { "Id": 1, "CurrentPath": "/api/v1/expression", "MethodType": "PUT", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"right_value\":\"0\",\"priority\":2,\"pause\":1,\"op\":\"==\",\"note\":\"this is a test exp\",\"max_step\":3,\"id\":5,\"func\":\"all(#3)\",\"expression\":\"each(metric=agent.alive endpoint=docker-agent)\",\"action\":{\"url\":\"http://localhost:1234/callback\",\"uic\":[\"test\",\"test2\"],\"callback\":0,\"before_callback_sms\":1,\"before_callback_mail\":0,\"after_callback_sms\":1,\"after_callback_mail\":0}}", "ResponseBody": "{\"message\":\"expression:5 has been updated\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/expression/5", "Calls": [ { "Id": 2, "CurrentPath": "/api/v1/expression/5", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"action\":{\"id\":5,\"uic\":\"taipei\",\"url\":\"\",\"callback\":0,\"before_callback_sms\":0,\"before_callback_mail\":0,\"after_callback_sms\":0,\"after_callback_mail\":0},\"expression\":{\"id\":5,\"expression\":\"each(metric=agent.alive endpoint=docker-agent)\",\"func\":\"all(#3)\",\"op\":\"==\",\"right_value\":\"0\",\"max_step\":3,\"priority\":2,\"note\":\"this is a test exp\",\"action_id\":177,\"create_user\":\"root\",\"pause\":1}}", "ResponseCode": 200 } ] }, { "HttpVerb": "DELETE", "Path": "/api/v1/expression/5", "Calls": [ { "Id": 3, "CurrentPath": "/api/v1/expression/5", "MethodType": "DELETE", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"message\":\"expression:5 has been deleted\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/expression", "Calls": [ { "Id": 4, "CurrentPath": "/api/v1/expression", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "[{\"id\":2,\"expression\":\"each(metric=? xx=yy)\",\"func\":\"all(#3)\",\"op\":\"==\",\"right_value\":\"0\",\"max_step\":3,\"priority\":0,\"note\":\"\",\"action_id\":18,\"create_user\":\"root\",\"pause\":0},{\"id\":3,\"expression\":\"each(metric=ss.close.wait endpoint=docker-A)\",\"func\":\"all(#1)\",\"op\":\"!=\",\"right_value\":\"0\",\"max_step\":1,\"priority\":4,\"note\":\"boss docker-A 连接数大于10\",\"action_id\":91,\"create_user\":\"root\",\"pause\":0},{\"id\":4,\"expression\":\"each(metric=agent.alive endpoint=docker-agent)\",\"func\":\"all(#3)\",\"op\":\"==\",\"right_value\":\"0\",\"max_step\":3,\"priority\":2,\"note\":\"this is a test exp\",\"action_id\":176,\"create_user\":\"root\",\"pause\":1}]", "ResponseCode": 200 }, { "Id": 0, "CurrentPath": "/api/v1/expression", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": { "limit": "2", "page": "1" }, "RequestBody": "", "ResponseBody": "[{\"id\":2,\"expression\":\"each(metric=? xx=yy)\",\"func\":\"all(#3)\",\"op\":\"==\",\"right_value\":\"0\",\"max_step\":3,\"priority\":0,\"note\":\"\",\"action_id\":18,\"create_user\":\"root\",\"pause\":0},{\"id\":3,\"expression\":\"each(metric=ss.close.wait endpoint=docker-A)\",\"func\":\"all(#1)\",\"op\":\"!=\",\"right_value\":\"0\",\"max_step\":1,\"priority\":4,\"note\":\"boss docker-A 连接数大于10\",\"action_id\":91,\"create_user\":\"root\",\"pause\":0}]", "ResponseCode": 200 } ] } ] } ================================================ FILE: docs/doc/graph.html ================================================ API Documentation

Request Headers

Key Value
Cookie name=test1; sig=d4f71cba377911e699d60242ac110010
X-Forwarded-For

Response Code

400

Response Headers

Key Value
Content-Type application/json; charset=utf-8

Response Body

{"error":"q is missing"}

Request Headers

Key Value
X-Forwarded-For

Response Code

401

Response Headers

Key Value
Content-Type application/json; charset=utf-8

Request Headers

Key Value
Cookie name=test1; sig=d4f71cba377911e699d60242ac110010
X-Forwarded-For

URL Params

Key Value
q a.+

Response Code

200

Response Headers

Key Value
Content-Type application/json; charset=utf-8

Response Body

[{"endpoint":"docker-agent","id":7},{"endpoint":"docker-task","id":6},{"endpoint":"graph","id":3},{"endpoint":"nodata","id":920},{"endpoint":"task","id":5}]

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

URL Params

Key Value
limit 10
q .+

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"endpoint":"docker-A","id":244525914},{"endpoint":"docker-B","id":12675145},{"endpoint":"docker-C","id":12683936},{"endpoint":"docker-D","id":12681439},{"endpoint":"docker-D","id":12676363},{"endpoint":"docker-E","id":12681715},{"endpoint":"docker-F","id":12678421},{"endpoint":"docker-F","id":12676879},{"endpoint":"docker-F","id":12675447},{"endpoint":"bgp-bj-058-083-161-110","id":12679349}]

Request Headers

Key Value
Cookie name=test1; sig=d4f71cba377911e699d60242ac110010
X-Forwarded-For

Response Code

400

Response Headers

Key Value
Content-Type application/json; charset=utf-8

Response Body

{"error":"eid is missing"}

Request Headers

Key Value
Cookie name=test1; sig=d4f71cba377911e699d60242ac110010
X-Forwarded-For

URL Params

Key Value
eid 6,7
metricQuery disk.+

Response Code

200

Response Headers

Key Value
Content-Type application/json; charset=utf-8

Response Body

["disk.io.avgqu-sz/device=sda","disk.io.ios_in_progress/device=sda","disk.io.msec_read/device=sda","disk.io.read_requests/device=sda","disk.io.read_sectors/device=sda","disk.io.write_bytes/device=sda","disk.io.write_merged/device=sda","disk.io.msec_write/device=sda","disk.io.read_merged/device=sda","disk.io.svctm/device=sda","disk.io.util/device=sda","disk.io.avgrq_sz/device=sda","disk.io.msec_weighted_total/device=sda","disk.io.await/device=sda","disk.io.msec_total/device=sda","disk.io.read_bytes/device=sda","disk.io.write_requests/device=sda","disk.io.write_sectors/device=sda"]

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

URL Params

Key Value
eid 244525914,12675145,12683936,12681439,12676363,12681715,12678421,12676879,12675447,12679349
limit 3
metricQuery disk.+

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

["disk.io.write_sectors/device=sdh","disk.device.size/device=sdm","disk.io.ios_in_progress/device=sdj"]

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
Content-Type application/json
X-Forwarded-For 127.0.0.1

Request Body

{"step":60,"start_time":1481854596,"hostnames":["docker-a","docker-b","docker-c"],"end_time":1481858193,"counters":["cpu.idle","cpu.iowait"],"consol_fun":"AVERAGE"}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"endpoint":"docker-a","counter":"cpu.idle","dstype":"GAUGE","step":60,"Values":[{"timestamp":1481854620,"value":98.154506},{"timestamp":1481854680,"value":97.864161},{"timestamp":1481854740,"value":97.521368},{"timestamp":1481854800,"value":97.587247},{"timestamp":1481854860,"value":97.440273},{"timestamp":1481854920,"value":97.914006},{"timestamp":1481854980,"value":97.223409},{"timestamp":1481855040,"value":98.029135},{"timestamp":1481855100,"value":97.614991},{"timestamp":1481855160,"value":97.565143},{"timestamp":1481855220,"value":97.070064},{"timestamp":1481855280,"value":98.726115},{"timestamp":1481855340,"value":98.720137},{"timestamp":1481855400,"value":98.205128},{"timestamp":1481855460,"value":97.700170},{"timestamp":1481855520,"value":97.780623},{"timestamp":1481855580,"value":97.379725},{"timestamp":1481855640,"value":98.034188},{"timestamp":1481855700,"value":98.246364},{"timestamp":1481855760,"value":98.372591},{"timestamp":1481855820,"value":98.152921},{"timestamp":1481855880,"value":97.914006},{"timestamp":1481855940,"value":95.592048},{"timestamp":1481856000,"value":94.115120},{"timestamp":1481856060,"value":97.596567},{"timestamp":1481856120,"value":97.501077},{"timestamp":1481856180,"value":96.374622},{"timestamp":1481856240,"value":89.570815},{"timestamp":1481856300,"value":96.410035},{"timestamp":1481856360,"value":97.567222},{"timestamp":1481856420,"value":97.252040},{"timestamp":1481856480,"value":95.356836},{"timestamp":1481856540,"value":97.330508},{"timestamp":1481856600,"value":96.999571},{"timestamp":1481856660,"value":97.278912},{"timestamp":1481856720,"value":97.229327},{"timestamp":1481856780,"value":97.212693},{"timestamp":1481856840,"value":96.503198},{"timestamp":1481856900,"value":96.790757},{"timestamp":1481856960,"value":98.121264},{"timestamp":1481857020,"value":98.550725},{"timestamp":1481857080,"value":97.548387},{"timestamp":1481857140,"value":98.466127},{"timestamp":1481857200,"value":97.900600},{"timestamp":1481857260,"value":97.985426},{"timestamp":1481857320,"value":97.357204},{"timestamp":1481857380,"value":97.086547},{"timestamp":1481857440,"value":98.770144},{"timestamp":1481857500,"value":97.727273},{"timestamp":1481857560,"value":98.595147},{"timestamp":1481857620,"value":97.867804},{"timestamp":1481857680,"value":98.128456},{"timestamp":1481857740,"value":97.886729},{"timestamp":1481857800,"value":95.969453},{"timestamp":1481857860,"value":97.134303},{"timestamp":1481857920,"value":98.033348},{"timestamp":1481857980,"value":96.511628},{"timestamp":1481858040,"value":96.522112},{"timestamp":1481858100,"value":97.490430},{"timestamp":1481858160,"value":96.958012}]},{"endpoint":"docker-a","counter":"cpu.iowait","dstype":"GAUGE","step":60,"Values":[{"timestamp":1481854620,"value":0.815451},{"timestamp":1481854680,"value":0.598035},{"timestamp":1481854740,"value":1.239316},{"timestamp":1481854800,"value":0.775528},{"timestamp":1481854860,"value":0.895904},{"timestamp":1481854920,"value":0.893997},{"timestamp":1481854980,"value":0.811619},{"timestamp":1481855040,"value":0.728363},{"timestamp":1481855100,"value":0.425894},{"timestamp":1481855160,"value":0.768902},{"timestamp":1481855220,"value":1.443737},{"timestamp":1481855280,"value":0.297240},{"timestamp":1481855340,"value":0.213311},{"timestamp":1481855400,"value":0.512821},{"timestamp":1481855460,"value":1.022147},{"timestamp":1481855520,"value":0.810926},{"timestamp":1481855580,"value":0.515464},{"timestamp":1481855640,"value":0.555556},{"timestamp":1481855700,"value":0.470488},{"timestamp":1481855760,"value":0.428266},{"timestamp":1481855820,"value":0.386598},{"timestamp":1481855880,"value":0.638570},{"timestamp":1481855940,"value":0.432152},{"timestamp":1481856000,"value":0.730241},{"timestamp":1481856060,"value":0.643777},{"timestamp":1481856120,"value":0.603188},{"timestamp":1481856180,"value":1.035822},{"timestamp":1481856240,"value":8.927039},{"timestamp":1481856300,"value":0.605536},{"timestamp":1481856360,"value":0.341443},{"timestamp":1481856420,"value":0.343495},{"timestamp":1481856480,"value":0.601892},{"timestamp":1481856540,"value":0.466102},{"timestamp":1481856600,"value":0.557222},{"timestamp":1481856660,"value":0.382653},{"timestamp":1481856720,"value":0.554135},{"timestamp":1481856780,"value":0.428816},{"timestamp":1481856840,"value":1.151386},{"timestamp":1481856900,"value":0.556269},{"timestamp":1481856960,"value":0.469684},{"timestamp":1481857020,"value":0.298380},{"timestamp":1481857080,"value":0.903226},{"timestamp":1481857140,"value":0.426076},{"timestamp":1481857200,"value":0.771208},{"timestamp":1481857260,"value":1.071582},{"timestamp":1481857320,"value":1.278772},{"timestamp":1481857380,"value":0.642674},{"timestamp":1481857440,"value":0.212044},{"timestamp":1481857500,"value":0.686106},{"timestamp":1481857560,"value":0.425713},{"timestamp":1481857620,"value":0.810235},{"timestamp":1481857680,"value":0.765632},{"timestamp":1481857740,"value":0.380389},{"timestamp":1481857800,"value":0.296988},{"timestamp":1481857860,"value":0.855432},{"timestamp":1481857920,"value":0.470286},{"timestamp":1481857980,"value":1.248923},{"timestamp":1481858040,"value":1.631602},{"timestamp":1481858100,"value":1.531263},{"timestamp":1481858160,"value":0.599829}]},{"endpoint":"docker-b","counter":"cpu.idle","dstype":"GAUGE","step":60,"Values":[{"timestamp":1481854620,"value":93.811775},{"timestamp":1481854680,"value":94.150538},{"timestamp":1481854740,"value":94.991438},{"timestamp":1481854800,"value":93.287435},{"timestamp":1481854860,"value":96.642584},{"timestamp":1481854920,"value":98.207426},{"timestamp":1481854980,"value":94.801875},{"timestamp":1481855040,"value":97.827939},{"timestamp":1481855100,"value":94.439692},{"timestamp":1481855160,"value":98.292787},{"timestamp":1481855220,"value":95.027624},{"timestamp":1481855280,"value":98.218074},{"timestamp":1481855340,"value":97.402044},{"timestamp":1481855400,"value":94.368601},{"timestamp":1481855460,"value":94.772631},{"timestamp":1481855520,"value":93.992331},{"timestamp":1481855580,"value":94.939446},{"timestamp":1481855640,"value":97.780623},{"timestamp":1481855700,"value":97.860505},{"timestamp":1481855760,"value":92.765411},{"timestamp":1481855820,"value":98.029979},{"timestamp":1481855880,"value":94.523502},{"timestamp":1481855940,"value":94.102564},{"timestamp":1481856000,"value":94.965870},{"timestamp":1481856060,"value":94.382979},{"timestamp":1481856120,"value":93.336181},{"timestamp":1481856180,"value":97.988875},{"timestamp":1481856240,"value":94.401709},{"timestamp":1481856300,"value":94.619983},{"timestamp":1481856360,"value":94.916702},{"timestamp":1481856420,"value":94.089733},{"timestamp":1481856480,"value":94.475375},{"timestamp":1481856540,"value":93.576017},{"timestamp":1481856600,"value":94.010195},{"timestamp":1481856660,"value":94.137783},{"timestamp":1481856720,"value":95.264505},{"timestamp":1481856780,"value":96.879008},{"timestamp":1481856840,"value":96.387590},{"timestamp":1481856900,"value":93.830334},{"timestamp":1481856960,"value":96.282051},{"timestamp":1481857020,"value":94.173093},{"timestamp":1481857080,"value":95.382642},{"timestamp":1481857140,"value":94.107452},{"timestamp":1481857200,"value":93.611584},{"timestamp":1481857260,"value":97.053800},{"timestamp":1481857320,"value":94.404101},{"timestamp":1481857380,"value":94.449189},{"timestamp":1481857440,"value":98.286938},{"timestamp":1481857500,"value":93.720632},{"timestamp":1481857560,"value":93.669803},{"timestamp":1481857620,"value":93.865294},{"timestamp":1481857680,"value":94.498934},{"timestamp":1481857740,"value":94.610778},{"timestamp":1481857800,"value":93.929029},{"timestamp":1481857860,"value":97.827939},{"timestamp":1481857920,"value":97.768240},{"timestamp":1481857980,"value":91.079014},{"timestamp":1481858040,"value":97.854998},{"timestamp":1481858100,"value":93.399482},{"timestamp":1481858160,"value":94.014536}]},{"endpoint":"docker-b","counter":"cpu.iowait","dstype":"GAUGE","step":60,"Values":[{"timestamp":1481854620,"value":0.171895},{"timestamp":1481854680,"value":0.645161},{"timestamp":1481854740,"value":0.470890},{"timestamp":1481854800,"value":0.731497},{"timestamp":1481854860,"value":0.594985},{"timestamp":1481854920,"value":0.256082},{"timestamp":1481854980,"value":0.340861},{"timestamp":1481855040,"value":0.255537},{"timestamp":1481855100,"value":0.684346},{"timestamp":1481855160,"value":0.384123},{"timestamp":1481855220,"value":0.084998},{"timestamp":1481855280,"value":0.466695},{"timestamp":1481855340,"value":1.192504},{"timestamp":1481855400,"value":0.511945},{"timestamp":1481855460,"value":0.594985},{"timestamp":1481855520,"value":0.383468},{"timestamp":1481855580,"value":1.038062},{"timestamp":1481855640,"value":0.981647},{"timestamp":1481855700,"value":0.599059},{"timestamp":1481855760,"value":0.770548},{"timestamp":1481855820,"value":0.428266},{"timestamp":1481855880,"value":0.301854},{"timestamp":1481855940,"value":0.598291},{"timestamp":1481856000,"value":0.853242},{"timestamp":1481856060,"value":0.723404},{"timestamp":1481856120,"value":1.025203},{"timestamp":1481856180,"value":0.470689},{"timestamp":1481856240,"value":0.213675},{"timestamp":1481856300,"value":0.768574},{"timestamp":1481856360,"value":0.256301},{"timestamp":1481856420,"value":0.388266},{"timestamp":1481856480,"value":0.342612},{"timestamp":1481856540,"value":0.813704},{"timestamp":1481856600,"value":0.594732},{"timestamp":1481856660,"value":0.684638},{"timestamp":1481856720,"value":1.535836},{"timestamp":1481856780,"value":0.256520},{"timestamp":1481856840,"value":0.382490},{"timestamp":1481856900,"value":1.028278},{"timestamp":1481856960,"value":1.025641},{"timestamp":1481857020,"value":0.642674},{"timestamp":1481857080,"value":0.726806},{"timestamp":1481857140,"value":0.649913},{"timestamp":1481857200,"value":0.809199},{"timestamp":1481857260,"value":0.256191},{"timestamp":1481857320,"value":0.512601},{"timestamp":1481857380,"value":0.597780},{"timestamp":1481857440,"value":0.342612},{"timestamp":1481857500,"value":1.196070},{"timestamp":1481857560,"value":0.983747},{"timestamp":1481857620,"value":0.900901},{"timestamp":1481857680,"value":0.639659},{"timestamp":1481857740,"value":0.641574},{"timestamp":1481857800,"value":0.598546},{"timestamp":1481857860,"value":0.425894},{"timestamp":1481857920,"value":0.729614},{"timestamp":1481857980,"value":0.339847},{"timestamp":1481858040,"value":0.686401},{"timestamp":1481858100,"value":0.560828},{"timestamp":1481858160,"value":0.513040}]},{"endpoint":"docker-c","counter":"cpu.idle","dstype":"","step":0,"Values":[]},{"endpoint":"docker-c","counter":"cpu.iowait","dstype":"","step":0,"Values":[]}]


================================================ FILE: docs/doc/graph.html.json ================================================ { "ApiSpecs": [ { "HttpVerb": "GET", "Path": "/api/v1/graph/endpoint", "Calls": [ { "Id": 0, "CurrentPath": "/api/v1/graph/endpoint", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Cookie": " name=test1; sig=d4f71cba377911e699d60242ac110010\r", "X-Forwarded-For": " " }, "CommonRequestHeaders": null, "ResponseHeader": { "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"error\":\"q is missing\"}", "ResponseCode": 400 }, { "Id": 1, "CurrentPath": "/api/v1/graph/endpoint", "MethodType": "GET", "PostForm": null, "RequestHeader": { "X-Forwarded-For": " " }, "CommonRequestHeaders": null, "ResponseHeader": { "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "", "ResponseCode": 401 }, { "Id": 2, "CurrentPath": "/api/v1/graph/endpoint", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Cookie": " name=test1; sig=d4f71cba377911e699d60242ac110010\r", "X-Forwarded-For": " " }, "CommonRequestHeaders": null, "ResponseHeader": { "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": { "q": "a.+" }, "RequestBody": "", "ResponseBody": "[{\"endpoint\":\"docker-agent\",\"id\":7},{\"endpoint\":\"docker-task\",\"id\":6},{\"endpoint\":\"graph\",\"id\":3},{\"endpoint\":\"nodata\",\"id\":920},{\"endpoint\":\"task\",\"id\":5}]", "ResponseCode": 200 }, { "Id": 0, "CurrentPath": "/api/v1/graph/endpoint", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": { "limit": "10", "q": ".+" }, "RequestBody": "", "ResponseBody": "[{\"endpoint\":\"docker-a\",\"id\":244525914},{\"endpoint\":\"docker-b\",\"id\":12675145},{\"endpoint\":\"docker-c\",\"id\":12683936},{\"endpoint\":\"docker-d\",\"id\":12681439},{\"endpoint\":\"docker-f\",\"id\":12676363},{\"endpoint\":\"docker-g\",\"id\":12681715},{\"endpoint\":\"docker-h\",\"id\":12678421},{\"endpoint\":\"docker-i\",\"id\":12676879},{\"endpoint\":\"docker-j\",\"id\":12675447},{\"endpoint\":\"docker-k\",\"id\":12679349}]", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/graph/endpoint_counter", "Calls": [ { "Id": 3, "CurrentPath": "/api/v1/graph/endpoint_counter", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Cookie": " name=test1; sig=d4f71cba377911e699d60242ac110010\r", "X-Forwarded-For": " " }, "CommonRequestHeaders": null, "ResponseHeader": { "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"error\":\"eid is missing\"}", "ResponseCode": 400 }, { "Id": 4, "CurrentPath": "/api/v1/graph/endpoint_counter", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Cookie": " name=test1; sig=d4f71cba377911e699d60242ac110010\r", "X-Forwarded-For": " " }, "CommonRequestHeaders": null, "ResponseHeader": { "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": { "eid": "6,7", "metricQuery": "disk.+" }, "RequestBody": "", "ResponseBody": "[\"disk.io.avgqu-sz/device=sda\",\"disk.io.ios_in_progress/device=sda\",\"disk.io.msec_read/device=sda\",\"disk.io.read_requests/device=sda\",\"disk.io.read_sectors/device=sda\",\"disk.io.write_bytes/device=sda\",\"disk.io.write_merged/device=sda\",\"disk.io.msec_write/device=sda\",\"disk.io.read_merged/device=sda\",\"disk.io.svctm/device=sda\",\"disk.io.util/device=sda\",\"disk.io.avgrq_sz/device=sda\",\"disk.io.msec_weighted_total/device=sda\",\"disk.io.await/device=sda\",\"disk.io.msec_total/device=sda\",\"disk.io.read_bytes/device=sda\",\"disk.io.write_requests/device=sda\",\"disk.io.write_sectors/device=sda\"]", "ResponseCode": 200 }, { "Id": 2, "CurrentPath": "/api/v1/graph/endpoint_counter", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": { "eid": "244525914,12675145,12683936,12681439,12676363,12681715,12678421,12676879,12675447,12679349", "limit": "3", "metricQuery": "disk.+" }, "RequestBody": "", "ResponseBody": "[\"disk.io.write_sectors/device=sdh\",\"disk.device.size/device=sdm\",\"disk.io.ios_in_progress/device=sdj\"]", "ResponseCode": 200 } ] }, { "HttpVerb": "POST", "Path": "/api/v1/graph/history", "Calls": [ { "Id": 0, "CurrentPath": "/api/v1/graph/history", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"step\":60,\"start_time\":1481854596,\"hostnames\":[\"docker-a\",\"docker-b\",\"docker-c\"],\"end_time\":1481858193,\"counters\":[\"cpu.idle\",\"cpu.iowait\"],\"consol_fun\":\"AVERAGE\"}", "ResponseBody": "[{\"endpoint\":\"docker-a\",\"counter\":\"cpu.idle\",\"dstype\":\"GAUGE\",\"step\":60,\"Values\":[{\"timestamp\":1481854620,\"value\":98.154506},{\"timestamp\":1481854680,\"value\":97.864161},{\"timestamp\":1481854740,\"value\":97.521368},{\"timestamp\":1481854800,\"value\":97.587247},{\"timestamp\":1481854860,\"value\":97.440273},{\"timestamp\":1481854920,\"value\":97.914006},{\"timestamp\":1481854980,\"value\":97.223409},{\"timestamp\":1481855040,\"value\":98.029135},{\"timestamp\":1481855100,\"value\":97.614991},{\"timestamp\":1481855160,\"value\":97.565143},{\"timestamp\":1481855220,\"value\":97.070064},{\"timestamp\":1481855280,\"value\":98.726115},{\"timestamp\":1481855340,\"value\":98.720137},{\"timestamp\":1481855400,\"value\":98.205128},{\"timestamp\":1481855460,\"value\":97.700170},{\"timestamp\":1481855520,\"value\":97.780623},{\"timestamp\":1481855580,\"value\":97.379725},{\"timestamp\":1481855640,\"value\":98.034188},{\"timestamp\":1481855700,\"value\":98.246364},{\"timestamp\":1481855760,\"value\":98.372591},{\"timestamp\":1481855820,\"value\":98.152921},{\"timestamp\":1481855880,\"value\":97.914006},{\"timestamp\":1481855940,\"value\":95.592048},{\"timestamp\":1481856000,\"value\":94.115120},{\"timestamp\":1481856060,\"value\":97.596567},{\"timestamp\":1481856120,\"value\":97.501077},{\"timestamp\":1481856180,\"value\":96.374622},{\"timestamp\":1481856240,\"value\":89.570815},{\"timestamp\":1481856300,\"value\":96.410035},{\"timestamp\":1481856360,\"value\":97.567222},{\"timestamp\":1481856420,\"value\":97.252040},{\"timestamp\":1481856480,\"value\":95.356836},{\"timestamp\":1481856540,\"value\":97.330508},{\"timestamp\":1481856600,\"value\":96.999571},{\"timestamp\":1481856660,\"value\":97.278912},{\"timestamp\":1481856720,\"value\":97.229327},{\"timestamp\":1481856780,\"value\":97.212693},{\"timestamp\":1481856840,\"value\":96.503198},{\"timestamp\":1481856900,\"value\":96.790757},{\"timestamp\":1481856960,\"value\":98.121264},{\"timestamp\":1481857020,\"value\":98.550725},{\"timestamp\":1481857080,\"value\":97.548387},{\"timestamp\":1481857140,\"value\":98.466127},{\"timestamp\":1481857200,\"value\":97.900600},{\"timestamp\":1481857260,\"value\":97.985426},{\"timestamp\":1481857320,\"value\":97.357204},{\"timestamp\":1481857380,\"value\":97.086547},{\"timestamp\":1481857440,\"value\":98.770144},{\"timestamp\":1481857500,\"value\":97.727273},{\"timestamp\":1481857560,\"value\":98.595147},{\"timestamp\":1481857620,\"value\":97.867804},{\"timestamp\":1481857680,\"value\":98.128456},{\"timestamp\":1481857740,\"value\":97.886729},{\"timestamp\":1481857800,\"value\":95.969453},{\"timestamp\":1481857860,\"value\":97.134303},{\"timestamp\":1481857920,\"value\":98.033348},{\"timestamp\":1481857980,\"value\":96.511628},{\"timestamp\":1481858040,\"value\":96.522112},{\"timestamp\":1481858100,\"value\":97.490430},{\"timestamp\":1481858160,\"value\":96.958012}]},{\"endpoint\":\"docker-a\",\"counter\":\"cpu.iowait\",\"dstype\":\"GAUGE\",\"step\":60,\"Values\":[{\"timestamp\":1481854620,\"value\":0.815451},{\"timestamp\":1481854680,\"value\":0.598035},{\"timestamp\":1481854740,\"value\":1.239316},{\"timestamp\":1481854800,\"value\":0.775528},{\"timestamp\":1481854860,\"value\":0.895904},{\"timestamp\":1481854920,\"value\":0.893997},{\"timestamp\":1481854980,\"value\":0.811619},{\"timestamp\":1481855040,\"value\":0.728363},{\"timestamp\":1481855100,\"value\":0.425894},{\"timestamp\":1481855160,\"value\":0.768902},{\"timestamp\":1481855220,\"value\":1.443737},{\"timestamp\":1481855280,\"value\":0.297240},{\"timestamp\":1481855340,\"value\":0.213311},{\"timestamp\":1481855400,\"value\":0.512821},{\"timestamp\":1481855460,\"value\":1.022147},{\"timestamp\":1481855520,\"value\":0.810926},{\"timestamp\":1481855580,\"value\":0.515464},{\"timestamp\":1481855640,\"value\":0.555556},{\"timestamp\":1481855700,\"value\":0.470488},{\"timestamp\":1481855760,\"value\":0.428266},{\"timestamp\":1481855820,\"value\":0.386598},{\"timestamp\":1481855880,\"value\":0.638570},{\"timestamp\":1481855940,\"value\":0.432152},{\"timestamp\":1481856000,\"value\":0.730241},{\"timestamp\":1481856060,\"value\":0.643777},{\"timestamp\":1481856120,\"value\":0.603188},{\"timestamp\":1481856180,\"value\":1.035822},{\"timestamp\":1481856240,\"value\":8.927039},{\"timestamp\":1481856300,\"value\":0.605536},{\"timestamp\":1481856360,\"value\":0.341443},{\"timestamp\":1481856420,\"value\":0.343495},{\"timestamp\":1481856480,\"value\":0.601892},{\"timestamp\":1481856540,\"value\":0.466102},{\"timestamp\":1481856600,\"value\":0.557222},{\"timestamp\":1481856660,\"value\":0.382653},{\"timestamp\":1481856720,\"value\":0.554135},{\"timestamp\":1481856780,\"value\":0.428816},{\"timestamp\":1481856840,\"value\":1.151386},{\"timestamp\":1481856900,\"value\":0.556269},{\"timestamp\":1481856960,\"value\":0.469684},{\"timestamp\":1481857020,\"value\":0.298380},{\"timestamp\":1481857080,\"value\":0.903226},{\"timestamp\":1481857140,\"value\":0.426076},{\"timestamp\":1481857200,\"value\":0.771208},{\"timestamp\":1481857260,\"value\":1.071582},{\"timestamp\":1481857320,\"value\":1.278772},{\"timestamp\":1481857380,\"value\":0.642674},{\"timestamp\":1481857440,\"value\":0.212044},{\"timestamp\":1481857500,\"value\":0.686106},{\"timestamp\":1481857560,\"value\":0.425713},{\"timestamp\":1481857620,\"value\":0.810235},{\"timestamp\":1481857680,\"value\":0.765632},{\"timestamp\":1481857740,\"value\":0.380389},{\"timestamp\":1481857800,\"value\":0.296988},{\"timestamp\":1481857860,\"value\":0.855432},{\"timestamp\":1481857920,\"value\":0.470286},{\"timestamp\":1481857980,\"value\":1.248923},{\"timestamp\":1481858040,\"value\":1.631602},{\"timestamp\":1481858100,\"value\":1.531263},{\"timestamp\":1481858160,\"value\":0.599829}]},{\"endpoint\":\"docker-b\",\"counter\":\"cpu.idle\",\"dstype\":\"GAUGE\",\"step\":60,\"Values\":[{\"timestamp\":1481854620,\"value\":93.811775},{\"timestamp\":1481854680,\"value\":94.150538},{\"timestamp\":1481854740,\"value\":94.991438},{\"timestamp\":1481854800,\"value\":93.287435},{\"timestamp\":1481854860,\"value\":96.642584},{\"timestamp\":1481854920,\"value\":98.207426},{\"timestamp\":1481854980,\"value\":94.801875},{\"timestamp\":1481855040,\"value\":97.827939},{\"timestamp\":1481855100,\"value\":94.439692},{\"timestamp\":1481855160,\"value\":98.292787},{\"timestamp\":1481855220,\"value\":95.027624},{\"timestamp\":1481855280,\"value\":98.218074},{\"timestamp\":1481855340,\"value\":97.402044},{\"timestamp\":1481855400,\"value\":94.368601},{\"timestamp\":1481855460,\"value\":94.772631},{\"timestamp\":1481855520,\"value\":93.992331},{\"timestamp\":1481855580,\"value\":94.939446},{\"timestamp\":1481855640,\"value\":97.780623},{\"timestamp\":1481855700,\"value\":97.860505},{\"timestamp\":1481855760,\"value\":92.765411},{\"timestamp\":1481855820,\"value\":98.029979},{\"timestamp\":1481855880,\"value\":94.523502},{\"timestamp\":1481855940,\"value\":94.102564},{\"timestamp\":1481856000,\"value\":94.965870},{\"timestamp\":1481856060,\"value\":94.382979},{\"timestamp\":1481856120,\"value\":93.336181},{\"timestamp\":1481856180,\"value\":97.988875},{\"timestamp\":1481856240,\"value\":94.401709},{\"timestamp\":1481856300,\"value\":94.619983},{\"timestamp\":1481856360,\"value\":94.916702},{\"timestamp\":1481856420,\"value\":94.089733},{\"timestamp\":1481856480,\"value\":94.475375},{\"timestamp\":1481856540,\"value\":93.576017},{\"timestamp\":1481856600,\"value\":94.010195},{\"timestamp\":1481856660,\"value\":94.137783},{\"timestamp\":1481856720,\"value\":95.264505},{\"timestamp\":1481856780,\"value\":96.879008},{\"timestamp\":1481856840,\"value\":96.387590},{\"timestamp\":1481856900,\"value\":93.830334},{\"timestamp\":1481856960,\"value\":96.282051},{\"timestamp\":1481857020,\"value\":94.173093},{\"timestamp\":1481857080,\"value\":95.382642},{\"timestamp\":1481857140,\"value\":94.107452},{\"timestamp\":1481857200,\"value\":93.611584},{\"timestamp\":1481857260,\"value\":97.053800},{\"timestamp\":1481857320,\"value\":94.404101},{\"timestamp\":1481857380,\"value\":94.449189},{\"timestamp\":1481857440,\"value\":98.286938},{\"timestamp\":1481857500,\"value\":93.720632},{\"timestamp\":1481857560,\"value\":93.669803},{\"timestamp\":1481857620,\"value\":93.865294},{\"timestamp\":1481857680,\"value\":94.498934},{\"timestamp\":1481857740,\"value\":94.610778},{\"timestamp\":1481857800,\"value\":93.929029},{\"timestamp\":1481857860,\"value\":97.827939},{\"timestamp\":1481857920,\"value\":97.768240},{\"timestamp\":1481857980,\"value\":91.079014},{\"timestamp\":1481858040,\"value\":97.854998},{\"timestamp\":1481858100,\"value\":93.399482},{\"timestamp\":1481858160,\"value\":94.014536}]},{\"endpoint\":\"docker-b\",\"counter\":\"cpu.iowait\",\"dstype\":\"GAUGE\",\"step\":60,\"Values\":[{\"timestamp\":1481854620,\"value\":0.171895},{\"timestamp\":1481854680,\"value\":0.645161},{\"timestamp\":1481854740,\"value\":0.470890},{\"timestamp\":1481854800,\"value\":0.731497},{\"timestamp\":1481854860,\"value\":0.594985},{\"timestamp\":1481854920,\"value\":0.256082},{\"timestamp\":1481854980,\"value\":0.340861},{\"timestamp\":1481855040,\"value\":0.255537},{\"timestamp\":1481855100,\"value\":0.684346},{\"timestamp\":1481855160,\"value\":0.384123},{\"timestamp\":1481855220,\"value\":0.084998},{\"timestamp\":1481855280,\"value\":0.466695},{\"timestamp\":1481855340,\"value\":1.192504},{\"timestamp\":1481855400,\"value\":0.511945},{\"timestamp\":1481855460,\"value\":0.594985},{\"timestamp\":1481855520,\"value\":0.383468},{\"timestamp\":1481855580,\"value\":1.038062},{\"timestamp\":1481855640,\"value\":0.981647},{\"timestamp\":1481855700,\"value\":0.599059},{\"timestamp\":1481855760,\"value\":0.770548},{\"timestamp\":1481855820,\"value\":0.428266},{\"timestamp\":1481855880,\"value\":0.301854},{\"timestamp\":1481855940,\"value\":0.598291},{\"timestamp\":1481856000,\"value\":0.853242},{\"timestamp\":1481856060,\"value\":0.723404},{\"timestamp\":1481856120,\"value\":1.025203},{\"timestamp\":1481856180,\"value\":0.470689},{\"timestamp\":1481856240,\"value\":0.213675},{\"timestamp\":1481856300,\"value\":0.768574},{\"timestamp\":1481856360,\"value\":0.256301},{\"timestamp\":1481856420,\"value\":0.388266},{\"timestamp\":1481856480,\"value\":0.342612},{\"timestamp\":1481856540,\"value\":0.813704},{\"timestamp\":1481856600,\"value\":0.594732},{\"timestamp\":1481856660,\"value\":0.684638},{\"timestamp\":1481856720,\"value\":1.535836},{\"timestamp\":1481856780,\"value\":0.256520},{\"timestamp\":1481856840,\"value\":0.382490},{\"timestamp\":1481856900,\"value\":1.028278},{\"timestamp\":1481856960,\"value\":1.025641},{\"timestamp\":1481857020,\"value\":0.642674},{\"timestamp\":1481857080,\"value\":0.726806},{\"timestamp\":1481857140,\"value\":0.649913},{\"timestamp\":1481857200,\"value\":0.809199},{\"timestamp\":1481857260,\"value\":0.256191},{\"timestamp\":1481857320,\"value\":0.512601},{\"timestamp\":1481857380,\"value\":0.597780},{\"timestamp\":1481857440,\"value\":0.342612},{\"timestamp\":1481857500,\"value\":1.196070},{\"timestamp\":1481857560,\"value\":0.983747},{\"timestamp\":1481857620,\"value\":0.900901},{\"timestamp\":1481857680,\"value\":0.639659},{\"timestamp\":1481857740,\"value\":0.641574},{\"timestamp\":1481857800,\"value\":0.598546},{\"timestamp\":1481857860,\"value\":0.425894},{\"timestamp\":1481857920,\"value\":0.729614},{\"timestamp\":1481857980,\"value\":0.339847},{\"timestamp\":1481858040,\"value\":0.686401},{\"timestamp\":1481858100,\"value\":0.560828},{\"timestamp\":1481858160,\"value\":0.513040}]},{\"endpoint\":\"docker-c\",\"counter\":\"cpu.idle\",\"dstype\":\"\",\"step\":0,\"Values\":[]},{\"endpoint\":\"docker-c\",\"counter\":\"cpu.iowait\",\"dstype\":\"\",\"step\":0,\"Values\":[]}]", "ResponseCode": 200 } ] } ] } ================================================ FILE: docs/doc/host.html ================================================ API Documentation
Base Urls

Production : /api/v1

Staging : /api/v1

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"id":125,"tpl_name":"tplA","parent_id":0,"action_id":99,"create_user":"root"},{"id":142,"tpl_name":"tplB","parent_id":0,"action_id":111,"create_user":"root"},{"id":180,"tpl_name":"tplC","parent_id":0,"action_id":142,"create_user":"root"}]

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"id":78,"grp_name":"tplB","create_user":"userA"},{"id":145,"grp_name":"Owl_Default_Group","create_user":"userA"}]


================================================ FILE: docs/doc/host.html.json ================================================ { "ApiSpecs": [ { "HttpVerb": "GET", "Path": "/api/v1/host/1647/template", "Calls": [ { "Id": 0, "CurrentPath": "/api/v1/host/1647/template", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "[{\"id\":125,\"tpl_name\":\"tplA\",\"parent_id\":0,\"action_id\":99,\"create_user\":\"root\"},{\"id\":142,\"tpl_name\":\"tplB\",\"parent_id\":0,\"action_id\":111,\"create_user\":\"root\"},{\"id\":180,\"tpl_name\":\"tplC\",\"parent_id\":0,\"action_id\":142,\"create_user\":\"root\"}]", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/host/1647/hostgroup", "Calls": [ { "Id": 1, "CurrentPath": "/api/v1/host/1647/hostgroup", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "[{\"id\":78,\"grp_name\":\"tplB\",\"create_user\":\"userA\"},{\"id\":145,\"grp_name\":\"Owl_Default_Group\",\"create_user\":\"userA\"}]", "ResponseCode": 200 } ] } ] } ================================================ FILE: docs/doc/hostgroup.html ================================================ API Documentation

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
Content-Type application/json
X-Forwarded-For 127.0.0.1

Request Body

{"name":"testhostgroup"}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"id":343,"grp_name":"testhostgroup","create_user":"root"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
Content-Type application/json
X-Forwarded-For 127.0.0.1

Request Body

{"hosts":["testhostgroup","agent_test"],"hostgroup_id":342}

Response Code

417

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"error":"record not found"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
Content-Type application/json
X-Forwarded-For 127.0.0.1

Request Body

{"hosts":["testhostgroup","agent_test"],"hostgroup_id":343}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"message":"[9312 9313] bind to hostgroup: 343"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
Content-Type application/json
X-Forwarded-For 127.0.0.1

Request Body

{"hostgroup_id":343,"host_id":9312}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"message":"unbind host:9312 of hostgroup: 343"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"hostgroup":{"id":343,"grp_name":"testhostgroup","create_user":"root"},"hosts":[{"id":9313,"hostname":"agent_test","ip":"","agent_version":"","plugin_version":"","maintain_begin":0,"maintain_end":0}]}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"id":3,"grp_name":"hostnameA","create_user":"UserA"},{"id":5,"grp_name":"TAI","create_user":"UserB"},{"id":8,"grp_name":"ForTestHostG","create_user":"root"}]

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

URL Params

Key Value
limit 10
page 1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"id":3,"grp_name":"docker-A","create_user":"user-A"},{"id":5,"grp_name":"docker-T","create_user":"cheminlin"},{"id":8,"grp_name":"docker-F","create_user":"root"},{"id":9,"grp_name":"docker-B","create_user":"root"},{"id":11,"grp_name":"docker-D","create_user":"user-C"},{"id":12,"grp_name":"docker-E","create_user":"user-C"},{"id":14,"grp_name":"docker-G","create_user":"user-C"},{"id":15,"grp_name":"docker-G2","create_user":"user-C"},{"id":16,"grp_name":"docker-H","create_user":"user-C"},{"id":17,"grp_name":"tools","create_user":"user-C"}]

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"message":"hostgroup:343 has been deleted"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"hostgroup":{"id":3,"grp_name":"hostgroupA","create_user":"root"},"templates":[{"id":5,"tpl_name":"TplA","parent_id":0,"action_id":12,"create_user":"root"},{"id":91,"tpl_name":"TplB","parent_id":0,"action_id":59,"create_user":"userA"},{"id":94,"tpl_name":"TplB","parent_id":0,"action_id":62,"create_user":"userA"},{"id":103,"tpl_name":"TplC","parent_id":0,"action_id":74,"create_user":"root"},{"id":104,"tpl_name":"TplD","parent_id":0,"action_id":75,"create_user":"root"},{"id":105,"tpl_name":"TplE","parent_id":0,"action_id":76,"create_user":"root"},{"id":116,"tpl_name":"TplG","parent_id":0,"action_id":87,"create_user":"root"},{"id":125,"tpl_name":"TplH","parent_id":0,"action_id":99,"create_user":"root"},{"id":126,"tpl_name":"http","parent_id":0,"action_id":100,"create_user":"root"},{"id":127,"tpl_name":"TplJ","parent_id":0,"action_id":101,"create_user":"root"},{"id":194,"tpl_name":"TplK","parent_id":0,"action_id":153,"create_user":"root"},{"id":208,"tpl_name":"PT_TEST","parent_id":0,"action_id":163,"create_user":"userO"}]}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
Content-Type application/json
X-Forwarded-For 127.0.0.1

Request Body

{"tpl_id":5,"grp_id":3}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"message":"template: 5 is unbind of HostGroup: 3"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
Content-Type application/json
X-Forwarded-For 127.0.0.1

Request Body

{"tpl_id":5,"grp_id":3}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"grp_id":3,"tpl_id":5,"bind_user":2}


================================================ FILE: docs/doc/hostgroup.html.json ================================================ { "ApiSpecs": [ { "HttpVerb": "POST", "Path": "/api/v1/hostgroup", "Calls": [ { "Id": 0, "CurrentPath": "/api/v1/hostgroup", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"name\":\"testhostgroup\"}", "ResponseBody": "{\"id\":343,\"grp_name\":\"testhostgroup\",\"create_user\":\"root\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "POST", "Path": "/api/v1/hostgroup/host", "Calls": [ { "Id": 1, "CurrentPath": "/api/v1/hostgroup/host", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"hosts\":[\"testhostgroup\",\"agent_test\"],\"hostgroup_id\":342}", "ResponseBody": "{\"error\":\"record not found\"}", "ResponseCode": 417 }, { "Id": 2, "CurrentPath": "/api/v1/hostgroup/host", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"hosts\":[\"testhostgroup\",\"agent_test\"],\"hostgroup_id\":343}", "ResponseBody": "{\"message\":\"[9312 9313] bind to hostgroup: 343\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "PUT", "Path": "/api/v1/hostgroup/host", "Calls": [ { "Id": 3, "CurrentPath": "/api/v1/hostgroup/host", "MethodType": "PUT", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"hostgroup_id\":343,\"host_id\":9312}", "ResponseBody": "{\"message\":\"unbind host:9312 of hostgroup: 343\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/hostgroup/343", "Calls": [ { "Id": 0, "CurrentPath": "/api/v1/hostgroup/343", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"hostgroup\":{\"id\":343,\"grp_name\":\"testhostgroup\",\"create_user\":\"root\"},\"hosts\":[{\"id\":9313,\"hostname\":\"agent_test\",\"ip\":\"\",\"agent_version\":\"\",\"plugin_version\":\"\",\"maintain_begin\":0,\"maintain_end\":0}]}", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/hostgroup", "Calls": [ { "Id": 1, "CurrentPath": "/api/v1/hostgroup", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "[{\"id\":3,\"grp_name\":\"hostnameA\",\"create_user\":\"UserA\"},{\"id\":5,\"grp_name\":\"TAI\",\"create_user\":\"UserB\"},{\"id\":8,\"grp_name\":\"ForTestHostG\",\"create_user\":\"root\"}]", "ResponseCode": 200 }, { "Id": 0, "CurrentPath": "/api/v1/hostgroup", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": { "limit": "10", "page": "1" }, "RequestBody": "", "ResponseBody": "[{\"id\":3,\"grp_name\":\"docker-A\",\"create_user\":\"user-A\"},{\"id\":5,\"grp_name\":\"docker-T\",\"create_user\":\"cheminlin\"},{\"id\":8,\"grp_name\":\"docker-F\",\"create_user\":\"root\"},{\"id\":9,\"grp_name\":\"docker-B\",\"create_user\":\"root\"},{\"id\":11,\"grp_name\":\"docker-D\",\"create_user\":\"user-C\"},{\"id\":12,\"grp_name\":\"docker-E\",\"create_user\":\"user-C\"},{\"id\":14,\"grp_name\":\"docker-G\",\"create_user\":\"user-C\"},{\"id\":15,\"grp_name\":\"docker-G2\",\"create_user\":\"user-C\"},{\"id\":16,\"grp_name\":\"docker-H\",\"create_user\":\"user-C\"},{\"id\":17,\"grp_name\":\"tools\",\"create_user\":\"user-C\"}]", "ResponseCode": 200 } ] }, { "HttpVerb": "DELETE", "Path": "/api/v1/hostgroup/343", "Calls": [ { "Id": 2, "CurrentPath": "/api/v1/hostgroup/343", "MethodType": "DELETE", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"message\":\"hostgroup:343 has been deleted\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/hostgroup/3/template", "Calls": [ { "Id": 0, "CurrentPath": "/api/v1/hostgroup/3/template", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"hostgroup\":{\"id\":3,\"grp_name\":\"hostgroupA\",\"create_user\":\"root\"},\"templates\":[{\"id\":5,\"tpl_name\":\"TplA\",\"parent_id\":0,\"action_id\":12,\"create_user\":\"root\"},{\"id\":91,\"tpl_name\":\"TplB\",\"parent_id\":0,\"action_id\":59,\"create_user\":\"userA\"},{\"id\":94,\"tpl_name\":\"TplB\",\"parent_id\":0,\"action_id\":62,\"create_user\":\"userA\"},{\"id\":103,\"tpl_name\":\"TplC\",\"parent_id\":0,\"action_id\":74,\"create_user\":\"root\"},{\"id\":104,\"tpl_name\":\"TplD\",\"parent_id\":0,\"action_id\":75,\"create_user\":\"root\"},{\"id\":105,\"tpl_name\":\"TplE\",\"parent_id\":0,\"action_id\":76,\"create_user\":\"root\"},{\"id\":116,\"tpl_name\":\"TplG\",\"parent_id\":0,\"action_id\":87,\"create_user\":\"root\"},{\"id\":125,\"tpl_name\":\"TplH\",\"parent_id\":0,\"action_id\":99,\"create_user\":\"root\"},{\"id\":126,\"tpl_name\":\"TplI\",\"parent_id\":0,\"action_id\":100,\"create_user\":\"root\"},{\"id\":127,\"tpl_name\":\"TplJ\",\"parent_id\":0,\"action_id\":101,\"create_user\":\"root\"},{\"id\":194,\"tpl_name\":\"TplK\",\"parent_id\":0,\"action_id\":153,\"create_user\":\"root\"},{\"id\":208,\"tpl_name\":\"TplM\",\"parent_id\":0,\"action_id\":163,\"create_user\":\"userO\"}]}", "ResponseCode": 200 } ] }, { "HttpVerb": "PUT", "Path": "/api/v1/hostgroup/template", "Calls": [ { "Id": 1, "CurrentPath": "/api/v1/hostgroup/template", "MethodType": "PUT", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"tpl_id\":5,\"grp_id\":3}", "ResponseBody": "{\"message\":\"template: 5 is unbind of HostGroup: 3\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "POST", "Path": "/api/v1/hostgroup/template", "Calls": [ { "Id": 2, "CurrentPath": "/api/v1/hostgroup/template", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"tpl_id\":5,\"grp_id\":3}", "ResponseBody": "{\"grp_id\":3,\"tpl_id\":5,\"bind_user\":2}", "ResponseCode": 200 } ] } ] } ================================================ FILE: docs/doc/nodata.html ================================================ API Documentation

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

URL Params

Key Value
limit 2
page 1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"id":2,"name":"owl_nodate","obj":"docker-agent","obj_type":"host","metric":"test.metric","tags":"","dstype":"GAUGE","step":60,"mock":-2,"creator":"root"}]

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"id":2,"name":"owl_nodate","obj":"docker-agent","obj_type":"host","metric":"test.metric","tags":"","dstype":"GAUGE","step":60,"mock":-2,"creator":"root"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
Content-Type application/json
X-Forwarded-For 127.0.0.1

Request Body

{"tags":"","step":60,"obj_type":"test","obj":"docker-agent","name":"testnodata","mock":-1,"metric":"test.metric","dstype":"GAUGE"}

Response Code

400

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"error":"obj_type only accpect \"group, host, other\""}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
Content-Type application/json
X-Forwarded-For 127.0.0.1

Request Body

{"tags":"","step":60,"obj_type":"host","obj":"docker-agent","name":"testnodata","mock":-1,"metric":"test.metric","dstype":"GAUGE"}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"id":4,"name":"testnodata","obj":"docker-agent","obj_type":"host","metric":"test.metric","tags":"","dstype":"GAUGE","step":60,"mock":-1,"creator":"root"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
Content-Type application/json
X-Forwarded-For 127.0.0.1

Request Body

{"tags":"","step":60,"obj_type":"host","obj":"docker-agent","mock":-2,"metric":"test.metric","id":4,"dstype":"GAUGE"}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"id":0,"name":"","obj":"docker-agent","obj_type":"host","metric":"test.metric","tags":"","dstype":"GAUGE","step":60,"mock":-2,"creator":""}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"message":"mockcfg:4 is deleted"}


================================================ FILE: docs/doc/nodata.html.json ================================================ { "ApiSpecs": [ { "HttpVerb": "GET", "Path": "/api/v1/nodata", "Calls": [ { "Id": 0, "CurrentPath": "/api/v1/nodata", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": { "limit": "2", "page": "1" }, "RequestBody": "", "ResponseBody": "[{\"id\":2,\"name\":\"owl_nodate\",\"obj\":\"docker-agent\",\"obj_type\":\"host\",\"metric\":\"test.metric\",\"tags\":\"\",\"dstype\":\"GAUGE\",\"step\":60,\"mock\":-2,\"creator\":\"root\"}]", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/nodata/2", "Calls": [ { "Id": 1, "CurrentPath": "/api/v1/nodata/2", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"id\":2,\"name\":\"owl_nodate\",\"obj\":\"docker-agent\",\"obj_type\":\"host\",\"metric\":\"test.metric\",\"tags\":\"\",\"dstype\":\"GAUGE\",\"step\":60,\"mock\":-2,\"creator\":\"root\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "POST", "Path": "/api/v1/nodata/", "Calls": [ { "Id": 2, "CurrentPath": "/api/v1/nodata/", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"tags\":\"\",\"step\":60,\"obj_type\":\"test\",\"obj\":\"docker-agent\",\"name\":\"testnodata\",\"mock\":-1,\"metric\":\"test.metric\",\"dstype\":\"GAUGE\"}", "ResponseBody": "{\"error\":\"obj_type only accpect \\\"group, host, other\\\"\"}", "ResponseCode": 400 }, { "Id": 3, "CurrentPath": "/api/v1/nodata/", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"tags\":\"\",\"step\":60,\"obj_type\":\"host\",\"obj\":\"docker-agent\",\"name\":\"testnodata\",\"mock\":-1,\"metric\":\"test.metric\",\"dstype\":\"GAUGE\"}", "ResponseBody": "{\"id\":4,\"name\":\"testnodata\",\"obj\":\"docker-agent\",\"obj_type\":\"host\",\"metric\":\"test.metric\",\"tags\":\"\",\"dstype\":\"GAUGE\",\"step\":60,\"mock\":-1,\"creator\":\"root\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "PUT", "Path": "/api/v1/nodata/", "Calls": [ { "Id": 4, "CurrentPath": "/api/v1/nodata/", "MethodType": "PUT", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"tags\":\"\",\"step\":60,\"obj_type\":\"host\",\"obj\":\"docker-agent\",\"mock\":-2,\"metric\":\"test.metric\",\"id\":4,\"dstype\":\"GAUGE\"}", "ResponseBody": "{\"id\":0,\"name\":\"\",\"obj\":\"docker-agent\",\"obj_type\":\"host\",\"metric\":\"test.metric\",\"tags\":\"\",\"dstype\":\"GAUGE\",\"step\":60,\"mock\":-2,\"creator\":\"\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "DELETE", "Path": "/api/v1/nodata/4", "Calls": [ { "Id": 5, "CurrentPath": "/api/v1/nodata/4", "MethodType": "DELETE", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"message\":\"mockcfg:4 is deleted\"}", "ResponseCode": 200 } ] } ] } ================================================ FILE: docs/doc/plugin.html ================================================ API Documentation

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
Content-Type application/json
X-Forwarded-For 127.0.0.1

Request Body

{"hostgroup_id":343,"dir_path":"testpath"}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"id":1501,"grp_id":343,"dir":"testpath","create_user":"root"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"id":1499,"grp_id":343,"dir":"testpath","create_user":"root"},{"id":1501,"grp_id":343,"dir":"testpath","create_user":"root"}]

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
Content-Type application/json
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"message":"plugin:1501 is deleted"}


================================================ FILE: docs/doc/plugin.html.json ================================================ { "ApiSpecs": [ { "HttpVerb": "POST", "Path": "/api/v1/plugin", "Calls": [ { "Id": 0, "CurrentPath": "/api/v1/plugin", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"hostgroup_id\":343,\"dir_path\":\"testpath\"}", "ResponseBody": "{\"id\":1501,\"grp_id\":343,\"dir\":\"testpath\",\"create_user\":\"root\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/hostgroup/343/plugins", "Calls": [ { "Id": 1, "CurrentPath": "/api/v1/hostgroup/343/plugins", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "[{\"id\":1499,\"grp_id\":343,\"dir\":\"testpath\",\"create_user\":\"root\"},{\"id\":1501,\"grp_id\":343,\"dir\":\"testpath\",\"create_user\":\"root\"}]", "ResponseCode": 200 } ] }, { "HttpVerb": "DELETE", "Path": "/api/v1/plugin/1501", "Calls": [ { "Id": 2, "CurrentPath": "/api/v1/plugin/1501", "MethodType": "DELETE", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"message\":\"plugin:1501 is deleted\"}", "ResponseCode": 200 } ] } ] } ================================================ FILE: docs/doc/team.html ================================================ API Documentation

Request Headers

Key Value
Apitoken {"name": "root", "sig": "dd81ea033c2d11e6a95d0242ac11000c"}
Content-Type application/json
X-Forwarded-For

Request Body

{"resume": "i'm descript"}

Response Code

400

Response Headers

Key Value
Access-Control-Allow-Headers Content-Type,Token,Apitoken
Access-Control-Allow-Origin *
Content-Type application/json; charset=utf-8

Response Body

{"error":"Key: 'APICreateTeamInput.Name' Error:Field validation for 'Name' failed on the 'required' tag"}

Request Headers

Key Value
Apitoken {"name": "root", "sig": "dd81ea033c2d11e6a95d0242ac11000c"}
Content-Type application/json
X-Forwarded-For

Request Body

{"team_name": "ateamname","resume": "i'm descript", "users": [1]}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Headers Content-Type,Token,Apitoken
Access-Control-Allow-Origin *
Content-Type application/json; charset=utf-8

Response Body

{"message":"team created! Afftect row: 1, Affect refer: 1"}

Request Headers

Key Value
Apitoken {"name": "root", "sig": "dd81ea033c2d11e6a95d0242ac11000c"}
X-Forwarded-For

URL Params

Key Value
q .+

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Headers Content-Type,Token,Apitoken
Access-Control-Allow-Origin *
Content-Type application/json; charset=utf-8

Response Body

[{"id":1,"name":"a","resume":"","creator":1},{"id":2,"name":"b","resume":"g","creator":1},{"id":4,"name":"testteam","resume":"i'm test","creator":15},{"id":5,"name":"atestteam","resume":"i'm test","creator":16},{"id":107,"name":"ateamname","resume":"i'm descript","creator":1}]

Request Headers

Key Value
Apitoken {"name": "root", "sig": "dd81ea033c2d11e6a95d0242ac11000c"}
X-Forwarded-For

URL Params

Key Value
q ateamname

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Headers Content-Type,Token,Apitoken
Access-Control-Allow-Origin *
Content-Type application/json; charset=utf-8

Response Body

[{"id":107,"name":"ateamname","resume":"i'm descript","creator":1}]

Request Headers

Key Value
Apitoken {"name": "root", "sig": "dd81ea033c2d11e6a95d0242ac11000c"}
Content-Type application/json
X-Forwarded-For

Request Body

{"team_id": 107, "resume": "i'm descript update", "users": [4,5,6,7]}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Headers Content-Type,Token,Apitoken
Access-Control-Allow-Origin *
Content-Type application/json; charset=utf-8

Response Body

{"message":"team updated!"}

Request Headers

Key Value
Apitoken {"name": "root", "sig": "dd81ea033c2d11e6a95d0242ac11000c"}
X-Forwarded-For

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Headers Content-Type,Token,Apitoken
Access-Control-Allow-Origin *
Content-Type application/json; charset=utf-8

Response Body

{"id":107,"name":"ateamname","resume":"i'm descript","creator":1,"users":[{"id":4,"name":"test1","cnname":"翱鶚Test","email":"root123@cepave.com","phone":"99999999999","im":"44955834958","qq":"904394234239","role":0},{"id":5,"name":"don","cnname":"","email":"","phone":"","im":"","qq":"904394234239","role":0},{"id":6,"name":"masato","cnname":"","email":"","phone":"","im":"","qq":"904394234239","role":0},{"id":7,"name":"cepave1","cnname":"","email":"","phone":"","im":"","qq":"904394234239","role":0}]}

Request Headers

Key Value
Apitoken {"name": "root", "sig": "dd81ea033c2d11e6a95d0242ac11000c"}
X-Forwarded-For

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Headers Content-Type,Token,Apitoken
Access-Control-Allow-Origin *
Content-Type application/json; charset=utf-8

Response Body

{"message":"team 107 is deleted. Affect row: 1 / refer delete: 4"}


================================================ FILE: docs/doc/team.html.json ================================================ { "ApiSpecs": [ { "HttpVerb": "POST", "Path": "/api/v1/team", "Calls": [ { "Id": 0, "CurrentPath": "/api/v1/team", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\": \"root\", \"sig\": \"dd81ea033c2d11e6a95d0242ac11000c\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " " }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Headers": "Content-Type,Token,Apitoken", "Access-Control-Allow-Origin": "*", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"resume\": \"i'm descript\"}", "ResponseBody": "{\"error\":\"Key: 'APICreateTeamInput.Name' Error:Field validation for 'Name' failed on the 'required' tag\"}", "ResponseCode": 400 }, { "Id": 1, "CurrentPath": "/api/v1/team", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\": \"root\", \"sig\": \"dd81ea033c2d11e6a95d0242ac11000c\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " " }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Headers": "Content-Type,Token,Apitoken", "Access-Control-Allow-Origin": "*", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"team_name\": \"ateamname\",\"resume\": \"i'm descript\", \"users\": [1]}", "ResponseBody": "{\"message\":\"team created! Afftect row: 1, Affect refer: 1\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/team", "Calls": [ { "Id": 0, "CurrentPath": "/api/v1/team", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\": \"root\", \"sig\": \"dd81ea033c2d11e6a95d0242ac11000c\"}", "X-Forwarded-For": " " }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Headers": "Content-Type,Token,Apitoken", "Access-Control-Allow-Origin": "*", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": { "q": ".+" }, "RequestBody": "", "ResponseBody": "[{\"id\":1,\"name\":\"a\",\"resume\":\"\",\"creator\":1},{\"id\":2,\"name\":\"b\",\"resume\":\"g\",\"creator\":1},{\"id\":4,\"name\":\"testteam\",\"resume\":\"i'm test\",\"creator\":15},{\"id\":5,\"name\":\"atestteam\",\"resume\":\"i'm test\",\"creator\":16},{\"id\":107,\"name\":\"ateamname\",\"resume\":\"i'm descript\",\"creator\":1}]", "ResponseCode": 200 }, { "Id": 1, "CurrentPath": "/api/v1/team", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\": \"root\", \"sig\": \"dd81ea033c2d11e6a95d0242ac11000c\"}", "X-Forwarded-For": " " }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Headers": "Content-Type,Token,Apitoken", "Access-Control-Allow-Origin": "*", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": { "q": "ateamname" }, "RequestBody": "", "ResponseBody": "[{\"id\":107,\"name\":\"ateamname\",\"resume\":\"i'm descript\",\"creator\":1}]", "ResponseCode": 200 } ] }, { "HttpVerb": "PUT", "Path": "/api/v1/team", "Calls": [ { "Id": 2, "CurrentPath": "/api/v1/team", "MethodType": "PUT", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\": \"root\", \"sig\": \"dd81ea033c2d11e6a95d0242ac11000c\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " " }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Headers": "Content-Type,Token,Apitoken", "Access-Control-Allow-Origin": "*", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"team_id\": 107, \"resume\": \"i'm descript update\", \"users\": [4,5,6,7]}", "ResponseBody": "{\"message\":\"team updated!\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/team/107", "Calls": [ { "Id": 4, "CurrentPath": "/api/v1/team/107", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\": \"root\", \"sig\": \"dd81ea033c2d11e6a95d0242ac11000c\"}", "X-Forwarded-For": " " }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Headers": "Content-Type,Token,Apitoken", "Access-Control-Allow-Origin": "*", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"id\":107,\"name\":\"ateamname\",\"resume\":\"i'm descript\",\"creator\":1,\"users\":[{\"id\":4,\"name\":\"test1\",\"cnname\":\"翱鶚Test\",\"email\":\"root123@cepave.com\",\"phone\":\"99999999999\",\"im\":\"44955834958\",\"qq\":\"904394234239\",\"role\":0},{\"id\":5,\"name\":\"don\",\"cnname\":\"\",\"email\":\"\",\"phone\":\"\",\"im\":\"\",\"qq\":\"904394234239\",\"role\":0},{\"id\":6,\"name\":\"masato\",\"cnname\":\"\",\"email\":\"\",\"phone\":\"\",\"im\":\"\",\"qq\":\"904394234239\",\"role\":0},{\"id\":7,\"name\":\"cepave1\",\"cnname\":\"\",\"email\":\"\",\"phone\":\"\",\"im\":\"\",\"qq\":\"904394234239\",\"role\":0}]}", "ResponseCode": 200 } ] }, { "HttpVerb": "DELETE", "Path": "/api/v1/team/107", "Calls": [ { "Id": 6, "CurrentPath": "/api/v1/team/107", "MethodType": "DELETE", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\": \"root\", \"sig\": \"dd81ea033c2d11e6a95d0242ac11000c\"}", "X-Forwarded-For": " " }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Headers": "Content-Type,Token,Apitoken", "Access-Control-Allow-Origin": "*", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"message\":\"team 107 is deleted. Affect row: 1 / refer delete: 4\"}", "ResponseCode": 200 } ] } ] } ================================================ FILE: docs/doc/template.html ================================================ API Documentation

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"action":{"id":141,"uic":"admin,mm1","url":"","callback":0,"before_callback_sms":0,"before_callback_mail":0,"after_callback_sms":0,"after_callback_mail":0},"stratges":[{"id":686,"metric":"xxx.check","tags":"name=xxx","max_step":3,"priority":2,"func":"all(#2)","op":"<","right_value":"1","note":"xxx服务异常","run_begin":"","run_end":"","tpl_id":178},{"id":687,"metric":"xxx.sync","tags":"","max_step":3,"priority":2,"func":"all(#3)","op":"!=","right_value":"0","note":"XXX同步异常","run_begin":"","run_end":"","tpl_id":178},{"id":688,"metric":"bbb.check.mq","tags":"","max_step":3,"priority":2,"func":"all(#3)","op":"==","right_value":"1","note":"bbb连接MQ异常","run_begin":"","run_end":"","tpl_id":178},{"id":793,"metric":"aaa.proc.num","tags":"","max_step":3,"priority":2,"func":"all(#3)","op":"==","right_value":"1","note":"aaaa 进程大于5","run_begin":"","run_end":"","tpl_id":178}],"template":{"id":178,"tpl_name":"TemplateA","parent_id":0,"action_id":141,"create_user":"root"}}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"message":"session is vaild!"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"id":1,"tpl_name":"cpu.board","parent_id":0,"action_id":5,"create_user":"usera"},{"id":2,"tpl_name":"traffic checking","parent_id":0,"action_id":6,"create_user":"userb"},{"id":3,"tpl_name":"cputest","parent_id":0,"action_id":7,"create_user":"userc"},{"id":5,"tpl_name":"all metrics base","parent_id":0,"action_id":12,"create_user":"root"}]

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
Content-Type application/json
X-Forwarded-For 127.0.0.1

Request Body

{"parent_id":0,"name":"AtmpForTesting"}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"message":"template created"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
Content-Type application/json
X-Forwarded-For 127.0.0.1

Request Body

{"url":"","uic":"test,tt2","tpl_id":225,"callback":1,"before_callback_sms":0,"before_callback_mail":0,"after_callback_sms":0,"after_callback_mail":0}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"message":"action is created and bind to template: 225"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
Content-Type application/json
X-Forwarded-For 127.0.0.1

Request Body

{"tpl_id":225,"parent_id":0,"name":"AtmpForTesting2"}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"message":"template updated"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
Content-Type application/json
X-Forwarded-For 127.0.0.1

Request Body

{"url":"","uic":"test,tt2,tt3","id":175,"callback":1,"before_callback_sms":0,"before_callback_mail":0,"after_callback_sms":0,"after_callback_mail":0}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"message":"action is updated, row affected: 1"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"message":"template 225 has been deleted"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

URL Params

Key Value
tid 221

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"id":893,"metric":"proc.num","tags":"name=redis-server","max_step":3,"priority":2,"func":"all(#2)","op":"\u003c","right_value":"1","note":"FWRedis服务异常","run_begin":"","run_end":"","tpl_id":221},{"id":894,"metric":"proc.num","tags":"name=beam.smp","max_step":3,"priority":2,"func":"all(#3)","op":"\u003c","right_value":"1","note":"FWCM进程状态异常","run_begin":"","run_end":"","tpl_id":221},{"id":895,"metric":"proc.num","tags":"cmdline=fwlog","max_step":3,"priority":3,"func":"all(#5)","op":"\u003c","right_value":"2","note":"fwlog服务异常","run_begin":"","run_end":"","tpl_id":221},{"id":896,"metric":"fcd.oldworker.count","tags":"","max_step":3,"priority":3,"func":"all(#1)","op":"\u003e","right_value":"10","note":"FastCache Old Worker 数量大于10","run_begin":"","run_end":"","tpl_id":221},{"id":897,"metric":"service.logs.jifei","tags":"","max_step":1,"priority":4,"func":"all(#3)","op":"\u003e","right_value":"10","note":"fastcache计费日志堆积","run_begin":"","run_end":"","tpl_id":221},{"id":898,"metric":"proc.num","tags":"cmdline=syslog","max_step":3,"priority":4,"func":"all(#1)","op":"\u003c","right_value":"1","note":"syslog/rsyslog服务异常","run_begin":"","run_end":"","tpl_id":221},{"id":899,"metric":"proc.num","tags":"name=fwsa2d","max_step":3,"priority":2,"func":"all(#2)","op":"\u003c","right_value":"1","note":"FWSA2服务异常","run_begin":"","run_end":"","tpl_id":221},{"id":900,"metric":"redis.log.null","tags":"","max_step":3,"priority":2,"func":"all(#3)","op":"!=","right_value":"0","note":"FWRedis同步异常","run_begin":"","run_end":"","tpl_id":221},{"id":901,"metric":"check.fwsa2","tags":"","max_step":3,"priority":2,"func":"all(#3)","op":"==","right_value":"1","note":"Fwsa2连接MQ异常","run_begin":"","run_end":"","tpl_id":221}]

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
Content-Type application/json
X-Forwarded-For 127.0.0.1

Request Body

{"tpl_id":221,"tags":"","run_end":"24:00","run_begin":"00:00","right_value":"1","priority":1,"op":"==","note":"this is a test","metric":"agent.alive","max_step":3,"func":"all(#3)"}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"message":"stragtegy created"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"id":904,"metric":"agent.alive","tags":"","max_step":3,"priority":1,"func":"all(#3)","op":"==","right_value":"1","note":"this is a test","run_begin":"00:00","run_end":"24:00","tpl_id":221}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
Content-Type application/json
X-Forwarded-For 127.0.0.1

Request Body

{"tags":"","run_end":"","run_begin":"","right_value":"1","priority":2,"op":"==","note":"this is a test","metric":"agent.alive","max_step":3,"id":904,"func":"all(#3)"}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"message":"stragtegy:904 has been updated"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"message":"strategy:904 has been deleted"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

["cpu.busy","cpu.cnt","cpu.guest","cpu.idle","cpu.iowait","cpu.irq","cpu.nice","cpu.softirq","cpu.steal","cpu.system","cpu.user","df.bytes.free","df.bytes.free.percent","df.bytes.total","df.bytes.used","df.bytes.used.percent","df.inodes.free","df.inodes.free.percent","df.inodes.total","df.inodes.used","df.inodes.used.percent","disk.io.avgqu-sz","disk.io.avgrq_sz","disk.io.await","disk.io.ios_in_progress","disk.io.msec_read","disk.io.msec_total","disk.io.msec_weighted_total","disk.io.msec_write","disk.io.read_bytes","disk.io.read_merged","disk.io.read_requests","disk.io.read_sectors","disk.io.svctm","disk.io.util","disk.io.write_bytes","disk.io.write_merged","disk.io.write_requests","disk.io.write_sectors","kernel.maxfiles","kernel.maxproc","load.15min","load.1min","load.5min","mem.memfree","mem.memfree.percent","mem.memtotal","mem.memused","mem.memused.percent","mem.swapfree","mem.swapfree.percent","mem.swaptotal","mem.swapused","mem.swapused.percent","net.if.in.bytes","net.if.in.compressed","net.if.in.dropped","net.if.in.errors","net.if.in.fifo.errs","net.if.in.frame.errs","net.if.in.multicast","net.if.in.packets","net.if.out.bytes","net.if.out.carrier.errs","net.if.out.collisions","net.if.out.compressed","net.if.out.dropped","net.if.out.errors","net.if.out.fifo.errs","net.if.out.packets","net.if.total.bytes","net.if.total.dropped","net.if.total.errors","net.if.total.packets","net.port.listen","proc.num",""]

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

URL Params

Key Value
q a

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

[{"id":63,"tpl_name":"tplAa","parent_id":0,"action_id":0,"create_user":""},{"id":53,"tpl_name":"TplBa","parent_id":0,"action_id":0,"create_user":""},{"id":220,"tpl_name":"TplCa","parent_id":0,"action_id":0,"create_user":""},{"id":42,"tpl_name":"basic","parent_id":0,"action_id":0,"create_user":""},{"id":149,"tpl_name":"TplDa","parent_id":0,"action_id":0,"create_user":""}]


================================================ FILE: docs/doc/template.html.json ================================================ { "ApiSpecs": [ { "HttpVerb": "GET", "Path": "/api/v1/template/178", "Calls": [ { "Id": 0, "CurrentPath": "/api/v1/template/178", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{}", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/user/auth_session", "Calls": [ { "Id": 1, "CurrentPath": "/api/v1/user/auth_session", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"message\":\"session is vaild!\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/template", "Calls": [ { "Id": 2, "CurrentPath": "/api/v1/template", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "[{\"id\":1,\"tpl_name\":\"cpu.board\",\"parent_id\":0,\"action_id\":5,\"create_user\":\"usera\"},{\"id\":2,\"tpl_name\":\"traffic checking\",\"parent_id\":0,\"action_id\":6,\"create_user\":\"userb\"},{\"id\":3,\"tpl_name\":\"cputest\",\"parent_id\":0,\"action_id\":7,\"create_user\":\"userc\"},{\"id\":5,\"tpl_name\":\"all metrics base\",\"parent_id\":0,\"action_id\":12,\"create_user\":\"root\"}]", "ResponseCode": 200 } ] }, { "HttpVerb": "POST", "Path": "/api/v1/template", "Calls": [ { "Id": 3, "CurrentPath": "/api/v1/template", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": "{\"action\":{\"id\":141,\"uic\":\"admin,mm1\",\"url\":\"\",\"callback\":0,\"before_callback_sms\":0,\"before_callback_mail\":0,\"after_callback_sms\":0,\"after_callback_mail\":0},\"stratges\":[{\"id\":686,\"metric\":\"xxx.check\",\"tags\":\"name=xxx\",\"max_step\":3,\"priority\":2,\"func\":\"all(#2)\",\"op\":\"<\",\"right_value\":\"1\",\"note\":\"xxx服务异常\",\"run_begin\":\"\",\"run_end\":\"\",\"tpl_id\":178},{\"id\":687,\"metric\":\"xxx.sync\",\"tags\":\"\",\"max_step\":3,\"priority\":2,\"func\":\"all(#3)\",\"op\":\"!=\",\"right_value\":\"0\",\"note\":\"XXX同步异常\",\"run_begin\":\"\",\"run_end\":\"\",\"tpl_id\":178},{\"id\":688,\"metric\":\"bbb.check.mq\",\"tags\":\"\",\"max_step\":3,\"priority\":2,\"func\":\"all(#3)\",\"op\":\"==\",\"right_value\":\"1\",\"note\":\"bbb连接MQ异常\",\"run_begin\":\"\",\"run_end\":\"\",\"tpl_id\":178},{\"id\":793,\"metric\":\"aaa.proc.num\",\"tags\":\"\",\"max_step\":3,\"priority\":2,\"func\":\"all(#3)\",\"op\":\"==\",\"right_value\":\"1\",\"note\":\"aaaa 进程大于5\",\"run_begin\":\"\",\"run_end\":\"\",\"tpl_id\":178}],\"template\":{\"id\":178,\"tpl_name\":\"TemplateA\",\"parent_id\":0,\"action_id\":141,\"create_user\":\"root\"}}", "RequestBody": "{\"parent_id\":0,\"name\":\"AtmpForTesting\"}", "ResponseBody": "{\"message\":\"template created\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "POST", "Path": "/api/v1/template/action", "Calls": [ { "Id": 4, "CurrentPath": "/api/v1/template/action", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"url\":\"\",\"uic\":\"test,tt2\",\"tpl_id\":225,\"callback\":1,\"before_callback_sms\":0,\"before_callback_mail\":0,\"after_callback_sms\":0,\"after_callback_mail\":0}", "ResponseBody": "{\"message\":\"action is created and bind to template: 225\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "PUT", "Path": "/api/v1/template", "Calls": [ { "Id": 5, "CurrentPath": "/api/v1/template", "MethodType": "PUT", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"tpl_id\":225,\"parent_id\":0,\"name\":\"AtmpForTesting2\"}", "ResponseBody": "{\"message\":\"template updated\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "PUT", "Path": "/api/v1/template/action", "Calls": [ { "Id": 6, "CurrentPath": "/api/v1/template/action", "MethodType": "PUT", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"url\":\"\",\"uic\":\"test,tt2,tt3\",\"id\":175,\"callback\":1,\"before_callback_sms\":0,\"before_callback_mail\":0,\"after_callback_sms\":0,\"after_callback_mail\":0}", "ResponseBody": "{\"message\":\"action is updated, row affected: 1\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "DELETE", "Path": "/api/v1/template/225", "Calls": [ { "Id": 7, "CurrentPath": "/api/v1/template/225", "MethodType": "DELETE", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"message\":\"template 225 has been deleted\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/strategy", "Calls": [ { "Id": 8, "CurrentPath": "/api/v1/strategy", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": { "tid": "221" }, "RequestBody": "", "ResponseBody": "[{\"id\":893,\"metric\":\"proc.num\",\"tags\":\"name=redis-server\",\"max_step\":3,\"priority\":2,\"func\":\"all(#2)\",\"op\":\"\\u003c\",\"right_value\":\"1\",\"note\":\"FWRedis服务异常\",\"run_begin\":\"\",\"run_end\":\"\",\"tpl_id\":221},{\"id\":894,\"metric\":\"proc.num\",\"tags\":\"name=beam.smp\",\"max_step\":3,\"priority\":2,\"func\":\"all(#3)\",\"op\":\"\\u003c\",\"right_value\":\"1\",\"note\":\"FWCM进程状态异常\",\"run_begin\":\"\",\"run_end\":\"\",\"tpl_id\":221},{\"id\":895,\"metric\":\"proc.num\",\"tags\":\"cmdline=fwlog\",\"max_step\":3,\"priority\":3,\"func\":\"all(#5)\",\"op\":\"\\u003c\",\"right_value\":\"2\",\"note\":\"fwlog服务异常\",\"run_begin\":\"\",\"run_end\":\"\",\"tpl_id\":221},{\"id\":896,\"metric\":\"fcd.oldworker.count\",\"tags\":\"\",\"max_step\":3,\"priority\":3,\"func\":\"all(#1)\",\"op\":\"\\u003e\",\"right_value\":\"10\",\"note\":\"FastCache Old Worker 数量大于10\",\"run_begin\":\"\",\"run_end\":\"\",\"tpl_id\":221},{\"id\":897,\"metric\":\"service.logs.jifei\",\"tags\":\"\",\"max_step\":1,\"priority\":4,\"func\":\"all(#3)\",\"op\":\"\\u003e\",\"right_value\":\"10\",\"note\":\"fastcache计费日志堆积\",\"run_begin\":\"\",\"run_end\":\"\",\"tpl_id\":221},{\"id\":898,\"metric\":\"proc.num\",\"tags\":\"cmdline=syslog\",\"max_step\":3,\"priority\":4,\"func\":\"all(#1)\",\"op\":\"\\u003c\",\"right_value\":\"1\",\"note\":\"syslog/rsyslog服务异常\",\"run_begin\":\"\",\"run_end\":\"\",\"tpl_id\":221},{\"id\":899,\"metric\":\"proc.num\",\"tags\":\"name=fwsa2d\",\"max_step\":3,\"priority\":2,\"func\":\"all(#2)\",\"op\":\"\\u003c\",\"right_value\":\"1\",\"note\":\"FWSA2服务异常\",\"run_begin\":\"\",\"run_end\":\"\",\"tpl_id\":221},{\"id\":900,\"metric\":\"redis.log.null\",\"tags\":\"\",\"max_step\":3,\"priority\":2,\"func\":\"all(#3)\",\"op\":\"!=\",\"right_value\":\"0\",\"note\":\"FWRedis同步异常\",\"run_begin\":\"\",\"run_end\":\"\",\"tpl_id\":221},{\"id\":901,\"metric\":\"check.fwsa2\",\"tags\":\"\",\"max_step\":3,\"priority\":2,\"func\":\"all(#3)\",\"op\":\"==\",\"right_value\":\"1\",\"note\":\"Fwsa2连接MQ异常\",\"run_begin\":\"\",\"run_end\":\"\",\"tpl_id\":221}]", "ResponseCode": 200 } ] }, { "HttpVerb": "POST", "Path": "/api/v1/strategy", "Calls": [ { "Id": 9, "CurrentPath": "/api/v1/strategy", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"tpl_id\":221,\"tags\":\"\",\"run_end\":\"24:00\",\"run_begin\":\"00:00\",\"right_value\":\"1\",\"priority\":1,\"op\":\"==\",\"note\":\"this is a test\",\"metric\":\"agent.alive\",\"max_step\":3,\"func\":\"all(#3)\"}", "ResponseBody": "{\"message\":\"stragtegy created\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/strategy/904", "Calls": [ { "Id": 10, "CurrentPath": "/api/v1/strategy/904", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"id\":904,\"metric\":\"agent.alive\",\"tags\":\"\",\"max_step\":3,\"priority\":1,\"func\":\"all(#3)\",\"op\":\"==\",\"right_value\":\"1\",\"note\":\"this is a test\",\"run_begin\":\"00:00\",\"run_end\":\"24:00\",\"tpl_id\":221}", "ResponseCode": 200 } ] }, { "HttpVerb": "PUT", "Path": "/api/v1/strategy", "Calls": [ { "Id": 11, "CurrentPath": "/api/v1/strategy", "MethodType": "PUT", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "Content-Type": " application/json\r", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"tags\":\"\",\"run_end\":\"\",\"run_begin\":\"\",\"right_value\":\"1\",\"priority\":2,\"op\":\"==\",\"note\":\"this is a test\",\"metric\":\"agent.alive\",\"max_step\":3,\"id\":904,\"func\":\"all(#3)\"}", "ResponseBody": "{\"message\":\"stragtegy:904 has been updated\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "DELETE", "Path": "/api/v1/strategy/904", "Calls": [ { "Id": 12, "CurrentPath": "/api/v1/strategy/904", "MethodType": "DELETE", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"message\":\"strategy:904 has been deleted\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/metric/default_list", "Calls": [ { "Id": 13, "CurrentPath": "/api/v1/metric/default_list", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "[\"cpu.busy\",\"cpu.cnt\",\"cpu.guest\",\"cpu.idle\",\"cpu.iowait\",\"cpu.irq\",\"cpu.nice\",\"cpu.softirq\",\"cpu.steal\",\"cpu.system\",\"cpu.user\",\"df.bytes.free\",\"df.bytes.free.percent\",\"df.bytes.total\",\"df.bytes.used\",\"df.bytes.used.percent\",\"df.inodes.free\",\"df.inodes.free.percent\",\"df.inodes.total\",\"df.inodes.used\",\"df.inodes.used.percent\",\"disk.io.avgqu-sz\",\"disk.io.avgrq_sz\",\"disk.io.await\",\"disk.io.ios_in_progress\",\"disk.io.msec_read\",\"disk.io.msec_total\",\"disk.io.msec_weighted_total\",\"disk.io.msec_write\",\"disk.io.read_bytes\",\"disk.io.read_merged\",\"disk.io.read_requests\",\"disk.io.read_sectors\",\"disk.io.svctm\",\"disk.io.util\",\"disk.io.write_bytes\",\"disk.io.write_merged\",\"disk.io.write_requests\",\"disk.io.write_sectors\",\"kernel.maxfiles\",\"kernel.maxproc\",\"load.15min\",\"load.1min\",\"load.5min\",\"mem.memfree\",\"mem.memfree.percent\",\"mem.memtotal\",\"mem.memused\",\"mem.memused.percent\",\"mem.swapfree\",\"mem.swapfree.percent\",\"mem.swaptotal\",\"mem.swapused\",\"mem.swapused.percent\",\"net.if.in.bytes\",\"net.if.in.compressed\",\"net.if.in.dropped\",\"net.if.in.errors\",\"net.if.in.fifo.errs\",\"net.if.in.frame.errs\",\"net.if.in.multicast\",\"net.if.in.packets\",\"net.if.out.bytes\",\"net.if.out.carrier.errs\",\"net.if.out.collisions\",\"net.if.out.compressed\",\"net.if.out.dropped\",\"net.if.out.errors\",\"net.if.out.fifo.errs\",\"net.if.out.packets\",\"net.if.total.bytes\",\"net.if.total.dropped\",\"net.if.total.errors\",\"net.if.total.packets\",\"net.port.listen\",\"proc.num\",\"\"]", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/template_simple", "Calls": [ { "Id": 0, "CurrentPath": "/api/v1/template_simple", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": { "q": "a" }, "RequestBody": "", "ResponseBody": "[{\"id\":63,\"tpl_name\":\"AllCacheServer\",\"parent_id\":0,\"action_id\":0,\"create_user\":\"\"},{\"id\":53,\"tpl_name\":\"arch2_monitor\",\"parent_id\":0,\"action_id\":0,\"create_user\":\"\"},{\"id\":220,\"tpl_name\":\"Bandwidth_trends\",\"parent_id\":0,\"action_id\":0,\"create_user\":\"\"},{\"id\":42,\"tpl_name\":\"basic\",\"parent_id\":0,\"action_id\":0,\"create_user\":\"\"},{\"id\":149,\"tpl_name\":\"bossapi\",\"parent_id\":0,\"action_id\":0,\"create_user\":\"\"}]", "ResponseCode": 200 } ] } ] } ================================================ FILE: docs/doc/user.html ================================================ API Documentation

Request Headers

Key Value
Content-Type application/json
X-Forwarded-For

Request Body

{"name": "test","password": "test"}

Response Code

400

Response Headers

Key Value
Access-Control-Allow-Headers Content-Type,Token
Access-Control-Allow-Origin *
Content-Type application/json; charset=utf-8

Response Body

{"error":"Key: 'APIUserInput.Cnname' Error:Field validation for 'Cnname' failed on the 'required' tag\nKey: 'APIUserInput.Email' Error:Field validation for 'Email' failed on the 'required' tag"}

Request Headers

Key Value
Content-Type application/json
X-Forwarded-For

Request Body

{"name": "owltester","password": "mypassword", "cnname": "翱鶚", "email": "root123@cepave.com", "im": "44955834958", "phone": "99999999999", "qq": "904394234239"}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Headers Content-Type,Token
Access-Control-Allow-Origin *
Content-Type application/json; charset=utf-8

Response Body

{"name":"owltester","sig":"9b42a728c0ea11e690c5001500c6ca5a"}

Request Headers

Key Value
Content-Type application/json
Cookie name=test1; sig=d4f71cba377911e699d60242ac110010
X-Forwarded-For

Request Body

{"name": "test1","password": "test1", "cnname": "翱鶚Test", "email": "root123@cepave.com", "im": "44955834958", "phone": "99999999999", "qq": "904394234239"}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Headers Content-Type,Token
Access-Control-Allow-Origin *
Content-Type application/json; charset=utf-8

Response Body

{"message":"user info updated"}

Request Headers

Key Value
Content-Type application/json
Cookie name=test1; sig=d4f71cba377911e699d60242ac110010
X-Forwarded-For

Request Body

{"new_password": "test1", "old_password": "test1"}

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Headers Content-Type,Token
Access-Control-Allow-Origin *
Content-Type application/json; charset=utf-8

Response Body

{"message":"password updated!"}

Request Headers

Key Value
Cookie name=test1; sig=d4f71cba377911e699d60242ac110010
X-Forwarded-For

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Headers Content-Type,Token
Access-Control-Allow-Origin *
Content-Type application/json; charset=utf-8

Response Body

[{"id":1,"name":"root","cnname":"","email":"","phone":"","im":"","qq":"904394234239","role":2},{"id":2,"name":"yao104","cnname":"","email":"","phone":"","im":"","qq":"904394234239","role":0},{"id":3,"name":"xiecz","cnname":"","email":"","phone":"","im":"","qq":"904394234239","role":0},{"id":4,"name":"test1","cnname":"翱鶚Test","email":"root123@cepave.com","phone":"99999999999","im":"44955834958","qq":"904394234239","role":0},{"id":5,"name":"don","cnname":"","email":"","phone":"","im":"","qq":"904394234239","role":0},{"id":6,"name":"masato","cnname":"","email":"","phone":"","im":"","qq":"904394234239","role":0},{"id":7,"name":"cepave1","cnname":"","email":"","phone":"","im":"","qq":"904394234239","role":0},{"id":9,"name":"test2","cnname":"","email":"","phone":"","im":"","qq":"904394234239","role":0},{"id":10,"name":"kordan","cnname":"","email":"","phone":"","im":"","qq":"904394234239","role":0},{"id":11,"name":"laurence","cnname":"","email":"","phone":"","im":"","qq":"904394234239","role":0},{"id":12,"name":"kelly","cnname":"","email":"","phone":"","im":"","qq":"904394234239","role":0},{"id":13,"name":"masato25","cnname":"","email":"","phone":"","im":"","qq":"904394234239","role":0},{"id":14,"name":"myhung","cnname":"","email":"","phone":"","im":"","qq":"904394234239","role":1},{"id":32,"name":"owltester","cnname":"翱鶚","email":"root123@cepave.com","phone":"99999999999","im":"44955834958","qq":"904394234239","role":0}]

Request Headers

Key Value
X-Forwarded-For

URL Params

Key Value
name gg123
password willnotpass

Response Code

400

Response Headers

Key Value
Access-Control-Allow-Headers Content-Type,Token
Access-Control-Allow-Origin *
Content-Type application/json; charset=utf-8

Response Body

{"error":"password error"}

Request Headers

Key Value
X-Forwarded-For

URL Params

Key Value
name test2
password test2

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Headers Content-Type,Token
Access-Control-Allow-Origin *
Content-Type application/json; charset=utf-8

Response Body

{"sig":"9d791331c0ea11e690c5001500c6ca5a","name":"test2","admin":false}

Request Headers

Key Value
Cookie name=test2; sig=9d791331c0ea11e690c5001500c6ca5a
X-Forwarded-For

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Headers Content-Type,Token
Access-Control-Allow-Origin *
Content-Type application/json; charset=utf-8

Response Body

{"message":"logout successful"}

Request Headers

Key Value
Cookie name=test1; sig=d4f71cba377911e699d60242ac110010
X-Forwarded-For

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Headers Content-Type,Token
Access-Control-Allow-Origin *
Content-Type application/json; charset=utf-8

Response Body

{"message":"session is vaild!"}

Request Headers

Key Value
Cookie name=testtest; sig=9a84ae1d377911e699d60242ac110010
X-Forwarded-For

Response Code

401

Response Headers

Key Value
Access-Control-Allow-Headers Content-Type,Token
Access-Control-Allow-Origin *
Content-Type application/json; charset=utf-8

Response Body

{"error":"not found this user"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"id":2,"name":"root","cnname":"","email":"","phone":"","im":"","qq":"","role":2}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

417

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"error":"record not found"}

Request Headers

Key Value
Apitoken {"name":"root","sig":"427d6803b78311e68afd0242ac130006"}
X-Forwarded-For 127.0.0.1

Response Code

200

Response Headers

Key Value
Access-Control-Allow-Credentials true
Access-Control-Allow-Headers Content-Type, Content-Length, Apitoken
Access-Control-Allow-Methods POST, GET, OPTIONS, PUT, DELETE, UPDATE
Access-Control-Allow-Origin *
Access-Control-Expose-Headers Content-Length
Access-Control-Max-Age 86400
Content-Type application/json; charset=utf-8

Response Body

{"id":4,"name":"userA","cnname":"tear","email":"","phone":"","im":"","qq":"","role":0}


================================================ FILE: docs/doc/user.html.json ================================================ { "ApiSpecs": [ { "HttpVerb": "POST", "Path": "/api/v1/user/create", "Calls": [ { "Id": 0, "CurrentPath": "/api/v1/user/create", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Content-Type": " application/json\r", "X-Forwarded-For": " " }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Headers": "Content-Type,Token", "Access-Control-Allow-Origin": "*", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"name\": \"test\",\"password\": \"test\"}", "ResponseBody": "{\"error\":\"Key: 'APIUserInput.Cnname' Error:Field validation for 'Cnname' failed on the 'required' tag\\nKey: 'APIUserInput.Email' Error:Field validation for 'Email' failed on the 'required' tag\"}", "ResponseCode": 400 }, { "Id": 1, "CurrentPath": "/api/v1/user/create", "MethodType": "POST", "PostForm": null, "RequestHeader": { "Content-Type": " application/json\r", "X-Forwarded-For": " " }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Headers": "Content-Type,Token", "Access-Control-Allow-Origin": "*", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"name\": \"owltester\",\"password\": \"mypassword\", \"cnname\": \"翱鶚\", \"email\": \"root123@cepave.com\", \"im\": \"44955834958\", \"phone\": \"99999999999\", \"qq\": \"904394234239\"}", "ResponseBody": "{\"name\":\"owltester\",\"sig\":\"9b42a728c0ea11e690c5001500c6ca5a\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "PUT", "Path": "/api/v1/user/update", "Calls": [ { "Id": 2, "CurrentPath": "/api/v1/user/update", "MethodType": "PUT", "PostForm": null, "RequestHeader": { "Content-Type": " application/json\r", "Cookie": " name=test1; sig=d4f71cba377911e699d60242ac110010\r", "X-Forwarded-For": " " }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Headers": "Content-Type,Token", "Access-Control-Allow-Origin": "*", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"name\": \"test1\",\"password\": \"test1\", \"cnname\": \"翱鶚Test\", \"email\": \"root123@cepave.com\", \"im\": \"44955834958\", \"phone\": \"99999999999\", \"qq\": \"904394234239\"}", "ResponseBody": "{\"message\":\"user info updated\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "PUT", "Path": "/api/v1/user/cgpasswd", "Calls": [ { "Id": 3, "CurrentPath": "/api/v1/user/cgpasswd", "MethodType": "PUT", "PostForm": null, "RequestHeader": { "Content-Type": " application/json\r", "Cookie": " name=test1; sig=d4f71cba377911e699d60242ac110010\r", "X-Forwarded-For": " " }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Headers": "Content-Type,Token", "Access-Control-Allow-Origin": "*", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "{\"new_password\": \"test1\", \"old_password\": \"test1\"}", "ResponseBody": "{\"message\":\"password updated!\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/user/users", "Calls": [ { "Id": 4, "CurrentPath": "/api/v1/user/users", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Cookie": " name=test1; sig=d4f71cba377911e699d60242ac110010\r", "X-Forwarded-For": " " }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Headers": "Content-Type,Token", "Access-Control-Allow-Origin": "*", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "[{\"id\":1,\"name\":\"root\",\"cnname\":\"\",\"email\":\"\",\"phone\":\"\",\"im\":\"\",\"qq\":\"904394234239\",\"role\":2},{\"id\":2,\"name\":\"yao104\",\"cnname\":\"\",\"email\":\"\",\"phone\":\"\",\"im\":\"\",\"qq\":\"904394234239\",\"role\":0},{\"id\":3,\"name\":\"xiecz\",\"cnname\":\"\",\"email\":\"\",\"phone\":\"\",\"im\":\"\",\"qq\":\"904394234239\",\"role\":0},{\"id\":4,\"name\":\"test1\",\"cnname\":\"翱鶚Test\",\"email\":\"root123@cepave.com\",\"phone\":\"99999999999\",\"im\":\"44955834958\",\"qq\":\"904394234239\",\"role\":0},{\"id\":5,\"name\":\"don\",\"cnname\":\"\",\"email\":\"\",\"phone\":\"\",\"im\":\"\",\"qq\":\"904394234239\",\"role\":0},{\"id\":6,\"name\":\"masato\",\"cnname\":\"\",\"email\":\"\",\"phone\":\"\",\"im\":\"\",\"qq\":\"904394234239\",\"role\":0},{\"id\":7,\"name\":\"cepave1\",\"cnname\":\"\",\"email\":\"\",\"phone\":\"\",\"im\":\"\",\"qq\":\"904394234239\",\"role\":0},{\"id\":9,\"name\":\"test2\",\"cnname\":\"\",\"email\":\"\",\"phone\":\"\",\"im\":\"\",\"qq\":\"904394234239\",\"role\":0},{\"id\":10,\"name\":\"kordan\",\"cnname\":\"\",\"email\":\"\",\"phone\":\"\",\"im\":\"\",\"qq\":\"904394234239\",\"role\":0},{\"id\":11,\"name\":\"laurence\",\"cnname\":\"\",\"email\":\"\",\"phone\":\"\",\"im\":\"\",\"qq\":\"904394234239\",\"role\":0},{\"id\":12,\"name\":\"kelly\",\"cnname\":\"\",\"email\":\"\",\"phone\":\"\",\"im\":\"\",\"qq\":\"904394234239\",\"role\":0},{\"id\":13,\"name\":\"masato25\",\"cnname\":\"\",\"email\":\"\",\"phone\":\"\",\"im\":\"\",\"qq\":\"904394234239\",\"role\":0},{\"id\":14,\"name\":\"myhung\",\"cnname\":\"\",\"email\":\"\",\"phone\":\"\",\"im\":\"\",\"qq\":\"904394234239\",\"role\":1},{\"id\":32,\"name\":\"owltester\",\"cnname\":\"翱鶚\",\"email\":\"root123@cepave.com\",\"phone\":\"99999999999\",\"im\":\"44955834958\",\"qq\":\"904394234239\",\"role\":0}]", "ResponseCode": 200 } ] }, { "HttpVerb": "POST", "Path": "/api/v1/user/login", "Calls": [ { "Id": 5, "CurrentPath": "/api/v1/user/login", "MethodType": "POST", "PostForm": null, "RequestHeader": { "X-Forwarded-For": " " }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Headers": "Content-Type,Token", "Access-Control-Allow-Origin": "*", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": { "name": "gg123", "password": "willnotpass" }, "RequestBody": "", "ResponseBody": "{\"error\":\"password error\"}", "ResponseCode": 400 }, { "Id": 6, "CurrentPath": "/api/v1/user/login", "MethodType": "POST", "PostForm": null, "RequestHeader": { "X-Forwarded-For": " " }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Headers": "Content-Type,Token", "Access-Control-Allow-Origin": "*", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": { "name": "test2", "password": "test2" }, "RequestBody": "", "ResponseBody": "{\"sig\":\"9d791331c0ea11e690c5001500c6ca5a\",\"name\":\"test2\",\"admin\":false}", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/user/logout", "Calls": [ { "Id": 8, "CurrentPath": "/api/v1/user/logout", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Cookie": " name=test2; sig=9d791331c0ea11e690c5001500c6ca5a\r", "X-Forwarded-For": " " }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Headers": "Content-Type,Token", "Access-Control-Allow-Origin": "*", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"message\":\"logout successful\"}", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/user/auth_session", "Calls": [ { "Id": 9, "CurrentPath": "/api/v1/user/auth_session", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Cookie": " name=test1; sig=d4f71cba377911e699d60242ac110010\r", "X-Forwarded-For": " " }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Headers": "Content-Type,Token", "Access-Control-Allow-Origin": "*", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"message\":\"session is vaild!\"}", "ResponseCode": 200 }, { "Id": 10, "CurrentPath": "/api/v1/user/auth_session", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Cookie": " name=testtest; sig=9a84ae1d377911e699d60242ac110010\r", "X-Forwarded-For": " " }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Headers": "Content-Type,Token", "Access-Control-Allow-Origin": "*", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"error\":\"not found this user\"}", "ResponseCode": 401 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/user/current", "Calls": [ { "Id": 0, "CurrentPath": "/api/v1/user/current", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"id\":2,\"name\":\"root\",\"cnname\":\"\",\"email\":\"\",\"phone\":\"\",\"im\":\"\",\"qq\":\"\",\"role\":2}", "ResponseCode": 200 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/user/u/3", "Calls": [ { "Id": 0, "CurrentPath": "/api/v1/user/u/3", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"error\":\"record not found\"}", "ResponseCode": 417 } ] }, { "HttpVerb": "GET", "Path": "/api/v1/user/u/4", "Calls": [ { "Id": 1, "CurrentPath": "/api/v1/user/u/4", "MethodType": "GET", "PostForm": null, "RequestHeader": { "Apitoken": "{\"name\":\"root\",\"sig\":\"427d6803b78311e68afd0242ac130006\"}", "X-Forwarded-For": " 127.0.0.1\r" }, "CommonRequestHeaders": null, "ResponseHeader": { "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Content-Length, Apitoken", "Access-Control-Allow-Methods": "POST, GET, OPTIONS, PUT, DELETE, UPDATE", "Access-Control-Allow-Origin": "*", "Access-Control-Expose-Headers": "Content-Length", "Access-Control-Max-Age": "86400", "Content-Type": "application/json; charset=utf-8" }, "RequestUrlParams": {}, "RequestBody": "", "ResponseBody": "{\"id\":4,\"name\":\"userA\",\"cnname\":\"tear\",\"email\":\"\",\"phone\":\"\",\"im\":\"\",\"qq\":\"\",\"role\":0}", "ResponseCode": 200 } ] } ] } ================================================ FILE: docs/index.html ================================================ --- layout: default ---
{% for post in site.posts %} {% endfor %}
================================================ FILE: docs/robots.txt ================================================ User-agent: * Disallow: /images/ ================================================ FILE: g/g.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package g import "path/filepath" var Modules map[string]bool var BinOf map[string]string var cfgOf map[string]string var ModuleApps map[string]string var logpathOf map[string]string var PidOf map[string]string var AllModulesInOrder []string func init() { Modules = map[string]bool{ "agent": true, "aggregator": true, "graph": true, "hbs": true, "judge": true, "nodata": true, "transfer": true, "gateway": true, "api": true, "alarm": true, "falcon2p8s": true, } BinOf = map[string]string{ "agent": "./agent/bin/falcon-agent", "aggregator": "./aggregator/bin/falcon-aggregator", "graph": "./graph/bin/falcon-graph", "hbs": "./hbs/bin/falcon-hbs", "judge": "./judge/bin/falcon-judge", "nodata": "./nodata/bin/falcon-nodata", "transfer": "./transfer/bin/falcon-transfer", "gateway": "./gateway/bin/falcon-gateway", "api": "./api/bin/falcon-api", "alarm": "./alarm/bin/falcon-alarm", "falcon2p8s": "./falcon2p8s/bin/falcon-falcon2p8s", } cfgOf = map[string]string{ "agent": "./agent/config/cfg.json", "aggregator": "./aggregator/config/cfg.json", "graph": "./graph/config/cfg.json", "hbs": "./hbs/config/cfg.json", "judge": "./judge/config/cfg.json", "nodata": "./nodata/config/cfg.json", "transfer": "./transfer/config/cfg.json", "gateway": "./gateway/config/cfg.json", "api": "./api/config/cfg.json", "alarm": "./alarm/config/cfg.json", "falcon2p8s": "./falcon2p8s/config/cfg.json", } ModuleApps = map[string]string{ "agent": "falcon-agent", "aggregator": "falcon-aggregator", "graph": "falcon-graph", "hbs": "falcon-hbs", "judge": "falcon-judge", "nodata": "falcon-nodata", "transfer": "falcon-transfer", "gateway": "falcon-gateway", "api": "falcon-api", "alarm": "falcon-alarm", "falcon2p8s": "falcon-falcon2p8s", } logpathOf = map[string]string{ "agent": "./agent/logs/agent.log", "aggregator": "./aggregator/logs/aggregator.log", "graph": "./graph/logs/graph.log", "hbs": "./hbs/logs/hbs.log", "judge": "./judge/logs/judge.log", "nodata": "./nodata/logs/nodata.log", "transfer": "./transfer/logs/transfer.log", "gateway": "./gateway/logs/gateway.log", "api": "./api/logs/api.log", "alarm": "./alarm/logs/alarm.log", "falcon2p8s": "./falcon2p8s/logs/falcon2p8s.log", } PidOf = map[string]string{ "agent": "", "aggregator": "", "graph": "", "hbs": "", "judge": "", "nodata": "", "transfer": "", "gateway": "", "api": "", "alarm": "", "falcon2p8s": "", } // Modules are deployed in this order AllModulesInOrder = []string{ "graph", "hbs", "judge", "transfer", "nodata", "aggregator", "agent", "gateway", "api", "alarm", "falcon2p8s", } } func Bin(name string) string { p, _ := filepath.Abs(BinOf[name]) return p } func Cfg(name string) string { p, _ := filepath.Abs(cfgOf[name]) return p } func LogPath(name string) string { p, _ := filepath.Abs(logpathOf[name]) return p } func LogDir(name string) string { d, _ := filepath.Abs(filepath.Dir(logpathOf[name])) return d } ================================================ FILE: g/tool.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package g import ( "os" "os/exec" "path/filepath" "strings" ) func HasLogfile(name string) bool { if _, err := os.Stat(LogPath(name)); err != nil { return false } return true } func PreqOrder(moduleArgs []string) []string { if len(moduleArgs) == 0 { return []string{} } var modulesInOrder []string // get arguments which are found in the order for _, nameOrder := range AllModulesInOrder { for _, nameArg := range moduleArgs { if nameOrder == nameArg { modulesInOrder = append(modulesInOrder, nameOrder) } } } // get arguments which are not found in the order for _, nameArg := range moduleArgs { end := 0 for _, nameOrder := range modulesInOrder { if nameOrder == nameArg { break } end++ } if end == len(modulesInOrder) { modulesInOrder = append(modulesInOrder, nameArg) } } return modulesInOrder } func Rel(p string) string { wd, err := os.Getwd() if err != nil { return "" } // filepath.Abs() returns an error only when os.Getwd() returns an error; abs, _ := filepath.Abs(p) r, err := filepath.Rel(wd, abs) if err != nil { return "" } return r } func HasCfg(name string) bool { if _, err := os.Stat(Cfg(name)); err != nil { return false } return true } func HasModule(name string) bool { return Modules[name] } func setPid(name string) { output, _ := exec.Command("pgrep", "-f", ModuleApps[name]).Output() pidStr := strings.TrimSpace(string(output)) PidOf[name] = pidStr } func Pid(name string) string { if PidOf[name] == "" { setPid(name) } return PidOf[name] } func IsRunning(name string) bool { setPid(name) return Pid(name) != "" } func RmDup(args []string) []string { if len(args) == 0 { return []string{} } if len(args) == 1 { return args } ret := []string{} isDup := make(map[string]bool) for _, arg := range args { if isDup[arg] == true { continue } ret = append(ret, arg) isDup[arg] = true } return ret } ================================================ FILE: g/tool_test.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package g import ( "os" "path/filepath" "reflect" "testing" ) func setup() { os.MkdirAll("falcon-module/config", 755) os.MkdirAll("falcon-module-without-cfg/config", 755) os.Create("falcon-module/config/cfg.json") cfgOf = map[string]string{ "falcon-module": "falcon-module/config/cfg.json", "falcon-module-without-cfg": "falcon-module-without-cfg/config/cfg.json", } Modules = map[string]bool{ "falcon-module": true, "falcon-module-without-cfg": true, } AllModulesInOrder = []string{ "1st-module", "2nd-module", "3rd-module", } } func teardown() { os.RemoveAll("falcon-module") os.RemoveAll("falcon-module-without-cfg") } func TestRel(t *testing.T) { wd, err := os.Getwd() if err != nil { t.Error(err) os.Exit(1) } tests := []struct { input string expected string }{ {"falcon-module/config/cfg.json", "falcon-module/config/cfg.json"}, {"./falcon-module/config/cfg.json", "falcon-module/config/cfg.json"}, {filepath.Join(wd, "falcon-module/config/cfg.json"), "falcon-module/config/cfg.json"}, } for i, v := range tests { actual := Rel(v.input) expected := v.expected t.Logf("Check case %d: %s(actual) == %s(expected)", i, actual, expected) if actual != expected { t.Errorf("Error on case %d: %s(actual) != %s(expected)", i, actual, expected) } } } func TestHasCfg(t *testing.T) { tests := []struct { input string expected bool }{ {"falcon-module", true}, {"falcon-module-without-cfg", false}, } for i, v := range tests { actual := HasCfg(v.input) expected := v.expected t.Logf("Check case %v: %v(actual) == %v(expected)", i, actual, expected) if !reflect.DeepEqual(actual, expected) { t.Errorf("Error on case %v: %v(actual) != %v(expected)", i, actual, expected) } } } func TestPreqOrder(t *testing.T) { tests := []struct { input []string expected []string }{ {[]string{"2nd-module", "1st-module"}, []string{"1st-module", "2nd-module"}}, {[]string{"2nd-module", "1st-module", "3rd-module"}, []string{"1st-module", "2nd-module", "3rd-module"}}, {[]string{"3rd-module", "2nd-module", "1st-module"}, []string{"1st-module", "2nd-module", "3rd-module"}}, {[]string{"3rd-module", "other-module", "1st-module", "2nd-module"}, []string{"1st-module", "2nd-module", "3rd-module", "other-module"}}, {[]string{"other-module", "1st-module", "2nd-module", "3rd-module"}, []string{"1st-module", "2nd-module", "3rd-module", "other-module"}}, } for i, v := range tests { actual := PreqOrder(v.input) expected := v.expected t.Logf("Check case %d: %s(actual) == %s(expected)", i, actual, expected) if !reflect.DeepEqual(actual, expected) { t.Errorf("Error on case %d: %s(actual) != %s(expected)", i, actual, expected) } } } func TestRmDup(t *testing.T) { tests := []struct { input []string expected []string }{ {[]string{"2nd-module", "1st-module"}, []string{"2nd-module", "1st-module"}}, {[]string{"2nd-module", "1st-module", "1st-module"}, []string{"2nd-module", "1st-module"}}, {[]string{"2nd-module", "2nd-module", "1st-module"}, []string{"2nd-module", "1st-module"}}, {[]string{"1st-module", "2nd-module", "1st-module"}, []string{"1st-module", "2nd-module"}}, {[]string{"2nd-module", "1st-module", "2nd-module"}, []string{"2nd-module", "1st-module"}}, {[]string{"2nd-module", "2nd-module", "1st-module", "3rd-module"}, []string{"2nd-module", "1st-module", "3rd-module"}}, {[]string{"2nd-module", "1st-module", "1st-module", "3rd-module"}, []string{"2nd-module", "1st-module", "3rd-module"}}, {[]string{"2nd-module", "1st-module", "3rd-module", "3rd-module"}, []string{"2nd-module", "1st-module", "3rd-module"}}, {[]string{"2nd-module", "1st-module", "2nd-module", "1st-module", "3rd-module"}, []string{"2nd-module", "1st-module", "3rd-module"}}, {[]string{"2nd-module", "1st-module", "2nd-module", "3rd-module"}, []string{"2nd-module", "1st-module", "3rd-module"}}, {[]string{"2nd-module", "1st-module", "3rd-module", "1st-module"}, []string{"2nd-module", "1st-module", "3rd-module"}}, } for i, v := range tests { actual := RmDup(v.input) expected := v.expected t.Logf("Check case %d: %s(actual) == %s(expected)", i, actual, expected) if !reflect.DeepEqual(actual, expected) { t.Errorf("Error on case %d: %s(actual) != %s(expected)", i, actual, expected) } } } func TestMain(m *testing.M) { setup() code := m.Run() teardown() os.Exit(code) } ================================================ FILE: go.mod ================================================ module github.com/open-falcon/falcon-plus go 1.15 require ( github.com/astaxie/beego v1.8.3 github.com/denisenkom/go-mssqldb v0.10.0 // indirect github.com/emirpasic/gods v1.9.0 github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 // indirect github.com/garyburd/redigo v1.6.2 github.com/gin-gonic/gin v1.7.0 github.com/go-resty/resty v0.0.0-00010101000000-000000000000 // indirect github.com/go-sql-driver/mysql v1.6.0 github.com/golang/protobuf v1.5.2 // indirect github.com/influxdata/influxdb v1.9.0 github.com/jinzhu/gorm v0.0.0-20170703134954-2a1463811ee1 github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d // indirect github.com/jinzhu/now v1.1.2 // indirect github.com/json-iterator/go v1.1.11 // indirect github.com/juju/errors v0.0.0-20200330140219-3fe23663418f github.com/juju/testing v0.0.0-20210324180055-18c50b0c2098 // indirect github.com/lib/pq v1.10.2 // indirect github.com/masato25/resty v0.4.2-0.20161209040832-927c0e7d74a0 github.com/masato25/yaag v0.0.0-20170704095552-00862ec4db8e github.com/mattn/go-isatty v0.0.13 // indirect github.com/mattn/go-sqlite3 v1.14.7 // indirect github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989 github.com/niean/go-metrics-lite v0.0.0-20151230091537-b5d30971b578 // indirect github.com/niean/goperfcounter v0.0.0-20160108100052-24860a8d3fac github.com/niean/gotools v0.0.0-20151221085310-ff3f51fc5c60 // indirect github.com/oleiade/lane v1.0.1 github.com/open-falcon/rrdlite v0.0.0-20170412122036-7d8646c85cc5 github.com/prometheus/client_golang v1.5.1 github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b github.com/sirupsen/logrus v1.8.1 github.com/smartystreets/goconvey v1.6.4 github.com/spf13/cobra v1.1.3 github.com/spf13/viper v1.7.0 github.com/stretchr/testify v1.6.1 // indirect github.com/toolkits/cache v0.0.0-20190218093630-cfb07b7585e5 github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3 github.com/toolkits/conn_pool v0.0.0-20170512061817-2b758bec1177 github.com/toolkits/consistent v0.0.0-20150827090850-a6f56a64d1b1 github.com/toolkits/container v0.0.0-20151219225805-ba7d73adeaca github.com/toolkits/core v0.0.0-20141116054942-0ebf14900fe2 github.com/toolkits/cron v0.0.0-20150624115642-bebc2953afa6 github.com/toolkits/file v0.0.0-20160325033739-a5b3c5147e07 github.com/toolkits/http v0.0.0-20150609122824-f3ac6e6c24be github.com/toolkits/net v0.0.0-20160910085801-3f39ab6fe3ce github.com/toolkits/nux v0.0.0-20200401110743-debb3829764a github.com/toolkits/proc v0.0.0-20170520054645-8c734d0eb018 github.com/toolkits/slice v0.0.0-20141116085117-e44a80af2484 github.com/toolkits/str v0.0.0-20160913030958-f82e0f0498cb github.com/toolkits/sys v0.0.0-20170615103026-1f33b217ffaf github.com/toolkits/time v0.0.0-20160524122720-c274716e8d7f github.com/ugorji/go v1.2.6 // indirect golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect golang.org/x/net v0.0.0-20210525063256-abc453219eb5 // indirect golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea // indirect gopkg.in/go-playground/assert.v1 v1.2.1 // indirect gopkg.in/go-playground/validator.v8 v8.18.2 // indirect ) replace github.com/go-resty/resty => gopkg.in/resty.v1 v1.11.0 ================================================ FILE: go.sum ================================================ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm+2xVAli2o= cloud.google.com/go/bigtable v1.3.0/go.mod h1:z5EyKrPE8OQmeg4h5MNdKvuSnI9CCT49Ki3f23aBzio= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/azure-sdk-for-go v41.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0= github.com/Azure/go-autorest/autorest v0.10.0/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= github.com/Azure/go-autorest/autorest v0.10.1/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= github.com/Azure/go-autorest/autorest/adal v0.8.3/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= github.com/Azure/go-autorest/autorest/azure/auth v0.4.2/go.mod h1:90gmfKdlmKgfjUpnCEpOJzsUEjrWDSLwHIG73tSXddM= github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9mNJVoIoLgXcirM2gF5i2kWloofxw= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA= github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DATA-DOG/go-sqlmock v1.4.1/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/sprig v2.16.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/SAP/go-hdb v0.14.1/go.mod h1:7fdQLVC2lER3urZLjZCm0AuMQfApof92n3aylBPEkMo= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ= github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0= github.com/apache/arrow/go/arrow v0.0.0-20200923215132-ac86123a3f01/go.mod h1:QNYViu/X0HXDHw7m3KXzWSVXIbfUvJqBFe6Gj8/pYA0= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.3.3/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= github.com/astaxie/beego v1.8.3 h1:6SwgDPBxYSs+E2cwIL7BzQn4nWgY8xwYE8wO6YpNa9k= github.com/astaxie/beego v1.8.3/go.mod h1:0R4++1tUqERR0WYFWdfkcrsyoVBCG4DgpDGokT3yb+U= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.29.16/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg= github.com/aws/aws-sdk-go v1.30.12/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/benbjohnson/immutable v0.2.1/go.mod h1:uc6OHo6PN2++n98KHLxW8ef4W42ylHiQSENghE1ezxI= github.com/benbjohnson/tmpl v1.0.0/go.mod h1:igT620JFIi44B6awvU9IsDhR77IXWtFigTLil/RPdps= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/bonitoo-io/go-sql-bigquery v0.3.4-1.4.0/go.mod h1:J4Y6YJm0qTWB9aFziB7cPeSyc6dOZFyJdteSeybVpXQ= github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= github.com/cactus/go-statsd-client/statsd v0.0.0-20191106001114-12b4e2b38748/go.mod h1:l/bIBLeOl9eX+wxJAzxS4TveKRtAqlyDpHjhkfO0MEI= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v0.0.0-20181003080854-62661b46c409/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/denisenkom/go-mssqldb v0.10.0 h1:QykgLZBorFE95+gO3u9esLd0BmbvpWp0/waNNZfHBM8= github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4= github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dgryski/go-sip13 v0.0.0-20190329191031-25c5027a8c7b/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emirpasic/gods v1.9.0 h1:rUF4PuzEjMChMiNsVjdI+SyLu7rEqpQ5reNFnhC7oFo= github.com/emirpasic/gods v1.9.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/foxcpp/go-mockdns v0.0.0-20201212160233-ede2f9158d15/go.mod h1:tPg4cp4nseejPd+UKxtCVQ2hUxNTZ7qQZJa7CLriIeo= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/garyburd/redigo v1.6.2 h1:yE/pwKCrbLpLpQICzYTeZ7JsTA/C53wFTJHaEtRqniM= github.com/garyburd/redigo v1.6.2/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3 h1:t8FVkw33L+wilf2QiWkw0UV77qRpcH/JHPKGpKa2E8g= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.4.0 h1:3tMoCCfM7ppqsR0ptz/wi1impNpT7/9wQtMZ8lr1mCQ= github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= github.com/gin-gonic/gin v1.7.0 h1:jGB9xAJQ12AIGNB4HguylppmDK1Am9ppF7XnGXXJuoU= github.com/gin-gonic/gin v1.7.0/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= github.com/go-chi/chi v4.1.0+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= github.com/go-openapi/analysis v0.19.4/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU= github.com/go-openapi/analysis v0.19.10/go.mod h1:qmhS3VNFxBlquFJ0RGoDtylO9y4pgTAUNE9AEEMdlJQ= github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= github.com/go-openapi/errors v0.19.3/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= github.com/go-openapi/errors v0.19.4/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs= github.com/go-openapi/loads v0.19.3/go.mod h1:YVfqhUCdahYwR3f3iiwQLhicVRvLlU/WO5WPaZvcvSI= github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk= github.com/go-openapi/loads v0.19.5/go.mod h1:dswLCAdonkRufe/gSUC3gN8nTSaB9uaS2es0x5/IbjY= github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64= github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4= github.com/go-openapi/runtime v0.19.15/go.mod h1:dhGWCTKRXlAfGnQG0ONViOZpjfg0m2gUt9nTQPQZuoo= github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= github.com/go-openapi/spec v0.19.6/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= github.com/go-openapi/spec v0.19.7/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= github.com/go-openapi/strfmt v0.19.2/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= github.com/go-openapi/strfmt v0.19.4/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.7/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY= github.com/go-openapi/swag v0.19.9/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY= github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= github.com/go-openapi/validate v0.19.3/go.mod h1:90Vh6jjkTn+OT1Eefm0ZixWNFjhtOH7vS9k0lo6zwJo= github.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.2.2-0.20190730201129-28a6bbf47e48/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200417002340-c6e0a841f49a/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.4.0/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gophercloud/gophercloud v0.10.0/go.mod h1:gmC5oQqMDOMO1t1gq5DquX/yAU808e/4mzjjDA76+Ss= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.14.4/go.mod h1:6CwZWGDSPRJidgKAtJVvND6soZe6fT7iteq8wDPdhb0= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/api v1.4.0/go.mod h1:xc8u05kyMa3Wjr9eEAsIAo3dg8+LywT5E/Cl7cNS5nU= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.4.0/go.mod h1:fY08Y9z5SvJqevyZNy6WWPXiG3KwBPAvlcdx16zZ0fM= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.12.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.2.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/memberlist v0.1.4/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/memberlist v0.2.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hashicorp/serf v0.9.0/go.mod h1:YL0HO+FifKOW2u1ke99DGVu1zhcpZzNwrLIqBC7vbYU= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/flux v0.65.0/go.mod h1:BwN2XG2lMszOoquQaFdPET8FRQfrXiZsWmcMO9rkaVY= github.com/influxdata/flux v0.113.0/go.mod h1:3TJtvbm/Kwuo5/PEo5P6HUzwVg4bXWkb2wPQHPtQdlU= github.com/influxdata/httprouter v1.3.1-0.20191122104820-ee83e2772f69/go.mod h1:pwymjR6SrP3gD3pRj9RJwdl1j5s3doEEV8gS4X9qSzA= github.com/influxdata/influxdb v1.8.0/go.mod h1:SIzcnsjaHRFpmlxpJ4S3NT64qtEKYweNTUMb/vh0OMQ= github.com/influxdata/influxdb v1.9.0 h1:9z/aRmTpWT1rIm4EN+qTJTZqgEdLGZ4xRMgvA276UEA= github.com/influxdata/influxdb v1.9.0/go.mod h1:UEe3MeD9AaP5rlPIes102IhYua3FhIWZuOXNHxDjSrI= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/influxdata/influxql v1.1.0/go.mod h1:KpVI7okXjK6PRi3Z5B+mtKZli+R1DnZgb3N+tzevNgo= github.com/influxdata/influxql v1.1.1-0.20210223160523-b6ab99450c93/go.mod h1:gHp9y86a/pxhjJ+zMjNXiQAA197Xk9wLxaz+fGG+kWk= github.com/influxdata/line-protocol v0.0.0-20180522152040-32c6aa80de5e/go.mod h1:4kt73NQhadE3daL3WhR5EJ/J2ocX0PZzwxQ0gXJ7oFE= github.com/influxdata/pkg-config v0.2.6/go.mod h1:EMS7Ll0S4qkzDk53XS3Z72/egBsPInt+BeRxb0WeSwk= github.com/influxdata/pkg-config v0.2.7/go.mod h1:EMS7Ll0S4qkzDk53XS3Z72/egBsPInt+BeRxb0WeSwk= github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19ybifQhZoQNF5D8= github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE= github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= github.com/influxdata/tdigest v0.0.2-0.20210216194612-fc98d27c9e8b/go.mod h1:Z0kXnxzbTC2qrx4NaIzYkE1k66+6oEDQTvL95hQFh5Y= github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jinzhu/gorm v0.0.0-20170703134954-2a1463811ee1 h1:sWeCm69jE8uwB/gHLNG65Szf24KebYqoWq1boLccYcQ= github.com/jinzhu/gorm v0.0.0-20170703134954-2a1463811ee1/go.mod h1:Vla75njaFJ8clLU1W44h34PjIkijhjHIYnZxMqCdxqo= github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d h1:jRQLvyVGL+iVtDElaEIDdKwpPqUIZJfzkNLV34htpEc= github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI= github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o= github.com/jsternberg/zap-logfmt v1.2.0/go.mod h1:kz+1CUmCutPWABnNkOu9hOHKdT2q3TDYCcsFy9hpqb0= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/juju/ansiterm v0.0.0-20160907234532-b99631de12cf/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= github.com/juju/clock v0.0.0-20190205081909-9c5c9712527c/go.mod h1:nD0vlnrUjcjJhqN5WuCWZyzfd5AHZAC9/ajvbSx69xA= github.com/juju/cmd v0.0.0-20171107070456-e74f39857ca0/go.mod h1:yWJQHl73rdSX4DHVKGqkAip+huBslxRwS8m9CrOLq18= github.com/juju/collections v0.0.0-20200605021417-0d0ec82b7271/go.mod h1:5XgO71dV1JClcOJE+4dzdn4HrI5LiyKd7PlVG6eZYhY= github.com/juju/errors v0.0.0-20150916125642-1b5e39b83d18/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= github.com/juju/errors v0.0.0-20200330140219-3fe23663418f h1:MCOvExGLpaSIzLYB4iQXEHP4jYVU6vmzLNQPdMVrxnM= github.com/juju/errors v0.0.0-20200330140219-3fe23663418f/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= github.com/juju/httpprof v0.0.0-20141217160036-14bf14c30767/go.mod h1:+MaLYz4PumRkkyHYeXJ2G5g5cIW0sli2bOfpmbaMV/g= github.com/juju/loggo v0.0.0-20170605014607-8232ab8918d9/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= github.com/juju/loggo v0.0.0-20200526014432-9ce3a2e09b5e h1:FdDd7bdI6cjq5vaoYlK1mfQYfF9sF2VZw8VEZMsl5t8= github.com/juju/loggo v0.0.0-20200526014432-9ce3a2e09b5e/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= github.com/juju/mgo/v2 v2.0.0-20210302023703-70d5d206e208 h1:/WiCm+Vpj87e4QWuWwPD/bNE9kDrWCLvPBHOQNcG2+A= github.com/juju/mgo/v2 v2.0.0-20210302023703-70d5d206e208/go.mod h1:0OChplkvPTZ174D2FYZXg4IB9hbEwyHkD+zT+/eK+Fg= github.com/juju/mutex v0.0.0-20171110020013-1fe2a4bf0a3a/go.mod h1:Y3oOzHH8CQ0Ppt0oCKJ2JFO81/EsWenH5AEqigLH+yY= github.com/juju/retry v0.0.0-20151029024821-62c620325291/go.mod h1:OohPQGsr4pnxwD5YljhQ+TZnuVRYpa5irjugL1Yuif4= github.com/juju/retry v0.0.0-20180821225755-9058e192b216/go.mod h1:OohPQGsr4pnxwD5YljhQ+TZnuVRYpa5irjugL1Yuif4= github.com/juju/testing v0.0.0-20180402130637-44801989f0f7/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA= github.com/juju/testing v0.0.0-20190723135506-ce30eb24acd2/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA= github.com/juju/testing v0.0.0-20210324180055-18c50b0c2098 h1:yrhek184cGp0IRyHg0uV1khLaorNg6GtDLkry4oNNjE= github.com/juju/testing v0.0.0-20210324180055-18c50b0c2098/go.mod h1:7lxZW0B50+xdGFkvhAb8bwAGt6IU87JB1H9w4t8MNVM= github.com/juju/utils v0.0.0-20180424094159-2000ea4ff043/go.mod h1:6/KLg8Wz/y2KVGWEpkK9vMNGkOnu4k/cqs8Z1fKjTOk= github.com/juju/utils v0.0.0-20200116185830-d40c2fe10647/go.mod h1:6/KLg8Wz/y2KVGWEpkK9vMNGkOnu4k/cqs8Z1fKjTOk= github.com/juju/utils/v2 v2.0.0-20200923005554-4646bfea2ef1/go.mod h1:fdlDtQlzundleLLz/ggoYinEt/LmnrpNKcNTABQATNI= github.com/juju/version v0.0.0-20161031051906-1f41e27e54f2/go.mod h1:kE8gK5X0CImdr7qpSKl3xB2PmpySSmfj7zVbkZFs81U= github.com/juju/version v0.0.0-20180108022336-b64dbd566305/go.mod h1:kE8gK5X0CImdr7qpSKl3xB2PmpySSmfj7zVbkZFs81U= github.com/juju/version v0.0.0-20191219164919-81c1be00b9a6/go.mod h1:kE8gK5X0CImdr7qpSKl3xB2PmpySSmfj7zVbkZFs81U= github.com/julienschmidt/httprouter v1.1.1-0.20151013225520-77a895ad01eb/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0= github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v0.0.0-20160406211939-eadb3ce320cb/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lunixbochs/vtclean v0.0.0-20160125035106-4fbf7632a2c6/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/masato25/resty v0.4.2-0.20161209040832-927c0e7d74a0 h1:N7lnRiOJGYBnyKNeAJPASQh1zIEAXpE82K4tZdk7CEU= github.com/masato25/resty v0.4.2-0.20161209040832-927c0e7d74a0/go.mod h1:/lGdnJcqS5VKHZIVQZifCge9J8eFdVNFt6VYwjZdedo= github.com/masato25/yaag v0.0.0-20170704095552-00862ec4db8e h1:55FVIPgrRTPWYz+mUa7m6lo5s8z2Y/OPj+EHEC5jx8Q= github.com/masato25/yaag v0.0.0-20170704095552-00862ec4db8e/go.mod h1:V4fa2eVm9p80MCLIl5kv5Aw6Uc0pRL2dYSV4lNK+2PU= github.com/masterzen/azure-sdk-for-go v3.2.0-beta.0.20161014135628-ee4f0065d00c+incompatible/go.mod h1:mf8fjOu33zCqxUjuiU3I8S1lJMyEAlH+0F2+M5xl3hE= github.com/masterzen/simplexml v0.0.0-20160608183007-4572e39b1ab9/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc= github.com/masterzen/winrm v0.0.0-20161014151040-7a535cd943fc/go.mod h1:CfZSN7zwz5gJiFhZJz49Uzk7mEBHIceWmbFmYx7Hf7E= github.com/masterzen/xmlpath v0.0.0-20140218185901-13f4951698ad/go.mod h1:A0zPC53iKKKcXYxr4ROjpQRQ5FgJXtelNdSmHHuq/tY= github.com/mattn/go-colorable v0.0.6/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.0-20160806122752-66b8e73f3f5c/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA= github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.7 h1:fxWBnXkxfM6sRiuH3bqJ4CfzZojMOLVc0UTsTglEghA= github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.22/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.29/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/mileusna/useragent v0.0.0-20190129205925-3e331f0949a5/go.mod h1:JWhYAp2EXqUtsxTKdeGlY8Wp44M7VxThC9FEoNGi2IE= github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989 h1:PS1dLCGtD8bb9RPKJrc8bS7qHL6JnW1CZvwzH9dPoUs= github.com/mindprince/gonvml v0.0.0-20190828220739-9ebdce4bb989/go.mod h1:2eu9pRWp8mo84xCg6KswZ+USQHjwgRhNp06sozOdsTY= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.2.2 h1:dxe5oCinTXiTIcfgmZecdCzPmAJKd46KsCWc35r0TV4= github.com/mitchellh/mapstructure v1.2.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/niean/go-metrics-lite v0.0.0-20151230091537-b5d30971b578 h1:bHDlu3H/z3ITiCCLjAro7dSZTlKy62ZbWHEN5JT7z9M= github.com/niean/go-metrics-lite v0.0.0-20151230091537-b5d30971b578/go.mod h1:F5oJZruubjYvF/hsrhP/QtVabIKrth79mug76XbqqGU= github.com/niean/goperfcounter v0.0.0-20160108100052-24860a8d3fac h1:n7YlHLG7nMXh9CdbINXe/39/9eHPU6pEa2pW3QJUSsM= github.com/niean/goperfcounter v0.0.0-20160108100052-24860a8d3fac/go.mod h1:BIoAJicLFAP0B1TYNsa8nV5Yur3JxpRCdVNC+45yCZI= github.com/niean/gotools v0.0.0-20151221085310-ff3f51fc5c60 h1:8kcIWCY09RdXZcXUKOWtvjvKTr5Lziq4R/6saxUOhvQ= github.com/niean/gotools v0.0.0-20151221085310-ff3f51fc5c60/go.mod h1:gH2bvE9/eX49hWK7CwwL/+/y+dodduyxs5cTpBzF5v0= github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/oleiade/lane v1.0.1 h1:hXofkn7GEOubzTwNpeL9MaNy8WxolCYb9cInAIeqShU= github.com/oleiade/lane v1.0.1/go.mod h1:IyTkraa4maLfjq/GmHR+Dxb4kCMtEGeb+qmhlrQ5Mk4= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/open-falcon/rrdlite v0.0.0-20170412122036-7d8646c85cc5 h1:OZRdjmzU7Q4cuzN4lx7d6zP6L8+Q2dqFfq95CqGcReM= github.com/open-falcon/rrdlite v0.0.0-20170412122036-7d8646c85cc5/go.mod h1:pXROoG0iWVnqq4u2Ii97S0Vt9iCTVypshsl9HXsV6cs= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing-contrib/go-stdlib v0.0.0-20190519235532-cf7a6c988dc9/go.mod h1:PLldrQSroqzH70Xl+1DQcGnefIbqsKR7UDaiux3zV+w= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.0.3-0.20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.4.0 h1:u3Z1r+oOXJIkxqw34zVhyPgjBsm6X2wn21NWs/HfSeg= github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/alertmanager v0.20.0/go.mod h1:9g2i48FAyZW6BtbsnvHtMHQXl2aVtrORKwKVCQ+nbrg= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.2.1/go.mod h1:XMU6Z2MjaRKVu/dC1qupJI9SiNkDYzz3xecMgSW/F+U= github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/prometheus v0.0.0-20200609090129-a6600f564e3c/go.mod h1:S5n0C6tSgdnwWshBUceRx5G1OsjLv/EeZ9t3wIfEtsY= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/satori/go.uuid v0.0.0-20160603004225-b111a074d5ef/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b h1:gQZ0qzfKHQIybLANtM3mBXNUtOfsCFXeTsnBqCsx1KM= github.com/satori/go.uuid v1.2.1-0.20181028125025-b2ce2384e17b/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/snowflakedb/gosnowflake v1.3.4/go.mod h1:NsRq2QeiMUuoNUJhp5Q6xGC4uBrsS9g6LwZVEkTWgsE= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M= github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.7.0 h1:xVKxvI7ouOI5I+U9s2eeiUfMaWBVoXA3AWskkrqK0VM= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/toolkits/cache v0.0.0-20190218093630-cfb07b7585e5 h1:aWeunbUwH8/P2E918Ge885/4wQBgjvkgUkmUGoyrUWQ= github.com/toolkits/cache v0.0.0-20190218093630-cfb07b7585e5/go.mod h1:NQTo1ikAmZPMbWwBZuRRT6ZR/7fIQJ3MVwe2Hyd/Gg8= github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3 h1:kF/7m/ZU+0D4Jj5eZ41Zm3IH/J8OElK1Qtd7tVKAwLk= github.com/toolkits/concurrent v0.0.0-20150624120057-a4371d70e3e3/go.mod h1:QDlpd3qS71vYtakd2hmdpqhJ9nwv6mD6A30bQ1BPBFE= github.com/toolkits/conn_pool v0.0.0-20170512061817-2b758bec1177 h1:maG51qtOSBRRgQorIBMLgklBZar3mEArIfRuUykjOXo= github.com/toolkits/conn_pool v0.0.0-20170512061817-2b758bec1177/go.mod h1:t11yckvHOPOwLPIqkILsCakC941LRZ5JqvXayfM37As= github.com/toolkits/consistent v0.0.0-20150827090850-a6f56a64d1b1 h1:KKVW3VjyAvOcaAtlssIfMRhGDnqQ90VcXGZfaaNvm1M= github.com/toolkits/consistent v0.0.0-20150827090850-a6f56a64d1b1/go.mod h1:/Oysd5WDkGyGtCOpVwF3OI3Bd4ZzfGgMvGyAf82R1kU= github.com/toolkits/container v0.0.0-20151219225805-ba7d73adeaca h1:bUNxqD2ULaaoBA5RLX6YJThj2c75S1BUMT4BmzqkE40= github.com/toolkits/container v0.0.0-20151219225805-ba7d73adeaca/go.mod h1:Z1hsEp8J9dDg5gRss4uixVSS19XDA4dw6S9ZcBm+hB8= github.com/toolkits/core v0.0.0-20141116054942-0ebf14900fe2 h1:KqJEPqqAyr7+GzVX3JrRkpruhcMTZJF5kEGO93Rfrqo= github.com/toolkits/core v0.0.0-20141116054942-0ebf14900fe2/go.mod h1:g5CfkC3ciO92SomFWVazgaQM+sUUG19GQrBNNzGwxZk= github.com/toolkits/cron v0.0.0-20150624115642-bebc2953afa6 h1:+AZ8/esXng2Jj/uG1lxI4Q7eloNovd542ZaB6V4iBIU= github.com/toolkits/cron v0.0.0-20150624115642-bebc2953afa6/go.mod h1:pp3NVdN4QF/u8CgBrjmLuNkDyX2AMR+fxAx+8M4761I= github.com/toolkits/file v0.0.0-20160325033739-a5b3c5147e07 h1:d/VUIMNTk65Xz69htmRPNfjypq2uNRqVsymcXQu6kKk= github.com/toolkits/file v0.0.0-20160325033739-a5b3c5147e07/go.mod h1:FbXpUxsx5in7z/OrWFDdhYetOy3/VGIJsVHN9G7RUPA= github.com/toolkits/http v0.0.0-20150609122824-f3ac6e6c24be h1:ApRE63RTLWH1wUnnMjzaONcBUQUPNfwIRx8BCDRRY4Q= github.com/toolkits/http v0.0.0-20150609122824-f3ac6e6c24be/go.mod h1:bsnr8hNMOaKLGhz/elAgwx8ncK3kaH/9NHTzqGQK9Zg= github.com/toolkits/net v0.0.0-20160910085801-3f39ab6fe3ce h1:XrGffRW+HbN/I45pd25GK3z419YAlHrgTljrQt/ogxk= github.com/toolkits/net v0.0.0-20160910085801-3f39ab6fe3ce/go.mod h1:6zuR3YGQf7EoHAyqA7EayVehUiQm1ZdGJ2PslJ9Xgls= github.com/toolkits/nux v0.0.0-20200401110743-debb3829764a h1:tZ18kQ73hny2GuMFDP38LIq0KFAF3hLBqc3kpjAyVlE= github.com/toolkits/nux v0.0.0-20200401110743-debb3829764a/go.mod h1:YO6BC09QPN1xharvGj2ZKH3uFILpBkrOWKxEgLYfqoo= github.com/toolkits/proc v0.0.0-20170520054645-8c734d0eb018 h1:3XcjQU/SBh80DXhAZOekQMb287zmYwIyaBlWIo8MhA8= github.com/toolkits/proc v0.0.0-20170520054645-8c734d0eb018/go.mod h1:qUAga2ZoGIcH8+lJeKAutG8SJry/D4+dQCKnmGbqk9s= github.com/toolkits/slice v0.0.0-20141116085117-e44a80af2484 h1:ERmNDajjCusGqV3uLhlHhRNpvQiGM1S6pd0RSe3LP+w= github.com/toolkits/slice v0.0.0-20141116085117-e44a80af2484/go.mod h1:2ZKxkgYEh//pN54EFSkJBak63sg0LxQQFjQmpEwxQx0= github.com/toolkits/str v0.0.0-20160913030958-f82e0f0498cb h1:K5v44sWq0aO/bgbrH7Ui81wqxZ3pikW4UcIh3UVKOP8= github.com/toolkits/str v0.0.0-20160913030958-f82e0f0498cb/go.mod h1:j1LqCeE5sJswcBT5LbyTBlZDZHOZ8T9cSxGmTpRvv2E= github.com/toolkits/sys v0.0.0-20170615103026-1f33b217ffaf h1:1/LnhAvvotcSWDl1ntwUePzLXcyHjAzZ0Ih0F+kKGZU= github.com/toolkits/sys v0.0.0-20170615103026-1f33b217ffaf/go.mod h1:GejnAYmB2Pr/2fWKp7OGdd6MzuXvRwClmdQAnvnr++I= github.com/toolkits/time v0.0.0-20160524122720-c274716e8d7f h1:dcluAE5OGvcWy7xfrNrYXQrgEUSK34vBpq7mKTE1zz0= github.com/toolkits/time v0.0.0-20160524122720-c274716e8d7f/go.mod h1:XaIcQHoNgaZn0rTaVOUwOBrsENnHREEBzWmon3ZjUFY= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/uber-go/tally v3.3.15+incompatible/go.mod h1:YDTIBxdXyOU/sCWilKB4bgyufu1cEi0jdVnRdxvjnmU= github.com/uber/athenadriver v1.1.4/go.mod h1:tQjho4NzXw55LGfSZEcETuYydpY1vtmixUabHkC1K/E= github.com/uber/jaeger-client-go v2.23.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E= github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ= github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.9/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.mongodb.org/mongo-driver v1.3.0/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE= go.mongodb.org/mongo-driver v1.3.2/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.5.1/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= golang.org/x/crypto v0.0.0-20180214000028-650f4a345ab4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180505025534-4ec37c66abab/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191202143827-86a70503ff7e/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200422194213-44a606286825/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180406214816-61147c48b25b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191126235420-ef20fe5d7933/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210525063256-abc453219eb5 h1:wjuX4b5yYQnEQHzd+CBcrcC6OVR2J1CN6mUy0oSxIPo= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191128015809-6d18c012aee9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea h1:+WiDlPBBaO+h9vPNZi8uJ3k4BkKQB7Iow3aqwHVA5hI= golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190813034749-528a2984e271/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191203134012-c197fd4bf371/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304024140-c4206d458c3f/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200422205258-72e4a01eba43/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200721032237-77f530d86f9a/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20190927181202-20e1ac93f88c/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200420144010-e5e8543f8aeb/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.0/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20160105164936-4f90aeace3a2/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v1 v1.0.0-20161222125816-442357a80af5/go.mod h1:u0ALmqvLRxLI95fkdCEWrE6mhWYZW1aMOJHp5YXLHTg= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/fsnotify/fsnotify.v1 v1.4.7/go.mod h1:Fyux9zXlo4rWoMSIzpn9fDAYjalPqJ/K1qJ27s+7ltE= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ= gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= gopkg.in/httprequest.v1 v1.1.1/go.mod h1:/CkavNL+g3qLOrpFHVrEx4NKepeqR4XTZWNj4sGGjz0= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/mgo.v2 v2.0.0-20160818015218-f2b6f6c918c4/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gopkg.in/resty.v1 v1.11.0 h1:z5nqGs/W/h91PLOc+WZefPj8rRZe8Ctlgxg/AtbJ+NE= gopkg.in/resty.v1 v1.11.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/resty.v1 v1.12.0 h1:CuXP0Pjfw9rOuY6EP+UvtNvt5DSqHpIxILZKT/quCZI= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637/go.mod h1:BHsqpu/nsuzkT5BpiH1EMZPLyqSMM8JbIavyFACoFNk= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170712054546-1be3d31502d6/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.17.5/go.mod h1:0zV5/ungglgy2Rlm3QK8fbxkXVs+BSJWpJP/+8gUVLY= k8s.io/apimachinery v0.17.5/go.mod h1:ioIo1G/a+uONV7Tv+ZmCbMG1/a3kVw5YcDdncd8ugQ0= k8s.io/client-go v0.17.5/go.mod h1:S8uZpBpjJJdEH/fEyxcqg7Rn0P5jH+ilkgBHjriSmNo= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/kube-openapi v0.0.0-20200316234421-82d701f24f9d/go.mod h1:F+5wygcW0wmRTnM3cOgIqGivxkwSWIWT5YdsDbeAOaU= k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20200414100711-2df71ebbae66/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= launchpad.net/xmlpath v0.0.0-20130614043138-000000000004/go.mod h1:vqyExLOM3qBx7mvYRkoxjSCF945s0mbe7YynlKYXtsA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/structured-merge-diff/v2 v2.0.1/go.mod h1:Wb7vfKAodbKgf6tn1Kl0VvGj7mRH6DGaRcixXEJXTsE= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= ================================================ FILE: main.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "fmt" "os" "github.com/open-falcon/falcon-plus/cmd" "github.com/spf13/cobra" ) var versionFlag bool var RootCmd = &cobra.Command{ Use: "open-falcon", RunE: func(c *cobra.Command, args []string) error { if versionFlag { fmt.Printf("%s version %s, build %s\n", BinaryName, Version, GitCommit) return nil } return c.Usage() }, } func init() { RootCmd.AddCommand(cmd.Start) RootCmd.AddCommand(cmd.Stop) RootCmd.AddCommand(cmd.Restart) RootCmd.AddCommand(cmd.Check) RootCmd.AddCommand(cmd.Monitor) RootCmd.AddCommand(cmd.Reload) RootCmd.Flags().BoolVarP(&versionFlag, "version", "v", false, "show version") cmd.Start.Flags().BoolVar(&cmd.PreqOrderFlag, "preq-order", false, "start modules in the order of prerequisites") cmd.Start.Flags().BoolVar(&cmd.ConsoleOutputFlag, "console-output", false, "print the module's output to the console") } func main() { if err := RootCmd.Execute(); err != nil { fmt.Println(err) os.Exit(1) } } ================================================ FILE: modules/agent/.gitignore ================================================ *.swp *.swo /cfg.json /agent /var /falcon-agent* /falcon_agent .DS_Store *.iml *.idea /gitversion ================================================ FILE: modules/agent/LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: modules/agent/NOTICE ================================================ Open-Falcon Copyright (c) 2014-2015 Xiaomi, Inc. All Rights Reserved. This product is licensed to you under the Apache License, Version 2.0 (the "License"). You may not use this product except in compliance with the License. This product may include a number of subcomponents with separate copyright notices and license terms. Your use of these subcomponents is subject to the terms and conditions of the subcomponent's license, as noted in the LICENSE file. ================================================ FILE: modules/agent/README.md ================================================ falcon-agent === This is a linux monitor agent. Just like zabbix-agent and tcollector. ## Installation It is a golang classic project ```bash # set $GOPATH and $GOROOT mkdir -p $GOPATH/src/github.com/open-falcon cd $GOPATH/src/github.com/open-falcon git clone https://github.com/open-falcon/falcon-plus.git cd falcon-plus/modules/agent go get ./control build ./control start # goto http://localhost:1988 ``` I use [linux-dash](https://github.com/afaqurk/linux-dash) as the page theme. ## Configuration - heartbeat: heartbeat server rpc address - transfer: transfer rpc address - ignore: the metrics should ignore # Auto deployment Just look at https://github.com/open-falcon/ops-updater ================================================ FILE: modules/agent/cfg.example.json ================================================ { "debug": true, "hostname": "", "ip": "", "plugin": { "enabled": false, "dir": "./plugin", "git": "https://github.com/open-falcon/plugin.git", "logs": "./logs" }, "heartbeat": { "enabled": true, "addr": "127.0.0.1:6030", "interval": 60, "timeout": 1000 }, "transfer": { "enabled": true, "addrs": [ "127.0.0.1:8433", "127.0.0.1:8433" ], "interval": 60, "timeout": 1000 }, "http": { "enabled": true, "listen": ":1988", "backdoor": false }, "collector": { "ifacePrefix": ["eth", "em", "ens"], "mountPoint": [] }, "default_tags": { }, "ignore": { "cpu.busy": true, "df.bytes.free": true, "df.bytes.total": true, "df.bytes.used": true, "df.bytes.used.percent": true, "df.inodes.total": true, "df.inodes.free": true, "df.inodes.used": true, "df.inodes.used.percent": true, "mem.memtotal": true, "mem.memused": true, "mem.memused.percent": true, "mem.memfree": true, "mem.swaptotal": true, "mem.swapused": true, "mem.swapfree": true } } ================================================ FILE: modules/agent/control ================================================ #!/bin/bash WORKSPACE=$(cd $(dirname $0)/; pwd) cd $WORKSPACE mkdir -p var module=agent app=falcon-$module conf=cfg.json pidfile=var/app.pid logfile=var/app.log function check_pid() { if [ -f $pidfile ];then pid=`cat $pidfile` if [ -n $pid ]; then running=`ps -p $pid|grep -v "PID TTY" |wc -l` return $running fi fi return 0 } function start() { check_pid running=$? if [ $running -gt 0 ];then echo -n "$app now is running already, pid=" cat $pidfile return 1 fi if ! [ -f $conf ];then echo "Config file $conf doesn't exist, creating one." cp cfg.example.json $conf fi nohup ./$app -c $conf &> $logfile & sleep 1 running=`ps -p $! | grep -v "PID TTY" | wc -l` if [ $running -gt 0 ];then echo $! > $pidfile echo "$app started..., pid=$!" else echo "$app failed to start." return 1 fi } function stop() { pid=`cat $pidfile` kill $pid rm -f $pidfile echo "$app stopped..." } function restart() { stop sleep 1 start } function status() { check_pid running=$? if [ $running -gt 0 ];then echo started else echo stopped fi } function tailf() { tail -f $logfile } function build() { go build if [ $? -ne 0 ]; then exit $? fi mv $module $app ./$app -v } function pack() { build git log -1 --pretty=%h > gitversion version=`./$app -v` file_list="public control cfg.example.json $app" echo "...tar $app-$version.tar.gz <= $file_list" tar zcf $app-$version.tar.gz gitversion $file_list } function packbin() { build git log -1 --pretty=%h > gitversion version=`./$app -v` tar zcvf $app-bin-$version.tar.gz $app gitversion } function help() { echo "$0 build|pack|start|stop|restart|status|tail" } if [ "$1" == "" ]; then help elif [ "$1" == "stop" ];then stop elif [ "$1" == "start" ];then start elif [ "$1" == "restart" ];then restart elif [ "$1" == "status" ];then status elif [ "$1" == "tail" ];then tailf elif [ "$1" == "build" ];then build elif [ "$1" == "pack" ];then pack elif [ "$1" == "packbin" ];then packbin else help fi ================================================ FILE: modules/agent/cron/builtin.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cron import ( "github.com/open-falcon/falcon-plus/common/model" "github.com/open-falcon/falcon-plus/modules/agent/g" "log" "strconv" "strings" "time" ) func SyncBuiltinMetrics() { if g.Config().Heartbeat.Enabled && g.Config().Heartbeat.Addr != "" { go syncBuiltinMetrics() } } func syncBuiltinMetrics() { var timestamp int64 = -1 var checksum string = "nil" duration := time.Duration(g.Config().Heartbeat.Interval) * time.Second for { time.Sleep(duration) var ports = []int64{} var paths = []string{} var procs = make(map[string]map[int]string) var urls = make(map[string]string) hostname, err := g.Hostname() if err != nil { continue } req := model.AgentHeartbeatRequest{ Hostname: hostname, Checksum: checksum, } var resp model.BuiltinMetricResponse err = g.HbsClient.Call("Agent.BuiltinMetrics", req, &resp) if err != nil { log.Println("ERROR:", err) continue } if resp.Timestamp <= timestamp { continue } if resp.Checksum == checksum { continue } timestamp = resp.Timestamp checksum = resp.Checksum for _, metric := range resp.Metrics { if metric.Metric == g.URL_CHECK_HEALTH { arr := strings.Split(metric.Tags, ",") if len(arr) != 2 { continue } url := strings.Split(arr[0], "=") if len(url) != 2 { continue } stime := strings.Split(arr[1], "=") if len(stime) != 2 { continue } if _, err := strconv.ParseInt(stime[1], 10, 64); err == nil { urls[url[1]] = stime[1] } else { log.Println("metric ParseInt timeout failed:", err) } } if metric.Metric == g.NET_PORT_LISTEN { arr := strings.Split(metric.Tags, "=") if len(arr) != 2 { continue } if port, err := strconv.ParseInt(arr[1], 10, 64); err == nil { ports = append(ports, port) } else { log.Println("metrics ParseInt failed:", err) } continue } if metric.Metric == g.DU_BS { arr := strings.Split(metric.Tags, "=") if len(arr) != 2 { continue } paths = append(paths, strings.TrimSpace(arr[1])) continue } if metric.Metric == g.PROC_NUM { arr := strings.Split(metric.Tags, ",") tmpMap := make(map[int]string) for i := 0; i < len(arr); i++ { if strings.HasPrefix(arr[i], "name=") { tmpMap[1] = strings.TrimSpace(arr[i][5:]) } else if strings.HasPrefix(arr[i], "cmdline=") { tmpMap[2] = strings.TrimSpace(arr[i][8:]) } } procs[metric.Tags] = tmpMap } } g.SetReportUrls(urls) g.SetReportPorts(ports) g.SetReportProcs(procs) g.SetDuPaths(paths) } } ================================================ FILE: modules/agent/cron/collector.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cron import ( "time" "github.com/open-falcon/falcon-plus/common/model" "github.com/open-falcon/falcon-plus/modules/agent/funcs" "github.com/open-falcon/falcon-plus/modules/agent/g" ) func InitDataHistory() { for { funcs.UpdateCpuStat() funcs.UpdateDiskStats() time.Sleep(g.COLLECT_INTERVAL) } } func Collect() { if !g.Config().Transfer.Enabled { return } if len(g.Config().Transfer.Addrs) == 0 { return } for _, v := range funcs.Mappers { go collect(int64(v.Interval), v.Fs) } } func collect(sec int64, fns []func() []*model.MetricValue) { t := time.NewTicker(time.Second * time.Duration(sec)) defer t.Stop() for { <-t.C hostname, err := g.Hostname() if err != nil { continue } mvs := []*model.MetricValue{} ignoreMetrics := g.Config().IgnoreMetrics for _, fn := range fns { items := fn() if items == nil { continue } if len(items) == 0 { continue } for _, mv := range items { if b, ok := ignoreMetrics[mv.Metric]; ok && b { continue } else { mvs = append(mvs, mv) } } } now := time.Now().Unix() for j := 0; j < len(mvs); j++ { mvs[j].Step = sec mvs[j].Endpoint = hostname mvs[j].Timestamp = now } g.SendToTransfer(mvs) } } ================================================ FILE: modules/agent/cron/ips.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cron import ( "github.com/open-falcon/falcon-plus/common/model" "github.com/open-falcon/falcon-plus/modules/agent/g" "log" "time" ) func SyncTrustableIps() { if g.Config().Heartbeat.Enabled && g.Config().Heartbeat.Addr != "" { go syncTrustableIps() } } func syncTrustableIps() { duration := time.Duration(g.Config().Heartbeat.Interval) * time.Second for { time.Sleep(duration) var ips string err := g.HbsClient.Call("Agent.TrustableIps", model.NullRpcRequest{}, &ips) if err != nil { log.Println("ERROR: call Agent.TrustableIps fail", err) continue } g.SetTrustableIps(ips) } } ================================================ FILE: modules/agent/cron/plugin.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cron import ( "github.com/open-falcon/falcon-plus/common/model" "github.com/open-falcon/falcon-plus/modules/agent/g" "github.com/open-falcon/falcon-plus/modules/agent/plugins" "github.com/toolkits/file" "log" "os" "path/filepath" "regexp" "strconv" "strings" "time" ) func SyncMinePlugins() { if !g.Config().Plugin.Enabled { return } if !g.Config().Heartbeat.Enabled { return } if g.Config().Heartbeat.Addr == "" { return } go syncMinePlugins() } func syncMinePlugins() { var ( timestamp int64 = -1 pluginDirs []string ) duration := time.Duration(g.Config().Heartbeat.Interval) * time.Second for { time.Sleep(duration) hostname, err := g.Hostname() if err != nil { continue } req := model.AgentHeartbeatRequest{ Hostname: hostname, } var resp model.AgentPluginsResponse err = g.HbsClient.Call("Agent.MinePlugins", req, &resp) if err != nil { log.Println("call Agent.MinePlugin fail:", err) continue } if resp.Timestamp <= timestamp { continue } pluginDirs = resp.Plugins timestamp = resp.Timestamp if g.Config().Debug { log.Printf("call Agent.MinePlugin:%v\n", resp) } if len(pluginDirs) == 0 { plugins.ClearAllPlugins() continue } desiredAll := make(map[string]*plugins.Plugin) filefmt_scripts := [][]string{} dirfmt_scripts := []string{} for _, script_path := range pluginDirs { //script_path could be a DIR or a SCRIPT_FILE_WITH_OR_WITHOUT_ARGS //比如: sys/ntp/60_ntp.py(arg1,arg2) 或者 sys/ntp/60_ntp.py 或者 sys/ntp //1. 参数只对单个脚本文件生效,目录不支持参数 //2. 如果某个目录下的某个脚本被单独绑定到某个机器,那么再次绑定该目录时,该文件会不会再次执行 var args string = "" re := regexp.MustCompile(`(.*)\((.*)\)`) path_args := re.FindAllStringSubmatch(script_path, -1) if path_args != nil { script_path = path_args[0][1] args = path_args[0][2] } abs_path := filepath.Join(g.Config().Plugin.Dir, script_path) if !file.IsExist(abs_path) { continue } if file.IsFile(abs_path) { filefmt_scripts = append(filefmt_scripts, []string{script_path, args}) continue } dirfmt_scripts = append(dirfmt_scripts, script_path) } taken := make(map[string]struct{}) for _, script_file := range filefmt_scripts { abs_path := filepath.Join(g.Config().Plugin.Dir, script_file[0]) _, file_name := filepath.Split(abs_path) arr := strings.Split(file_name, "_") var cycle int var err error cycle, err = strconv.Atoi(arr[0]) if err == nil { fi, _ := os.Stat(abs_path) plugin := &plugins.Plugin{FilePath: script_file[0], MTime: fi.ModTime().Unix(), Cycle: cycle, Args: script_file[1]} desiredAll[script_file[0]+"("+script_file[1]+")"] = plugin } //针对某个 hostgroup 绑定了单个脚本后,再绑定该脚本的目录时,会忽略目录中的该文件 taken[script_file[0]] = struct{}{} } for _, script_path := range dirfmt_scripts { ps := plugins.ListPlugins(strings.Trim(script_path, "/")) for k, p := range ps { if _, ok := taken[k]; ok { continue } desiredAll[k] = p } } plugins.DelNoUsePlugins(desiredAll) plugins.AddNewPlugins(desiredAll) if g.Config().Debug { log.Printf("current plugins:%v\n", plugins.Plugins) } } } ================================================ FILE: modules/agent/cron/reporter.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package cron import ( "fmt" "github.com/open-falcon/falcon-plus/common/model" "github.com/open-falcon/falcon-plus/modules/agent/g" "log" "time" ) func ReportAgentStatus() { if g.Config().Heartbeat.Enabled && g.Config().Heartbeat.Addr != "" { go reportAgentStatus(time.Duration(g.Config().Heartbeat.Interval) * time.Second) } } func reportAgentStatus(interval time.Duration) { for { hostname, err := g.Hostname() if err != nil { hostname = fmt.Sprintf("error:%s", err.Error()) } req := model.AgentReportRequest{ Hostname: hostname, IP: g.IP(), AgentVersion: g.VersionMsg(), PluginVersion: g.GetCurrPluginVersion(), } var resp model.SimpleRpcResponse err = g.HbsClient.Call("Agent.ReportStatus", req, &resp) if err != nil || resp.Code != 0 { log.Println("call Agent.ReportStatus fail:", err, "Request:", req, "Response:", resp) } time.Sleep(interval) } } ================================================ FILE: modules/agent/funcs/agent.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package funcs import ( "github.com/open-falcon/falcon-plus/common/model" ) func AgentMetrics() []*model.MetricValue { return []*model.MetricValue{GaugeValue("agent.alive", 1)} } ================================================ FILE: modules/agent/funcs/checker.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package funcs import ( "fmt" "github.com/toolkits/nux" "github.com/toolkits/sys" ) func CheckCollector() { output := make(map[string]bool) _, procStatErr := nux.CurrentProcStat() _, listDiskErr := nux.ListDiskStats() ports, listeningPortsErr := nux.ListeningPorts() procs, psErr := nux.AllProcs() _, duErr := sys.CmdOut("du", "--help") output["kernel "] = len(KernelMetrics()) > 0 output["df.bytes"] = DeviceMetricsCheck() output["net.if "] = len(CoreNetMetrics([]string{})) > 0 output["loadavg "] = len(LoadAvgMetrics()) > 0 output["cpustat "] = procStatErr == nil output["disk.io "] = listDiskErr == nil output["memory "] = len(MemMetrics()) > 0 output["netstat "] = len(NetstatMetrics()) > 0 output["ss -s "] = len(SocketStatSummaryMetrics()) > 0 output["ss -tln "] = listeningPortsErr == nil && len(ports) > 0 output["ps aux "] = psErr == nil && len(procs) > 0 output["du -bs "] = duErr == nil for k, v := range output { status := "fail" if v { status = "ok" } fmt.Println(k, "...", status) } } ================================================ FILE: modules/agent/funcs/common.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package funcs import ( "github.com/open-falcon/falcon-plus/common/model" "strings" ) func NewMetricValue(metric string, val interface{}, dataType string, tags ...string) *model.MetricValue { mv := model.MetricValue{ Metric: metric, Value: val, Type: dataType, } size := len(tags) if size > 0 { mv.Tags = strings.Join(tags, ",") } return &mv } func GaugeValue(metric string, val interface{}, tags ...string) *model.MetricValue { return NewMetricValue(metric, val, "GAUGE", tags...) } func CounterValue(metric string, val interface{}, tags ...string) *model.MetricValue { return NewMetricValue(metric, val, "COUNTER", tags...) } ================================================ FILE: modules/agent/funcs/cpustat.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package funcs import ( "github.com/open-falcon/falcon-plus/common/model" "github.com/toolkits/nux" "sync" ) const ( historyCount int = 2 ) var ( procStatHistory [historyCount]*nux.ProcStat psLock = new(sync.RWMutex) ) func UpdateCpuStat() error { ps, err := nux.CurrentProcStat() if err != nil { return err } psLock.Lock() defer psLock.Unlock() for i := historyCount - 1; i > 0; i-- { procStatHistory[i] = procStatHistory[i-1] } procStatHistory[0] = ps return nil } func deltaTotal() uint64 { if procStatHistory[1] == nil { return 0 } return procStatHistory[0].Cpu.Total - procStatHistory[1].Cpu.Total } func CpuIdle() float64 { psLock.RLock() defer psLock.RUnlock() dt := deltaTotal() if dt == 0 { return 0.0 } invQuotient := 100.00 / float64(dt) return float64(procStatHistory[0].Cpu.Idle-procStatHistory[1].Cpu.Idle) * invQuotient } func CpuUser() float64 { psLock.RLock() defer psLock.RUnlock() dt := deltaTotal() if dt == 0 { return 0.0 } invQuotient := 100.00 / float64(dt) return float64(procStatHistory[0].Cpu.User-procStatHistory[1].Cpu.User) * invQuotient } func CpuNice() float64 { psLock.RLock() defer psLock.RUnlock() dt := deltaTotal() if dt == 0 { return 0.0 } invQuotient := 100.00 / float64(dt) return float64(procStatHistory[0].Cpu.Nice-procStatHistory[1].Cpu.Nice) * invQuotient } func CpuSystem() float64 { psLock.RLock() defer psLock.RUnlock() dt := deltaTotal() if dt == 0 { return 0.0 } invQuotient := 100.00 / float64(dt) return float64(procStatHistory[0].Cpu.System-procStatHistory[1].Cpu.System) * invQuotient } func CpuIowait() float64 { psLock.RLock() defer psLock.RUnlock() dt := deltaTotal() if dt == 0 { return 0.0 } invQuotient := 100.00 / float64(dt) return float64(procStatHistory[0].Cpu.Iowait-procStatHistory[1].Cpu.Iowait) * invQuotient } func CpuIrq() float64 { psLock.RLock() defer psLock.RUnlock() dt := deltaTotal() if dt == 0 { return 0.0 } invQuotient := 100.00 / float64(dt) return float64(procStatHistory[0].Cpu.Irq-procStatHistory[1].Cpu.Irq) * invQuotient } func CpuSoftIrq() float64 { psLock.RLock() defer psLock.RUnlock() dt := deltaTotal() if dt == 0 { return 0.0 } invQuotient := 100.00 / float64(dt) return float64(procStatHistory[0].Cpu.SoftIrq-procStatHistory[1].Cpu.SoftIrq) * invQuotient } func CpuSteal() float64 { psLock.RLock() defer psLock.RUnlock() dt := deltaTotal() if dt == 0 { return 0.0 } invQuotient := 100.00 / float64(dt) return float64(procStatHistory[0].Cpu.Steal-procStatHistory[1].Cpu.Steal) * invQuotient } func CpuGuest() float64 { psLock.RLock() defer psLock.RUnlock() dt := deltaTotal() if dt == 0 { return 0.0 } invQuotient := 100.00 / float64(dt) return float64(procStatHistory[0].Cpu.Guest-procStatHistory[1].Cpu.Guest) * invQuotient } func CurrentCpuSwitches() uint64 { psLock.RLock() defer psLock.RUnlock() return procStatHistory[0].Ctxt } func CpuPrepared() bool { psLock.RLock() defer psLock.RUnlock() return procStatHistory[1] != nil } func CpuMetrics() []*model.MetricValue { if !CpuPrepared() { return []*model.MetricValue{} } cpuIdleVal := CpuIdle() idle := GaugeValue("cpu.idle", cpuIdleVal) busy := GaugeValue("cpu.busy", 100.0-cpuIdleVal) user := GaugeValue("cpu.user", CpuUser()) nice := GaugeValue("cpu.nice", CpuNice()) system := GaugeValue("cpu.system", CpuSystem()) iowait := GaugeValue("cpu.iowait", CpuIowait()) irq := GaugeValue("cpu.irq", CpuIrq()) softirq := GaugeValue("cpu.softirq", CpuSoftIrq()) steal := GaugeValue("cpu.steal", CpuSteal()) guest := GaugeValue("cpu.guest", CpuGuest()) switches := CounterValue("cpu.switches", CurrentCpuSwitches()) return []*model.MetricValue{idle, busy, user, nice, system, iowait, irq, softirq, steal, guest, switches} } ================================================ FILE: modules/agent/funcs/dfstat.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package funcs import ( "fmt" "github.com/open-falcon/falcon-plus/common/model" "github.com/open-falcon/falcon-plus/modules/agent/g" log "github.com/sirupsen/logrus" "github.com/toolkits/nux" ) func DeviceMetrics() (L []*model.MetricValue) { mountPoints, err := nux.ListMountPoint() if err != nil { log.Error("collect device metrics fail:", err) return } var myMountPoints map[string]bool = make(map[string]bool) if len(g.Config().Collector.MountPoint) > 0 { for _, mp := range g.Config().Collector.MountPoint { myMountPoints[mp] = true } } var diskTotal uint64 = 0 var diskUsed uint64 = 0 for idx := range mountPoints { fsSpec, fsFile, fsVfstype := mountPoints[idx][0], mountPoints[idx][1], mountPoints[idx][2] if len(myMountPoints) > 0 { if _, ok := myMountPoints[fsFile]; !ok { log.Debug("mount point not matched with config", fsFile, "ignored.") continue } } var du *nux.DeviceUsage du, err = nux.BuildDeviceUsage(fsSpec, fsFile, fsVfstype) if err != nil { log.Error(err) continue } if du.BlocksAll == 0 { continue } diskTotal += du.BlocksAll diskUsed += du.BlocksUsed tags := fmt.Sprintf("mount=%s,fstype=%s", du.FsFile, du.FsVfstype) L = append(L, GaugeValue("df.bytes.total", du.BlocksAll, tags)) L = append(L, GaugeValue("df.bytes.used", du.BlocksUsed, tags)) L = append(L, GaugeValue("df.bytes.free", du.BlocksFree, tags)) L = append(L, GaugeValue("df.bytes.used.percent", du.BlocksUsedPercent, tags)) L = append(L, GaugeValue("df.bytes.free.percent", du.BlocksFreePercent, tags)) if du.InodesAll == 0 { continue } L = append(L, GaugeValue("df.inodes.total", du.InodesAll, tags)) L = append(L, GaugeValue("df.inodes.used", du.InodesUsed, tags)) L = append(L, GaugeValue("df.inodes.free", du.InodesFree, tags)) L = append(L, GaugeValue("df.inodes.used.percent", du.InodesUsedPercent, tags)) L = append(L, GaugeValue("df.inodes.free.percent", du.InodesFreePercent, tags)) } if len(L) > 0 && diskTotal > 0 { L = append(L, GaugeValue("df.statistics.total", float64(diskTotal))) L = append(L, GaugeValue("df.statistics.used", float64(diskUsed))) L = append(L, GaugeValue("df.statistics.used.percent", float64(diskUsed)*100.0/float64(diskTotal))) } return } func DeviceMetricsCheck() bool { mountPoints, err := nux.ListMountPoint() if err != nil { log.Error("collect device metrics fail:", err) return false } if len(mountPoints) <= 0 { return false } return true } ================================================ FILE: modules/agent/funcs/diskstats.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package funcs import ( "fmt" "log" "strings" "sync" "github.com/open-falcon/falcon-plus/common/model" "github.com/toolkits/nux" ) var ( diskStatsMap = make(map[string][2]*nux.DiskStats) dsLock = new(sync.RWMutex) ) func UpdateDiskStats() error { dsList, err := nux.ListDiskStats() if err != nil { return err } dsLock.Lock() defer dsLock.Unlock() for i := 0; i < len(dsList); i++ { device := dsList[i].Device diskStatsMap[device] = [2]*nux.DiskStats{dsList[i], diskStatsMap[device][0]} } return nil } func IOReadRequests(arr [2]*nux.DiskStats) uint64 { return arr[0].ReadRequests - arr[1].ReadRequests } func IOReadMerged(arr [2]*nux.DiskStats) uint64 { return arr[0].ReadMerged - arr[1].ReadMerged } func IOReadSectors(arr [2]*nux.DiskStats) uint64 { return arr[0].ReadSectors - arr[1].ReadSectors } func IOMsecRead(arr [2]*nux.DiskStats) uint64 { return arr[0].MsecRead - arr[1].MsecRead } func IOWriteRequests(arr [2]*nux.DiskStats) uint64 { return arr[0].WriteRequests - arr[1].WriteRequests } func IOWriteMerged(arr [2]*nux.DiskStats) uint64 { return arr[0].WriteMerged - arr[1].WriteMerged } func IOWriteSectors(arr [2]*nux.DiskStats) uint64 { return arr[0].WriteSectors - arr[1].WriteSectors } func IOMsecWrite(arr [2]*nux.DiskStats) uint64 { return arr[0].MsecWrite - arr[1].MsecWrite } func IOMsecTotal(arr [2]*nux.DiskStats) uint64 { return arr[0].MsecTotal - arr[1].MsecTotal } func IOMsecWeightedTotal(arr [2]*nux.DiskStats) uint64 { return arr[0].MsecWeightedTotal - arr[1].MsecWeightedTotal } func TS(arr [2]*nux.DiskStats) uint64 { return uint64(arr[0].TS.Sub(arr[1].TS).Nanoseconds() / 1000000) } func IODelta(device string, f func([2]*nux.DiskStats) uint64) uint64 { val, ok := diskStatsMap[device] if !ok { return 0 } if val[1] == nil { return 0 } return f(val) } func DiskIOMetrics() (L []*model.MetricValue) { dsList, err := nux.ListDiskStats() if err != nil { log.Println(err) return } for _, ds := range dsList { if !ShouldHandleDevice(ds.Device) { continue } device := "device=" + ds.Device L = append(L, CounterValue("disk.io.read_requests", ds.ReadRequests, device)) L = append(L, CounterValue("disk.io.read_merged", ds.ReadMerged, device)) L = append(L, CounterValue("disk.io.read_sectors", ds.ReadSectors, device)) L = append(L, CounterValue("disk.io.msec_read", ds.MsecRead, device)) L = append(L, CounterValue("disk.io.write_requests", ds.WriteRequests, device)) L = append(L, CounterValue("disk.io.write_merged", ds.WriteMerged, device)) L = append(L, CounterValue("disk.io.write_sectors", ds.WriteSectors, device)) L = append(L, CounterValue("disk.io.msec_write", ds.MsecWrite, device)) L = append(L, CounterValue("disk.io.ios_in_progress", ds.IosInProgress, device)) L = append(L, CounterValue("disk.io.msec_total", ds.MsecTotal, device)) L = append(L, CounterValue("disk.io.msec_weighted_total", ds.MsecWeightedTotal, device)) } return } func IOStatsMetrics() (L []*model.MetricValue) { dsLock.RLock() defer dsLock.RUnlock() for device := range diskStatsMap { if !ShouldHandleDevice(device) { continue } tags := "device=" + device rio := IODelta(device, IOReadRequests) wio := IODelta(device, IOWriteRequests) delta_rsec := IODelta(device, IOReadSectors) delta_wsec := IODelta(device, IOWriteSectors) ruse := IODelta(device, IOMsecRead) wuse := IODelta(device, IOMsecWrite) use := IODelta(device, IOMsecTotal) n_io := rio + wio avgrq_sz := 0.0 await := 0.0 svctm := 0.0 if n_io != 0 { avgrq_sz = float64(delta_rsec+delta_wsec) / float64(n_io) await = float64(ruse+wuse) / float64(n_io) svctm = float64(use) / float64(n_io) } duration := IODelta(device, TS) L = append(L, GaugeValue("disk.io.read_bytes", float64(delta_rsec)*512.0, tags)) L = append(L, GaugeValue("disk.io.write_bytes", float64(delta_wsec)*512.0, tags)) L = append(L, GaugeValue("disk.io.avgrq_sz", avgrq_sz, tags)) L = append(L, GaugeValue("disk.io.avgqu-sz", float64(IODelta(device, IOMsecWeightedTotal))/1000.0, tags)) L = append(L, GaugeValue("disk.io.await", await, tags)) L = append(L, GaugeValue("disk.io.svctm", svctm, tags)) tmp := float64(use) * 100.0 / float64(duration) if tmp > 100.0 { tmp = 100.0 } L = append(L, GaugeValue("disk.io.util", tmp, tags)) } return } func IOStatsForPage() (L [][]string) { dsLock.RLock() defer dsLock.RUnlock() for device := range diskStatsMap { if !ShouldHandleDevice(device) { continue } rio := IODelta(device, IOReadRequests) wio := IODelta(device, IOWriteRequests) delta_rsec := IODelta(device, IOReadSectors) delta_wsec := IODelta(device, IOWriteSectors) ruse := IODelta(device, IOMsecRead) wuse := IODelta(device, IOMsecWrite) use := IODelta(device, IOMsecTotal) n_io := rio + wio avgrq_sz := 0.0 await := 0.0 svctm := 0.0 if n_io != 0 { avgrq_sz = float64(delta_rsec+delta_wsec) / float64(n_io) await = float64(ruse+wuse) / float64(n_io) svctm = float64(use) / float64(n_io) } item := []string{ device, fmt.Sprintf("%d", IODelta(device, IOReadMerged)), fmt.Sprintf("%d", IODelta(device, IOWriteMerged)), fmt.Sprintf("%d", rio), fmt.Sprintf("%d", wio), fmt.Sprintf("%.2f", float64(delta_rsec)/2.0), fmt.Sprintf("%.2f", float64(delta_wsec)/2.0), fmt.Sprintf("%.2f", avgrq_sz), // avgrq-sz: delta(rsect+wsect)/delta(rio+wio) fmt.Sprintf("%.2f", float64(IODelta(device, IOMsecWeightedTotal))/1000.0), // avgqu-sz: delta(aveq)/s/1000 fmt.Sprintf("%.2f", await), // await: delta(ruse+wuse)/delta(rio+wio) fmt.Sprintf("%.2f", svctm), // svctm: delta(use)/delta(rio+wio) fmt.Sprintf("%.2f%%", float64(use)/10.0), // %util: delta(use)/s/1000 * 100% } L = append(L, item) } return } func ShouldHandleDevice(device string) bool { normal := len(device) <= 4 && (strings.HasPrefix(device, "sd") || strings.HasPrefix(device, "vd")) && !strings.ContainsAny(device, "1234") aws := len(device) >= 4 && strings.HasPrefix(device, "xvd") flash := len(device) >= 4 && (strings.HasPrefix(device, "fio") || strings.HasPrefix(device, "nvme")) nbd := len(device) >= 4 && strings.HasPrefix(device, "nbd") return normal || aws || flash || nbd } ================================================ FILE: modules/agent/funcs/du.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package funcs import ( "bytes" "errors" "fmt" "log" "os/exec" "strconv" "strings" "sync" "time" "github.com/open-falcon/falcon-plus/common/model" "github.com/open-falcon/falcon-plus/modules/agent/g" "github.com/toolkits/sys" ) var timeout = 30 func DuMetrics() (L []*model.MetricValue) { paths := g.DuPaths() result := make(chan *model.MetricValue, len(paths)) var wg sync.WaitGroup for _, path := range paths { wg.Add(1) go func(path string) { var err error defer func() { if err != nil { log.Println(err) result <- GaugeValue(g.DU_BS, -1, "path="+path) } wg.Done() }() //tips:osx does not support -b. cmd := exec.Command("du", "-bs", path) var stdout bytes.Buffer cmd.Stdout = &stdout var stderr bytes.Buffer cmd.Stderr = &stderr err = cmd.Start() if err != nil { return } err, isTimeout := sys.CmdRunWithTimeout(cmd, time.Duration(timeout)*time.Second) if isTimeout { err = errors.New(fmt.Sprintf("exec cmd : du -bs %s timeout", path)) return } errStr := stderr.String() if errStr != "" { err = errors.New(errStr) return } if err != nil { err = errors.New(fmt.Sprintf("du -bs %s failed: %s", path, err.Error())) return } arr := strings.Fields(stdout.String()) if len(arr) < 2 { err = errors.New(fmt.Sprintf("du -bs %s failed: %s", path, "return fields < 2")) return } size, err := strconv.ParseUint(arr[0], 10, 64) if err != nil { err = errors.New(fmt.Sprintf("cannot parse du -bs %s output", path)) return } result <- GaugeValue(g.DU_BS, size, "path="+path) }(path) } wg.Wait() resultLen := len(result) for i := 0; i < resultLen; i++ { L = append(L, <-result) } return } ================================================ FILE: modules/agent/funcs/du_test.go ================================================ package funcs import ( "fmt" "github.com/open-falcon/falcon-plus/modules/agent/g" "os" "path/filepath" "testing" ) var testPath = "" func init() { dir, err := filepath.Abs(filepath.Dir(os.Args[0])) if err != nil { fmt.Println(err) os.Exit(1) } testPath = dir } func TestDuMetrics(t *testing.T) { paths := []string{testPath} g.SetDuPaths(paths) duMetrics := DuMetrics() if duMetrics[0].Value == -1 { t.Error("expect metric value > 0 ,but -1") } } func TestDuMetricsPathNotExist(t *testing.T) { paths := []string{"'path does not exist'"} g.SetDuPaths(paths) duMetrics := DuMetrics() if len(duMetrics) != 1 || duMetrics[0].Value != -1 { t.Errorf("metric value expect -1, but metric : %v", duMetrics) } } func TestDuMetricsTimeout(t *testing.T) { timeout = 0 paths := []string{testPath} g.SetDuPaths(paths) duMetrics := DuMetrics() if len(duMetrics) != 1 || duMetrics[0].Value != -1 { t.Errorf("metric value expect -1, but metric : %v", duMetrics) } } ================================================ FILE: modules/agent/funcs/funcs.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package funcs import ( "github.com/open-falcon/falcon-plus/common/model" "github.com/open-falcon/falcon-plus/modules/agent/g" ) type FuncsAndInterval struct { Fs []func() []*model.MetricValue Interval int } var Mappers []FuncsAndInterval func BuildMappers() { interval := g.Config().Transfer.Interval Mappers = []FuncsAndInterval{ { Fs: []func() []*model.MetricValue{ AgentMetrics, CpuMetrics, NetMetrics, KernelMetrics, LoadAvgMetrics, MemMetrics, DiskIOMetrics, IOStatsMetrics, NetstatMetrics, ProcMetrics, UdpMetrics, }, Interval: interval, }, { Fs: []func() []*model.MetricValue{ DeviceMetrics, }, Interval: interval, }, { Fs: []func() []*model.MetricValue{ PortMetrics, SocketStatSummaryMetrics, }, Interval: interval, }, { Fs: []func() []*model.MetricValue{ DuMetrics, }, Interval: interval, }, { Fs: []func() []*model.MetricValue{ UrlMetrics, }, Interval: interval, }, { Fs: []func() []*model.MetricValue{ GpuMetrics, }, Interval: interval, }, } } ================================================ FILE: modules/agent/funcs/gpu.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package funcs import ( "log" "github.com/mindprince/gonvml" "github.com/open-falcon/falcon-plus/common/model" "github.com/open-falcon/falcon-plus/modules/agent/g" ) // 需要load libnvidia-ml.so.1库 func GpuMetrics() (L []*model.MetricValue) { if err := gonvml.Initialize(); err != nil { debug := g.Config().Debug if debug { log.Println("Initialize error: ", err) } return } defer gonvml.Shutdown() count, err := gonvml.DeviceCount() if err != nil { log.Println("DeviceCount error: ", err) return } if count == 0 { return } temperature := uint(0) totalMemory := uint64(0) usedMemory := uint64(0) gpuUtilization := uint(0) memoryUtilization := uint(0) powerUsage := uint(0) allUtilization := uint(0) allMemoryUtilization := uint(0) for i := 0; i < int(count); i++ { dev, err := gonvml.DeviceHandleByIndex(uint(i)) if err != nil { log.Println("DeviceHandleByIndex error:", err) continue } uuid, err := dev.UUID() if err != nil { log.Println("dev.UUID error", err) } tag := "uuid=" + uuid // 不是所有gpu都有风扇 fanSpeed, err := dev.FanSpeed() if err != nil { log.Println("dev.FanSpeed error: ", err) } else { L = append(L, GaugeValue("gpu.fan.speed", fanSpeed, tag)) } temperature, err = dev.Temperature() if err != nil { log.Println("dev.Temperature error: ", err) continue } totalMemory, usedMemory, err = dev.MemoryInfo() if err != nil { log.Println("dev.MemoryInfo error: ", err) continue } // 单位换算为兆 totalBillion := float64(totalMemory / 1024 / 1024) usedBillion := float64(usedMemory / 1024 / 1024) gpuUtilization, memoryUtilization, err = dev.UtilizationRates() if err != nil { log.Println("dev.UtilizationRates error: ", err) continue } allUtilization += gpuUtilization allMemoryUtilization += memoryUtilization powerUsage, err = dev.PowerUsage() if err != nil { log.Println("dev.PowerUsage error: ", err) } // 单位换算为瓦特 powerWatt := float64(powerUsage / 1000) L = append(L, GaugeValue("gpu.temperature", temperature, tag)) L = append(L, GaugeValue("gpu.memory.total", totalBillion, tag)) L = append(L, GaugeValue("gpu.memory.used", usedBillion, tag)) L = append(L, GaugeValue("gpu.memory.util", memoryUtilization, tag)) L = append(L, GaugeValue("gpu.util", gpuUtilization, tag)) L = append(L, GaugeValue("gpu.power.usage", powerWatt, tag)) } L = append(L, GaugeValue("gpu.count", count)) L = append(L, GaugeValue("gpu.util.avg", allUtilization/count)) L = append(L, GaugeValue("gpu.memory.util.avg", allMemoryUtilization/count)) return L } ================================================ FILE: modules/agent/funcs/ifstat.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package funcs import ( "github.com/open-falcon/falcon-plus/common/model" "github.com/open-falcon/falcon-plus/modules/agent/g" "github.com/toolkits/nux" "log" ) func NetMetrics() []*model.MetricValue { return CoreNetMetrics(g.Config().Collector.IfacePrefix) } func CoreNetMetrics(ifacePrefix []string) []*model.MetricValue { netIfs, err := nux.NetIfs(ifacePrefix) if err != nil { log.Println(err) return []*model.MetricValue{} } cnt := len(netIfs) ret := make([]*model.MetricValue, cnt*26) for idx, netIf := range netIfs { iface := "iface=" + netIf.Iface ret[idx*26+0] = CounterValue("net.if.in.bytes", netIf.InBytes, iface) ret[idx*26+1] = CounterValue("net.if.in.packets", netIf.InPackages, iface) ret[idx*26+2] = CounterValue("net.if.in.errors", netIf.InErrors, iface) ret[idx*26+3] = CounterValue("net.if.in.dropped", netIf.InDropped, iface) ret[idx*26+4] = CounterValue("net.if.in.fifo.errs", netIf.InFifoErrs, iface) ret[idx*26+5] = CounterValue("net.if.in.frame.errs", netIf.InFrameErrs, iface) ret[idx*26+6] = CounterValue("net.if.in.compressed", netIf.InCompressed, iface) ret[idx*26+7] = CounterValue("net.if.in.multicast", netIf.InMulticast, iface) ret[idx*26+8] = CounterValue("net.if.out.bytes", netIf.OutBytes, iface) ret[idx*26+9] = CounterValue("net.if.out.packets", netIf.OutPackages, iface) ret[idx*26+10] = CounterValue("net.if.out.errors", netIf.OutErrors, iface) ret[idx*26+11] = CounterValue("net.if.out.dropped", netIf.OutDropped, iface) ret[idx*26+12] = CounterValue("net.if.out.fifo.errs", netIf.OutFifoErrs, iface) ret[idx*26+13] = CounterValue("net.if.out.collisions", netIf.OutCollisions, iface) ret[idx*26+14] = CounterValue("net.if.out.carrier.errs", netIf.OutCarrierErrs, iface) ret[idx*26+15] = CounterValue("net.if.out.compressed", netIf.OutCompressed, iface) ret[idx*26+16] = CounterValue("net.if.total.bytes", netIf.TotalBytes, iface) ret[idx*26+17] = CounterValue("net.if.total.packets", netIf.TotalPackages, iface) ret[idx*26+18] = CounterValue("net.if.total.errors", netIf.TotalErrors, iface) ret[idx*26+19] = CounterValue("net.if.total.dropped", netIf.TotalDropped, iface) ret[idx*26+20] = GaugeValue("net.if.speed.bits", netIf.SpeedBits, iface) ret[idx*26+21] = CounterValue("net.if.in.percent", netIf.InPercent, iface) ret[idx*26+22] = CounterValue("net.if.out.percent", netIf.OutPercent, iface) ret[idx*26+23] = CounterValue("net.if.in.bits", netIf.InBytes*8, iface) ret[idx*26+24] = CounterValue("net.if.out.bits", netIf.OutBytes*8, iface) ret[idx*26+25] = CounterValue("net.if.total.bits", netIf.TotalBytes*8, iface) } return ret } ================================================ FILE: modules/agent/funcs/kernel.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package funcs import ( "github.com/open-falcon/falcon-plus/common/model" "github.com/toolkits/nux" "log" ) func KernelMetrics() (L []*model.MetricValue) { maxFiles, err := nux.KernelMaxFiles() if err != nil { log.Println(err) return } L = append(L, GaugeValue("kernel.maxfiles", maxFiles)) maxProc, err := nux.KernelMaxProc() if err != nil { log.Println(err) return } L = append(L, GaugeValue("kernel.maxproc", maxProc)) allocateFiles, err := nux.KernelAllocateFiles() if err != nil { log.Println(err) return } L = append(L, GaugeValue("kernel.files.allocated", allocateFiles)) L = append(L, GaugeValue("kernel.files.left", maxFiles-allocateFiles)) return } ================================================ FILE: modules/agent/funcs/loadavg.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package funcs import ( "github.com/open-falcon/falcon-plus/common/model" "github.com/toolkits/nux" "log" ) func LoadAvgMetrics() []*model.MetricValue { load, err := nux.LoadAvg() if err != nil { log.Println(err) return nil } return []*model.MetricValue{ GaugeValue("load.1min", load.Avg1min), GaugeValue("load.5min", load.Avg5min), GaugeValue("load.15min", load.Avg15min), } } ================================================ FILE: modules/agent/funcs/meminfo.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package funcs import ( "github.com/open-falcon/falcon-plus/common/model" "github.com/toolkits/nux" "log" ) func MemMetrics() []*model.MetricValue { m, err := nux.MemInfo() if err != nil { log.Println(err) return nil } memFree := m.MemFree + m.Buffers + m.Cached if m.MemAvailable > 0 { memFree = m.MemAvailable } memUsed := m.MemTotal - memFree pmemFree := 0.0 pmemUsed := 0.0 if m.MemTotal != 0 { pmemFree = float64(memFree) * 100.0 / float64(m.MemTotal) pmemUsed = float64(memUsed) * 100.0 / float64(m.MemTotal) } pswapFree := 0.0 pswapUsed := 0.0 if m.SwapTotal != 0 { pswapFree = float64(m.SwapFree) * 100.0 / float64(m.SwapTotal) pswapUsed = float64(m.SwapUsed) * 100.0 / float64(m.SwapTotal) } return []*model.MetricValue{ GaugeValue("mem.memtotal", m.MemTotal), GaugeValue("mem.memused", memUsed), GaugeValue("mem.memfree", memFree), GaugeValue("mem.swaptotal", m.SwapTotal), GaugeValue("mem.swapused", m.SwapUsed), GaugeValue("mem.swapfree", m.SwapFree), GaugeValue("mem.memfree.percent", pmemFree), GaugeValue("mem.memused.percent", pmemUsed), GaugeValue("mem.swapfree.percent", pswapFree), GaugeValue("mem.swapused.percent", pswapUsed), } } ================================================ FILE: modules/agent/funcs/netstat.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package funcs import ( "github.com/open-falcon/falcon-plus/common/model" "github.com/toolkits/nux" "log" ) var USES = map[string]struct{}{ "PruneCalled": {}, "LockDroppedIcmps": {}, "ArpFilter": {}, "TW": {}, "DelayedACKLocked": {}, "ListenOverflows": {}, "ListenDrops": {}, "TCPPrequeueDropped": {}, "TCPTSReorder": {}, "TCPDSACKUndo": {}, "TCPLoss": {}, "TCPLostRetransmit": {}, "TCPLossFailures": {}, "TCPFastRetrans": {}, "TCPTimeouts": {}, "TCPSchedulerFailed": {}, "TCPAbortOnMemory": {}, "TCPAbortOnTimeout": {}, "TCPAbortFailed": {}, "TCPMemoryPressures": {}, "TCPSpuriousRTOs": {}, "TCPBacklogDrop": {}, "TCPMinTTLDrop": {}, } func NetstatMetrics() (L []*model.MetricValue) { tcpExts, err := nux.Netstat("TcpExt") if err != nil { log.Println(err) return } cnt := len(tcpExts) if cnt == 0 { return } for key, val := range tcpExts { if _, ok := USES[key]; !ok { continue } L = append(L, CounterValue("TcpExt."+key, val)) } return } ================================================ FILE: modules/agent/funcs/portstat.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package funcs import ( "fmt" "github.com/open-falcon/falcon-plus/common/model" "github.com/open-falcon/falcon-plus/modules/agent/g" "github.com/toolkits/nux" "github.com/toolkits/slice" "log" ) func PortMetrics() (L []*model.MetricValue) { reportPorts := g.ReportPorts() sz := len(reportPorts) if sz == 0 { return } allTcpPorts, err := nux.TcpPorts() if err != nil { log.Println(err) return } allUdpPorts, err := nux.UdpPorts() if err != nil { log.Println(err) return } for i := 0; i < sz; i++ { tags := fmt.Sprintf("port=%d", reportPorts[i]) if slice.ContainsInt64(allTcpPorts, reportPorts[i]) || slice.ContainsInt64(allUdpPorts, reportPorts[i]) { L = append(L, GaugeValue(g.NET_PORT_LISTEN, 1, tags)) } else { L = append(L, GaugeValue(g.NET_PORT_LISTEN, 0, tags)) } } return } ================================================ FILE: modules/agent/funcs/procs.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package funcs import ( "github.com/open-falcon/falcon-plus/common/model" "github.com/open-falcon/falcon-plus/modules/agent/g" "github.com/toolkits/nux" "log" "strings" ) func ProcMetrics() (L []*model.MetricValue) { reportProcs := g.ReportProcs() sz := len(reportProcs) if sz == 0 { return } ps, err := nux.AllProcs() if err != nil { log.Println(err) return } pslen := len(ps) for tags, m := range reportProcs { cnt := 0 for i := 0; i < pslen; i++ { if is_a(ps[i], m) { cnt++ } } L = append(L, GaugeValue(g.PROC_NUM, cnt, tags)) } return } func is_a(p *nux.Proc, m map[int]string) bool { // only one kv pair for key, val := range m { if key == 1 { // name if val != p.Name { return false } } else if key == 2 { // cmdline if !strings.Contains(p.Cmdline, val) { return false } } } return true } ================================================ FILE: modules/agent/funcs/snmp.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package funcs import ( "github.com/open-falcon/falcon-plus/common/model" "github.com/toolkits/nux" "log" ) func UdpMetrics() []*model.MetricValue { udp, err := nux.Snmp("Udp") if err != nil { log.Println("read snmp fail", err) return []*model.MetricValue{} } count := len(udp) ret := make([]*model.MetricValue, count) i := 0 for key, val := range udp { ret[i] = CounterValue("snmp.Udp."+key, val) i++ } return ret } ================================================ FILE: modules/agent/funcs/sockstat.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package funcs import ( "github.com/open-falcon/falcon-plus/common/model" "github.com/toolkits/nux" "log" ) func SocketStatSummaryMetrics() (L []*model.MetricValue) { ssMap, err := nux.SocketStatSummary() if err != nil { log.Println(err) return } for k, v := range ssMap { L = append(L, GaugeValue("ss."+k, v)) } return } ================================================ FILE: modules/agent/funcs/urlstat.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package funcs import ( "bufio" "bytes" "fmt" "log" "strings" "github.com/open-falcon/falcon-plus/common/model" "github.com/open-falcon/falcon-plus/modules/agent/g" "github.com/toolkits/file" "github.com/toolkits/sys" ) func UrlMetrics() (L []*model.MetricValue) { reportUrls := g.ReportUrls() sz := len(reportUrls) if sz == 0 { return } hostname, err := g.Hostname() if err != nil { hostname = "None" } for furl, timeout := range reportUrls { tags := fmt.Sprintf("url=%v,timeout=%v,src=%v", furl, timeout, hostname) if ok, _ := probeUrl(furl, timeout); !ok { L = append(L, GaugeValue(g.URL_CHECK_HEALTH, 0, tags)) continue } L = append(L, GaugeValue(g.URL_CHECK_HEALTH, 1, tags)) } return } func probeUrl(furl string, timeout string) (bool, error) { bs, err := sys.CmdOutBytes("curl", "--max-filesize", "102400", "-I", "-m", timeout, "-o", "/dev/null", "-s", "-w", "%{http_code}", furl) if err != nil { log.Printf("probe url [%v] failed.the err is: [%v]\n", furl, err) return false, err } reader := bufio.NewReader(bytes.NewBuffer(bs)) retcode, err := file.ReadLine(reader) if err != nil { log.Println("read retcode failed.err is:", err) return false, err } if strings.TrimSpace(string(retcode)) != "200" { log.Printf("return code [%v] is not 200.query url is [%v]", string(retcode), furl) return false, err } return true, err } ================================================ FILE: modules/agent/g/cfg.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package g import ( "encoding/json" "log" "os" "sync" "github.com/toolkits/file" ) type PluginConfig struct { Enabled bool `json:"enabled"` Dir string `json:"dir"` Git string `json:"git"` LogDir string `json:"logs"` } type HeartbeatConfig struct { Enabled bool `json:"enabled"` Addr string `json:"addr"` Interval int `json:"interval"` Timeout int `json:"timeout"` } type TransferConfig struct { Enabled bool `json:"enabled"` Addrs []string `json:"addrs"` Interval int `json:"interval"` Timeout int `json:"timeout"` } type HttpConfig struct { Enabled bool `json:"enabled"` Listen string `json:"listen"` Backdoor bool `json:"backdoor"` } type CollectorConfig struct { IfacePrefix []string `json:"ifacePrefix"` MountPoint []string `json:"mountPoint"` } type GlobalConfig struct { Debug bool `json:"debug"` Hostname string `json:"hostname"` IP string `json:"ip"` Plugin *PluginConfig `json:"plugin"` Heartbeat *HeartbeatConfig `json:"heartbeat"` Transfer *TransferConfig `json:"transfer"` Http *HttpConfig `json:"http"` Collector *CollectorConfig `json:"collector"` DefaultTags map[string]string `json:"default_tags"` IgnoreMetrics map[string]bool `json:"ignore"` } var ( ConfigFile string config *GlobalConfig lock = new(sync.RWMutex) ) func Config() *GlobalConfig { lock.RLock() defer lock.RUnlock() return config } func Hostname() (string, error) { hostname := Config().Hostname if hostname != "" { return hostname, nil } if os.Getenv("FALCON_ENDPOINT") != "" { hostname = os.Getenv("FALCON_ENDPOINT") return hostname, nil } hostname, err := os.Hostname() if err != nil { log.Println("ERROR: os.Hostname() fail", err) } return hostname, err } func IP() string { ip := Config().IP if ip != "" { // use ip in configuration return ip } if len(LocalIp) > 0 { ip = LocalIp } return ip } func ParseConfig(cfg string) { if cfg == "" { log.Fatalln("use -c to specify configuration file") } if !file.IsExist(cfg) { log.Fatalln("config file:", cfg, "is not existent. maybe you need `mv cfg.example.json cfg.json`") } ConfigFile = cfg configContent, err := file.ToTrimString(cfg) if err != nil { log.Fatalln("read config file:", cfg, "fail:", err) } var c GlobalConfig err = json.Unmarshal([]byte(configContent), &c) if err != nil { log.Fatalln("parse config file:", cfg, "fail:", err) } lock.Lock() defer lock.Unlock() config = &c log.Println("read config file:", cfg, "successfully") } ================================================ FILE: modules/agent/g/const.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package g import ( "time" ) // changelog: // 3.1.3: code refactor // 3.1.4: bugfix ignore configuration // 5.0.0: 支持通过配置控制是否开启/run接口;收集udp流量数据;du某个目录的大小 // 5.1.0: 同步插件的时候不再使用checksum机制 // 5.1.1: 修复往多个transfer发送数据的时候crash的问题 // 5.1.2: ignore mount point when blocks=0 var ( BinaryName string Version string GitCommit string ) func VersionMsg() string { return Version + "@" + GitCommit } const ( COLLECT_INTERVAL = time.Second URL_CHECK_HEALTH = "url.check.health" NET_PORT_LISTEN = "net.port.listen" DU_BS = "du.bs" PROC_NUM = "proc.num" ) ================================================ FILE: modules/agent/g/g.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package g import ( "log" "runtime" ) func init() { runtime.GOMAXPROCS(runtime.NumCPU()) log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile) } ================================================ FILE: modules/agent/g/logger.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package g import log "github.com/sirupsen/logrus" func InitLog(level string) (err error) { switch level { case "info": log.SetLevel(log.InfoLevel) case "debug": log.SetLevel(log.DebugLevel) case "warn": log.SetLevel(log.WarnLevel) default: log.Fatal("log conf only allow [info, debug, warn], please check your confguire") } return } ================================================ FILE: modules/agent/g/rpc.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package g import ( "errors" "github.com/toolkits/net" "log" "math" "net/rpc" "sync" "time" ) type SingleConnRpcClient struct { sync.Mutex rpcClient *rpc.Client RpcServer string Timeout time.Duration } func (this *SingleConnRpcClient) close() { if this.rpcClient != nil { this.rpcClient.Close() this.rpcClient = nil } } func (this *SingleConnRpcClient) serverConn() error { if this.rpcClient != nil { return nil } var err error var retry int = 1 for { if this.rpcClient != nil { return nil } this.rpcClient, err = net.JsonRpcClient("tcp", this.RpcServer, this.Timeout) if err != nil { log.Printf("dial %s fail: %v", this.RpcServer, err) if retry > 3 { return err } time.Sleep(time.Duration(math.Pow(2.0, float64(retry))) * time.Second) retry++ continue } return err } } func (this *SingleConnRpcClient) Call(method string, args interface{}, reply interface{}) error { this.Lock() defer this.Unlock() err := this.serverConn() if err != nil { return err } timeout := time.Duration(10 * time.Second) done := make(chan error, 1) go func() { err := this.rpcClient.Call(method, args, reply) done <- err }() select { case <-time.After(timeout): log.Printf("[WARN] rpc call timeout %v => %v", this.rpcClient, this.RpcServer) this.close() return errors.New(this.RpcServer + " rpc call timeout") case err := <-done: if err != nil { this.close() return err } } return nil } ================================================ FILE: modules/agent/g/tool.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package g import ( "bytes" "fmt" "github.com/toolkits/file" "os/exec" "strings" ) func GetCurrPluginVersion() string { if !Config().Plugin.Enabled { return "plugin not enabled" } pluginDir := Config().Plugin.Dir if !file.IsExist(pluginDir) { return "plugin dir not existent" } cmd := exec.Command("git", "rev-parse", "HEAD") cmd.Dir = pluginDir var out bytes.Buffer cmd.Stdout = &out err := cmd.Run() if err != nil { return fmt.Sprintf("Error:%s", err.Error()) } return strings.TrimSpace(out.String()) } ================================================ FILE: modules/agent/g/transfer.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package g import ( "log" "math/rand" "sync" "time" "github.com/open-falcon/falcon-plus/common/model" ) var ( TransferClientsLock *sync.RWMutex = new(sync.RWMutex) TransferClients map[string]*SingleConnRpcClient = map[string]*SingleConnRpcClient{} ) func SendMetrics(metrics []*model.MetricValue, resp *model.TransferResponse) { rand.Seed(time.Now().UnixNano()) for _, i := range rand.Perm(len(Config().Transfer.Addrs)) { addr := Config().Transfer.Addrs[i] c := getTransferClient(addr) if c == nil { c = initTransferClient(addr) } if updateMetrics(c, metrics, resp) { break } } } func initTransferClient(addr string) *SingleConnRpcClient { var c *SingleConnRpcClient = &SingleConnRpcClient{ RpcServer: addr, Timeout: time.Duration(Config().Transfer.Timeout) * time.Millisecond, } TransferClientsLock.Lock() defer TransferClientsLock.Unlock() TransferClients[addr] = c return c } func updateMetrics(c *SingleConnRpcClient, metrics []*model.MetricValue, resp *model.TransferResponse) bool { err := c.Call("Transfer.Update", metrics, resp) if err != nil { log.Println("call Transfer.Update fail:", c, err) return false } return true } func getTransferClient(addr string) *SingleConnRpcClient { TransferClientsLock.RLock() defer TransferClientsLock.RUnlock() if c, ok := TransferClients[addr]; ok { return c } return nil } ================================================ FILE: modules/agent/g/var.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package g import ( "bytes" "log" "net" "os" "os/exec" "path" "path/filepath" "strings" "sync" "time" "github.com/open-falcon/falcon-plus/common/model" "github.com/toolkits/slice" ) var Root string func InitRootDir() { defer func() { log.Printf("Root dir: %s", Root) }() pwd, err := os.Getwd() if err != nil { log.Fatalln("getwd fail:", err) } if root := lookupRootDir(pwd); root != "" { Root = root return } file, _ := exec.LookPath(os.Args[0]) execDir, _ := filepath.Abs(file) if root := lookupRootDir(path.Dir(execDir)); root != "" { Root = root return } Root = pwd } // path目录下找 public,判断是否存在,不存在上级目录找 func lookupRootDir(dir string) string { index := filepath.Join("public", "index.html") public := filepath.Join(dir, index) if _, err := os.Stat(public); os.IsNotExist(err) { for i := 0; i < 2; i++ { parent := path.Dir(dir) public = filepath.Join(parent, index) if _, err := os.Stat(public); err == nil { return parent } dir = parent } } else if err == nil { return dir } return "" } var LocalIp string func InitLocalIp() { if Config().Heartbeat.Enabled { conn, err := net.DialTimeout("tcp", Config().Heartbeat.Addr, time.Second*10) if err != nil { log.Println("get local addr failed !") } else { LocalIp = strings.Split(conn.LocalAddr().String(), ":")[0] conn.Close() } } else { log.Println("hearbeat is not enabled, can't get localip") } } var ( HbsClient *SingleConnRpcClient ) func InitRpcClients() { if Config().Heartbeat.Enabled { HbsClient = &SingleConnRpcClient{ RpcServer: Config().Heartbeat.Addr, Timeout: time.Duration(Config().Heartbeat.Timeout) * time.Millisecond, } } } func SendToTransfer(metrics []*model.MetricValue) { if len(metrics) == 0 { return } dt := Config().DefaultTags if len(dt) > 0 { var buf bytes.Buffer default_tags_list := []string{} for k, v := range dt { buf.Reset() buf.WriteString(k) buf.WriteString("=") buf.WriteString(v) default_tags_list = append(default_tags_list, buf.String()) } default_tags := strings.Join(default_tags_list, ",") for i, x := range metrics { buf.Reset() if x.Tags == "" { metrics[i].Tags = default_tags } else { buf.WriteString(metrics[i].Tags) buf.WriteString(",") buf.WriteString(default_tags) metrics[i].Tags = buf.String() } } } debug := Config().Debug if debug { log.Printf("=> %v\n", len(metrics), metrics[0]) } var resp model.TransferResponse SendMetrics(metrics, &resp) if debug { log.Println("<=", &resp) } } var ( reportUrls map[string]string reportUrlsLock = new(sync.RWMutex) ) func ReportUrls() map[string]string { reportUrlsLock.RLock() defer reportUrlsLock.RUnlock() return reportUrls } func SetReportUrls(urls map[string]string) { reportUrlsLock.RLock() defer reportUrlsLock.RUnlock() reportUrls = urls } var ( reportPorts []int64 reportPortsLock = new(sync.RWMutex) ) func ReportPorts() []int64 { reportPortsLock.RLock() defer reportPortsLock.RUnlock() return reportPorts } func SetReportPorts(ports []int64) { reportPortsLock.Lock() defer reportPortsLock.Unlock() reportPorts = ports } var ( duPaths []string duPathsLock = new(sync.RWMutex) ) func DuPaths() []string { duPathsLock.RLock() defer duPathsLock.RUnlock() return duPaths } func SetDuPaths(paths []string) { duPathsLock.Lock() defer duPathsLock.Unlock() duPaths = paths } var ( // tags => {1=>name, 2=>cmdline} // e.g. 'name=falcon-agent'=>{1=>falcon-agent} // e.g. 'cmdline=xx'=>{2=>xx} reportProcs map[string]map[int]string reportProcsLock = new(sync.RWMutex) ) func ReportProcs() map[string]map[int]string { reportProcsLock.RLock() defer reportProcsLock.RUnlock() return reportProcs } func SetReportProcs(procs map[string]map[int]string) { reportProcsLock.Lock() defer reportProcsLock.Unlock() reportProcs = procs } var ( ips []string ipsLock = new(sync.Mutex) ) func TrustableIps() []string { ipsLock.Lock() defer ipsLock.Unlock() return ips } func SetTrustableIps(ipStr string) { arr := strings.Split(ipStr, ",") ipsLock.Lock() defer ipsLock.Unlock() ips = arr } func IsTrustable(remoteAddr string) bool { ip := remoteAddr idx := strings.LastIndex(remoteAddr, ":") if idx > 0 { ip = remoteAddr[0:idx] } if ip == "127.0.0.1" { return true } return slice.ContainsString(TrustableIps(), ip) } ================================================ FILE: modules/agent/g/var_test.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package g import ( "path/filepath" "runtime" "testing" ) func TestInitRootDir(t *testing.T) { tests := []struct { name string }{ {}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { InitRootDir() if getCurrentPath() != Root { t.Errorf("Root: [%v], actually: [%v]", getCurrentPath(), Root) } }) } } func getCurrentPath() string { _, filename, _, _ := runtime.Caller(1) return filepath.Dir(filepath.Dir(filename)) } ================================================ FILE: modules/agent/http/admin.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package http import ( "github.com/open-falcon/falcon-plus/modules/agent/g" "github.com/toolkits/file" "net/http" "os" "time" ) func configAdminRoutes() { http.HandleFunc("/exit", func(w http.ResponseWriter, r *http.Request) { if g.IsTrustable(r.RemoteAddr) { w.Write([]byte("exiting...")) go func() { time.Sleep(time.Second) os.Exit(0) }() } else { w.Write([]byte("no privilege")) } }) http.HandleFunc("/config/reload", func(w http.ResponseWriter, r *http.Request) { if g.IsTrustable(r.RemoteAddr) { g.ParseConfig(g.ConfigFile) RenderDataJson(w, g.Config()) } else { w.Write([]byte("no privilege")) } }) http.HandleFunc("/workdir", func(w http.ResponseWriter, r *http.Request) { RenderDataJson(w, file.SelfDir()) }) http.HandleFunc("/ips", func(w http.ResponseWriter, r *http.Request) { RenderDataJson(w, g.TrustableIps()) }) } ================================================ FILE: modules/agent/http/cpu.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package http import ( "fmt" "github.com/open-falcon/falcon-plus/modules/agent/funcs" "github.com/toolkits/nux" "net/http" "runtime" ) func configCpuRoutes() { http.HandleFunc("/proc/cpu/num", func(w http.ResponseWriter, r *http.Request) { RenderDataJson(w, runtime.NumCPU()) }) http.HandleFunc("/proc/cpu/mhz", func(w http.ResponseWriter, r *http.Request) { data, err := nux.CpuMHz() AutoRender(w, data, err) }) http.HandleFunc("/page/cpu/usage", func(w http.ResponseWriter, r *http.Request) { if !funcs.CpuPrepared() { RenderMsgJson(w, "not prepared") return } idle := funcs.CpuIdle() busy := 100.0 - idle item := [10]string{ fmt.Sprintf("%.1f%%", idle), fmt.Sprintf("%.1f%%", busy), fmt.Sprintf("%.1f%%", funcs.CpuUser()), fmt.Sprintf("%.1f%%", funcs.CpuNice()), fmt.Sprintf("%.1f%%", funcs.CpuSystem()), fmt.Sprintf("%.1f%%", funcs.CpuIowait()), fmt.Sprintf("%.1f%%", funcs.CpuIrq()), fmt.Sprintf("%.1f%%", funcs.CpuSoftIrq()), fmt.Sprintf("%.1f%%", funcs.CpuSteal()), fmt.Sprintf("%.1f%%", funcs.CpuGuest()), } RenderDataJson(w, [][10]string{item}) }) http.HandleFunc("/proc/cpu/usage", func(w http.ResponseWriter, r *http.Request) { if !funcs.CpuPrepared() { RenderMsgJson(w, "not prepared") return } idle := funcs.CpuIdle() busy := 100.0 - idle RenderDataJson(w, map[string]interface{}{ "idle": idle, "busy": busy, "user": funcs.CpuUser(), "nice": funcs.CpuNice(), "system": funcs.CpuSystem(), "iowait": funcs.CpuIowait(), "irq": funcs.CpuIrq(), "softirq": funcs.CpuSoftIrq(), "steal": funcs.CpuSteal(), "guest": funcs.CpuGuest(), }) }) } ================================================ FILE: modules/agent/http/df.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package http import ( "fmt" "github.com/toolkits/core" "github.com/toolkits/nux" "net/http" ) func configDfRoutes() { http.HandleFunc("/page/df", func(w http.ResponseWriter, r *http.Request) { mountPoints, err := nux.ListMountPoint() if err != nil { RenderMsgJson(w, err.Error()) return } var ret [][]interface{} = make([][]interface{}, 0) for idx := range mountPoints { var du *nux.DeviceUsage du, err = nux.BuildDeviceUsage(mountPoints[idx][0], mountPoints[idx][1], mountPoints[idx][2]) if err == nil { ret = append(ret, []interface{}{ du.FsSpec, core.ReadableSize(float64(du.BlocksAll)), core.ReadableSize(float64(du.BlocksUsed)), core.ReadableSize(float64(du.BlocksFree)), fmt.Sprintf("%.1f%%", du.BlocksUsedPercent), du.FsFile, core.ReadableSize(float64(du.InodesAll)), core.ReadableSize(float64(du.InodesUsed)), core.ReadableSize(float64(du.InodesFree)), fmt.Sprintf("%.1f%%", du.InodesUsedPercent), du.FsVfstype, }) } } RenderDataJson(w, ret) }) } ================================================ FILE: modules/agent/http/health.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package http import ( "github.com/open-falcon/falcon-plus/modules/agent/g" "net/http" ) func configHealthRoutes() { http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("ok")) }) http.HandleFunc("/version", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(g.VersionMsg())) }) } ================================================ FILE: modules/agent/http/http.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package http import ( "encoding/json" "github.com/open-falcon/falcon-plus/modules/agent/g" "log" "net/http" _ "net/http/pprof" ) type Dto struct { Msg string `json:"msg"` Data interface{} `json:"data"` } func init() { configAdminRoutes() configCpuRoutes() configDfRoutes() configHealthRoutes() configIoStatRoutes() configKernelRoutes() configMemoryRoutes() configPageRoutes() configPluginRoutes() configPushRoutes() configRunRoutes() configSystemRoutes() } func RenderJson(w http.ResponseWriter, v interface{}) { bs, err := json.Marshal(v) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.Write(bs) } func RenderDataJson(w http.ResponseWriter, data interface{}) { RenderJson(w, Dto{Msg: "success", Data: data}) } func RenderMsgJson(w http.ResponseWriter, msg string) { RenderJson(w, map[string]string{"msg": msg}) } func AutoRender(w http.ResponseWriter, data interface{}, err error) { if err != nil { RenderMsgJson(w, err.Error()) return } RenderDataJson(w, data) } func Start() { if !g.Config().Http.Enabled { return } addr := g.Config().Http.Listen if addr == "" { return } s := &http.Server{ Addr: addr, MaxHeaderBytes: 1 << 30, } log.Println("listening", addr) log.Fatalln(s.ListenAndServe()) } ================================================ FILE: modules/agent/http/iostat.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package http import ( "github.com/open-falcon/falcon-plus/modules/agent/funcs" "net/http" ) func configIoStatRoutes() { http.HandleFunc("/page/diskio", func(w http.ResponseWriter, r *http.Request) { RenderDataJson(w, funcs.IOStatsForPage()) }) } ================================================ FILE: modules/agent/http/kernel.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package http import ( "github.com/open-falcon/falcon-plus/modules/agent/g" "github.com/toolkits/nux" "github.com/toolkits/sys" "net/http" ) func configKernelRoutes() { http.HandleFunc("/proc/kernel/hostname", func(w http.ResponseWriter, r *http.Request) { data, err := g.Hostname() AutoRender(w, data, err) }) http.HandleFunc("/proc/kernel/maxproc", func(w http.ResponseWriter, r *http.Request) { data, err := nux.KernelMaxProc() AutoRender(w, data, err) }) http.HandleFunc("/proc/kernel/maxfiles", func(w http.ResponseWriter, r *http.Request) { data, err := nux.KernelMaxFiles() AutoRender(w, data, err) }) http.HandleFunc("/proc/kernel/version", func(w http.ResponseWriter, r *http.Request) { data, err := sys.CmdOutNoLn("uname", "-r") AutoRender(w, data, err) }) } ================================================ FILE: modules/agent/http/memory.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package http import ( "github.com/toolkits/nux" "net/http" ) func configMemoryRoutes() { http.HandleFunc("/page/memory", func(w http.ResponseWriter, r *http.Request) { mem, err := nux.MemInfo() if err != nil { RenderMsgJson(w, err.Error()) return } memFree := mem.MemFree + mem.Buffers + mem.Cached memUsed := mem.MemTotal - memFree var t uint64 = 1024 * 1024 RenderDataJson(w, []interface{}{mem.MemTotal / t, memUsed / t, memFree / t}) }) http.HandleFunc("/proc/memory", func(w http.ResponseWriter, r *http.Request) { mem, err := nux.MemInfo() if err != nil { RenderMsgJson(w, err.Error()) return } memFree := mem.MemFree + mem.Buffers + mem.Cached memUsed := mem.MemTotal - memFree RenderDataJson(w, map[string]interface{}{ "total": mem.MemTotal, "free": memFree, "used": memUsed, }) }) } ================================================ FILE: modules/agent/http/page.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package http import ( "github.com/open-falcon/falcon-plus/modules/agent/g" "github.com/toolkits/file" "net/http" "path/filepath" "strings" ) func configPageRoutes() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if strings.HasSuffix(r.URL.Path, "/") { if !file.IsExist(filepath.Join(g.Root, "/public", r.URL.Path, "index.html")) { http.NotFound(w, r) return } } http.FileServer(http.Dir(filepath.Join(g.Root, "/public"))).ServeHTTP(w, r) }) } ================================================ FILE: modules/agent/http/plugin.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package http import ( "fmt" "github.com/open-falcon/falcon-plus/modules/agent/g" "github.com/open-falcon/falcon-plus/modules/agent/plugins" "github.com/toolkits/file" "net/http" "os/exec" ) func configPluginRoutes() { http.HandleFunc("/plugin/update", func(w http.ResponseWriter, r *http.Request) { if !g.Config().Plugin.Enabled { w.Write([]byte("plugin not enabled")) return } dir := g.Config().Plugin.Dir parentDir := file.Dir(dir) file.InsureDir(parentDir) if file.IsExist(dir) { // git pull cmd := exec.Command("git", "pull") cmd.Dir = dir err := cmd.Run() if err != nil { w.Write([]byte(fmt.Sprintf("git pull in dir:%s fail. error: %s", dir, err))) return } } else { // git clone cmd := exec.Command("git", "clone", g.Config().Plugin.Git, file.Basename(dir)) cmd.Dir = parentDir err := cmd.Run() if err != nil { w.Write([]byte(fmt.Sprintf("git clone in dir:%s fail. error: %s", parentDir, err))) return } } w.Write([]byte("success")) }) http.HandleFunc("/plugin/reset", func(w http.ResponseWriter, r *http.Request) { if !g.Config().Plugin.Enabled { w.Write([]byte("plugin not enabled")) return } dir := g.Config().Plugin.Dir if file.IsExist(dir) { cmd := exec.Command("git", "reset", "--hard") cmd.Dir = dir err := cmd.Run() if err != nil { w.Write([]byte(fmt.Sprintf("git reset --hard in dir:%s fail. error: %s", dir, err))) return } } w.Write([]byte("success")) }) http.HandleFunc("/plugins", func(w http.ResponseWriter, r *http.Request) { //TODO: not thread safe RenderDataJson(w, plugins.Plugins) }) } ================================================ FILE: modules/agent/http/push.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package http import ( "encoding/json" "github.com/open-falcon/falcon-plus/common/model" "github.com/open-falcon/falcon-plus/modules/agent/g" "net/http" ) func configPushRoutes() { http.HandleFunc("/v1/push", func(w http.ResponseWriter, req *http.Request) { if req.ContentLength == 0 { http.Error(w, "body is blank", http.StatusBadRequest) return } decoder := json.NewDecoder(req.Body) var metrics []*model.MetricValue err := decoder.Decode(&metrics) if err != nil { http.Error(w, "connot decode body", http.StatusBadRequest) return } g.SendToTransfer(metrics) w.Write([]byte("success")) }) } ================================================ FILE: modules/agent/http/run.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package http import ( "github.com/open-falcon/falcon-plus/modules/agent/g" "github.com/toolkits/sys" "io/ioutil" "net/http" ) func configRunRoutes() { http.HandleFunc("/run", func(w http.ResponseWriter, r *http.Request) { if !g.Config().Http.Backdoor { w.Write([]byte("/run disabled")) return } if g.IsTrustable(r.RemoteAddr) { if r.ContentLength == 0 { http.Error(w, "body is blank", http.StatusBadRequest) return } bs, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } body := string(bs) out, err := sys.CmdOutBytes("sh", "-c", body) if err != nil { w.Write([]byte("exec fail: " + err.Error())) return } w.Write(out) } else { w.Write([]byte("no privilege")) } }) } ================================================ FILE: modules/agent/http/system.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package http import ( "fmt" "github.com/toolkits/nux" "net/http" "runtime" "time" ) func configSystemRoutes() { http.HandleFunc("/system/date", func(w http.ResponseWriter, req *http.Request) { RenderDataJson(w, time.Now().Format("2006-01-02 15:04:05")) }) http.HandleFunc("/page/system/uptime", func(w http.ResponseWriter, req *http.Request) { days, hours, mins, err := nux.SystemUptime() AutoRender(w, fmt.Sprintf("%d days %d hours %d minutes", days, hours, mins), err) }) http.HandleFunc("/proc/system/uptime", func(w http.ResponseWriter, req *http.Request) { days, hours, mins, err := nux.SystemUptime() if err != nil { RenderMsgJson(w, err.Error()) return } RenderDataJson(w, map[string]interface{}{ "days": days, "hours": hours, "mins": mins, }) }) http.HandleFunc("/page/system/loadavg", func(w http.ResponseWriter, req *http.Request) { cpuNum := runtime.NumCPU() load, err := nux.LoadAvg() if err != nil { RenderMsgJson(w, err.Error()) return } ret := [3][2]interface{}{ {load.Avg1min, int64(load.Avg1min * 100.0 / float64(cpuNum))}, {load.Avg5min, int64(load.Avg5min * 100.0 / float64(cpuNum))}, {load.Avg15min, int64(load.Avg15min * 100.0 / float64(cpuNum))}, } RenderDataJson(w, ret) }) http.HandleFunc("/proc/system/loadavg", func(w http.ResponseWriter, req *http.Request) { data, err := nux.LoadAvg() AutoRender(w, data, err) }) } ================================================ FILE: modules/agent/main.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "flag" "fmt" "github.com/open-falcon/falcon-plus/modules/agent/cron" "github.com/open-falcon/falcon-plus/modules/agent/funcs" "github.com/open-falcon/falcon-plus/modules/agent/g" "github.com/open-falcon/falcon-plus/modules/agent/http" "os" ) func main() { g.BinaryName = BinaryName g.Version = Version g.GitCommit = GitCommit cfg := flag.String("c", "cfg.json", "configuration file") version := flag.Bool("v", false, "show version") check := flag.Bool("check", false, "check collector") flag.Parse() if *version { fmt.Printf("Open-Falcon %s version %s, build %s\n", BinaryName, Version, GitCommit) os.Exit(0) } if *check { funcs.CheckCollector() os.Exit(0) } g.ParseConfig(*cfg) if g.Config().Debug { g.InitLog("debug") } else { g.InitLog("info") } g.InitRootDir() g.InitLocalIp() g.InitRpcClients() funcs.BuildMappers() go cron.InitDataHistory() cron.ReportAgentStatus() cron.SyncMinePlugins() cron.SyncBuiltinMetrics() cron.SyncTrustableIps() cron.Collect() go http.Start() select {} } ================================================ FILE: modules/agent/plugins/plugins.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package plugins type Plugin struct { FilePath string MTime int64 Cycle int Args string } var ( Plugins = make(map[string]*Plugin) PluginsWithScheduler = make(map[string]*PluginScheduler) ) func DelNoUsePlugins(newPlugins map[string]*Plugin) { for currKey, currPlugin := range Plugins { newPlugin, ok := newPlugins[currKey] if !ok || currPlugin.MTime != newPlugin.MTime { deletePlugin(currKey) } } } func AddNewPlugins(newPlugins map[string]*Plugin) { for fpath, newPlugin := range newPlugins { if _, ok := Plugins[fpath]; ok && newPlugin.MTime == Plugins[fpath].MTime { continue } Plugins[fpath] = newPlugin sch := NewPluginScheduler(newPlugin) PluginsWithScheduler[fpath] = sch sch.Schedule() } } func ClearAllPlugins() { for k := range Plugins { deletePlugin(k) } } func deletePlugin(key string) { v, ok := PluginsWithScheduler[key] if ok { v.Stop() delete(PluginsWithScheduler, key) } delete(Plugins, key) } ================================================ FILE: modules/agent/plugins/reader.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package plugins import ( "github.com/open-falcon/falcon-plus/modules/agent/g" "io/ioutil" "log" "path/filepath" "strconv" "strings" ) // return: dict{sys/ntp/60_ntp.py : *Plugin} func ListPlugins(script_path string) map[string]*Plugin { ret := make(map[string]*Plugin) if script_path == "" { return ret } abs_path := filepath.Join(g.Config().Plugin.Dir, script_path) fs, err := ioutil.ReadDir(abs_path) if err != nil { log.Println("can not list files under", abs_path) return ret } for _, f := range fs { if f.IsDir() { continue } filename := f.Name() arr := strings.Split(filename, "_") if len(arr) < 2 { continue } // filename should be: $cycle_$xx var cycle int cycle, err = strconv.Atoi(arr[0]) if err != nil { continue } fpath := filepath.Join(script_path, filename) plugin := &Plugin{FilePath: fpath, MTime: f.ModTime().Unix(), Cycle: cycle, Args: ""} ret[fpath] = plugin } return ret } ================================================ FILE: modules/agent/plugins/scheduler.go ================================================ // Copyright 2017 Xiaomi, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package plugins import ( "bytes" "encoding/json" "log" "os/exec" "path/filepath" "strings" "syscall" "time" "github.com/open-falcon/falcon-plus/common/model" "github.com/open-falcon/falcon-plus/modules/agent/g" "github.com/toolkits/file" "github.com/toolkits/sys" ) type PluginScheduler struct { Ticker *time.Ticker Plugin *Plugin Quit chan struct{} } func NewPluginScheduler(p *Plugin) *PluginScheduler { scheduler := PluginScheduler{Plugin: p} scheduler.Ticker = time.NewTicker(time.Duration(p.Cycle) * time.Second) scheduler.Quit = make(chan struct{}) return &scheduler } func (this *PluginScheduler) Schedule() { go func() { for { select { case <-this.Ticker.C: PluginRun(this.Plugin) case <-this.Quit: this.Ticker.Stop() return } } }() } func (this *PluginScheduler) Stop() { close(this.Quit) } // using ',' as the seprator of args and '\,' to espace func PluginArgsParse(raw_args string) []string { ss := strings.Split(raw_args, "\\,") out := [][]string{} for _, s := range ss { clean_args := []string{} for _, arg := range strings.Split(s, ",") { arg = strings.Trim(arg, " ") arg = strings.Trim(arg, "\"") arg = strings.Trim(arg, "'") clean_args = append(clean_args, arg) } out = append(out, clean_args) } ret := []string{} tail := "" for _, x := range out { for j, y := range x { if j == 0 { if tail != "" { ret = append(ret, tail+","+y) tail = "" } else { ret = append(ret, y) } } else if j == len(x)-1 { tail = y } else { ret = append(ret, y) } } } if tail != "" { ret = append(ret, tail) } return ret } func PluginRun(plugin *Plugin) { timeout := plugin.Cycle*1000 - 500 fpath := filepath.Join(g.Config().Plugin.Dir, plugin.FilePath) args := plugin.Args if !file.IsExist(fpath) { log.Printf("no such plugin: %s(%s)", fpath, args) return } debug := g.Config().Debug if debug { log.Printf("%s(%s) running...", fpath, args) } var cmd *exec.Cmd if args == "" { cmd = exec.Command(fpath) } else { arg_list := PluginArgsParse(args) cmd = exec.Command(fpath, arg_list...) } var stdout bytes.Buffer cmd.Stdout = &stdout var stderr bytes.Buffer cmd.Stderr = &stderr cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} err := cmd.Start() if err != nil { log.Printf("[ERROR] plugin start fail: %s(%s) , error: %s\n", fpath, args, err) return } if debug { log.Printf("plugin started: %s(%s)", fpath, args) } err, isTimeout := sys.CmdRunWithTimeout(cmd, time.Duration(timeout)*time.Millisecond) errStr := stderr.String() if errStr != "" { logFile := filepath.Join(g.Config().Plugin.LogDir, plugin.FilePath+"("+plugin.Args+")"+".stderr.log") if _, err = file.WriteString(logFile, errStr); err != nil { log.Printf("[ERROR] write log to %s fail, error: %s\n", logFile, err) } } if isTimeout { // has be killed if err == nil && debug { log.Println("[INFO] timeout and kill process ", fpath, "(", args, ")", " successfully") } if err != nil { log.Println("[ERROR] kill process ", fpath, "(", args, ")", " occur error:", err) } return } if err != nil { log.Println("[ERROR] exec plugin", fpath, "(", args, ")", "fail. error:", err) return } // exec successfully data := stdout.Bytes() if len(data) == 0 { if debug { log.Println("[DEBUG] stdout of", fpath, "(", args, ")", "is blank") } return } var metrics []*model.MetricValue err = json.Unmarshal(data, &metrics) if err != nil { log.Printf("[ERROR] json.Unmarshal stdout of %s(%s) fail. error:%s stdout: \n%s\n", fpath, args, err, stdout.String()) return } g.SendToTransfer(metrics) } ================================================ FILE: modules/agent/public/css/font-awesome/css/archive/font-awesome-ie7.css ================================================ /*! * Font Awesome 3.2.1 * the iconic font designed for Bootstrap * ------------------------------------------------------------------------------ * The full suite of pictographic icons, examples, and documentation can be * found at http://fontawesome.io. Stay up to date on Twitter at * http://twitter.com/fontawesome. * * License * ------------------------------------------------------------------------------ * - The Font Awesome font is licensed under SIL OFL 1.1 - * http://scripts.sil.org/OFL * - Font Awesome CSS, LESS, and SASS files are licensed under MIT License - * http://opensource.org/licenses/mit-license.html * - Font Awesome documentation licensed under CC BY 3.0 - * http://creativecommons.org/licenses/by/3.0/ * - Attribution is no longer required in Font Awesome 3.0, but much appreciated: * "Font Awesome by Dave Gandy - http://fontawesome.io" * * Author - Dave Gandy * ------------------------------------------------------------------------------ * Email: dave@fontawesome.io * Twitter: http://twitter.com/davegandy * Work: Lead Product Designer @ Kyruus - http://kyruus.com */ .icon-large { font-size: 1.3333333333333333em; margin-top: -4px; padding-top: 3px; margin-bottom: -4px; padding-bottom: 3px; vertical-align: middle; } .nav [class^="icon-"], .nav [class*=" icon-"] { vertical-align: inherit; margin-top: -4px; padding-top: 3px; margin-bottom: -4px; padding-bottom: 3px; } .nav [class^="icon-"].icon-large, .nav [class*=" icon-"].icon-large { vertical-align: -25%; } .nav-pills [class^="icon-"].icon-large, .nav-tabs [class^="icon-"].icon-large, .nav-pills [class*=" icon-"].icon-large, .nav-tabs [class*=" icon-"].icon-large { line-height: .75em; margin-top: -7px; padding-top: 5px; margin-bottom: -5px; padding-bottom: 4px; } .btn [class^="icon-"].pull-left, .btn [class*=" icon-"].pull-left, .btn [class^="icon-"].pull-right, .btn [class*=" icon-"].pull-right { vertical-align: inherit; } .btn [class^="icon-"].icon-large, .btn [class*=" icon-"].icon-large { margin-top: -0.5em; } a [class^="icon-"], a [class*=" icon-"] { cursor: pointer; } .icon-glass { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-music { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-search { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-envelope-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-heart { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-star { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-star-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-user { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-film { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-th-large { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-th { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-th-list { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-ok { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-remove { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-zoom-in { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-zoom-out { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-off { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-power-off { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-signal { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-cog { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-gear { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-trash { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-home { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-file-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-time { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-road { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-download-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-download { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-upload { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-inbox { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-play-circle { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-repeat { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-rotate-right { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-refresh { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-list-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-lock { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-flag { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-headphones { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-volume-off { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-volume-down { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-volume-up { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-qrcode { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-barcode { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-tag { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-tags { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-book { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-bookmark { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-print { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-camera { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-font { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-bold { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-italic { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-text-height { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-text-width { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-align-left { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-align-center { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-align-right { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-align-justify { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-list { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-indent-left { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-indent-right { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-facetime-video { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-picture { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-pencil { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-map-marker { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-adjust { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-tint { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-edit { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-share { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-check { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-move { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-step-backward { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-fast-backward { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-backward { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-play { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-pause { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-stop { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-forward { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-fast-forward { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-step-forward { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-eject { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-chevron-left { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-chevron-right { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-plus-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-minus-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-remove-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-ok-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-question-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-info-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-screenshot { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-remove-circle { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-ok-circle { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-ban-circle { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-arrow-left { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-arrow-right { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-arrow-up { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-arrow-down { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-share-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-mail-forward { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-resize-full { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-resize-small { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-minus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-asterisk { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-exclamation-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-gift { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-leaf { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-fire { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-eye-open { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-eye-close { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-warning-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-plane { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-calendar { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-random { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-comment { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-magnet { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-chevron-up { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-chevron-down { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-retweet { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-shopping-cart { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-folder-close { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-folder-open { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-resize-vertical { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-resize-horizontal { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-bar-chart { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-twitter-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-facebook-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-camera-retro { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-key { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-cogs { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-gears { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-comments { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-thumbs-up-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-thumbs-down-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-star-half { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-heart-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-signout { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-linkedin-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-pushpin { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-external-link { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-signin { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-trophy { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-github-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-upload-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-lemon { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-phone { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-check-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-unchecked { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-bookmark-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-phone-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-twitter { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-facebook { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-github { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-unlock { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-credit-card { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-rss { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-hdd { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-bullhorn { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-bell { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-certificate { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-hand-right { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-hand-left { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-hand-up { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-hand-down { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-circle-arrow-left { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-circle-arrow-right { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-circle-arrow-up { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-circle-arrow-down { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-globe { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-wrench { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-tasks { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-filter { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-briefcase { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-fullscreen { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-group { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-link { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-cloud { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-beaker { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-cut { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-copy { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-paper-clip { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-paperclip { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-save { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-sign-blank { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-reorder { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-list-ul { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-list-ol { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-strikethrough { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-underline { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-table { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-magic { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-truck { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-pinterest { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-pinterest-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-google-plus-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-google-plus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-money { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-caret-down { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-caret-up { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-caret-left { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-caret-right { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-columns { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-sort { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-sort-down { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-sort-up { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-envelope { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-linkedin { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-undo { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-rotate-left { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-legal { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-dashboard { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-comment-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-comments-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-bolt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-sitemap { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-umbrella { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-paste { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-lightbulb { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-exchange { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-cloud-download { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-cloud-upload { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-user-md { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-stethoscope { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-suitcase { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-bell-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-coffee { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-food { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-file-text-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-building { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-hospital { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-ambulance { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-medkit { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-fighter-jet { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-beer { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-h-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-plus-sign-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-double-angle-left { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-double-angle-right { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-double-angle-up { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-double-angle-down { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-angle-left { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-angle-right { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-angle-up { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-angle-down { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-desktop { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-laptop { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-tablet { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-mobile-phone { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-circle-blank { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-quote-left { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-quote-right { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-spinner { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-circle { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-reply { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-mail-reply { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-github-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-folder-close-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-folder-open-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-expand-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-collapse-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-smile { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-frown { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-meh { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-gamepad { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-keyboard { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-flag-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-flag-checkered { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-terminal { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-code { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-reply-all { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-mail-reply-all { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-star-half-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-star-half-full { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-location-arrow { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-crop { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-code-fork { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-unlink { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-question { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-info { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-exclamation { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-superscript { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-subscript { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-eraser { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-puzzle-piece { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-microphone { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-microphone-off { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-shield { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-calendar-empty { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-fire-extinguisher { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-rocket { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-maxcdn { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-chevron-sign-left { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-chevron-sign-right { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-chevron-sign-up { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-chevron-sign-down { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-html5 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-css3 { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-anchor { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-unlock-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-bullseye { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-ellipsis-horizontal { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-ellipsis-vertical { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-rss-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-play-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-ticket { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-minus-sign-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-check-minus { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-level-up { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-level-down { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-check-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-edit-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-external-link-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-share-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-compass { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-collapse { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-collapse-top { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-expand { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-eur { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-euro { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-gbp { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-usd { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-dollar { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-inr { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-rupee { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-jpy { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-yen { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-cny { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-renminbi { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-krw { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-won { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-btc { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-bitcoin { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-file { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-file-text { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-sort-by-alphabet { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-sort-by-alphabet-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-sort-by-attributes { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-sort-by-attributes-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-sort-by-order { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-sort-by-order-alt { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-thumbs-up { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-thumbs-down { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-youtube-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-youtube { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-xing { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-xing-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-youtube-play { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-dropbox { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-stackexchange { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-instagram { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-flickr { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-adn { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-bitbucket { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-bitbucket-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-tumblr { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-tumblr-sign { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-long-arrow-down { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-long-arrow-up { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-long-arrow-left { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-long-arrow-right { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-apple { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-windows { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-android { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-linux { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-dribbble { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-skype { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-foursquare { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-trello { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-female { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-male { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-gittip { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-sun { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-moon { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-archive { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-bug { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-vk { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-weibo { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } .icon-renren { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ''); } ================================================ FILE: modules/agent/public/css/font-awesome/css/archive/font-awesome.css ================================================ /*! * Font Awesome 3.2.1 * the iconic font designed for Bootstrap * ------------------------------------------------------------------------------ * The full suite of pictographic icons, examples, and documentation can be * found at http://fontawesome.io. Stay up to date on Twitter at * http://twitter.com/fontawesome. * * License * ------------------------------------------------------------------------------ * - The Font Awesome font is licensed under SIL OFL 1.1 - * http://scripts.sil.org/OFL * - Font Awesome CSS, LESS, and SASS files are licensed under MIT License - * http://opensource.org/licenses/mit-license.html * - Font Awesome documentation licensed under CC BY 3.0 - * http://creativecommons.org/licenses/by/3.0/ * - Attribution is no longer required in Font Awesome 3.0, but much appreciated: * "Font Awesome by Dave Gandy - http://fontawesome.io" * * Author - Dave Gandy * ------------------------------------------------------------------------------ * Email: dave@fontawesome.io * Twitter: http://twitter.com/davegandy * Work: Lead Product Designer @ Kyruus - http://kyruus.com */ /* FONT PATH * -------------------------- */ @font-face { font-family: 'FontAwesome'; src: url('../font/fontawesome-webfont.eot?v=3.2.1'); src: url('../font/fontawesome-webfont.eot?#iefix&v=3.2.1') format('embedded-opentype'), url('../font/fontawesome-webfont.woff?v=3.2.1') format('woff'), url('../font/fontawesome-webfont.ttf?v=3.2.1') format('truetype'), url('../font/fontawesome-webfont.svg#fontawesomeregular?v=3.2.1') format('svg'); font-weight: normal; font-style: normal; } /* FONT AWESOME CORE * -------------------------- */ [class^="icon-"], [class*=" icon-"] { font-family: FontAwesome; font-weight: normal; font-style: normal; text-decoration: inherit; -webkit-font-smoothing: antialiased; *margin-right: .3em; } [class^="icon-"]:before, [class*=" icon-"]:before { text-decoration: inherit; display: inline-block; speak: none; } /* makes the font 33% larger relative to the icon container */ .icon-large:before { vertical-align: -10%; font-size: 1.3333333333333333em; } /* makes sure icons active on rollover in links */ a [class^="icon-"], a [class*=" icon-"] { display: inline; } /* increased font size for icon-large */ [class^="icon-"].icon-fixed-width, [class*=" icon-"].icon-fixed-width { display: inline-block; width: 1.1428571428571428em; text-align: right; padding-right: 0.2857142857142857em; } [class^="icon-"].icon-fixed-width.icon-large, [class*=" icon-"].icon-fixed-width.icon-large { width: 1.4285714285714286em; } .icons-ul { margin-left: 2.142857142857143em; list-style-type: none; } .icons-ul > li { position: relative; } .icons-ul .icon-li { position: absolute; left: -2.142857142857143em; width: 2.142857142857143em; text-align: center; line-height: inherit; } [class^="icon-"].hide, [class*=" icon-"].hide { display: none; } .icon-muted { color: #eeeeee; } .icon-light { color: #ffffff; } .icon-dark { color: #333333; } .icon-border { border: solid 1px #eeeeee; padding: .2em .25em .15em; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; } .icon-2x { font-size: 2em; } .icon-2x.icon-border { border-width: 2px; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; } .icon-3x { font-size: 3em; } .icon-3x.icon-border { border-width: 3px; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; } .icon-4x { font-size: 4em; } .icon-4x.icon-border { border-width: 4px; -webkit-border-radius: 6px; -moz-border-radius: 6px; border-radius: 6px; } .icon-5x { font-size: 5em; } .icon-5x.icon-border { border-width: 5px; -webkit-border-radius: 7px; -moz-border-radius: 7px; border-radius: 7px; } .pull-right { float: right; } .pull-left { float: left; } [class^="icon-"].pull-left, [class*=" icon-"].pull-left { margin-right: .3em; } [class^="icon-"].pull-right, [class*=" icon-"].pull-right { margin-left: .3em; } /* BOOTSTRAP SPECIFIC CLASSES * -------------------------- */ /* Bootstrap 2.0 sprites.less reset */ [class^="icon-"], [class*=" icon-"] { display: inline; width: auto; height: auto; line-height: normal; vertical-align: baseline; background-image: none; background-position: 0% 0%; background-repeat: repeat; margin-top: 0; } /* more sprites.less reset */ .icon-white, .nav-pills > .active > a > [class^="icon-"], .nav-pills > .active > a > [class*=" icon-"], .nav-list > .active > a > [class^="icon-"], .nav-list > .active > a > [class*=" icon-"], .navbar-inverse .nav > .active > a > [class^="icon-"], .navbar-inverse .nav > .active > a > [class*=" icon-"], .dropdown-menu > li > a:hover > [class^="icon-"], .dropdown-menu > li > a:hover > [class*=" icon-"], .dropdown-menu > .active > a > [class^="icon-"], .dropdown-menu > .active > a > [class*=" icon-"], .dropdown-submenu:hover > a > [class^="icon-"], .dropdown-submenu:hover > a > [class*=" icon-"] { background-image: none; } /* keeps Bootstrap styles with and without icons the same */ .btn [class^="icon-"].icon-large, .nav [class^="icon-"].icon-large, .btn [class*=" icon-"].icon-large, .nav [class*=" icon-"].icon-large { line-height: .9em; } .btn [class^="icon-"].icon-spin, .nav [class^="icon-"].icon-spin, .btn [class*=" icon-"].icon-spin, .nav [class*=" icon-"].icon-spin { display: inline-block; } .nav-tabs [class^="icon-"], .nav-pills [class^="icon-"], .nav-tabs [class*=" icon-"], .nav-pills [class*=" icon-"], .nav-tabs [class^="icon-"].icon-large, .nav-pills [class^="icon-"].icon-large, .nav-tabs [class*=" icon-"].icon-large, .nav-pills [class*=" icon-"].icon-large { line-height: .9em; } .btn [class^="icon-"].pull-left.icon-2x, .btn [class*=" icon-"].pull-left.icon-2x, .btn [class^="icon-"].pull-right.icon-2x, .btn [class*=" icon-"].pull-right.icon-2x { margin-top: .18em; } .btn [class^="icon-"].icon-spin.icon-large, .btn [class*=" icon-"].icon-spin.icon-large { line-height: .8em; } .btn.btn-small [class^="icon-"].pull-left.icon-2x, .btn.btn-small [class*=" icon-"].pull-left.icon-2x, .btn.btn-small [class^="icon-"].pull-right.icon-2x, .btn.btn-small [class*=" icon-"].pull-right.icon-2x { margin-top: .25em; } .btn.btn-large [class^="icon-"], .btn.btn-large [class*=" icon-"] { margin-top: 0; } .btn.btn-large [class^="icon-"].pull-left.icon-2x, .btn.btn-large [class*=" icon-"].pull-left.icon-2x, .btn.btn-large [class^="icon-"].pull-right.icon-2x, .btn.btn-large [class*=" icon-"].pull-right.icon-2x { margin-top: .05em; } .btn.btn-large [class^="icon-"].pull-left.icon-2x, .btn.btn-large [class*=" icon-"].pull-left.icon-2x { margin-right: .2em; } .btn.btn-large [class^="icon-"].pull-right.icon-2x, .btn.btn-large [class*=" icon-"].pull-right.icon-2x { margin-left: .2em; } /* Fixes alignment in nav lists */ .nav-list [class^="icon-"], .nav-list [class*=" icon-"] { line-height: inherit; } /* EXTRAS * -------------------------- */ /* Stacked and layered icon */ .icon-stack { position: relative; display: inline-block; width: 2em; height: 2em; line-height: 2em; vertical-align: -35%; } .icon-stack [class^="icon-"], .icon-stack [class*=" icon-"] { display: block; text-align: center; position: absolute; width: 100%; height: 100%; font-size: 1em; line-height: inherit; *line-height: 2em; } .icon-stack .icon-stack-base { font-size: 2em; *line-height: 1em; } /* Animated rotating icon */ .icon-spin { display: inline-block; -moz-animation: spin 2s infinite linear; -o-animation: spin 2s infinite linear; -webkit-animation: spin 2s infinite linear; animation: spin 2s infinite linear; } /* Prevent stack and spinners from being taken inline when inside a link */ a .icon-stack, a .icon-spin { display: inline-block; text-decoration: none; } @-moz-keyframes spin { 0% { -moz-transform: rotate(0deg); } 100% { -moz-transform: rotate(359deg); } } @-webkit-keyframes spin { 0% { -webkit-transform: rotate(0deg); } 100% { -webkit-transform: rotate(359deg); } } @-o-keyframes spin { 0% { -o-transform: rotate(0deg); } 100% { -o-transform: rotate(359deg); } } @-ms-keyframes spin { 0% { -ms-transform: rotate(0deg); } 100% { -ms-transform: rotate(359deg); } } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(359deg); } } /* Icon rotations and mirroring */ .icon-rotate-90:before { -webkit-transform: rotate(90deg); -moz-transform: rotate(90deg); -ms-transform: rotate(90deg); -o-transform: rotate(90deg); transform: rotate(90deg); filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); } .icon-rotate-180:before { -webkit-transform: rotate(180deg); -moz-transform: rotate(180deg); -ms-transform: rotate(180deg); -o-transform: rotate(180deg); transform: rotate(180deg); filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); } .icon-rotate-270:before { -webkit-transform: rotate(270deg); -moz-transform: rotate(270deg); -ms-transform: rotate(270deg); -o-transform: rotate(270deg); transform: rotate(270deg); filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); } .icon-flip-horizontal:before { -webkit-transform: scale(-1, 1); -moz-transform: scale(-1, 1); -ms-transform: scale(-1, 1); -o-transform: scale(-1, 1); transform: scale(-1, 1); } .icon-flip-vertical:before { -webkit-transform: scale(1, -1); -moz-transform: scale(1, -1); -ms-transform: scale(1, -1); -o-transform: scale(1, -1); transform: scale(1, -1); } /* ensure rotation occurs inside anchor tags */ a .icon-rotate-90:before, a .icon-rotate-180:before, a .icon-rotate-270:before, a .icon-flip-horizontal:before, a .icon-flip-vertical:before { display: inline-block; } /* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen readers do not read off random characters that represent icons */ .icon-glass:before { content: "\f000"; } .icon-music:before { content: "\f001"; } .icon-search:before { content: "\f002"; } .icon-envelope-alt:before { content: "\f003"; } .icon-heart:before { content: "\f004"; } .icon-star:before { content: "\f005"; } .icon-star-empty:before { content: "\f006"; } .icon-user:before { content: "\f007"; } .icon-film:before { content: "\f008"; } .icon-th-large:before { content: "\f009"; } .icon-th:before { content: "\f00a"; } .icon-th-list:before { content: "\f00b"; } .icon-ok:before { content: "\f00c"; } .icon-remove:before { content: "\f00d"; } .icon-zoom-in:before { content: "\f00e"; } .icon-zoom-out:before { content: "\f010"; } .icon-power-off:before, .icon-off:before { content: "\f011"; } .icon-signal:before { content: "\f012"; } .icon-gear:before, .icon-cog:before { content: "\f013"; } .icon-trash:before { content: "\f014"; } .icon-home:before { content: "\f015"; } .icon-file-alt:before { content: "\f016"; } .icon-time:before { content: "\f017"; } .icon-road:before { content: "\f018"; } .icon-download-alt:before { content: "\f019"; } .icon-download:before { content: "\f01a"; } .icon-upload:before { content: "\f01b"; } .icon-inbox:before { content: "\f01c"; } .icon-play-circle:before { content: "\f01d"; } .icon-rotate-right:before, .icon-repeat:before { content: "\f01e"; } .icon-refresh:before { content: "\f021"; } .icon-list-alt:before { content: "\f022"; } .icon-lock:before { content: "\f023"; } .icon-flag:before { content: "\f024"; } .icon-headphones:before { content: "\f025"; } .icon-volume-off:before { content: "\f026"; } .icon-volume-down:before { content: "\f027"; } .icon-volume-up:before { content: "\f028"; } .icon-qrcode:before { content: "\f029"; } .icon-barcode:before { content: "\f02a"; } .icon-tag:before { content: "\f02b"; } .icon-tags:before { content: "\f02c"; } .icon-book:before { content: "\f02d"; } .icon-bookmark:before { content: "\f02e"; } .icon-print:before { content: "\f02f"; } .icon-camera:before { content: "\f030"; } .icon-font:before { content: "\f031"; } .icon-bold:before { content: "\f032"; } .icon-italic:before { content: "\f033"; } .icon-text-height:before { content: "\f034"; } .icon-text-width:before { content: "\f035"; } .icon-align-left:before { content: "\f036"; } .icon-align-center:before { content: "\f037"; } .icon-align-right:before { content: "\f038"; } .icon-align-justify:before { content: "\f039"; } .icon-list:before { content: "\f03a"; } .icon-indent-left:before { content: "\f03b"; } .icon-indent-right:before { content: "\f03c"; } .icon-facetime-video:before { content: "\f03d"; } .icon-picture:before { content: "\f03e"; } .icon-pencil:before { content: "\f040"; } .icon-map-marker:before { content: "\f041"; } .icon-adjust:before { content: "\f042"; } .icon-tint:before { content: "\f043"; } .icon-edit:before { content: "\f044"; } .icon-share:before { content: "\f045"; } .icon-check:before { content: "\f046"; } .icon-move:before { content: "\f047"; } .icon-step-backward:before { content: "\f048"; } .icon-fast-backward:before { content: "\f049"; } .icon-backward:before { content: "\f04a"; } .icon-play:before { content: "\f04b"; } .icon-pause:before { content: "\f04c"; } .icon-stop:before { content: "\f04d"; } .icon-forward:before { content: "\f04e"; } .icon-fast-forward:before { content: "\f050"; } .icon-step-forward:before { content: "\f051"; } .icon-eject:before { content: "\f052"; } .icon-chevron-left:before { content: "\f053"; } .icon-chevron-right:before { content: "\f054"; } .icon-plus-sign:before { content: "\f055"; } .icon-minus-sign:before { content: "\f056"; } .icon-remove-sign:before { content: "\f057"; } .icon-ok-sign:before { content: "\f058"; } .icon-question-sign:before { content: "\f059"; } .icon-info-sign:before { content: "\f05a"; } .icon-screenshot:before { content: "\f05b"; } .icon-remove-circle:before { content: "\f05c"; } .icon-ok-circle:before { content: "\f05d"; } .icon-ban-circle:before { content: "\f05e"; } .icon-arrow-left:before { content: "\f060"; } .icon-arrow-right:before { content: "\f061"; } .icon-arrow-up:before { content: "\f062"; } .icon-arrow-down:before { content: "\f063"; } .icon-mail-forward:before, .icon-share-alt:before { content: "\f064"; } .icon-resize-full:before { content: "\f065"; } .icon-resize-small:before { content: "\f066"; } .icon-plus:before { content: "\f067"; } .icon-minus:before { content: "\f068"; } .icon-asterisk:before { content: "\f069"; } .icon-exclamation-sign:before { content: "\f06a"; } .icon-gift:before { content: "\f06b"; } .icon-leaf:before { content: "\f06c"; } .icon-fire:before { content: "\f06d"; } .icon-eye-open:before { content: "\f06e"; } .icon-eye-close:before { content: "\f070"; } .icon-warning-sign:before { content: "\f071"; } .icon-plane:before { content: "\f072"; } .icon-calendar:before { content: "\f073"; } .icon-random:before { content: "\f074"; } .icon-comment:before { content: "\f075"; } .icon-magnet:before { content: "\f076"; } .icon-chevron-up:before { content: "\f077"; } .icon-chevron-down:before { content: "\f078"; } .icon-retweet:before { content: "\f079"; } .icon-shopping-cart:before { content: "\f07a"; } .icon-folder-close:before { content: "\f07b"; } .icon-folder-open:before { content: "\f07c"; } .icon-resize-vertical:before { content: "\f07d"; } .icon-resize-horizontal:before { content: "\f07e"; } .icon-bar-chart:before { content: "\f080"; } .icon-twitter-sign:before { content: "\f081"; } .icon-facebook-sign:before { content: "\f082"; } .icon-camera-retro:before { content: "\f083"; } .icon-key:before { content: "\f084"; } .icon-gears:before, .icon-cogs:before { content: "\f085"; } .icon-comments:before { content: "\f086"; } .icon-thumbs-up-alt:before { content: "\f087"; } .icon-thumbs-down-alt:before { content: "\f088"; } .icon-star-half:before { content: "\f089"; } .icon-heart-empty:before { content: "\f08a"; } .icon-signout:before { content: "\f08b"; } .icon-linkedin-sign:before { content: "\f08c"; } .icon-pushpin:before { content: "\f08d"; } .icon-external-link:before { content: "\f08e"; } .icon-signin:before { content: "\f090"; } .icon-trophy:before { content: "\f091"; } .icon-github-sign:before { content: "\f092"; } .icon-upload-alt:before { content: "\f093"; } .icon-lemon:before { content: "\f094"; } .icon-phone:before { content: "\f095"; } .icon-unchecked:before, .icon-check-empty:before { content: "\f096"; } .icon-bookmark-empty:before { content: "\f097"; } .icon-phone-sign:before { content: "\f098"; } .icon-twitter:before { content: "\f099"; } .icon-facebook:before { content: "\f09a"; } .icon-github:before { content: "\f09b"; } .icon-unlock:before { content: "\f09c"; } .icon-credit-card:before { content: "\f09d"; } .icon-rss:before { content: "\f09e"; } .icon-hdd:before { content: "\f0a0"; } .icon-bullhorn:before { content: "\f0a1"; } .icon-bell:before { content: "\f0a2"; } .icon-certificate:before { content: "\f0a3"; } .icon-hand-right:before { content: "\f0a4"; } .icon-hand-left:before { content: "\f0a5"; } .icon-hand-up:before { content: "\f0a6"; } .icon-hand-down:before { content: "\f0a7"; } .icon-circle-arrow-left:before { content: "\f0a8"; } .icon-circle-arrow-right:before { content: "\f0a9"; } .icon-circle-arrow-up:before { content: "\f0aa"; } .icon-circle-arrow-down:before { content: "\f0ab"; } .icon-globe:before { content: "\f0ac"; } .icon-wrench:before { content: "\f0ad"; } .icon-tasks:before { content: "\f0ae"; } .icon-filter:before { content: "\f0b0"; } .icon-briefcase:before { content: "\f0b1"; } .icon-fullscreen:before { content: "\f0b2"; } .icon-group:before { content: "\f0c0"; } .icon-link:before { content: "\f0c1"; } .icon-cloud:before { content: "\f0c2"; } .icon-beaker:before { content: "\f0c3"; } .icon-cut:before { content: "\f0c4"; } .icon-copy:before { content: "\f0c5"; } .icon-paperclip:before, .icon-paper-clip:before { content: "\f0c6"; } .icon-save:before { content: "\f0c7"; } .icon-sign-blank:before { content: "\f0c8"; } .icon-reorder:before { content: "\f0c9"; } .icon-list-ul:before { content: "\f0ca"; } .icon-list-ol:before { content: "\f0cb"; } .icon-strikethrough:before { content: "\f0cc"; } .icon-underline:before { content: "\f0cd"; } .icon-table:before { content: "\f0ce"; } .icon-magic:before { content: "\f0d0"; } .icon-truck:before { content: "\f0d1"; } .icon-pinterest:before { content: "\f0d2"; } .icon-pinterest-sign:before { content: "\f0d3"; } .icon-google-plus-sign:before { content: "\f0d4"; } .icon-google-plus:before { content: "\f0d5"; } .icon-money:before { content: "\f0d6"; } .icon-caret-down:before { content: "\f0d7"; } .icon-caret-up:before { content: "\f0d8"; } .icon-caret-left:before { content: "\f0d9"; } .icon-caret-right:before { content: "\f0da"; } .icon-columns:before { content: "\f0db"; } .icon-sort:before { content: "\f0dc"; } .icon-sort-down:before { content: "\f0dd"; } .icon-sort-up:before { content: "\f0de"; } .icon-envelope:before { content: "\f0e0"; } .icon-linkedin:before { content: "\f0e1"; } .icon-rotate-left:before, .icon-undo:before { content: "\f0e2"; } .icon-legal:before { content: "\f0e3"; } .icon-dashboard:before { content: "\f0e4"; } .icon-comment-alt:before { content: "\f0e5"; } .icon-comments-alt:before { content: "\f0e6"; } .icon-bolt:before { content: "\f0e7"; } .icon-sitemap:before { content: "\f0e8"; } .icon-umbrella:before { content: "\f0e9"; } .icon-paste:before { content: "\f0ea"; } .icon-lightbulb:before { content: "\f0eb"; } .icon-exchange:before { content: "\f0ec"; } .icon-cloud-download:before { content: "\f0ed"; } .icon-cloud-upload:before { content: "\f0ee"; } .icon-user-md:before { content: "\f0f0"; } .icon-stethoscope:before { content: "\f0f1"; } .icon-suitcase:before { content: "\f0f2"; } .icon-bell-alt:before { content: "\f0f3"; } .icon-coffee:before { content: "\f0f4"; } .icon-food:before { content: "\f0f5"; } .icon-file-text-alt:before { content: "\f0f6"; } .icon-building:before { content: "\f0f7"; } .icon-hospital:before { content: "\f0f8"; } .icon-ambulance:before { content: "\f0f9"; } .icon-medkit:before { content: "\f0fa"; } .icon-fighter-jet:before { content: "\f0fb"; } .icon-beer:before { content: "\f0fc"; } .icon-h-sign:before { content: "\f0fd"; } .icon-plus-sign-alt:before { content: "\f0fe"; } .icon-double-angle-left:before { content: "\f100"; } .icon-double-angle-right:before { content: "\f101"; } .icon-double-angle-up:before { content: "\f102"; } .icon-double-angle-down:before { content: "\f103"; } .icon-angle-left:before { content: "\f104"; } .icon-angle-right:before { content: "\f105"; } .icon-angle-up:before { content: "\f106"; } .icon-angle-down:before { content: "\f107"; } .icon-desktop:before { content: "\f108"; } .icon-laptop:before { content: "\f109"; } .icon-tablet:before { content: "\f10a"; } .icon-mobile-phone:before { content: "\f10b"; } .icon-circle-blank:before { content: "\f10c"; } .icon-quote-left:before { content: "\f10d"; } .icon-quote-right:before { content: "\f10e"; } .icon-spinner:before { content: "\f110"; } .icon-circle:before { content: "\f111"; } .icon-mail-reply:before, .icon-reply:before { content: "\f112"; } .icon-github-alt:before { content: "\f113"; } .icon-folder-close-alt:before { content: "\f114"; } .icon-folder-open-alt:before { content: "\f115"; } .icon-expand-alt:before { content: "\f116"; } .icon-collapse-alt:before { content: "\f117"; } .icon-smile:before { content: "\f118"; } .icon-frown:before { content: "\f119"; } .icon-meh:before { content: "\f11a"; } .icon-gamepad:before { content: "\f11b"; } .icon-keyboard:before { content: "\f11c"; } .icon-flag-alt:before { content: "\f11d"; } .icon-flag-checkered:before { content: "\f11e"; } .icon-terminal:before { content: "\f120"; } .icon-code:before { content: "\f121"; } .icon-reply-all:before { content: "\f122"; } .icon-mail-reply-all:before { content: "\f122"; } .icon-star-half-full:before, .icon-star-half-empty:before { content: "\f123"; } .icon-location-arrow:before { content: "\f124"; } .icon-crop:before { content: "\f125"; } .icon-code-fork:before { content: "\f126"; } .icon-unlink:before { content: "\f127"; } .icon-question:before { content: "\f128"; } .icon-info:before { content: "\f129"; } .icon-exclamation:before { content: "\f12a"; } .icon-superscript:before { content: "\f12b"; } .icon-subscript:before { content: "\f12c"; } .icon-eraser:before { content: "\f12d"; } .icon-puzzle-piece:before { content: "\f12e"; } .icon-microphone:before { content: "\f130"; } .icon-microphone-off:before { content: "\f131"; } .icon-shield:before { content: "\f132"; } .icon-calendar-empty:before { content: "\f133"; } .icon-fire-extinguisher:before { content: "\f134"; } .icon-rocket:before { content: "\f135"; } .icon-maxcdn:before { content: "\f136"; } .icon-chevron-sign-left:before { content: "\f137"; } .icon-chevron-sign-right:before { content: "\f138"; } .icon-chevron-sign-up:before { content: "\f139"; } .icon-chevron-sign-down:before { content: "\f13a"; } .icon-html5:before { content: "\f13b"; } .icon-css3:before { content: "\f13c"; } .icon-anchor:before { content: "\f13d"; } .icon-unlock-alt:before { content: "\f13e"; } .icon-bullseye:before { content: "\f140"; } .icon-ellipsis-horizontal:before { content: "\f141"; } .icon-ellipsis-vertical:before { content: "\f142"; } .icon-rss-sign:before { content: "\f143"; } .icon-play-sign:before { content: "\f144"; } .icon-ticket:before { content: "\f145"; } .icon-minus-sign-alt:before { content: "\f146"; } .icon-check-minus:before { content: "\f147"; } .icon-level-up:before { content: "\f148"; } .icon-level-down:before { content: "\f149"; } .icon-check-sign:before { content: "\f14a"; } .icon-edit-sign:before { content: "\f14b"; } .icon-external-link-sign:before { content: "\f14c"; } .icon-share-sign:before { content: "\f14d"; } .icon-compass:before { content: "\f14e"; } .icon-collapse:before { content: "\f150"; } .icon-collapse-top:before { content: "\f151"; } .icon-expand:before { content: "\f152"; } .icon-euro:before, .icon-eur:before { content: "\f153"; } .icon-gbp:before { content: "\f154"; } .icon-dollar:before, .icon-usd:before { content: "\f155"; } .icon-rupee:before, .icon-inr:before { content: "\f156"; } .icon-yen:before, .icon-jpy:before { content: "\f157"; } .icon-renminbi:before, .icon-cny:before { content: "\f158"; } .icon-won:before, .icon-krw:before { content: "\f159"; } .icon-bitcoin:before, .icon-btc:before { content: "\f15a"; } .icon-file:before { content: "\f15b"; } .icon-file-text:before { content: "\f15c"; } .icon-sort-by-alphabet:before { content: "\f15d"; } .icon-sort-by-alphabet-alt:before { content: "\f15e"; } .icon-sort-by-attributes:before { content: "\f160"; } .icon-sort-by-attributes-alt:before { content: "\f161"; } .icon-sort-by-order:before { content: "\f162"; } .icon-sort-by-order-alt:before { content: "\f163"; } .icon-thumbs-up:before { content: "\f164"; } .icon-thumbs-down:before { content: "\f165"; } .icon-youtube-sign:before { content: "\f166"; } .icon-youtube:before { content: "\f167"; } .icon-xing:before { content: "\f168"; } .icon-xing-sign:before { content: "\f169"; } .icon-youtube-play:before { content: "\f16a"; } .icon-dropbox:before { content: "\f16b"; } .icon-stackexchange:before { content: "\f16c"; } .icon-instagram:before { content: "\f16d"; } .icon-flickr:before { content: "\f16e"; } .icon-adn:before { content: "\f170"; } .icon-bitbucket:before { content: "\f171"; } .icon-bitbucket-sign:before { content: "\f172"; } .icon-tumblr:before { content: "\f173"; } .icon-tumblr-sign:before { content: "\f174"; } .icon-long-arrow-down:before { content: "\f175"; } .icon-long-arrow-up:before { content: "\f176"; } .icon-long-arrow-left:before { content: "\f177"; } .icon-long-arrow-right:before { content: "\f178"; } .icon-apple:before { content: "\f179"; } .icon-windows:before { content: "\f17a"; } .icon-android:before { content: "\f17b"; } .icon-linux:before { content: "\f17c"; } .icon-dribbble:before { content: "\f17d"; } .icon-skype:before { content: "\f17e"; } .icon-foursquare:before { content: "\f180"; } .icon-trello:before { content: "\f181"; } .icon-female:before { content: "\f182"; } .icon-male:before { content: "\f183"; } .icon-gittip:before { content: "\f184"; } .icon-sun:before { content: "\f185"; } .icon-moon:before { content: "\f186"; } .icon-archive:before { content: "\f187"; } .icon-bug:before { content: "\f188"; } .icon-vk:before { content: "\f189"; } .icon-weibo:before { content: "\f18a"; } .icon-renren:before { content: "\f18b"; } ================================================ FILE: modules/agent/public/css/g.css ================================================ *{ font:11pt Verdana,Arial,Microsoft YaHei,sans-serif; color:#111; word-wrap:break-word;} th {font-weight: bold;} h3.tit {font-weight: bold; border-left: 3px solid #FF8000; padding-left: 5px;} .mt0{ margin-top:0px!important;} .mt5{ margin-top:5px!important;} .mt10{ margin-top:10px!important;} .m10{ margin:10px!important;} .mt15{ margin-top:15px!important;} .mt20{ margin-top:20px!important;} .mb0{ margin-bottom:0px!important;} .mb5{ margin-bottom:5px!important;} .mb10{ margin-bottom:10px!important;} .mb15{ margin-bottom:15px!important;} .mb20{ margin-bottom:20px!important;} /*float*/ .fl{ float:left!important;} .fr{ float:right!important;} .fn{ float:none!important;} .pagination{display:inline-block;padding-left:0;margin:18px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.428571429;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{background-color:#eee}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;cursor:default;background-color:#428bca;border-color:#428bca}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:17px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px} hr { height: 0; -moz-box-sizing: content-box; box-sizing: content-box; margin-top: 20px; margin-bottom: 20px; border: 0; border-top: 1px solid #eee; } ================================================ FILE: modules/agent/public/css/odometer.css ================================================ .odometer.odometer-auto-theme, .odometer.odometer-theme-default { display: -moz-inline-box; -moz-box-orient: vertical; display: inline-block; vertical-align: middle; *vertical-align: auto; position: relative; } .odometer.odometer-auto-theme, .odometer.odometer-theme-default { *display: inline; } .odometer.odometer-auto-theme .odometer-digit, .odometer.odometer-theme-default .odometer-digit { display: -moz-inline-box; -moz-box-orient: vertical; display: inline-block; vertical-align: middle; *vertical-align: auto; position: relative; } .odometer.odometer-auto-theme .odometer-digit, .odometer.odometer-theme-default .odometer-digit { *display: inline; } .odometer.odometer-auto-theme .odometer-digit .odometer-digit-spacer, .odometer.odometer-theme-default .odometer-digit .odometer-digit-spacer { display: -moz-inline-box; -moz-box-orient: vertical; display: inline-block; vertical-align: middle; *vertical-align: auto; visibility: hidden; } .odometer.odometer-auto-theme .odometer-digit .odometer-digit-spacer, .odometer.odometer-theme-default .odometer-digit .odometer-digit-spacer { *display: inline; } .odometer.odometer-auto-theme .odometer-digit .odometer-digit-inner, .odometer.odometer-theme-default .odometer-digit .odometer-digit-inner { text-align: left; display: block; position: absolute; top: 0; left: 0; right: 0; bottom: 0; overflow: hidden; } .odometer.odometer-auto-theme .odometer-digit .odometer-ribbon, .odometer.odometer-theme-default .odometer-digit .odometer-ribbon { display: block; } .odometer.odometer-auto-theme .odometer-digit .odometer-ribbon-inner, .odometer.odometer-theme-default .odometer-digit .odometer-ribbon-inner { display: block; } .odometer.odometer-auto-theme .odometer-digit .odometer-value, .odometer.odometer-theme-default .odometer-digit .odometer-value { display: block; } .odometer.odometer-auto-theme .odometer-digit .odometer-value.odometer-last-value, .odometer.odometer-theme-default .odometer-digit .odometer-value.odometer-last-value { position: absolute; } .odometer.odometer-auto-theme.odometer-animating-up .odometer-ribbon-inner, .odometer.odometer-theme-default.odometer-animating-up .odometer-ribbon-inner { -webkit-transition: -webkit-transform 1s; -moz-transition: -moz-transform 1s; -ms-transition: -ms-transform 1s; -o-transition: -o-transform 1s; transition: transform 1s; } .odometer.odometer-auto-theme.odometer-animating-up.odometer-animating .odometer-ribbon-inner, .odometer.odometer-theme-default.odometer-animating-up.odometer-animating .odometer-ribbon-inner { -webkit-transform: translateY(-100%); -moz-transform: translateY(-100%); -ms-transform: translateY(-100%); -o-transform: translateY(-100%); transform: translateY(-100%); } .odometer.odometer-auto-theme.odometer-animating-down .odometer-ribbon-inner, .odometer.odometer-theme-default.odometer-animating-down .odometer-ribbon-inner { -webkit-transform: translateY(-100%); -moz-transform: translateY(-100%); -ms-transform: translateY(-100%); -o-transform: translateY(-100%); transform: translateY(-100%); } .odometer.odometer-auto-theme.odometer-animating-down.odometer-animating .odometer-ribbon-inner, .odometer.odometer-theme-default.odometer-animating-down.odometer-animating .odometer-ribbon-inner { -webkit-transition: -webkit-transform 1s; -moz-transition: -moz-transform 1s; -ms-transition: -ms-transform 1s; -o-transition: -o-transform 1s; -o-transition: -o-transform 1s; transition: transform 1s; -webkit-transform: translateY(0); -moz-transform: translateY(0); -ms-transform: translateY(0); -o-transform: translateY(0); transform: translateY(0); } .odometer.odometer-auto-theme, .odometer.odometer-theme-default { font-family: "Helvetica Neue", sans-serif; line-height: 1.1em; } ================================================ FILE: modules/agent/public/css/pages/dashboard.css ================================================ /*------------------------------------------------------------------ Bootstrap Admin Template by EGrappler.com ------------------------------------------------------------------*/ /*------------------------------------------------------------------ [1. Shortcuts / .shortcuts] */ .shortcuts { text-align: center; } .shortcuts .shortcut { width: 22.50%; display: inline-block; padding: 12px 0; margin: 0 .9% 1em; vertical-align: top; text-decoration: none; background: #f9f6f1; border-radius: 5px; } .shortcuts .shortcut .shortcut-icon { margin-top: .25em; margin-bottom: .25em; font-size: 32px; color: #545454; } .shortcuts .shortcut:hover { background: #00ba8b; } .shortcuts .shortcut:hover span{ color: #fff; } .shortcuts .shortcut:hover .shortcut-icon { color: #fff; } .shortcuts .shortcut-label { display: block; font-weight: 400; color: #545454; } /*------------------------------------------------------------------ [2. Stats / .stats] */ .stats { width: 100%; display: table; padding: 0 0 0 10px; margin-top: .5em; margin-bottom: 1.9em; } .stats .stat { display: table-cell; width: 40%; vertical-align: top; font-size: 11px; font-weight: bold; color: #999; } .stat-value { display: block; margin-bottom: .55em; font-size: 30px; font-weight: bold; letter-spacing: -2px; color: #444; } .stat-time { text-align: center; padding-top: 1.5em; } .stat-time .stat-value { color: #19bc9c; font-size: 40px; } .stats #donut-chart { height: 100px; margin-left: -20px; } /*------------------------------------------------------------------ [3. News Item / .news-items] */ .news-items { margin: 1em 0 0; } .news-items li { display: table; padding: 0 2em 0 1.5em; padding-bottom: 1em; margin-bottom: 1em; border-bottom: 1px dotted #CCC; } .news-items li:last-child { padding-bottom: 0; border: none; } .news-item-date { display: table-cell; } .news-item-detail { display: table-cell; } .news-item-title { font-size: 13px; font-weight: 600; } .news-item-date { width: 75px; vertical-align: middle; text-align: center; } .news-item-day { display: block; margin-bottom: .25em; font-size: 24px; color: #888; } .news-item-preview { margin-bottom: 0; color: #777; } .news-item-month { display: block; padding-right: 1px; font-size: 12px; font-weight: 600; color: #888; } /*------------------------------------------------------------------ [4. Action Table / .action-table] */ .action-table .btn-small { padding: 4px 5px 5px; font-size: 10px; } .action-table .td-actions { width: 80px; text-align: center; } .action-table .td-actions .btn { margin-right: .5em; } .action-table .td-actions .btn:last-child { margin-rigth: 0; } .big_stats { width: 100%; display: table; margin-top: 1.5em; } .big-stats-container .widget-content { border:0; } .big_stats .stat { width: 35%; height: auto; text-align: center; display: table-cell; padding: 0 0 1em; position: relative; border-right: 1px solid #CCC; border-left: 1px solid #FFF; } .big_stats i { font-size:20px; display:block; line-height: 30px; color:#b2afaa; } .big_stats .stat i { font: 20px/2em "Open Sans", sans-serif; color:#19bc9c; } h6.bigstats { margin: 20px; border-bottom: 1px solid #eee; padding-bottom: 20px; margin-bottom: 26px; } .big_stats .stat:first-child { border-left: none; width:33%; } .big_stats .stat:last-child { border-right: none; width:33%; } .big_stats .stat h4 { font-size: 11px; font-weight: bold; color: #777; margin-bottom: 1.5em; } .big_stats .stat .value { font-size: 20px; font-weight: bold; color: #545454; line-height: 1em; } @media all and (max-width: 950px) and (min-width: 1px) { .big_stats { display: block; margin-bottom: -10px; } .big_stats .stat { width: 32%; display: block; margin-bottom: 1em; float: left; } } @media (max-width: 767px) { .big_stats .stat .value { font-size: 25px; } } @media (max-width: 979px) { .shortcuts .shortcut { width: 31%; } } @media (max-width: 480px) { .stats .stat { margin-bottom: 3em; } .stats .stat .stat-value { margin-bottom: .15em; font-size: 20px; } .stats { float: left; display: block; margin-bottom: 0; } #chart-stats { margin: 2em 0 1em; } .shortcuts .shortcut { width: 48%; } } /* ADDED BY AFAQ */ .widget-content { padding:0px; } .dataTables_length { display:none; } .dataTable { margin-bottom:0px; } .pulse { background:#19bc9c; border:1px solid #19bc9c; color:white; } .pulse-border { border-color:#19bc9c; } .navbar { position:fixed; top:0; z-index:9999999; width:100%; } .subnavbar { position:fixed; top:50px; z-index:9999999; width:100%; } .main { margin-top:130px; } .dataTables_paginate{ width:100%; text-align:center; margin-top:10px; margin-left:-30px;} .dataTables_paginate a{ margin-left:8px;} .dataTables_paginate a:hover{ pointer:pointer;} .navbar-fixed-top{ margin-left:0px;} .widget-search{display: inline-block; vertical-align: middle; margin: 0 6px; width: 200px;} ================================================ FILE: modules/agent/public/css/style.css ================================================ /*------------------------------------------------------------------ Bootstrap Admin Template by EGrappler.com ------------------------------------------------------------------*/ /*------------------------------------------------------------------ [1. Global] */ @font-face { font-family: "Open Sans"; font-style: normal; font-weight: normal; src: url("font/OpenSans-Regular-webfont.eot") format("embedded-opentype"), url("font/OpenSans-Regular-webfont.woff") format("woff"), url("font/OpenSans-Regular-webfont.ttf") format("truetype"), url("font/OpenSans-Regular-webfont.svg#OpenSansRegular") format("svg"); } body { background: #f9f6f1; font: 12px/1.5em "Open Sans", sans-serif; } a { cursor: pointer; } input, button, select, textarea { font-family: 'Open Sans'; } .dropdown .dropdown-menu { -webkit-border-radius: 6px; -moz-border-radius: 6px; border-radius: 6px; } .btn-icon-only { padding-right: 3px; padding-left: 3px; } .table td { vertical-align: middle; } .table-bordered th { background: #E9E9E9; background:-moz-linear-gradient(top, #FAFAFA 0%, #E9E9E9 100%); /* FF3.6+ */ background:-webkit-gradient(linear, left top, left bottom, color-stop(0%,#FAFAFA), color-stop(100%,#E9E9E9)); /* Chrome,Safari4+ */ background:-webkit-linear-gradient(top, #FAFAFA 0%,#E9E9E9 100%); /* Chrome10+,Safari5.1+ */ background:-o-linear-gradient(top, #FAFAFA 0%,#E9E9E9 100%); /* Opera11.10+ */ background:-ms-linear-gradient(top, #FAFAFA 0%,#E9E9E9 100%); /* IE10+ */ background:linear-gradient(top, #FAFAFA 0%,#E9E9E9 100%); /* W3C */ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FAFAFA', endColorstr='#E9E9E9'); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#FAFAFA', endColorstr='#E9E9E9')"; font-size: 10px; color: #444; text-transform: uppercase; } /*------------------------------------------------------------------ [2. Navbar / .navbar] */ .navbar .container { position: relative; } .navbar-inner { padding: 7px 0; background: #00ba8b !important; -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; } .navbar-fixed-top { position: static; } .navbar .nav a { font-size: 11px; } .navbar .nav>li>a { color:#fff !important;} .navbar .brand { font-weight: 600; position: relative; top: 2px; } .navbar .search-query { background-color: #444; width: 150px; font-size: 11px; font-weight: bold; } .navbar .search-query::-webkit-input-placeholder { color: #666; } .navbar .search-query:-moz-placeholder { color: #666; } .navbar-search .search-query { background:#008866; border:0; color:#fff; line-height:normal;} /*------------------------------------------------------------------ [3. Subnavbar / .subnavbar] */ .subnavbar { margin-bottom: 2.5em; } .subnavbar-inner { height: 60px; background: #fff; border-bottom: 1px solid #d6d6d6; } .subnavbar .container > ul { display: inline-block; height: 80px; padding: 0; margin: 0; } .subnavbar .container > ul > li { float: left; min-width: 90px; height: 60px; padding: 0; margin: 0; text-align: center; list-style: none; border-left: 1px solid #d9d9d9; } .subnavbar .container > ul > li > a { display: block; height: 100%; padding: 0 15px; font-size: 12px; font-weight: bold; color: #b2afaa; } .subnavbar .container > ul > li > a:hover { color: #888; text-decoration: none; } .subnavbar .container > ul > li > a > i { display: inline-block; width: 24px; height: 24px; margin-top: 11px; margin-bottom: -3px; font-size: 20px; } .subnavbar .container > ul > li > a > span { display: block; } .subnavbar .container > ul > li:hover > a { border-bottom:3px solid #ff7f74; color: #383838; } .subnavbar .dropdown .dropdown-menu a { font-size: 12px; } .subnavbar .dropdown .dropdown-menu { text-align: left; -webkit-border-top-left-radius: 0; -webkit-border-top-right-radius: 0; -moz-border-radius-topleft: 0; -moz-border-radius-topright: 0; border-top-left-radius: 0; border-top-right-radius: 0; } .subnavbar .dropdown-menu::before { content: ''; display: inline-block; border-left: 7px solid transparent; border-right: 7px solid transparent; border-bottom: 7px solid #CCC; border-bottom-color: rgba(0, 0, 0, 0.2); position: absolute; top: -7px; left: 9px; } .subnavbar .dropdown-menu::after { content: ''; display: inline-block; border-left: 6px solid transparent; border-right: 6px solid transparent; border-bottom: 6px solid white; position: absolute; top: -6px; left: 10px; } .subnavbar .caret { margin-top: 4px; border-top-color: white; border-bottom-color: white; } .subnavbar .dropdown.open .caret { display: none; } /*------------------------------------------------------------------ [4. Main / .main] .main { padding-bottom: 2em; border-bottom: 1px solid #000; } */ /*------------------------------------------------------------------ [5. Extra / .extra] */ .extra { border-top: 1px solid #585858; border-bottom: 1px solid #000; } .extra-inner { padding: 20px 0; font-size: 11px; color: #BBB; background: #1A1A1A; } .extra a { color: #666; } .extra h4 { margin-bottom: 1em; font-weight: 400; } .extra ul { padding: 0; margin: 0; } .extra li { margin-bottom: .6em; list-style: none; } /*------------------------------------------------------------------ [6. Footer/ .footer] */ .footer { margin-top: 0; border-top: 1px solid #292929; } .footer-inner { padding: 15px 0; font-size: 12px; background: #111; color: #999; } .footer a { color: #999; } .footer a:hover { color: #FFF; text-decoration: none; } /*------------------------------------------------------------------ [6. Widget / .widget] */ .widget { position: relative; clear: both; width: auto; margin-bottom: 2em; overflow: hidden; } .widget-header { position: relative; cursor: move; height: 40px; line-height: 40px; background: #f9f6f1; background:-moz-linear-gradient(top, #f9f6f1 0%, #f2efea 100%); /* FF3.6+ */ background:-webkit-gradient(linear, left top, left bottom, color-stop(0%,#f9f6f1), color-stop(100%,#f2efea)); /* Chrome,Safari4+ */ background:-webkit-linear-gradient(top, #f9f6f1 0%,#f2efea 100%); /* Chrome10+,Safari5.1+ */ background:-o-linear-gradient(top, #f9f6f1 0%,#f2efea 100%); /* Opera11.10+ */ background:-ms-linear-gradient(top, #f9f6f1 0%,#f2efea 100%); /* IE10+ */ background:linear-gradient(top, #f9f6f1 0%,#f2efea 100%); /* W3C */ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f9f6f1', endColorstr='#f2efea'); -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#f9f6f1', endColorstr='#f2efea')"; border: 1px solid #d6d6d6; -webkit-background-clip: padding-box; } .widget-header h3 { position: relative; top: 2px; left: 10px; display: inline-block; margin-right: 3em; font-size: 14px; font-weight: 800; color: #525252; line-height: 18px; text-shadow: 1px 1px 2px rgba(255,255,255,.5); } .widget-header [class^="icon-"], .widget-header [class*=" icon-"] { display: inline-block; margin-left: 13px; margin-right: -2px; font-size: 16px; color: #555; vertical-align: middle; } .widget-content { padding: 20px 15px 15px; background: #FFF; border: 1px solid #D5D5D5; -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; } .widget-header+.widget-content { border-top: none; -webkit-border-top-left-radius: 0; -webkit-border-top-right-radius: 0; -moz-border-radius-topleft: 0; -moz-border-radius-topright: 0; border-top-left-radius: 0; border-top-right-radius: 0; } .widget-nopad .widget-content { padding: 0; } /* Widget Content Clearfix */ .widget-content:before, .widget-content:after { content:""; display:table; } .widget-content:after { clear:both; } /* For IE 6/7 (trigger hasLayout) */ .widget-content { zoom:1; } /* Widget Table */ .widget-table .widget-content { padding: 0; } .widget-table .table { margin-bottom: 0; border: none; } .widget-table .table tr td:first-child { border-left: none; } .widget-table .table tr th:first-child { border-left: none; } /* Widget Plain */ .widget-plain { background: transparent; border: none; } .widget-plain .widget-content { padding: 0; background: transparent; border: none; } /* Widget Box */ .widget-box { } .widget-box .widget-content { background: #E3E3E3; background: #FFF; } /*------------------------------------------------------------------ [7. Error / .error-container] */ .error-container { margin-top: 4em; margin-bottom: 4em; text-align: center; } .error-container h1 { margin-bottom: .5em; font-size: 120px; line-height: 1em; } .error-container h2 { margin-bottom: .75em; font-size: 28px; } .error-container .error-details { margin-bottom: 1.5em; font-size: 16px; } .error-container .error-actions a { margin: 0 .5em; } /* Message layout */ ul.messages_layout { position: relative; margin: 0; padding: 0 } ul.messages_layout li { float: left; list-style: none; position: relative } ul.messages_layout li.left { padding-left: 75px } ul.messages_layout li.right { padding-right: 75px } ul.messages_layout li.right .avatar { right: 0; left: auto } ul.messages_layout li.right .message_wrap .arrow { right: -12px; left: auto; background-position: 0 -213px; height: 15px; width: 12px } ul.messages_layout li.by_myself .message_wrap { border: 1px solid #b3cdf8 } ul.messages_layout li.by_myself .message_wrap .info a.name { color: #4a8cf7 } ul.messages_layout li a.avatar { position: absolute; left: 0; top: 0 } ul.messages_layout li a.avatar img { -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px } ul.messages_layout li .message_wrap { -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; position: relative; border: 1px solid #e9e9e9; padding: 10px; border: 1px solid #cbcbcb; margin-bottom: 20px; float: left; background: #fefefe; -webkit-box-shadow: rgba(0,0,0,0.1) 0 1px 0px; -moz-box-shadow: rgba(0,0,0,0.1) 0 1px 0px; box-shadow: rgba(0,0,0,0.1) 0 1px 0px } ul.messages_layout li .message_wrap .arrow { background-position: 0 -228px; height: 15px; width: 12px; height: 15px; width: 12px; position: absolute; left: -12px; top: 13px } ul.messages_layout li .message_wrap .info { float: left; width: 100%; border-bottom: 1px solid #fff; line-height: 23px } ul.messages_layout li .message_wrap .info .name { float: left; font-weight: bold; color: #483734 } ul.messages_layout li .message_wrap .info .time { float: left; font-size: 11px; margin-left: 6px } ul.messages_layout li .message_wrap .text { float: left; width: 100%; border-top: 1px solid #cfcfcf; padding-top: 5px } ul.messages_layout .dropdown-menu li{ width:100%; font-size:11px;} /* Full Calendar */ .fc { direction: ltr; text-align: left; position: relative } .fc table { border-collapse: collapse; border-spacing: 0 } html .fc, .fc table { font-size: 1em } .fc td, .fc th { padding: 0; vertical-align: top } .fc-header td { white-space: nowrap; background: none } .fc-header-left { width: 100%; text-align: left; position: absolute; left: 0; top: 6px } .fc-header-left .fc-button { margin: 0; position: relative } .fc-header-left .fc-button-prev, .fc-header-left .fc-button-next { float: left; border: none; padding: 14px 10px; opacity: 0.5 } .fc-header-left .fc-button-prev .fc-button-inner, .fc-header-left .fc-button-next .fc-button-inner { border: none } .fc-header-left .fc-button-prev .fc-button-inner .fc-button-content, .fc-header-left .fc-button-next .fc-button-inner .fc-button-content { display: none } .fc-header-left .fc-button-prev.fc-state-hover, .fc-header-left .fc-button-next.fc-state-hover { opacity: 1 } .fc-header-left .fc-button-prev.fc-state-down, .fc-header-left .fc-button-next.fc-state-down { background: none !important; margin-top: -1px } .fc-header-left .fc-button-prev .fc-button-inner { background-position: 0 -351px; height: 16px; width: 11px } .fc-header-left .fc-button-next { float: right } .fc-header-left .fc-button-next .fc-button-inner { background-position: 0 -367px; height: 16px; width: 11px } .fc-header-center { text-align: center } .fc-header-right { text-align: right; position: absolute; top: -34px; right: 10px } .fc-header-title { display: inline-block; vertical-align: top } .fc-header-title h2 { margin-top: 0; white-space: nowrap; font-size: 1.1rem; color: #6C737F; line-height: 55px; } .fc .fc-header-space { padding-left: 10px } .fc-header .fc-button { margin-bottom: 1em; vertical-align: top } .fc-header .fc-button { margin-right: -1px } .fc-header .fc-corner-right { margin-right: 1px } .fc-header .ui-corner-right { margin-right: 0 } .fc-header .fc-state-hover, .fc-header .ui-state-hover { z-index: 2 } .fc-header .fc-state-down { z-index: 3 } .fc-header .fc-state-active, .fc-header .ui-state-active { z-index: 4 } .fc-content { clear: both; background: #f9f9f9 } .fc-view { width: 100%; overflow: hidden } .fc-view thead { background:#e9ecf1; line-height: 35px } .fc-widget-header, .fc-widget-content { border: 1px solid #ccc } .fc-state-highlight { background: #F4F3E6 } .fc-cell-overlay { background: #9cf; opacity: .2; filter: alpha(opacity=20) } .fc-button { position: relative; display: inline-block; cursor: pointer } .fc-button-today{margin-top: 8px !important;} .fc-state-default { border-style: solid; border-width: 1px 0 } .fc-button-inner { position: relative; float: left; overflow: hidden } .fc-state-default .fc-button-inner { border-style: solid; border-width: 0 1px } .fc-button-content { position: relative; float: left; height: 1.9em; line-height: 1.9em; padding: 0 .6em; white-space: nowrap } .fc-button-content .fc-icon-wrap { position: relative; float: left; top: 50% } .fc-button-content .ui-icon { position: relative; float: left; margin-top: -50%; *margin-top:0; *top:-50% } .fc-state-default .fc-button-effect { position: absolute; top: 50%; left: 0 } .fc-state-default .fc-button-effect span { position: absolute; top: -100px; left: 0; width: 500px; height: 100px; border-width: 100px 0 0 1px; border-style: solid; border-color: #fff; background: #444; opacity: .09; filter: alpha(opacity=9) } .fc-state-default, .fc-state-default .fc-button-inner { border-style: solid; border-color: #ccc #bbb #aaa; color: #000 } .fc-state-hover, .fc-state-hover .fc-button-inner { border-color: #999 } .fc-state-down { border-color: #555; background: #777 } .fc-state-active, .fc-state-active .fc-button-inner { border-color: #555; background: #777; color: #fff } .fc-state-disabled, .fc-state-disabled .fc-button-inner { color: #999; border-color: #ddd } .fc-state-disabled { cursor: default } .fc-state-disabled .fc-button-effect { display: none } .fc-event { border-style: solid; border-width: 0; font-size: .85em; cursor: default } a.fc-event, .fc-event-draggable { cursor: pointer } a.fc-event { text-decoration: none } .fc-rtl .fc-event { text-align: right } .fc-event-skin { border-color: #3f85f5; background-color: #5e96ea; color: #fff } .fc-event-inner { position: relative; width: 100%; height: 100%; border-style: solid; border-width: 0; overflow: hidden } .fc-event-time, .fc-event-title { padding: 0 1px } .fc .ui-resizable-handle { display: block; position: absolute; z-index: 99999; overflow: hidden; font-size: 300%; line-height: 50% } .fc-event-hori { border-width: 1px 0; margin-bottom: 1px } .fc-event-hori .ui-resizable-e { top: 0 !important; right: -3px !important; width: 7px !important; height: 100% !important; cursor: e-resize } .fc-event-hori .ui-resizable-w { top: 0 !important; left: -3px !important; width: 7px !important; height: 100% !important; cursor: w-resize } .fc-event-hori .ui-resizable-handle { _padding-bottom: 14px } .fc-corner-left { margin-left: 1px } .fc-corner-left .fc-button-inner, .fc-corner-left .fc-event-inner { margin-left: -1px } .fc-corner-right { margin-right: 1px } .fc-corner-right .fc-button-inner, .fc-corner-right .fc-event-inner { margin-right: -1px } .fc-corner-top { margin-top: 1px } .fc-corner-top .fc-event-inner { margin-top: -1px } .fc-corner-bottom { margin-bottom: 1px } .fc-corner-bottom .fc-event-inner { margin-bottom: -1px } .fc-corner-left .fc-event-inner { border-left-width: 1px } .fc-corner-right .fc-event-inner { border-right-width: 1px } .fc-corner-top .fc-event-inner { border-top-width: 1px } .fc-corner-bottom .fc-event-inner { border-bottom-width: 1px } table.fc-border-separate { border-collapse: separate } .fc-border-separate th, .fc-border-separate td { border-width: 1px 0 0 1px } .fc-border-separate th.fc-last, .fc-border-separate td.fc-last { border-right-width: 1px } .fc-border-separate tr.fc-last th, .fc-border-separate tr.fc-last td { border-bottom-width: 0px } .fc-first { border-left-width: 0 !important } .fc-last { border-right-width: 0 !important } .fc-grid th { text-align: center } .fc-grid .fc-day-number { float: right; padding: 0 2px } .fc-grid .fc-other-month .fc-day-number { opacity: 0.3; filter: alpha(opacity=30) } .fc-grid .fc-day-content { clear: both; padding: 2px 2px 1px } .fc-grid .fc-event-time { font-weight: bold } .fc-rtl .fc-grid .fc-day-number { float: left } .fc-rtl .fc-grid .fc-event-time { float: right } .fc-agenda table { border-collapse: separate } .fc-agenda-days th { text-align: center } .fc-agenda .fc-agenda-axis { width: 60px !important; padding: 0 4px; vertical-align: middle; text-align: right; white-space: nowrap; font-weight: normal } .fc-agenda .fc-day-content { padding: 2px 2px 1px } .fc-agenda-days .fc-agenda-axis { border-right-width: 1px } .fc-agenda-days .fc-col0 { border-left-width: 0 } .fc-agenda-allday th { border-width: 0 1px } .fc-agenda-allday .fc-day-content { min-height: 34px; _height: 34px } .fc-agenda-divider-inner { height: 2px; overflow: hidden } .fc-widget-header .fc-agenda-divider-inner { background: #eee } .fc-agenda-slots th { border-width: 1px 1px 0 } .fc-agenda-slots td { border-width: 1px 0 0; background: none } .fc-agenda-slots td div { height: 20px } .fc-agenda-slots tr.fc-slot0 th, .fc-agenda-slots tr.fc-slot0 td { border-top-width: 0 } .fc-agenda-slots tr.fc-minor th, .fc-agenda-slots tr.fc-minor td { border-top-style: dotted } .fc-agenda-slots tr.fc-minor th.ui-widget-header { *border-top-style:solid } .fc-event-vert { border-width: 0 1px } .fc-event-vert .fc-event-head, .fc-event-vert .fc-event-content { position: relative; z-index: 2; width: 100%; overflow: hidden } .fc-event-vert .fc-event-time { white-space: nowrap; font-size: 10px } .fc-event-vert .fc-event-bg { position: absolute; z-index: 1; top: 0; left: 0; width: 100%; height: 100%; background: #fff; opacity: .3; filter: alpha(opacity=30) } .fc .ui-draggable-dragging .fc-event-bg, .fc-select-helper .fc-event-bg { display: none\9 } .fc-event-vert .ui-resizable-s { bottom: 0 !important; width: 100% !important; height: 8px !important; overflow: hidden !important; line-height: 8px !important; font-size: 11px !important; font-family: monospace; text-align: center; cursor: s-resize } .fc-agenda .ui-resizable-resizing { _overflow: hidden } .fc-header-left .fc-button-prev .fc-button-inner {background: url('../img/icons-sa7c41345d9.png') no-repeat; background-position: 0 -351px; height: 16px; width: 11px;} .fc-header-left .fc-button-next .fc-button-inner {background: url('../img/icons-sa7c41345d9.png') no-repeat; background-position: 0 -367px; height: 16px; width: 11px;} /*------------------------------------------------------------------ [8. Miscellaneous] */ .chart-holder { width: 100%; height: 250px; } .dropdown-menu li>a:hover, .dropdown-menu .active>a, .dropdown-menu .active>a:hover { background:#00ba8b;} .accordion-heading { background:#e5e5e5; } .accordion-heading a { color:#545454; text-decoration:none; font-weight:bold; } .btn-facebook-alt i { color: #23386a; } .btn-twitter-alt i { color: #0098d0; } .btn-google-alt i { color: #b6362d; } .btn-linkedin-alt i { color: #0073b2; } .btn-pinterest-alt i { color: #ab171e; } .btn-github-alt i { color: #333; } .all-icons li { list-style:none;} .ML0 { margin-left:0} .MR0 { margin-right:0;} .paginate_active { text-decoration: underline; } #refresh-ispeed .icon-refresh, #refresh-ping .icon-refresh, #refresh-bandwidth .icon-refresh { margin: 0; } /*------------------------------------------------------------------ [1. Max Width: 480px] */ @media (max-width: 480px) { .error-container h1 { font-size: 72px; } } /*------------------------------------------------------------------ [1. Max Width: 767px] */ @media (max-width: 767px) { #main { padding: 0 10px; margin-right: -20px; margin-left: -20px; } .subnavbar { margin-left: -20px; margin-right: -20px; } .subnavbar-inner { height: auto; } .subnavbar .container > ul { width: 100%; height: auto; border: none; } .subnavbar .container > ul > li { width: 33%; height: 70px; margin-bottom: 0; border: none; } .subnavbar .container > ul > li.active > a { font-size: 11px; background: transparent; } .subnavbar .container > ul > li > a > i { display: inline-block; margin-bottom: 0; font-size: 20px; } .subnavbar-open-right .dropdown-menu { left: auto; right: 0; } .subnavbar-open-right .dropdown-menu:before { left: auto; right: 12px; } .subnavbar-open-right .dropdown-menu:after { left: auto; right: 13px; } .extra { margin-right: -20px; margin-left: -20px; } .extra .container { padding: 0 20px; } .footer { margin-right: -20px; margin-left: -20px; } .footer .container { padding: 0 20px; } .footer .footer-terms { text-align: left; } .footer .footer-terms a { margin-left: 0; margin-right: 1em; } } /*------------------------------------------------------------------ [2. Max Width: 979px] */ @media (max-width: 979px) { .navbar-fixed-top { position: static; margin-bottom: 0; } .subnavbar { } .subnavbar .container { width: auto; } .widget-header { height: 100%; } .widget-header h3 { margin-right: 1em; } .js-refresh-info { margin-left: 25px; } } /*------------------------------------------------------------------ [3. Max Width: 1199px] */ @media (max-width: 1199px) { .navbar .search-query { width: 200px; } .widget-header { height: 100%; } .js-refresh-info { margin-left: 25px; } } /* ---------------------------------------- Subnavbar CSS fix/work-around */ .container.nav-collapse.in { overflow:visible; } .btn-navbar { margin-top:-38px; } /*------------------------------------------------------------------ general-info widget specific style */ #general-info-widget .general-title { font-weight: bold; } #general-info-widget .general-title:after { content:":"; } #general-info-widget .widget-content { padding:5px; } #general-info-widget .widget-content div { margin-bottom:5px; } footer { border-top: 1px solid #D8D7CF; clear: both; color: #9A9994; font-size: 12px; line-height: 15.4px; margin-top: 15px; overflow: hidden; padding: 20px 0 40px; } footer .site-source { background: url("../img/code.png") no-repeat scroll 0 2px transparent; float: left; padding-left: 46px; } footer .sfc-member {float: right;text-align: right;} footer a {color: #403F3C;} ================================================ FILE: modules/agent/public/index.html ================================================ linux-dash : Server Monitoring Web Dashboard
A simple web dashboard to monitor your server.

General Info

Kernel Version
Uptime
Server Time
Hostname
Agent Version

Load average

Number of cores: 0
1 min  %
5 min  %
15 min  %

RAM

Total  MB
Used  MB
%
Free  MB
%

Disk Usage

Disk IO Stats

CPU

================================================ FILE: modules/agent/public/js/base.js ================================================ $(document).ready(function() { // enable popovers $(".pop").popover(); // activate tooltips on hover $("[data-toggle='tooltip']").tooltip({trigger: 'hover', placement:'right'}); dashboard.getAll(); }).on("click", ".js-smoothscroll", function(event) { event.preventDefault(); var target = $(this.hash).parent(); pulseElement(target, 8, 400); $("html,body").animate({ scrollTop: target.offset().top - 130 }, 1000); }).on("click", ".js-refresh-info", function(event) { event.preventDefault(); var target = event.target; var item = target.id.split("-").splice(-1)[0]; // if the refresh icon is click (where in a ) target will not have an id, so grab its parent instead if(target.id == "") { var parent = $(target).parent()[0]; item = parent.id.split("-").splice(-1)[0]; } dashboard.fnMap[item](); }); // Handle for cancelling active effect. var pulsing = { element: null, timeoutIDs: [], resetfn: function() { pulsing.element = null; pulsing.timeoutIDs = []; } }; /** * Applies a pulse effect to the specified element. If triggered while already * active the ongoing effect is cancelled immediately. * * @param {HTMLElement} element The element to apply the effect to. * @param {Number} times How many pulses. * @param {Number} interval Milliseconds between pulses. */ function pulseElement(element, times, interval) { if (pulsing.element) { pulsing.element.removeClass("pulse"). parent().removeClass("pulse-border"); pulsing.timeoutIDs.forEach(function(ID) { clearTimeout(ID); }); pulsing.timeoutIDs = []; } pulsing.element = element; var parent = element.parent(); var f = function() { element.toggleClass("pulse"); parent.toggleClass("pulse-border"); }; pulsing.timeoutIDs.push(setTimeout(pulsing.resetfn, (times + 1) * interval)); for (; times > 0; --times) { pulsing.timeoutIDs.push(setTimeout(f, times * interval)); } } function isInArray(array, search) { return (array.indexOf(search) >= 0) ? true : false; } ================================================ FILE: modules/agent/public/js/bootstrap.js ================================================ /* =================================================== * bootstrap-transition.js v2.0.2 * http://twitter.github.com/bootstrap/javascript.html#transitions * =================================================== * Copyright 2012 Twitter, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ========================================================== */ !function( $ ) { $(function () { "use strict" /* CSS TRANSITION SUPPORT (https://gist.github.com/373874) * ======================================================= */ $.support.transition = (function () { var thisBody = document.body || document.documentElement , thisStyle = thisBody.style , support = thisStyle.transition !== undefined || thisStyle.WebkitTransition !== undefined || thisStyle.MozTransition !== undefined || thisStyle.MsTransition !== undefined || thisStyle.OTransition !== undefined return support && { end: (function () { var transitionEnd = "TransitionEnd" if ( $.browser.webkit ) { transitionEnd = "webkitTransitionEnd" } else if ( $.browser.mozilla ) { transitionEnd = "transitionend" } else if ( $.browser.opera ) { transitionEnd = "oTransitionEnd" } return transitionEnd }()) } })() }) }( window.jQuery );/* ========================================================== * bootstrap-alert.js v2.0.2 * http://twitter.github.com/bootstrap/javascript.html#alerts * ========================================================== * Copyright 2012 Twitter, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ========================================================== */ !function( $ ){ "use strict" /* ALERT CLASS DEFINITION * ====================== */ var dismiss = '[data-dismiss="alert"]' , Alert = function ( el ) { $(el).on('click', dismiss, this.close) } Alert.prototype = { constructor: Alert , close: function ( e ) { var $this = $(this) , selector = $this.attr('data-target') , $parent if (!selector) { selector = $this.attr('href') selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 } $parent = $(selector) $parent.trigger('close') e && e.preventDefault() $parent.length || ($parent = $this.hasClass('alert') ? $this : $this.parent()) $parent .trigger('close') .removeClass('in') function removeElement() { $parent .trigger('closed') .remove() } $.support.transition && $parent.hasClass('fade') ? $parent.on($.support.transition.end, removeElement) : removeElement() } } /* ALERT PLUGIN DEFINITION * ======================= */ $.fn.alert = function ( option ) { return this.each(function () { var $this = $(this) , data = $this.data('alert') if (!data) $this.data('alert', (data = new Alert(this))) if (typeof option == 'string') data[option].call($this) }) } $.fn.alert.Constructor = Alert /* ALERT DATA-API * ============== */ $(function () { $('body').on('click.alert.data-api', dismiss, Alert.prototype.close) }) }( window.jQuery );/* ============================================================ * bootstrap-button.js v2.0.2 * http://twitter.github.com/bootstrap/javascript.html#buttons * ============================================================ * Copyright 2012 Twitter, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============================================================ */ !function( $ ){ "use strict" /* BUTTON PUBLIC CLASS DEFINITION * ============================== */ var Button = function ( element, options ) { this.$element = $(element) this.options = $.extend({}, $.fn.button.defaults, options) } Button.prototype = { constructor: Button , setState: function ( state ) { var d = 'disabled' , $el = this.$element , data = $el.data() , val = $el.is('input') ? 'val' : 'html' state = state + 'Text' data.resetText || $el.data('resetText', $el[val]()) $el[val](data[state] || this.options[state]) // push to event loop to allow forms to submit setTimeout(function () { state == 'loadingText' ? $el.addClass(d).attr(d, d) : $el.removeClass(d).removeAttr(d) }, 0) } , toggle: function () { var $parent = this.$element.parent('[data-toggle="buttons-radio"]') $parent && $parent .find('.active') .removeClass('active') this.$element.toggleClass('active') } } /* BUTTON PLUGIN DEFINITION * ======================== */ $.fn.button = function ( option ) { return this.each(function () { var $this = $(this) , data = $this.data('button') , options = typeof option == 'object' && option if (!data) $this.data('button', (data = new Button(this, options))) if (option == 'toggle') data.toggle() else if (option) data.setState(option) }) } $.fn.button.defaults = { loadingText: 'loading...' } $.fn.button.Constructor = Button /* BUTTON DATA-API * =============== */ $(function () { $('body').on('click.button.data-api', '[data-toggle^=button]', function ( e ) { var $btn = $(e.target) if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') $btn.button('toggle') }) }) }( window.jQuery );/* ========================================================== * bootstrap-carousel.js v2.0.2 * http://twitter.github.com/bootstrap/javascript.html#carousel * ========================================================== * Copyright 2012 Twitter, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ========================================================== */ !function( $ ){ "use strict" /* CAROUSEL CLASS DEFINITION * ========================= */ var Carousel = function (element, options) { this.$element = $(element) this.options = $.extend({}, $.fn.carousel.defaults, options) this.options.slide && this.slide(this.options.slide) this.options.pause == 'hover' && this.$element .on('mouseenter', $.proxy(this.pause, this)) .on('mouseleave', $.proxy(this.cycle, this)) } Carousel.prototype = { cycle: function () { this.interval = setInterval($.proxy(this.next, this), this.options.interval) return this } , to: function (pos) { var $active = this.$element.find('.active') , children = $active.parent().children() , activePos = children.index($active) , that = this if (pos > (children.length - 1) || pos < 0) return if (this.sliding) { return this.$element.one('slid', function () { that.to(pos) }) } if (activePos == pos) { return this.pause().cycle() } return this.slide(pos > activePos ? 'next' : 'prev', $(children[pos])) } , pause: function () { clearInterval(this.interval) this.interval = null return this } , next: function () { if (this.sliding) return return this.slide('next') } , prev: function () { if (this.sliding) return return this.slide('prev') } , slide: function (type, next) { var $active = this.$element.find('.active') , $next = next || $active[type]() , isCycling = this.interval , direction = type == 'next' ? 'left' : 'right' , fallback = type == 'next' ? 'first' : 'last' , that = this this.sliding = true isCycling && this.pause() $next = $next.length ? $next : this.$element.find('.item')[fallback]() if ($next.hasClass('active')) return if (!$.support.transition && this.$element.hasClass('slide')) { this.$element.trigger('slide') $active.removeClass('active') $next.addClass('active') this.sliding = false this.$element.trigger('slid') } else { $next.addClass(type) $next[0].offsetWidth // force reflow $active.addClass(direction) $next.addClass(direction) this.$element.trigger('slide') this.$element.one($.support.transition.end, function () { $next.removeClass([type, direction].join(' ')).addClass('active') $active.removeClass(['active', direction].join(' ')) that.sliding = false setTimeout(function () { that.$element.trigger('slid') }, 0) }) } isCycling && this.cycle() return this } } /* CAROUSEL PLUGIN DEFINITION * ========================== */ $.fn.carousel = function ( option ) { return this.each(function () { var $this = $(this) , data = $this.data('carousel') , options = typeof option == 'object' && option if (!data) $this.data('carousel', (data = new Carousel(this, options))) if (typeof option == 'number') data.to(option) else if (typeof option == 'string' || (option = options.slide)) data[option]() else data.cycle() }) } $.fn.carousel.defaults = { interval: 5000 , pause: 'hover' } $.fn.carousel.Constructor = Carousel /* CAROUSEL DATA-API * ================= */ $(function () { $('body').on('click.carousel.data-api', '[data-slide]', function ( e ) { var $this = $(this), href , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 , options = !$target.data('modal') && $.extend({}, $target.data(), $this.data()) $target.carousel(options) e.preventDefault() }) }) }( window.jQuery );/* ============================================================= * bootstrap-collapse.js v2.0.2 * http://twitter.github.com/bootstrap/javascript.html#collapse * ============================================================= * Copyright 2012 Twitter, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============================================================ */ !function( $ ){ "use strict" var Collapse = function ( element, options ) { this.$element = $(element) this.options = $.extend({}, $.fn.collapse.defaults, options) if (this.options["parent"]) { this.$parent = $(this.options["parent"]) } this.options.toggle && this.toggle() } Collapse.prototype = { constructor: Collapse , dimension: function () { var hasWidth = this.$element.hasClass('width') return hasWidth ? 'width' : 'height' } , show: function () { var dimension = this.dimension() , scroll = $.camelCase(['scroll', dimension].join('-')) , actives = this.$parent && this.$parent.find('.in') , hasData if (actives && actives.length) { hasData = actives.data('collapse') actives.collapse('hide') hasData || actives.data('collapse', null) } this.$element[dimension](0) this.transition('addClass', 'show', 'shown') this.$element[dimension](this.$element[0][scroll]) } , hide: function () { var dimension = this.dimension() this.reset(this.$element[dimension]()) this.transition('removeClass', 'hide', 'hidden') this.$element[dimension](0) } , reset: function ( size ) { var dimension = this.dimension() this.$element .removeClass('collapse') [dimension](size || 'auto') [0].offsetWidth this.$element[size ? 'addClass' : 'removeClass']('collapse') return this } , transition: function ( method, startEvent, completeEvent ) { var that = this , complete = function () { if (startEvent == 'show') that.reset() that.$element.trigger(completeEvent) } this.$element .trigger(startEvent) [method]('in') $.support.transition && this.$element.hasClass('collapse') ? this.$element.one($.support.transition.end, complete) : complete() } , toggle: function () { this[this.$element.hasClass('in') ? 'hide' : 'show']() } } /* COLLAPSIBLE PLUGIN DEFINITION * ============================== */ $.fn.collapse = function ( option ) { return this.each(function () { var $this = $(this) , data = $this.data('collapse') , options = typeof option == 'object' && option if (!data) $this.data('collapse', (data = new Collapse(this, options))) if (typeof option == 'string') data[option]() }) } $.fn.collapse.defaults = { toggle: true } $.fn.collapse.Constructor = Collapse /* COLLAPSIBLE DATA-API * ==================== */ $(function () { $('body').on('click.collapse.data-api', '[data-toggle=collapse]', function ( e ) { var $this = $(this), href , target = $this.attr('data-target') || e.preventDefault() || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 , option = $(target).data('collapse') ? 'toggle' : $this.data() $(target).collapse(option) }) }) }( window.jQuery );/* ============================================================ * bootstrap-dropdown.js v2.0.2 * http://twitter.github.com/bootstrap/javascript.html#dropdowns * ============================================================ * Copyright 2012 Twitter, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============================================================ */ !function( $ ){ "use strict" /* DROPDOWN CLASS DEFINITION * ========================= */ var toggle = '[data-toggle="dropdown"]' , Dropdown = function ( element ) { var $el = $(element).on('click.dropdown.data-api', this.toggle) $('html').on('click.dropdown.data-api', function () { $el.parent().removeClass('open') }) } Dropdown.prototype = { constructor: Dropdown , toggle: function ( e ) { var $this = $(this) , selector = $this.attr('data-target') , $parent , isActive if (!selector) { selector = $this.attr('href') selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7 } $parent = $(selector) $parent.length || ($parent = $this.parent()) isActive = $parent.hasClass('open') clearMenus() !isActive && $parent.toggleClass('open') return false } } function clearMenus() { $(toggle).parent().removeClass('open') } /* DROPDOWN PLUGIN DEFINITION * ========================== */ $.fn.dropdown = function ( option ) { return this.each(function () { var $this = $(this) , data = $this.data('dropdown') if (!data) $this.data('dropdown', (data = new Dropdown(this))) if (typeof option == 'string') data[option].call($this) }) } $.fn.dropdown.Constructor = Dropdown /* APPLY TO STANDARD DROPDOWN ELEMENTS * =================================== */ $(function () { $('html').on('click.dropdown.data-api', clearMenus) $('body').on('click.dropdown.data-api', toggle, Dropdown.prototype.toggle) }) }( window.jQuery );/* ========================================================= * bootstrap-modal.js v2.0.2 * http://twitter.github.com/bootstrap/javascript.html#modals * ========================================================= * Copyright 2012 Twitter, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ========================================================= */ !function( $ ){ "use strict" /* MODAL CLASS DEFINITION * ====================== */ var Modal = function ( content, options ) { this.options = options this.$element = $(content) .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this)) } Modal.prototype = { constructor: Modal , toggle: function () { return this[!this.isShown ? 'show' : 'hide']() } , show: function () { var that = this if (this.isShown) return $('body').addClass('modal-open') this.isShown = true this.$element.trigger('show') escape.call(this) backdrop.call(this, function () { var transition = $.support.transition && that.$element.hasClass('fade') !that.$element.parent().length && that.$element.appendTo(document.body) //don't move modals dom position that.$element .show() if (transition) { that.$element[0].offsetWidth // force reflow } that.$element.addClass('in') transition ? that.$element.one($.support.transition.end, function () { that.$element.trigger('shown') }) : that.$element.trigger('shown') }) } , hide: function ( e ) { e && e.preventDefault() if (!this.isShown) return var that = this this.isShown = false $('body').removeClass('modal-open') escape.call(this) this.$element .trigger('hide') .removeClass('in') $.support.transition && this.$element.hasClass('fade') ? hideWithTransition.call(this) : hideModal.call(this) } } /* MODAL PRIVATE METHODS * ===================== */ function hideWithTransition() { var that = this , timeout = setTimeout(function () { that.$element.off($.support.transition.end) hideModal.call(that) }, 500) this.$element.one($.support.transition.end, function () { clearTimeout(timeout) hideModal.call(that) }) } function hideModal( that ) { this.$element .hide() .trigger('hidden') backdrop.call(this) } function backdrop( callback ) { var that = this , animate = this.$element.hasClass('fade') ? 'fade' : '' if (this.isShown && this.options.backdrop) { var doAnimate = $.support.transition && animate this.$backdrop = $('