Add analytics (#118)
* ELK stack to analyze logs from client and server * Short-live container to configure kibana. Import kibana dashboards from export.json on startup. * Client and server logging is working throw python-logstash * Minor polishing of events and dashboards. * Default is discover, new visualizations. * Make comments more readable inside logger.js. * Added a path for backups.main
parent
e4638685cd
commit
c096c2a600
@ -0,0 +1,64 @@
|
||||
version: '2.3'
|
||||
services:
|
||||
cvat_elasticsearch:
|
||||
container_name: cvat_elasticsearch
|
||||
image: cvat_elasticsearch
|
||||
networks:
|
||||
default:
|
||||
aliases:
|
||||
- elasticsearch
|
||||
build:
|
||||
context: ./analytics/elasticsearch
|
||||
args:
|
||||
ELK_VERSION: 6.4.0
|
||||
restart: always
|
||||
|
||||
cvat_kibana:
|
||||
container_name: cvat_kibana
|
||||
image: cvat_kibana
|
||||
networks:
|
||||
default:
|
||||
aliases:
|
||||
- kibana
|
||||
build:
|
||||
context: ./analytics/kibana
|
||||
args:
|
||||
ELK_VERSION: 6.4.0
|
||||
ports:
|
||||
- "5601:5601"
|
||||
depends_on: ['cvat_elasticsearch']
|
||||
restart: always
|
||||
|
||||
cvat_kibana_setup:
|
||||
container_name: cvat_kibana_setup
|
||||
image: cvat
|
||||
volumes: ['./analytics/kibana:/home/django/kibana:ro']
|
||||
depends_on: ['cvat']
|
||||
working_dir: '/home/django'
|
||||
entrypoint: ['bash', 'wait-for-it.sh', 'elasticsearch:9200', '-t', '0', '--',
|
||||
'/bin/bash', 'wait-for-it.sh', 'kibana:5601', '-t', '0', '--',
|
||||
'/usr/bin/python3', 'kibana/setup.py', 'kibana/export.json']
|
||||
environment:
|
||||
no_proxy: elasticsearch,kibana,${no_proxy}
|
||||
|
||||
cvat_logstash:
|
||||
container_name: cvat_logstash
|
||||
image: cvat_logstash
|
||||
networks:
|
||||
default:
|
||||
aliases:
|
||||
- logstash
|
||||
build:
|
||||
context: ./analytics/logstash
|
||||
args:
|
||||
ELK_VERSION: 6.4.0
|
||||
http_proxy: ${http_proxy}
|
||||
https_proxy: ${https_proxy}
|
||||
depends_on: ['cvat_elasticsearch']
|
||||
restart: always
|
||||
|
||||
cvat:
|
||||
environment:
|
||||
DJANGO_LOG_SERVER_HOST: "logstash"
|
||||
DJANGO_LOG_SERVER_PORT: 5000
|
||||
no_proxy: logstash,${no_proxy}
|
||||
@ -0,0 +1,3 @@
|
||||
ARG ELK_VERSION
|
||||
FROM docker.elastic.co/elasticsearch/elasticsearch-oss:${ELK_VERSION}
|
||||
COPY --chown=elasticsearch:elasticsearch elasticsearch.yml /usr/share/elasticsearch/config/
|
||||
@ -0,0 +1,3 @@
|
||||
http.host: 0.0.0.0
|
||||
script.painless.regex.enabled: true
|
||||
path.repo: ["/usr/share/elasticsearch/backup"]
|
||||
@ -0,0 +1,5 @@
|
||||
ARG ELK_VERSION
|
||||
FROM docker.elastic.co/kibana/kibana-oss:${ELK_VERSION}
|
||||
COPY kibana.yml /usr/share/kibana/config/
|
||||
|
||||
|
||||
@ -0,0 +1,198 @@
|
||||
[
|
||||
{
|
||||
"_id": "3ade53d0-c23e-11e8-8e1b-758ef07f6de8",
|
||||
"_type": "visualization",
|
||||
"_source": {
|
||||
"title": "Timeline for exceptions",
|
||||
"visState": "{\"title\":\"Timeline for exceptions\",\"type\":\"histogram\",\"params\":{\"addLegend\":true,\"addTimeMarker\":false,\"addTooltip\":true,\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"labels\":{\"show\":true,\"truncate\":100},\"position\":\"bottom\",\"scale\":{\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{},\"type\":\"category\"}],\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"legendPosition\":\"right\",\"seriesParams\":[{\"data\":{\"id\":\"1\",\"label\":\"Exceptions\"},\"drawLinesBetweenPoints\":true,\"mode\":\"stacked\",\"show\":\"true\",\"showCircles\":true,\"type\":\"histogram\",\"valueAxis\":\"ValueAxis-1\"}],\"times\":[],\"type\":\"histogram\",\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"labels\":{\"filter\":false,\"rotate\":0,\"show\":true,\"truncate\":100},\"name\":\"LeftAxis-1\",\"position\":\"left\",\"scale\":{\"mode\":\"normal\",\"type\":\"linear\"},\"show\":true,\"style\":{},\"title\":{\"text\":\"Exceptions\"},\"type\":\"value\"}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"sum_bucket\",\"schema\":\"metric\",\"params\":{\"customBucket\":{\"id\":\"1-bucket\",\"enabled\":true,\"type\":\"filters\",\"schema\":\"bucketAgg\",\"params\":{\"filters\":[{\"input\":{\"query\":\"event:\\\"Send exception\\\"\"},\"label\":\"\"}]}},\"customMetric\":{\"id\":\"1-metric\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metricAgg\",\"params\":{\"customLabel\":\"Exceptions\"}},\"customLabel\":\"Exceptions\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{},\"customLabel\":\"Time\"}}]}",
|
||||
"uiStateJSON": "{}",
|
||||
"description": "",
|
||||
"version": 1,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"index\":\"ec510550-c238-11e8-8e1b-758ef07f6de8\",\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "7e8996e0-c23d-11e8-8e1b-758ef07f6de8",
|
||||
"_type": "dashboard",
|
||||
"_source": {
|
||||
"optionsJSON": "{\"darkTheme\":false,\"hidePanelTitles\":false,\"useMargins\":true}",
|
||||
"timeRestore": false,
|
||||
"description": "",
|
||||
"hits": 0,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[]}"
|
||||
},
|
||||
"panelsJSON": "[{\"embeddableConfig\":{},\"gridData\":{\"x\":0,\"y\":21,\"w\":48,\"h\":13,\"i\":\"1\"},\"id\":\"3ade53d0-c23e-11e8-8e1b-758ef07f6de8\",\"panelIndex\":\"1\",\"type\":\"visualization\",\"version\":\"6.4.0\"},{\"embeddableConfig\":{},\"gridData\":{\"x\":0,\"y\":34,\"w\":48,\"h\":27,\"i\":\"2\"},\"id\":\"9397f350-c23e-11e8-8e1b-758ef07f6de8\",\"panelIndex\":\"2\",\"type\":\"search\",\"version\":\"6.4.0\"},{\"embeddableConfig\":{},\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":21,\"i\":\"3\"},\"id\":\"1ec6a660-c244-11e8-8e1b-758ef07f6de8\",\"panelIndex\":\"3\",\"type\":\"visualization\",\"version\":\"6.4.0\"},{\"embeddableConfig\":{},\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":21,\"i\":\"4\"},\"id\":\"65918380-c244-11e8-8e1b-758ef07f6de8\",\"panelIndex\":\"4\",\"type\":\"visualization\",\"version\":\"6.4.0\"}]",
|
||||
"title": "Monitoring",
|
||||
"version": 1
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "31ac2d60-c25b-11e8-8e1b-758ef07f6de8",
|
||||
"_type": "visualization",
|
||||
"_source": {
|
||||
"title": "List of users",
|
||||
"visState": "{\"title\":\"List of users\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showMetricsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"userid.keyword\",\"size\":100,\"order\":\"desc\",\"orderBy\":\"_key\",\"otherBucket\":true,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"User\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"sum_bucket\",\"schema\":\"metric\",\"params\":{\"customBucket\":{\"id\":\"3-bucket\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"bucketAgg\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},\"customMetric\":{\"id\":\"3-metric\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metricAgg\",\"params\":{}},\"customLabel\":\"Activity\"}},{\"id\":\"1\",\"enabled\":true,\"type\":\"sum\",\"schema\":\"metric\",\"params\":{\"field\":\"working time\",\"customLabel\":\"Working Time (h)\"}}]}",
|
||||
"uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}",
|
||||
"description": "",
|
||||
"version": 1,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"index\":\"ec510550-c238-11e8-8e1b-758ef07f6de8\",\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[]}"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "1ec6a660-c244-11e8-8e1b-758ef07f6de8",
|
||||
"_type": "visualization",
|
||||
"_source": {
|
||||
"title": "Duration of events",
|
||||
"visState": "{\"title\":\"Duration of events\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showMetricsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"event.keyword\",\"size\":100,\"order\":\"desc\",\"orderBy\":\"_key\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"Action\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"avg\",\"schema\":\"metric\",\"params\":{\"field\":\"duration\",\"customLabel\":\"\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"min\",\"schema\":\"metric\",\"params\":{\"field\":\"duration\",\"customLabel\":\"\"}},{\"id\":\"5\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"duration\"}}]}",
|
||||
"uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}",
|
||||
"description": "",
|
||||
"version": 1,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"index\":\"ec510550-c238-11e8-8e1b-758ef07f6de8\",\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[{\"$state\":{\"store\":\"appState\"},\"exists\":{\"field\":\"duration\"},\"meta\":{\"alias\":null,\"disabled\":false,\"index\":\"ec510550-c238-11e8-8e1b-758ef07f6de8\",\"key\":\"duration\",\"negate\":false,\"type\":\"exists\",\"value\":\"exists\"}}]}"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "ec510550-c238-11e8-8e1b-758ef07f6de8",
|
||||
"_type": "index-pattern",
|
||||
"_source": {
|
||||
"fields": "[{\"name\":\"@timestamp\",\"type\":\"date\",\"count\":2,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"@version\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"@version.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"_id\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_index\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"_score\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_source\",\"type\":\"_source\",\"count\":0,\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"_type\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"name\":\"application\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"application.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"box count\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"duration\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"event\",\"type\":\"string\",\"count\":2,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"event.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"frame count\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"object count\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"points count\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"polygon count\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"polyline count\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"task\",\"type\":\"string\",\"count\":1,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"task.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"timestamp\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"track count\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"userid\",\"type\":\"string\",\"count\":1,\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"name\":\"userid.keyword\",\"type\":\"string\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"name\":\"working time\",\"type\":\"number\",\"count\":0,\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true}]",
|
||||
"fieldFormatMap": "{\"duration\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"milliseconds\",\"outputFormat\":\"asSeconds\"}},\"working time\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"milliseconds\",\"outputFormat\":\"asHours\"}}}",
|
||||
"title": "cvat*",
|
||||
"timeFieldName": "@timestamp"
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "65918380-c244-11e8-8e1b-758ef07f6de8",
|
||||
"_type": "visualization",
|
||||
"_source": {
|
||||
"title": "Number of events",
|
||||
"visState": "{\"title\":\"Number of events\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showMetricsAtAllLevels\":false,\"showPartialRows\":false,\"showTotal\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"event.keyword\",\"size\":100,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"Action\"}}]}",
|
||||
"uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}",
|
||||
"description": "",
|
||||
"version": 1,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"index\":\"ec510550-c238-11e8-8e1b-758ef07f6de8\",\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[]}"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "d92524b0-c25c-11e8-8e1b-758ef07f6de8",
|
||||
"_type": "visualization",
|
||||
"_source": {
|
||||
"title": "Activity of users",
|
||||
"visState": "{\"title\":\"Activity of users\",\"type\":\"metrics\",\"params\":{\"id\":\"61ca57f0-469d-11e7-af02-69e470af7417\",\"type\":\"timeseries\",\"series\":[{\"id\":\"61ca57f1-469d-11e7-af02-69e470af7417\",\"color\":\"#68BC00\",\"split_mode\":\"terms\",\"metrics\":[{\"id\":\"61ca57f2-469d-11e7-af02-69e470af7417\",\"type\":\"count\"}],\"separate_axis\":0,\"axis_position\":\"right\",\"formatter\":\"number\",\"chart_type\":\"line\",\"line_width\":1,\"point_size\":1,\"fill\":0.5,\"stacked\":\"none\",\"label\":\"User\",\"terms_field\":\"userid.keyword\",\"terms_size\":\"100\"}],\"time_field\":\"@timestamp\",\"index_pattern\":\"cvat*\",\"interval\":\"auto\",\"axis_position\":\"left\",\"axis_formatter\":\"number\",\"axis_scale\":\"normal\",\"show_legend\":1,\"show_grid\":1},\"aggs\":[]}",
|
||||
"uiStateJSON": "{}",
|
||||
"description": "",
|
||||
"version": 1,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "9397f350-c23e-11e8-8e1b-758ef07f6de8",
|
||||
"_type": "search",
|
||||
"_source": {
|
||||
"title": "Table with exceptions",
|
||||
"description": "",
|
||||
"hits": 0,
|
||||
"columns": [
|
||||
"task",
|
||||
"type",
|
||||
"userid",
|
||||
"stack"
|
||||
],
|
||||
"sort": [
|
||||
"@timestamp",
|
||||
"desc"
|
||||
],
|
||||
"version": 1,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"index\":\"ec510550-c238-11e8-8e1b-758ef07f6de8\",\"highlightAll\":true,\"version\":true,\"query\":{\"language\":\"lucene\",\"query\":\"event:\\\"Send exception\\\"\"},\"filter\":[]}"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "b6339c70-c7d4-11e8-a035-258d2bd7d91f",
|
||||
"_type": "visualization",
|
||||
"_source": {
|
||||
"title": "Working calendar",
|
||||
"visState": "{\"title\":\"Working calendar\",\"type\":\"heatmap\",\"params\":{\"type\":\"heatmap\",\"addTooltip\":true,\"addLegend\":true,\"enableHover\":false,\"legendPosition\":\"right\",\"times\":[],\"colorsNumber\":4,\"colorSchema\":\"Green to Red\",\"setColorRange\":false,\"colorsRange\":[],\"invertColors\":true,\"percentageMode\":false,\"valueAxes\":[{\"show\":false,\"id\":\"ValueAxis-1\",\"type\":\"value\",\"scale\":{\"type\":\"linear\",\"defaultYExtents\":false},\"labels\":{\"show\":false,\"rotate\":0,\"overwriteColor\":false,\"color\":\"#555\"}}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{\"customLabel\":\"\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"userid.keyword\",\"size\":100,\"order\":\"desc\",\"orderBy\":\"_key\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"Users\"}},{\"id\":\"3\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"d\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{},\"customLabel\":\"Date\"}}]}",
|
||||
"uiStateJSON": "{\"vis\":{\"defaultColors\":{\"0 - 8\":\"rgb(165,0,38)\",\"8 - 15\":\"rgb(249,142,82)\",\"15 - 23\":\"rgb(255,255,190)\",\"23 - 30\":\"rgb(135,203,103)\"}}}",
|
||||
"description": "",
|
||||
"version": 1,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"index\":\"ec510550-c238-11e8-8e1b-758ef07f6de8\",\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "22250a40-c25d-11e8-8e1b-758ef07f6de8",
|
||||
"_type": "dashboard",
|
||||
"_source": {
|
||||
"title": "Managment",
|
||||
"hits": 0,
|
||||
"description": "",
|
||||
"panelsJSON": "[{\"embeddableConfig\":{},\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":21,\"i\":\"1\"},\"id\":\"31ac2d60-c25b-11e8-8e1b-758ef07f6de8\",\"panelIndex\":\"1\",\"type\":\"visualization\",\"version\":\"6.4.0\"},{\"embeddableConfig\":{},\"gridData\":{\"x\":24,\"y\":0,\"w\":24,\"h\":21,\"i\":\"2\"},\"id\":\"543f6260-c25c-11e8-8e1b-758ef07f6de8\",\"panelIndex\":\"2\",\"type\":\"visualization\",\"version\":\"6.4.0\"},{\"embeddableConfig\":{},\"gridData\":{\"x\":24,\"y\":21,\"w\":24,\"h\":16,\"i\":\"3\"},\"id\":\"d92524b0-c25c-11e8-8e1b-758ef07f6de8\",\"panelIndex\":\"3\",\"type\":\"visualization\",\"version\":\"6.4.0\"},{\"gridData\":{\"x\":0,\"y\":21,\"w\":24,\"h\":16,\"i\":\"4\"},\"version\":\"6.4.0\",\"panelIndex\":\"4\",\"type\":\"visualization\",\"id\":\"b6339c70-c7d4-11e8-a035-258d2bd7d91f\",\"embeddableConfig\":{}}]",
|
||||
"optionsJSON": "{\"darkTheme\":false,\"hidePanelTitles\":false,\"useMargins\":true}",
|
||||
"version": 1,
|
||||
"timeRestore": false,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"query\":{\"language\":\"lucene\",\"query\":\"\"},\"filter\":[]}"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"_id": "543f6260-c25c-11e8-8e1b-758ef07f6de8",
|
||||
"_type": "visualization",
|
||||
"_source": {
|
||||
"title": "Working day",
|
||||
"visState": "{\"title\":\"Working day\",\"type\":\"table\",\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMetricsAtAllLevels\":false,\"sort\":{\"columnIndex\":null,\"direction\":null},\"showTotal\":false,\"totalFunc\":\"sum\"},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"min\",\"schema\":\"metric\",\"params\":{\"field\":\"@timestamp\",\"customLabel\":\"Start\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"split\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"d\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{},\"customLabel\":\"_\",\"row\":true}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"bucket\",\"params\":{\"field\":\"userid.keyword\",\"size\":100,\"order\":\"desc\",\"orderBy\":\"1\",\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"User\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"max\",\"schema\":\"metric\",\"params\":{\"field\":\"@timestamp\",\"customLabel\":\"End\"}}]}",
|
||||
"uiStateJSON": "{\"vis\":{\"params\":{\"sort\":{\"columnIndex\":null,\"direction\":null}}}}",
|
||||
"description": "",
|
||||
"version": 1,
|
||||
"kibanaSavedObjectMeta": {
|
||||
"searchSourceJSON": "{\"index\":\"ec510550-c238-11e8-8e1b-758ef07f6de8\",\"query\":{\"query\":\"\",\"language\":\"lucene\"},\"filter\":[]}"
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"savedObjectVersion": 2
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -0,0 +1,4 @@
|
||||
server.host: 0.0.0.0
|
||||
elasticsearch.url: http://elasticsearch:9200
|
||||
elasticsearch.requestHeadersWhitelist: [ cookie, authorization, x-forwarded-user ]
|
||||
kibana.defaultAppId: "discover"
|
||||
@ -0,0 +1,40 @@
|
||||
#/usr/bin/env python
|
||||
|
||||
import os
|
||||
import argparse
|
||||
import requests
|
||||
import json
|
||||
|
||||
def import_resources(host, port, cfg_file):
|
||||
with open(cfg_file, 'r') as f:
|
||||
for saved_object in json.load(f):
|
||||
_id = saved_object["_id"]
|
||||
_type = saved_object["_type"]
|
||||
_doc = saved_object["_source"]
|
||||
import_saved_object(host, port, _type, _id, _doc)
|
||||
|
||||
def import_saved_object(host, port, _type, _id, data):
|
||||
saved_objects_api = "http://{}:{}/api/saved_objects/{}/{}".format(
|
||||
host, port, _type, _id)
|
||||
request = requests.get(saved_objects_api)
|
||||
if request.status_code == 404:
|
||||
print("Creating {} as {}".format(_type, _id))
|
||||
request = requests.post(saved_objects_api, json={"attributes": data},
|
||||
headers={'kbn-xsrf': 'true'})
|
||||
else:
|
||||
print("Updating {} named {}".format(_type, _id))
|
||||
request = requests.put(saved_objects_api, json={"attributes": data},
|
||||
headers={'kbn-xsrf': 'true'})
|
||||
request.raise_for_status()
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='import Kibana 6.x resources',
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
||||
parser.add_argument('export_file', metavar='FILE',
|
||||
help='JSON export file with resources')
|
||||
parser.add_argument('-p', '--port', metavar='PORT', default=5601, type=int,
|
||||
help='port of Kibana instance')
|
||||
parser.add_argument('-H', '--host', metavar='HOST', default='kibana',
|
||||
help='host of Kibana instance')
|
||||
args = parser.parse_args()
|
||||
import_resources(args.host, args.port, args.export_file)
|
||||
@ -0,0 +1,7 @@
|
||||
ARG ELK_VERSION
|
||||
FROM docker.elastic.co/logstash/logstash-oss:${ELK_VERSION}
|
||||
RUN logstash-plugin install logstash-input-http logstash-filter-aggregate \
|
||||
logstash-filter-prune logstash-output-email
|
||||
|
||||
COPY logstash.conf /usr/share/logstash/pipeline/
|
||||
EXPOSE 5000
|
||||
@ -0,0 +1,85 @@
|
||||
input {
|
||||
tcp {
|
||||
port => 5000
|
||||
codec => json
|
||||
}
|
||||
}
|
||||
|
||||
filter {
|
||||
if [logger_name] =~ /cvat.client/ {
|
||||
# 1. Decode the event from json in 'message' field
|
||||
# 2. Remove unnecessary field from it
|
||||
# 3. Type it as client
|
||||
json {
|
||||
source => "message"
|
||||
}
|
||||
|
||||
date {
|
||||
match => ["timestamp", "UNIX", "UNIX_MS"]
|
||||
remove_field => "timestamp"
|
||||
}
|
||||
|
||||
if [event] == "Send exception" {
|
||||
aggregate {
|
||||
task_id => "%{userid}_%{application}_%{message}_%{filename}_%{line}"
|
||||
code => "
|
||||
require 'time'
|
||||
|
||||
map['userid'] ||= event.get('userid');
|
||||
map['application'] ||= event.get('application');
|
||||
map['message'] ||= event.get('message');
|
||||
map['filename'] ||= event.get('filename');
|
||||
map['line'] ||= event.get('line');
|
||||
map['task'] ||= event.get('task');
|
||||
|
||||
map['error_count'] ||= 0;
|
||||
map['error_count'] += 1;
|
||||
|
||||
map['aggregated_message'] ||= '';
|
||||
time = Time.strptime(event.get('timestamp').to_s,'%Q').localtime('+03:00')
|
||||
map['aggregated_message'] += time.to_s + '\n' + event.get('stack') + '\n\n\n';"
|
||||
|
||||
timeout => 3600
|
||||
timeout_tags => ['send_email_notification']
|
||||
push_map_as_event_on_timeout => true
|
||||
}
|
||||
}
|
||||
|
||||
prune {
|
||||
blacklist_names => ["level", "host", "logger_name", "message", "path",
|
||||
"port", "stack_info"]
|
||||
}
|
||||
|
||||
mutate {
|
||||
replace => { "type" => "client" }
|
||||
}
|
||||
} else if [logger_name] =~ /cvat.server/ {
|
||||
# 1. Remove unnecessary field from it
|
||||
# 2. Type it as server
|
||||
prune {
|
||||
blacklist_names => ["host", "port"]
|
||||
}
|
||||
|
||||
mutate {
|
||||
replace => { "type" => "server" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output {
|
||||
stdout {
|
||||
codec => rubydebug
|
||||
}
|
||||
|
||||
if [type] == "client" {
|
||||
elasticsearch {
|
||||
hosts => ["elasticsearch:9200"]
|
||||
index => "cvat.client"
|
||||
}
|
||||
} else if [type] == "server" {
|
||||
elasticsearch {
|
||||
hosts => ["elasticsearch:9200"]
|
||||
index => "cvat.server"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
|
||||
# Copyright (C) 2018 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
|
||||
# Copyright (C) 2018 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
|
||||
# Copyright (C) 2018 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class LogProxyConfig(AppConfig):
|
||||
name = 'log_proxy'
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
|
||||
# Copyright (C) 2018 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
|
||||
# Copyright (C) 2018 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
from django.db import models
|
||||
|
||||
# Create your models here.
|
||||
|
||||
@ -1,91 +0,0 @@
|
||||
|
||||
# Copyright (C) 2018 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
from django.conf import settings
|
||||
import os
|
||||
import logging
|
||||
import requests
|
||||
import json
|
||||
from urllib.parse import urlparse
|
||||
from enum import Enum
|
||||
from cvat.apps.engine.models import Job, Task
|
||||
|
||||
from requests.adapters import HTTPAdapter
|
||||
from urllib3.util.retry import Retry
|
||||
|
||||
class ClientLoggerStorage:
|
||||
def __init__(self):
|
||||
self._storage = dict()
|
||||
self._formatter = logging.Formatter('%(message)s')
|
||||
|
||||
def __getitem__(self, tid):
|
||||
if tid not in self._storage:
|
||||
self._storage[tid] = self._create_client_logger(tid)
|
||||
return self._storage[tid]
|
||||
|
||||
def _create_client_logger(self, tid):
|
||||
task = self._get_task(tid)
|
||||
logger = logging.getLogger(name='client_annotation_logger_{}'.format(tid))
|
||||
logger.setLevel(logging.INFO)
|
||||
handler = logging.FileHandler(filename=task.get_client_log_path())
|
||||
handler.setFormatter(self._formatter)
|
||||
logger.addHandler(handler)
|
||||
return logger
|
||||
|
||||
def _get_task(self, tid):
|
||||
try:
|
||||
return Task.objects.get(pk=tid)
|
||||
except Exception:
|
||||
raise Exception('Key must be task indentificator')
|
||||
|
||||
class ClientLogProxy():
|
||||
class _HandlerType(Enum):
|
||||
FILE = 1
|
||||
HTTP = 2
|
||||
|
||||
def __init__(self):
|
||||
self._client_logger = ClientLoggerStorage()
|
||||
def file_log_handler(tid, messages):
|
||||
for event in messages:
|
||||
self._client_logger[tid].info(json.dumps(event))
|
||||
|
||||
self._handlers = {self._HandlerType.FILE: file_log_handler}
|
||||
|
||||
log_server_url = os.environ.get('DJANGO_LOG_SERVER_URL')
|
||||
|
||||
def create_retry_session(retries=3, session=None, backoff_factor=0.3):
|
||||
session = session or requests.Session()
|
||||
retry = Retry(total=retries, backoff_factor=backoff_factor)
|
||||
adapter = HTTPAdapter(max_retries=retry)
|
||||
session.mount('http://', adapter)
|
||||
session.mount('https://', adapter)
|
||||
return session
|
||||
|
||||
if log_server_url:
|
||||
parse_result = urlparse(log_server_url)
|
||||
|
||||
if parse_result.scheme and 'http' not in parse_result.scheme:
|
||||
raise Exception('unsuported annotation log destination')
|
||||
|
||||
def http_log_handler(taskID, messages):
|
||||
r = create_retry_session().post(url=log_server_url, json=messages, verify=False)
|
||||
r.raise_for_status()
|
||||
|
||||
self._handlers[self._HandlerType.HTTP] = http_log_handler
|
||||
|
||||
def push_logs(self, jid, logs):
|
||||
taskID = self._get_task_id(jid)
|
||||
|
||||
for handler in self._handlers.values():
|
||||
handler(taskID, logs)
|
||||
|
||||
def _get_task_id(self, jid):
|
||||
try:
|
||||
job = Job.objects.select_related("segment__task").get(id=jid)
|
||||
return job.segment.task.id
|
||||
except:
|
||||
raise Exception('Key must be job indentificator')
|
||||
|
||||
client_log_proxy = ClientLogProxy()
|
||||
@ -1,9 +0,0 @@
|
||||
|
||||
# Copyright (C) 2018 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
|
||||
@ -1,12 +0,0 @@
|
||||
|
||||
# Copyright (C) 2018 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
from django.urls import path
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
path('exception/<int:jid>', views.exception_receiver),
|
||||
]
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
|
||||
# Copyright (C) 2018 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
from django.http import HttpResponse, HttpResponseBadRequest
|
||||
from django.contrib.auth.decorators import permission_required
|
||||
from .proxy_logger import client_log_proxy
|
||||
from cvat.apps.authentication.decorators import login_required
|
||||
|
||||
|
||||
import json
|
||||
|
||||
# Create your views here.
|
||||
@login_required()
|
||||
@permission_required('engine.view_task', raise_exception=True)
|
||||
def exception_receiver(request, jid):
|
||||
data = json.loads(request.body.decode('utf-8'))
|
||||
try:
|
||||
if 'exceptions' in data:
|
||||
client_log_proxy.push_logs(jid, data['exceptions'])
|
||||
except Exception as e:
|
||||
return HttpResponseBadRequest(str(e))
|
||||
|
||||
return HttpResponse()
|
||||
Loading…
Reference in New Issue