From ab4d64959f117ca64ba9c099b60965fb55231968 Mon Sep 17 00:00:00 2001 From: Matt Bostock Date: Tue, 20 Jun 2017 15:43:36 +0100 Subject: [PATCH 01/13] Marathon SD: Set port index label The changes [1][] to Marathon service discovery to support multiple ports mean that Prometheus now attempts to scrape all ports belonging to a Marathon service. You can use port definition or port mapping labels to filter out which ports to scrape but that requires service owners to update their Marathon configuration. To allow for a smoother migration path, add a `__meta_marathon_port_index` label, whose value is set to the port's sequential index integer. For example, PORT0 has the value `0`, PORT1 has the value `1`, and so on. This allows you to support scraping both the first available port (the previous behaviour) in addition to ports with a `metrics` label. For example, here's the relabel configuration we might use with this patch: - action: keep source_labels: ['__meta_marathon_port_definition_label_metrics', '__meta_marathon_port_mapping_label_metrics', '__meta_marathon_port_index'] # Keep if port mapping or definition has a 'metrics' label with any # non-empty value, or if no 'metrics' port label exists but this is the # service's first available port regex: ([^;]+;;[^;]+|;[^;]+;[^;]+|;;0) This assumes that the Marathon API returns the ports in sorted order (matching PORT0, PORT1, etc), which it appears that it does. [1]: https://github.com/prometheus/prometheus/pull/2506 --- discovery/marathon/marathon.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/discovery/marathon/marathon.go b/discovery/marathon/marathon.go index d1f2b2f6c..2c1101722 100644 --- a/discovery/marathon/marathon.go +++ b/discovery/marathon/marathon.go @@ -20,6 +20,7 @@ import ( "math/rand" "net" "net/http" + "strconv" "strings" "time" @@ -43,6 +44,9 @@ const ( appLabel model.LabelName = metaLabelPrefix + "app" // imageLabel is the label that is used for the docker image running the service. imageLabel model.LabelName = metaLabelPrefix + "image" + // portIndexLabel is the integer port index when multiple ports are defined; + // e.g. PORT1 would have a value of '1' + portIndexLabel model.LabelName = metaLabelPrefix + "port_index" // taskLabel contains the mesos task name of the app instance. taskLabel model.LabelName = metaLabelPrefix + "task" @@ -323,6 +327,7 @@ func targetsForApp(app *App) []model.LabelSet { target := model.LabelSet{ model.AddressLabel: model.LabelValue(targetAddress), taskLabel: model.LabelValue(t.ID), + portIndexLabel: model.LabelValue(strconv.Itoa(i)), } if i < len(app.PortDefinitions) { for ln, lv := range app.PortDefinitions[i].Labels { From 38de290d5f1c394844a2e43862cad08b29529a95 Mon Sep 17 00:00:00 2001 From: Alin Sinpalean Date: Tue, 4 Jul 2017 16:30:12 +0200 Subject: [PATCH 02/13] Console graph color scheme support (#2900) Add a colorScheme parameter to PromConsole.Graph, to allow using custom colors in console graphs. --- web/ui/bindata.go | 80 ++++++++++++++++---------------- web/ui/static/js/prom_console.js | 5 +- 2 files changed, 44 insertions(+), 41 deletions(-) diff --git a/web/ui/bindata.go b/web/ui/bindata.go index ad099acd3..bff8dc66c 100644 --- a/web/ui/bindata.go +++ b/web/ui/bindata.go @@ -121,7 +121,7 @@ func webUiTemplates_baseHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/templates/_base.html", size: 2858, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/templates/_base.html", size: 2858, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -141,7 +141,7 @@ func webUiTemplatesAlertsHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/templates/alerts.html", size: 1837, mode: os.FileMode(420), modTime: time.Unix(1497867041, 0)} + info := bindataFileInfo{name: "web/ui/templates/alerts.html", size: 1837, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -161,7 +161,7 @@ func webUiTemplatesConfigHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/templates/config.html", size: 175, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/templates/config.html", size: 175, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -181,7 +181,7 @@ func webUiTemplatesFlagsHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/templates/flags.html", size: 433, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/templates/flags.html", size: 433, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -201,7 +201,7 @@ func webUiTemplatesGraphHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/templates/graph.html", size: 1941, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/templates/graph.html", size: 1941, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -221,7 +221,7 @@ func webUiTemplatesRulesHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/templates/rules.html", size: 209, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/templates/rules.html", size: 209, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -241,7 +241,7 @@ func webUiTemplatesStatusHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/templates/status.html", size: 1756, mode: os.FileMode(420), modTime: time.Unix(1497884603, 0)} + info := bindataFileInfo{name: "web/ui/templates/status.html", size: 1756, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -261,7 +261,7 @@ func webUiTemplatesTargetsHtml() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/templates/targets.html", size: 2271, mode: os.FileMode(420), modTime: time.Unix(1497867041, 0)} + info := bindataFileInfo{name: "web/ui/templates/targets.html", size: 2271, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -281,7 +281,7 @@ func webUiStaticCssAlertsCss() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/static/css/alerts.css", size: 74, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/css/alerts.css", size: 74, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -301,7 +301,7 @@ func webUiStaticCssGraphCss() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/static/css/graph.css", size: 2710, mode: os.FileMode(420), modTime: time.Unix(1494837474, 0)} + info := bindataFileInfo{name: "web/ui/static/css/graph.css", size: 2710, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -321,7 +321,7 @@ func webUiStaticCssProm_consoleCss() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/static/css/prom_console.css", size: 2883, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/css/prom_console.css", size: 2883, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -341,7 +341,7 @@ func webUiStaticCssPrometheusCss() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/static/css/prometheus.css", size: 405, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/css/prometheus.css", size: 405, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -361,7 +361,7 @@ func webUiStaticImgAjaxLoaderGif() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/static/img/ajax-loader.gif", size: 847, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/img/ajax-loader.gif", size: 847, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -381,7 +381,7 @@ func webUiStaticImgFaviconIco() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/static/img/favicon.ico", size: 15086, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/img/favicon.ico", size: 15086, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -401,7 +401,7 @@ func webUiStaticJsAlertsJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/static/js/alerts.js", size: 445, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/js/alerts.js", size: 445, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -421,7 +421,7 @@ func webUiStaticJsGraphJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/static/js/graph.js", size: 27425, mode: os.FileMode(420), modTime: time.Unix(1497888380, 0)} + info := bindataFileInfo{name: "web/ui/static/js/graph.js", size: 27425, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -441,12 +441,12 @@ func webUiStaticJsGraph_templateHandlebar() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/static/js/graph_template.handlebar", size: 6337, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/js/graph_template.handlebar", size: 6337, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } -var _webUiStaticJsProm_consoleJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xdc\x3c\x7f\x77\xdb\xb8\x91\x7f\xc7\x9f\x62\xc2\xb6\x21\x65\xc9\x94\x9d\xec\xee\x5d\xa5\x28\xfb\xb2\xf9\xb1\xc9\x5d\x92\xcd\x25\x4e\xdb\xad\xa2\xf3\x83\x49\x48\x42\x4c\x91\x2c\x00\xd9\x52\x13\x7f\xf7\x7b\x18\x00\x24\x40\x51\xb2\xec\x5e\xf7\xde\x35\x7f\x30\x26\x30\x98\x19\xcc\x0c\x06\x83\xc1\x50\xfd\xc3\x03\x38\x84\x97\xcb\x3c\x91\xac\xc8\x05\xc8\x02\x16\xe4\x82\x02\x93\x40\x89\x60\x94\xab\x96\x2b\xce\x24\x85\x92\x17\x0b\x2a\xe7\x74\x29\x20\x29\x72\x51\x64\x54\xf4\x40\x2c\x93\xb9\xc2\x40\x04\xcc\x38\x29\xe7\x22\x3e\x00\x85\xb2\x7f\x70\xf0\x9e\x17\x8b\x67\x1a\x10\x46\xf0\xf5\x7a\xe8\x35\xc5\xef\x96\x8b\x73\xca\x5f\x16\x7c\x41\xa4\xa4\xdc\x80\xec\x80\x88\x4b\x4e\xa7\x6c\x45\xc5\x4f\x6c\x06\x23\x18\x07\x17\x41\x0f\x82\xb7\xea\xf1\xb3\x7a\x9c\xaa\xc7\x7b\xf5\x78\xa1\x1e\x7f\x55\x8f\x5f\x83\xc9\xde\x38\x4f\x8e\x1f\x7e\xa7\xf1\x32\x44\x8c\xcf\x9f\xf1\x79\x8a\xcf\xf7\xf8\x7c\x81\xcf\xbf\xe2\xf3\x57\xb6\x2f\xfe\x8f\x0b\x92\x65\x88\x7d\xa1\x06\x2e\xd5\x23\x57\x8f\x52\x3d\xa6\xea\x41\xd4\xe3\xef\xea\xb1\x56\x58\x3d\xb4\x67\x42\x72\x56\x9e\x72\xc2\x32\x96\xcf\xfe\x4a\x79\x01\x23\x98\x1a\xad\x45\xab\x0e\x7c\x3d\x00\x00\x60\x53\x88\x56\x31\xcb\x53\xba\xfa\x65\x1a\x05\x34\xe8\xc0\x68\x04\x47\x27\xb6\x1f\xa0\xdf\x87\xd7\x32\x14\x90\x17\x12\x04\x99\x52\xa5\x5e\xc4\xad\xc6\x32\xd5\x23\x12\x46\x73\xc9\xa6\x2c\x51\x40\x44\x11\x88\xcd\x60\x4e\xe5\x92\xe7\xb0\x8a\x39\x2d\x33\x92\xd0\xa8\xff\x39\xfe\xf1\xf8\xf0\xf7\xfd\x1e\x84\x61\x67\x88\x50\xd7\x07\x2e\xe4\xf0\x40\xa9\xbd\xdf\x87\x57\xcb\x05\xc9\xd9\xdf\x29\x10\xc8\x51\x44\xf1\x4e\xb1\xcd\x2d\xf8\xe6\x2c\x2f\x09\x57\xe8\x61\x04\xbb\x10\x9c\x59\x0c\x11\xf2\xb3\xea\xed\x84\x76\xac\xa0\x87\xf0\x7b\xab\xb4\x07\x27\xc7\xc7\xc7\x38\xf7\x15\x8c\x14\x63\xe3\xe3\xc9\xd0\xb0\xa9\x21\x4d\xf3\x09\x36\x2b\x0d\xbd\x25\x72\x1e\x93\x73\xa1\x66\xf4\x18\x2a\xe5\x54\xd2\x95\xc5\x8b\x55\x59\xe4\x4a\x0b\x24\x8b\x1e\x75\xa0\x6b\x30\x29\x04\x4a\xbe\x06\x72\xb7\x81\x44\x0a\xd1\x4b\xb6\xa2\x69\xf4\xa8\xe3\xe2\xd8\xa6\x91\x1e\xa4\x45\x1e\x4a\x58\x0a\x0a\x0b\x96\x65\xac\xbf\x60\x09\x2f\xfa\x54\x26\x31\xd8\x49\xef\xa7\xb6\x77\x05\x0a\xe7\xbd\x9d\x7f\x53\x87\x37\x4b\x61\x8f\xb9\xbd\xe7\x34\x61\x42\x61\x7d\xd4\xe9\x58\xd1\xfc\x26\xd6\x31\x9e\xdc\x56\xed\xff\x1c\x8d\xc1\x15\x93\x73\x40\xbf\x45\x04\xc8\x39\x85\x73\x22\x68\x0f\x38\x91\x73\xe5\xb9\xe7\x24\x47\x3e\xf7\x53\x9a\xf1\x7f\xbf\xf1\x7a\x53\x54\x5d\xa9\x3e\xfc\xee\x5f\x64\x31\x69\xbc\x2c\x9f\x01\xc9\x81\xae\x48\x22\x81\xd3\x92\x53\x41\x73\xeb\x55\xf7\xd1\xca\x0b\x1c\xf9\xff\xc8\x0d\x1a\x79\x6a\xe5\x41\xb7\x52\xd7\x0d\xfb\x7f\xcd\xaa\x37\xd9\x1e\xb8\x4c\x41\x83\xe8\x94\x24\xb2\xe0\xb5\x40\x2a\x1b\x09\x02\x6b\x1f\x2b\x18\x8d\x46\x70\x6c\xed\xa2\x7f\x08\xcf\x0b\xb5\xb1\xcd\x59\x3e\x8b\x55\x9c\x02\x70\x0d\x34\x13\x74\xc3\x9a\x9e\x8c\x6a\x73\x9a\x16\x1c\x22\x45\x81\x8d\x8e\x87\xc0\xe0\xb1\xcb\x56\x9c\xd1\x7c\x26\xe7\xf0\xe0\x01\x34\xc6\x6b\xfe\x86\xd0\xed\xb2\x7a\x0b\x5e\x41\xbf\xea\x31\x4d\x15\xdf\x0e\xd6\x31\x9b\xd4\x3b\xaa\x61\xf1\x26\x66\x50\x2c\x5b\xd8\x79\x0c\x27\x1b\x8c\x1c\xde\xc8\x08\x62\xf4\x59\xa9\x75\x3c\xae\xd4\x63\xf4\xeb\x29\xf8\x94\x2d\xe8\xb3\x22\x97\xbc\xc8\x5c\x95\x6a\xfa\x69\x91\x2c\x17\x34\x97\xf1\x8c\xca\x17\x19\x55\x7f\xfe\xb4\x7e\x9d\x46\x81\x8a\x32\xcf\x30\x94\x3c\x4b\x97\x1c\x17\xca\x99\x98\x73\x96\x5f\x04\x9d\xb8\xc8\x93\x8c\x25\x17\x30\x02\x39\x67\x22\x4e\x69\xc2\x29\x11\xf4\xb9\x01\x8c\xcf\x59\x9e\x46\xaa\x0b\x2d\xf1\x56\x34\x66\xbc\xb8\xda\xa4\xc0\xf2\x7f\x98\x82\x64\x0b\x7a\x76\x4e\x92\x1d\xfc\xbf\xc8\xd3\xbb\x22\x9e\x16\xfc\x8a\xf0\x74\x3b\xe7\x77\xc3\xcd\xe9\x94\x53\x31\x3f\x3b\x5f\x4a\x59\xe4\x9b\xd8\x4d\x7f\x03\xb3\x9e\x94\x11\x95\x41\x0d\xa3\x5b\xe9\x21\xa8\x11\xd1\x3c\xbd\x1d\x0e\x14\x08\xcd\xd3\x60\x2b\x33\x71\x91\xb3\xbc\x5c\xca\x4a\x01\x4c\x94\x44\x26\xad\xf3\xa8\xc9\xff\xf3\x47\x19\x71\xfe\x89\x64\x4b\x7a\xbb\x39\xfb\x8a\x3a\xbb\x54\x18\xd4\xfc\xab\x1d\x02\xbb\xdf\x30\x71\x5b\x84\x2c\x97\x94\x5f\x92\x4c\x68\x69\x3a\xc8\x5e\xdb\x1e\x3c\xce\xfc\x32\xc5\xc3\xcb\x09\x1e\x6b\xbe\xc7\xe7\x89\xf9\x6f\x1e\xa0\xdb\xd8\x74\x57\x4d\x44\xc6\x63\x79\xee\x49\x0d\xc8\x98\xcb\xb4\xb2\x67\x69\xc5\x13\x05\x19\x0b\xcc\x91\x23\x63\x4d\xf3\x14\x54\x7e\x68\x5a\x68\x6f\x83\xec\x98\x4d\x6a\x0c\x92\xae\xa4\xf2\x56\x5a\xf4\x2d\xa0\x43\x13\x57\x54\x02\x8d\x49\x59\xd2\x3c\x7d\x36\x67\x59\x1a\x65\xcc\x84\xa0\xdb\x2c\x0f\x35\xd3\xd8\xad\x1d\x0f\x19\x97\xbc\x90\x85\x5c\x97\x54\x29\x07\xc3\x09\xeb\x73\xa2\x8d\xad\xd8\x1d\x77\xc6\x72\xa6\x42\x1b\xb4\x9d\x9a\x6c\xc7\xee\x7f\xf7\xf7\x1c\x48\xf3\x54\xf5\xbe\x2b\xae\xac\x06\x9a\xf6\x7c\x87\x19\x10\x69\x02\x0f\x80\x9c\x5e\x01\xbe\xdf\x8e\x1f\x38\xd4\x91\x85\x91\x6e\x33\x88\x70\x11\xa8\xe5\xff\x12\x77\x33\x65\x99\x6a\x0e\xc1\x3a\x18\xc0\x0f\xc7\x70\xa8\x1f\x0f\xbf\x83\x43\x78\xf4\xc3\xf7\x2a\xb6\x09\xae\x36\xbb\xfe\x0d\x3b\xd2\x46\x07\x36\xce\xeb\x46\x7c\x5f\xe0\x3b\xfe\x29\x82\x01\x9c\xec\x64\x4c\x48\x5a\xea\x59\xa9\x15\xa3\xc6\x9c\x1c\x8b\x2d\x8b\xe6\xd1\xb1\x5d\x3b\x3d\x08\x1e\xe2\xf3\x07\x7c\x9e\xe8\x97\x93\x14\x3b\xd2\x00\x69\x9f\x5c\xe1\x1b\x3e\xbf\xc3\xe7\xbf\xe3\xf3\x64\x8d\xed\xeb\xe0\xa0\x99\x48\x68\x57\xd8\x99\xa0\xf2\x15\x11\xf3\xcd\x7d\x5a\x2d\x43\x6b\x53\x76\x75\x95\x84\xd7\x3b\x62\xb4\xdd\xda\x2b\xc7\x61\x75\x69\xc6\x2b\xef\x93\xa7\x68\x0c\x1d\xe8\xa3\x7e\x15\xe4\x15\xcb\xd3\xe2\x2a\xce\x8a\x44\x6f\xb5\x73\xcd\x50\xf0\xbb\x32\x91\x49\x00\x5d\xa0\x79\x52\xa4\xf4\xd3\x87\xd7\xcf\x8a\x85\x0e\xe9\xa3\xff\xf8\xf8\xcb\xbb\x58\x45\xeb\xf9\x8c\x4d\xd7\xda\xd6\xbe\x5a\x66\x06\x15\xe7\x3d\xcb\xc2\xc0\xfe\x71\xad\x2c\x6a\x97\xd2\x7c\x73\x6c\x17\x8c\xe1\xb0\x8d\x71\x3b\x75\x14\x84\xb0\x8b\x51\xf5\x54\xe9\x99\x10\x27\x16\x76\xfc\x00\xf5\xd2\xd2\xc3\xa9\xa1\xa8\xa3\x94\x6e\x4c\x1c\x31\x89\xe5\xb9\x9e\x7b\xf4\x7d\xc7\xac\x10\x37\x4e\xac\x50\x39\x12\x79\xf4\xc3\xf1\xb1\x23\x8d\xe3\x6b\x7b\x0c\x52\xec\x5d\xfa\x4b\x6f\x93\xad\xba\xab\x5e\xcf\x1d\xa5\x4f\xd5\xe8\x29\xb3\x39\xe2\x5d\x71\xa5\xd4\xcf\x97\xb4\x71\xee\xb2\x02\xba\x8e\x3a\x7b\x99\xaa\x67\x7c\xae\x5a\xec\x1c\x4f\xe9\x4a\x6e\xda\xee\x87\x17\x86\xe7\x0f\x74\xf6\x62\x55\x46\xc1\x7f\x47\xe3\xe3\xa3\x3f\x4e\xba\x9d\x68\xbc\xbe\x4a\xe7\x0b\x31\xf9\xb1\xf3\xfb\x7a\xaf\x5b\xa8\xad\x1a\x85\xe7\xe2\x8d\xb1\x39\xaa\x91\xd6\x6e\xd6\x0c\xe8\xc0\x57\x3b\x33\x25\xea\x61\x95\x94\xb0\xde\x13\xf9\x7f\x9d\xcb\xc8\x0c\x18\x9f\x4c\x2a\xa2\xcb\x9c\xa9\xcd\xc7\xf6\x3c\x9c\xc0\xb7\x6f\x10\x8a\x70\xd8\x10\x17\x1c\x6e\x75\xc2\x8e\x13\x1c\x2b\x74\x2d\x07\xaf\xfd\x76\x9d\x36\xd1\xd6\x62\x55\xa8\xd1\x9b\xf9\x3b\xfc\x05\x5d\x03\xcb\xf7\x61\xce\xda\x15\x22\x8a\xcb\xa5\x98\x47\xe3\x7d\xe6\x74\x41\xd7\x93\x9e\xa2\x33\xa9\x52\x3e\x1a\x85\x28\xb8\x8c\x2a\x8e\x49\x0f\xce\x1d\x55\x9c\xab\xa3\xe8\x11\x90\xf1\xf1\x64\x08\xd7\x1d\x3f\x2a\x81\x11\x98\xb8\x44\x63\x6a\x09\x46\x94\x86\x2b\x2f\xf8\x07\x0d\x37\x66\x13\x85\xd5\x5b\xbc\x95\x9a\x6a\xe8\xbe\x0b\xdd\x81\x6e\xfd\x7a\xd2\x7e\xa8\xb2\x23\xf7\x55\x5c\xf3\x88\xb2\xdb\x87\x7f\xa4\x49\x91\xa7\xe2\x4e\xae\xbc\x4d\x64\x37\xef\x79\x95\x3c\x59\xb7\xdb\x26\x4f\xcb\xd1\xe3\x36\x8e\x6e\x46\xaf\x82\xb8\x5a\xfc\x36\xfa\xbb\x25\x82\xa1\x3b\xdc\x06\xea\x51\xd5\xac\x35\xe3\x6a\x6b\x3f\xd5\x34\xcf\xa7\xbf\x91\x6a\xf6\xd6\x09\x1c\xc1\x89\x52\xe3\x13\xad\xce\xa3\xa3\x5d\xfa\x79\xf2\xaf\xa7\x1f\x87\x91\xed\xee\x6e\x67\x34\x5f\x2f\x56\x03\x68\x23\xa9\xe8\x86\xf0\xc2\x73\xbc\x26\x1a\xda\x34\x0f\xa5\x87\x2d\x61\xf8\x68\x04\x61\xd8\xc8\x76\xe6\xcb\x2c\x73\x13\xe1\x29\x91\xf4\x3d\xe1\xb2\xb2\xa9\x26\x9a\x58\x94\x19\x93\x51\x7f\x7c\x04\x83\x49\xbf\x53\x3b\x21\xc5\x4e\xfc\xe9\xf4\x59\x54\xa1\x18\x1f\x4f\x7a\x35\xc2\xf1\x89\xf2\xa7\x27\x6e\xcb\x43\xaf\xff\x91\xf7\xf6\xdd\xe4\x36\xe2\xf8\x85\x7f\xdc\x21\x13\x3b\xb1\xb6\x68\xd2\xee\xc6\xaa\xbf\x21\x1b\xd5\x64\x65\x63\x86\xd7\x21\x4c\xa5\x3e\x51\x23\x43\x1c\xce\xce\xab\xde\xeb\x50\xe7\xd6\xdb\x6a\x63\x2e\x35\x87\x18\x48\x16\x4b\x3c\xb4\x58\x1a\x9f\x4e\x9f\xbd\x52\x4d\x11\xa6\xed\x8e\xe1\x47\x08\x8f\x43\xe8\xb6\xf5\x0f\x5a\x1a\xab\x20\x86\xe5\x4b\x49\x1b\x88\xdf\xea\xc6\x1d\xa8\x6b\x88\x41\x6b\x73\x8b\x50\x3e\x9d\x3e\x7b\xb9\xcc\xb2\x5f\x29\xe1\x91\xda\xe4\x82\x23\x15\xb0\x47\xee\xe8\x22\x97\xf3\xa8\xd3\x3d\xa9\xbb\x9d\x5e\x73\x18\xe8\x42\x00\x01\x74\xcd\xb2\xd6\x52\xe9\x42\x30\x50\xd0\x66\x32\xfb\x0a\x5e\xb4\x9a\x50\x2d\xf6\x46\x9e\x20\xc2\x44\x46\x6b\x1e\xc7\xae\x75\x6b\x6d\xf5\xd1\xb6\x32\x91\x3b\x2e\x7d\x27\x47\xb7\x69\xe7\xfd\x3e\xbc\x36\xfd\xf5\x09\xec\xe1\xf7\x7f\x00\x4e\xf2\x19\x85\x07\x90\x14\xf9\x25\xe5\x12\x16\x78\x6b\x2f\xe2\x16\x1b\xae\x2c\xdc\xf2\xee\x2e\x2d\x94\xf7\xed\xb6\x1a\x73\x1a\xef\x7f\x07\x1d\x27\xc7\xe6\xf8\xe3\xdb\xed\x8b\xad\xf3\xbe\xed\x1c\x8e\xfe\x6f\xe6\x60\x12\x41\x5b\xf8\x6f\x31\x9f\x30\x6c\xb5\x94\xbb\x0b\xd1\x8c\xf8\xe7\x05\x15\xe6\xe8\xbe\xcb\xd1\x62\xf7\x68\x84\x3b\x8f\x75\xb8\x7a\x48\xdb\xf9\xd0\xfa\xdf\x8d\x40\xd2\x8f\x23\xab\x4c\xe4\x8c\x09\xc9\xd7\x6d\x01\xa4\x1a\x8c\x50\x8d\x70\xa7\x31\xb4\x4a\xdb\x61\xb3\x9a\x3d\x59\xd4\x33\x76\xf6\x6f\x23\xa6\x16\xe0\xfa\xc4\xab\xe6\xe5\x1e\x70\x35\x98\x1f\x8d\xec\x1b\x79\x9c\x35\x12\x8c\x30\x32\x9b\xf7\x7e\x9e\xed\xc3\xa6\xf1\xf9\x41\x4b\x15\x38\x6c\x10\xba\xdf\xd0\x96\x49\x5e\x24\x19\x25\xdc\x02\xb5\x0f\x35\xe1\x56\x3b\xda\x91\x17\x7c\x78\xe7\xa5\xfb\x23\xd0\xce\xd5\x09\x2e\xdb\x17\xc9\x7d\x2f\xa8\xf1\x73\xe3\x91\x57\x5f\xb2\xb7\x89\x7b\xf9\xd0\xed\xcc\x1b\x29\x08\x2a\x7d\x19\xb4\x24\xed\x7b\x1b\x84\x0f\xeb\xcb\xcf\xeb\x1d\x19\xfd\x46\x8a\xd9\x3f\xe7\xf5\xfb\x80\x49\xfa\x62\x0a\x24\xcb\x4c\x2d\x55\x0f\x96\x82\xa6\x70\xbe\x06\x75\x04\x56\x0e\x5f\x99\x42\xa3\x06\xa3\x61\xf2\xe6\x50\xee\x81\x20\xc4\x73\x3a\x25\xcb\x4c\xda\xdc\x28\x5d\x95\x7c\x80\x4a\xeb\xd9\xc2\xa0\x17\xab\x92\x53\x21\x94\xce\x64\x61\xcc\x1b\x9e\x91\x1c\xce\x29\x10\xc8\x0c\x7b\x3a\xe3\x84\xdb\x4d\x5e\xa4\xb4\x81\xe3\xf9\x2f\x6f\xb1\x59\x61\xc0\x1a\x21\xb3\x4c\x97\x79\x4a\xb9\xad\x23\x72\xff\xf5\xfb\xf0\xaa\xb8\x82\xac\xc8\x67\x58\xc1\xa0\xc1\x99\x80\xe2\x92\xf2\x1e\xb0\x1c\x84\x16\xb3\x1a\x5c\xe7\xb1\x6e\x99\x0e\xef\xb5\x53\x3e\x9d\x53\x75\x1e\x5f\xa1\x78\x6b\xea\x54\x69\x95\x48\x45\xb1\xca\x94\xed\x4b\xd1\x0c\xe8\x61\x42\x33\x95\x73\x47\x3e\x6a\xaa\x94\xcd\xe6\x28\xc6\x9a\x5a\xca\x2e\x7b\x40\x57\x49\xb6\x4c\x99\x12\x02\x93\x19\x15\x40\xf2\x14\x32\x3a\xa3\x66\xe6\x2d\xcc\x57\x0a\x95\x05\x90\xa5\x2c\x8e\x52\x2a\x69\x62\xeb\xb5\xe6\x48\x69\x00\x0f\x8f\x8f\xff\x61\xe2\x0b\x96\x0f\x20\x50\x34\x02\x8b\xeb\x2d\xcb\xd9\x62\xb9\x80\x5f\x8f\xc8\x8a\x09\x9d\x96\xea\x41\xea\xb0\x94\x15\x57\x54\x48\x15\xe4\x11\xdd\x8d\x98\xc8\x6a\x80\xb6\x30\x65\x39\x4d\x7b\x88\x89\xac\x6e\xc0\x34\x67\xb3\xf9\x26\x2a\x4e\x95\x49\x51\x3e\x80\x30\x63\x39\x0d\x7b\x5a\xa3\xeb\x92\xaa\x19\xda\x05\x54\x94\xba\xae\x91\x70\x6a\xe0\x70\x72\x21\xe1\x94\x84\x68\xc3\x64\xd1\xb4\xe1\x3f\xcf\x89\x54\x74\x13\xb5\x12\xcb\xac\x90\xc2\xe7\x47\xf2\x35\xca\xaa\x80\xb4\x68\x57\x8d\xc0\x4a\x49\x05\xa4\xe2\x9c\x22\x27\xe7\x19\xdd\xa2\xc5\xd7\x53\x20\x66\x4d\xf5\x80\xc9\x30\xcb\xb0\x00\x4b\xce\x89\x8c\x61\x3c\x86\x8c\x9c\xd3\x0c\x26\x13\xb8\x62\x59\xa6\x56\x22\x26\x7d\x99\x5c\x4a\x9a\xee\x42\x69\x37\x06\x83\xf3\x9c\xe2\x74\x68\xaa\x6b\x86\x08\x2c\x48\xa9\xe4\x74\x41\xd7\x38\x27\x9d\x86\xdd\xb2\x4c\x94\xc4\xc4\xbc\x58\x66\xa9\x8d\xfb\x95\x01\x29\xc9\xa9\xa1\x4b\xb1\x6d\x6e\xdb\x7c\x47\xdf\x32\x27\x7a\x40\x49\x32\x07\xaa\x3d\x64\x3b\x16\x3b\x71\x52\x96\x19\xa3\x29\x6a\x60\x4e\xb5\x62\x60\xca\x8b\x05\xbe\x26\x05\xe7\x54\x94\x45\xae\xec\xb8\x1d\x91\xa1\x62\x17\x80\xf2\x80\xc8\x99\xe2\x7e\x75\xaa\x2c\x7f\x00\x81\x5a\xbc\x41\xcf\x75\x10\xb8\x26\xec\xa0\x15\x28\x2b\x55\x23\xd6\x9f\x72\x26\xc5\x00\x02\x1f\x5a\x67\x46\x0d\xf4\xba\x86\xb6\xf8\x77\xe0\xae\xa1\xfb\x7d\xd0\xe5\x31\x2a\x54\x32\xf5\xb1\x2a\x68\x72\xf0\x3d\x5d\x31\x51\x15\xcf\x0c\x76\x56\xea\xd8\xc2\x9a\xde\x4e\xcc\xe6\xb6\x60\xae\xfc\x2e\xa4\x54\x12\x96\x21\xa1\x57\xaa\xe1\x96\x94\xb0\x68\xa9\xb7\x11\x0b\xfd\x6c\x22\xb6\x2a\x68\xd1\x31\x96\xde\xf0\xeb\x24\x72\x33\x85\xec\x6d\x5f\x6e\x14\x71\x3f\x42\x58\x83\xa5\x8e\x1b\x74\xc3\xf8\x62\xd2\x88\x0e\x3d\x44\xe3\x8b\x46\xfe\x15\xe3\x92\x75\x49\x8b\x29\xd8\xd8\x4f\x59\xc8\x68\x04\x81\xb6\xdb\x2a\x82\xf1\xba\x61\xec\xbc\x4e\x86\x5b\x91\xe1\x72\x71\x90\xc1\xb7\x6f\xb0\x05\xc2\xca\x27\x70\xc3\x5d\xdd\x6b\x32\xee\xed\xc9\x58\x87\x91\xb6\xa0\x59\x3b\x3b\x9d\x6c\x77\x48\x7a\x81\x95\xc7\x0a\xc2\xfb\xd7\xda\xba\x5f\xdf\x63\x90\x85\x70\x2a\x18\xd0\x1b\xa7\x67\xe8\xa4\xeb\x68\xb0\xdf\x87\xff\xa4\xb4\x04\x02\x9c\x4e\x29\xa7\x79\x42\x41\x14\xe8\xde\x60\xba\xe4\x58\xa7\xb8\x2c\xd5\x41\x5a\x40\x44\xe3\x59\x0c\x24\xb7\x65\xc7\xa2\x03\x89\xf6\x20\x0b\x92\x52\x8d\x4c\xc5\x42\x6a\x95\x09\xca\x95\xea\xe5\x9c\x32\x0e\x92\x2e\xca\x4c\xa1\xa8\xce\xc0\x9c\x25\x17\x62\x4e\xae\xac\xc5\x59\x76\x76\x1d\x33\x50\x2e\xa6\x2e\x43\x11\x3b\x54\x02\x39\x84\x53\xe5\xbc\x21\x23\xeb\x62\x29\x07\xba\xe9\x9b\x59\xce\xf0\x0d\x34\x01\xf8\x66\x3b\xcc\xbf\x6f\xc6\xa1\xd4\x1d\x7d\xbd\xdf\x7e\x83\x37\xb8\xaf\x9a\x8e\xbe\x39\x66\x49\x24\xb2\xbd\xd8\x01\xfb\x4d\x7a\x02\x37\x93\x24\x23\x42\xbc\xd3\x5a\xf2\x6a\x60\x10\x50\xc1\x59\x4d\x16\x29\xf5\x2a\x15\x10\xa2\x3a\xdf\x49\xbe\x8b\x2a\x77\x49\x7a\x48\x78\x85\x41\x8b\xe2\x34\xdd\x85\xc7\x96\xe4\x70\x0f\x89\x1d\xd9\x40\xf5\x9c\x5d\xee\x81\xcb\x0e\x6e\xc1\xf8\x9c\x5d\x3a\x20\xcf\xd9\xe5\x56\x69\xad\xd1\xff\x06\x3e\xb0\x1f\xa6\x1b\x31\x1a\x85\x77\xc1\xae\x1c\xed\xfe\xe1\x47\x08\x20\x0a\xa0\x0b\x5e\x73\x2c\x39\x5b\xe8\x7c\x56\x27\x00\xe5\xf5\xb5\x4d\xe9\x73\xb4\x22\x7d\x17\x79\xb9\xa3\xeb\xcc\x81\x69\xf0\xe7\x68\xed\x5f\xcf\x33\xd8\x00\xc6\xd0\xb4\x9e\x1d\xbe\x6e\x00\xe9\x10\xb2\x86\xd2\xef\x7a\x22\xff\x90\xd9\x34\xe6\xb5\x4b\x0c\x95\x6d\xac\xee\x6c\x66\x2b\xd7\xcc\xec\xcb\x56\x93\x58\xd5\x26\x51\xc1\xb6\x5a\x84\xee\xfd\x5f\x90\x46\x95\xcb\x78\xc3\xf2\x8b\xbb\x4c\xd0\x19\xbc\x89\xf0\xe9\x0e\x7c\x44\xa3\x73\xc6\xb7\xe3\x7d\xea\x83\x3d\xdd\x2a\xbc\x8c\xe5\x17\x41\x03\xd6\x17\x5e\xd0\x6d\xf6\xcf\x39\x9d\xb6\x66\x71\xc4\x69\xf1\x31\x23\x62\x8e\x2e\xf6\xd3\x87\x37\x91\xb3\xbd\x55\xf3\xd4\xa7\x94\xbb\x48\xcd\x8e\xac\x57\x92\x6e\xd9\xed\x7e\x52\x76\xa9\xb1\xd9\xe1\x5b\x97\x52\x05\xb0\xb1\x84\x2b\x3a\xda\x29\x98\xdc\x03\x49\xd3\x17\x97\x34\x97\x6f\x98\x90\x34\xa7\x3c\x0a\x39\x15\xec\xef\xea\x60\xd3\xc8\xef\xa9\xe8\x22\x6a\xd9\x75\x9b\xa9\x9d\x3a\xdd\xa1\xa0\x5a\x46\x38\x3b\xff\xb5\x93\xe1\x70\x7c\xd5\xae\xb4\xe4\xcf\x3a\x4d\x56\xe7\xb4\x30\xf3\xf2\x27\x93\xee\xac\x78\x36\x59\xd7\xaf\x75\x1d\x84\xad\x82\x78\x99\x15\x44\x46\x75\xbe\x51\xc5\x4c\x4c\xbc\x23\xef\x54\x5b\x15\xce\xf5\xfb\x10\x74\x5f\xe7\x58\x65\x78\x64\xfe\xc7\xf7\xea\x60\x80\xc8\x52\x60\xb9\x2c\xe0\x1d\x79\xa7\x62\x04\x07\x7f\x27\x56\x91\xb6\x45\x95\x90\x3c\x94\x6a\x10\x9a\x98\x3a\x82\x8a\x42\x9d\x6d\xae\x54\x28\xb1\xc0\xcf\xd8\x48\x29\x20\x42\x39\xc6\xdb\x2e\xd7\xea\x62\x8c\x3d\xc4\x42\x45\x42\x4a\xfa\xea\xf4\xed\x1b\x57\x2c\x3a\x0a\xac\xe5\x42\x73\xc9\xe4\xfa\x2d\x29\x4d\x7e\x06\x20\x78\x10\x0c\x20\x78\x40\x16\xe5\x30\xd0\x07\xb3\xe0\x31\xb6\x64\xb2\x6a\x78\x82\x0d\xb3\xaa\x21\x0c\xc2\x01\x84\x0f\xfe\xb6\x2c\xe4\x30\x34\x30\x61\xa0\x9a\x7e\xf7\xe8\x8f\x55\x4b\x5f\xb7\xac\x1e\xbe\x1c\x86\x6a\x46\xa8\x6f\x33\x27\xcd\x57\xfd\x85\xd7\xf8\xc1\xe3\x27\x41\xf8\xb9\x3f\xe9\xcf\x6a\x43\x84\x48\x34\xae\xd7\x2a\xf6\xc7\x42\xc7\xc0\xfb\x18\x8c\x36\xc6\xc6\xfd\x0c\xa9\x65\x22\x68\x36\x35\x69\xbd\xea\x2b\x10\x92\x51\x59\xdd\xde\x7d\x30\xdb\x5c\xfc\xac\xc8\x0a\x1e\xbf\xd7\x9d\xf5\x05\x98\xa0\x9c\x51\x5b\xa7\x72\x60\x4e\x5d\x4c\x54\x96\x83\xe9\xb5\x22\x07\xbd\xd2\xe2\x6d\xc1\xac\xfa\x6f\x78\x60\x6b\x6a\x55\x50\xfc\x72\x99\x27\x75\xfd\x4b\x95\xd1\xf4\x03\x79\x7f\x35\xaa\xa1\xc9\xbc\x28\x04\xce\xd8\x73\x77\xba\xf9\x9d\xc1\x5b\x0b\x62\x7b\xa4\xef\x52\xdb\x1d\xee\x23\xa7\x3a\xb6\x35\xd4\x3b\x37\x7e\x56\xd0\x4e\x07\x0f\x0f\xad\x74\x9c\xc3\x4e\x73\xc0\x98\x4d\xda\x4e\x50\x2d\xdc\x55\x36\xc0\x7a\xb0\xa0\x92\xb3\xc4\x05\x6e\xff\x4e\x07\x8b\x94\xcb\x42\xc5\xfe\x4a\x7a\x1b\x4a\x18\xb3\x49\x85\x6c\x58\xe1\xba\x76\x8b\x82\x59\xa7\xea\xf1\xa4\xd1\xc2\x61\x0b\xf6\x7a\xac\x73\x94\xd4\x86\xf6\x33\x95\x78\x54\x41\x1b\x42\xdf\xa4\xde\x38\x86\x54\xfa\xec\x1d\x7b\x56\xfa\x86\xe6\x28\xf7\x03\xf7\x2c\x4c\xb5\x2a\x28\x3c\x46\x3c\x95\xf8\x69\x2d\xfe\x36\xb5\x29\xd8\x31\x9d\xc4\x38\x86\x53\xb1\xcc\x64\xbb\xe6\x34\xe9\x71\xc5\xc1\xa4\xf2\x3e\xf6\x9f\x42\x31\x68\x43\x38\x66\x93\xd8\xd4\xf8\x2d\x48\x59\xab\xcf\x2d\x81\xfb\xba\x1a\x80\xae\x1c\x58\x0f\x70\x35\xbb\x9b\x44\x84\xb5\x6f\xd7\x43\xb8\xee\xf8\x79\xa7\x44\x2d\xe6\x81\x5d\xea\x31\xbe\x46\x0d\x18\x9d\xb6\xd3\x28\x6b\x07\x1b\x55\x1a\x1b\xd3\x49\xb4\x85\x69\x63\x0f\x15\xc2\xeb\xe1\xc1\xbd\x7b\xf7\xf0\xba\x55\x50\x2e\x71\xd1\x0a\x14\x2b\xc9\x32\x58\x30\x21\x58\x3e\x03\x21\x69\x29\x62\x05\x89\x3e\x80\x5e\x7d\x74\x7d\x8b\x69\x2e\x0b\xa1\x75\x68\xde\x85\x24\x5c\x45\x3d\xc8\x67\xe3\x42\xe9\xc8\x6b\x75\x0b\x49\xac\xb7\x50\x24\x1b\x83\x9d\xb2\x32\x2f\x54\x2f\xa6\x53\x41\xe5\x9f\x75\xec\x71\xef\xde\xbd\xca\x28\x90\xba\xe2\x62\x08\x12\x1e\xb7\x72\xa2\x7a\xba\x23\xa4\xa6\x0c\xe3\x9e\x16\xc6\xd3\x2c\x2b\xae\x50\x0a\x53\xb5\x8d\x2a\x11\x94\x05\xcb\x25\xb0\x9c\x24\xc9\x92\x93\x64\x8d\xd2\xb8\xa7\x16\xff\x86\x19\xc5\x8e\xb5\xc2\x13\x94\xcb\x83\x07\x9b\xd6\x86\x60\xe3\xb2\x10\x93\x78\xa5\xbc\x0d\x74\xf5\xa4\xf1\x9a\xcd\x32\x73\xaf\x12\xb6\x5e\x86\x3b\xb0\x74\x86\x7a\x44\x59\x88\x6e\x57\xff\x5d\x2d\xea\x36\x54\xca\x3e\x25\x1a\xa7\x52\xfa\xb5\x19\x7e\x7d\x60\x1f\xed\xa4\xf4\xe6\xa3\xf1\x0c\xbd\x85\xf4\x86\xe6\x8a\xae\x9b\x55\xd2\x21\x18\x5e\xaf\xe1\xfe\x57\xdf\x9d\xde\xd7\x63\x8c\x94\xdc\x6d\x82\x72\x5e\xf0\x53\xba\x92\xfb\x04\xa2\x50\x83\x7b\x71\x79\xe8\xc4\xe5\x08\x11\x36\xa1\xfd\xc8\x3c\x7c\x57\xe0\x35\x93\xd9\x33\xf5\x0a\xa6\x69\xe8\x5c\x9c\x59\x6b\x73\x23\xda\x0a\x5d\x67\xe8\xc4\x03\x36\x50\xea\xf7\xe1\x03\xb5\x57\x3f\xee\xa5\xad\xb7\x7b\x6b\xc1\xb8\x7e\xa7\x76\xec\x78\xdb\x13\x64\x2c\xa7\x84\x07\xae\x0f\x30\xb7\x2b\xdb\x96\x81\x0b\x6a\xef\x42\x5c\x07\xae\xdb\x5c\x28\x93\x1e\xf6\x51\xf6\xbc\x1d\xc8\xde\x38\xb8\x88\x6c\xab\x0b\x89\xd7\x1c\x2e\xd0\x82\xac\xbc\x7e\x96\x37\xfa\x99\x77\x45\xa5\x75\x30\x30\xff\x9b\x70\xca\x96\x0a\x5d\x52\xfe\x1c\xd3\xb3\xad\x62\x8c\x5f\xd5\x00\x95\x48\x71\x32\x03\xfd\x9f\xa5\x53\xe4\x5a\x33\x83\xcd\xe3\x85\xb5\xc3\xd5\x1b\xbc\x7c\xb0\xc5\x63\xe6\x1a\xb3\xfe\x78\x48\xfc\xb4\x7e\x66\x2d\x2e\x0a\x56\x67\x78\x57\x11\x74\xcc\x47\xbb\x35\x1e\x26\xe9\x62\x5f\x2c\x0a\xb6\x81\x02\x3f\xe3\x44\x56\x5c\x05\x43\x17\xbc\xc6\x37\x74\x2a\x6d\x41\x8b\x25\xe2\xf4\x3c\x31\x17\x9a\x7e\x97\xc6\xf4\xed\x9b\x6b\x7a\x92\x2e\x1a\x74\x9c\xa6\xbb\x53\xf1\xa3\x19\xc3\x3a\x2e\x58\xfd\x31\x51\xea\x7f\x87\x85\x7a\x3e\x9b\x66\xac\x2c\x69\x1a\x38\xd1\x8b\xe1\xf0\x0e\x23\x37\xe2\x9b\x16\x36\x38\x5d\x14\x97\xf4\x8e\x9c\xdc\x66\xf0\xb5\xdd\x7d\xad\x3d\xae\x9d\x3b\x86\xca\x22\xd7\xae\xd4\x94\x1d\xac\x37\xe2\x6a\xbb\x36\x31\xe0\xd0\xdf\xfd\xfa\x14\xa0\xbe\xb4\xaa\x17\x5c\xe3\x5a\x43\x11\xea\xfa\x00\x98\xc8\xab\xc2\x3b\xe7\x78\xec\x2d\x47\xbc\x87\x69\x5f\x88\xaa\x27\xfe\x75\xe7\x1a\x94\x2c\xb9\xd0\x3c\xf8\xee\xc0\xbf\xdd\xf1\x08\xae\x6e\x20\x88\x95\x36\xdb\x68\x5e\x37\xf2\x26\xed\x78\x74\x86\x7a\x27\xe3\xbe\xaf\xac\x12\x1a\x15\x09\xe4\xd2\xb8\x46\xbd\xe3\xad\x37\x5a\xf4\x4a\xa9\x5b\xb6\xe5\xee\x11\x6e\x8f\xd3\x64\xbd\xc7\x6e\x96\x44\x5d\xcd\x59\x46\xc1\xcb\xa0\xc6\x19\x11\x12\xf7\x30\xef\x83\x37\xdb\xab\x6d\x79\x33\xf1\xea\x0c\xb3\x9b\x9c\x8b\xbc\x12\xc5\x16\xf4\x75\xff\x06\x81\xb6\xa1\x7e\x4d\x49\xeb\xa5\xc6\x8d\x72\x59\xcd\xb9\x68\xab\x0a\x69\x02\x9e\x2f\x59\x96\xfe\xd7\x92\xf2\xf5\x27\xee\x7d\xb1\x8d\x09\xb7\xfa\x1b\x7b\xa7\xd0\xc6\xdc\x00\xd9\xa3\xd9\xd3\xd3\x57\x67\xef\x3f\xbc\x78\xf9\xfa\x2f\xd0\x85\xa0\x4f\x4a\xd6\xbf\x3c\xe9\xff\x4d\xa1\x3c\xc3\xaa\xc5\x1f\xf1\xef\x91\x2d\xf1\x6c\xf9\xa0\x4b\xd3\xea\x9a\x04\x88\x0a\x06\x47\x98\x5d\xdf\x27\xf2\x75\x86\x11\x2e\x71\x5c\x54\x3a\xf1\x76\x8d\x04\x33\xf3\x0f\x68\x9e\x1a\xe4\x36\x12\xbe\x51\x98\xdb\x8b\xee\xaa\x88\xfb\x8b\x3e\x86\x7d\xb1\xa7\x67\x94\x7f\x75\xfa\xfa\x52\x9f\xbe\xea\xde\xf1\x97\x49\x4c\xce\x0b\x2e\x23\xef\x77\x4c\x48\x96\x9d\xd5\xf1\x26\x3c\xe5\x9c\xac\xa3\x2d\x27\x7f\xa7\x0c\xd5\xe8\x7b\xbf\x21\xa8\x51\x8a\x97\xe6\x67\x9c\xfe\x6d\x49\x85\x14\xbe\x82\xbd\xfc\xc2\x96\xaf\x40\xb6\xa6\x23\x1a\x1f\xf4\x36\x3e\x04\x6c\x9c\x43\x2a\xb0\x25\xaf\x82\x0e\xcf\x28\x37\x66\x52\x9f\xc0\xd1\x35\xce\xb9\x99\xf7\x5f\xde\xbe\x79\x25\x65\xf9\x41\x4f\xc8\x96\x8e\xad\xe6\x3c\x2e\x4a\x9a\x47\xe1\x8c\xca\xb0\xa7\xc8\xf4\xf0\x93\x34\xa7\x5f\xd7\x10\x08\x8a\x75\x24\x23\x08\xbf\x88\x22\x0f\x9d\xe1\x39\xc6\xbb\xde\x4f\x54\xcc\x79\x0f\x58\x33\xe7\xda\x0c\xf8\xe1\x6e\xa1\xfd\x6d\x83\xfb\x1d\xe1\xfd\x0b\x64\x3c\x2b\x08\x16\xfa\x28\xbb\x0a\xbd\xcf\x2a\xf6\x09\xee\xc1\xfe\xf2\x57\x9c\x15\xb3\xa8\x05\x25\x5a\x47\xd8\xd8\x4a\x7d\x4d\x41\x9b\xbd\x1d\xdb\xbe\x7e\x1f\x8a\x1c\xd7\x02\xcc\xa8\x14\x40\xf2\x35\xe0\x6b\x55\x05\xd5\xb6\xd0\x9a\x18\xbd\x75\xb6\x73\xad\xd5\x81\x82\x97\x15\x32\x4a\x75\x15\xaf\xa6\xb9\x4b\xef\x2a\x3a\xd9\x9c\x99\xff\x75\x98\x4e\x0c\x15\x12\x7f\x12\x06\x85\x77\x4e\xa7\x05\xa7\xc8\x1f\x88\x65\x92\x50\xe1\x94\x7b\xb9\xdf\xb5\xd4\xf1\x8c\xf9\x00\x42\xb9\x05\xd7\x62\x87\x9b\xc9\xb8\xea\x56\x20\x28\xce\xbf\xd0\x44\x7a\xe9\x37\x83\xc2\xf9\xcc\xd4\xb3\x7f\x57\xe9\xd7\xdb\x14\x77\x34\x82\x13\x0b\x64\xbd\x15\x66\xfc\x4c\xca\xf4\x36\x92\xf1\x9c\xd7\xd8\x09\xff\xbd\x4b\x0c\x4b\xe5\x56\xca\x13\x2a\x9c\xf1\x2a\x40\xd1\x12\x90\xd1\xd5\x9c\x57\x15\x0e\x18\x18\x69\x6b\x7e\xbd\x98\xed\x58\xa1\x6c\x31\x33\xb7\x40\x15\x74\x2c\x78\x02\xa3\xc6\x1e\x18\xf6\x85\x24\x92\x25\x7d\xb6\x98\xf5\xc9\x17\xb2\x3a\x52\x03\x28\x8f\x67\x6c\x1a\x36\xc6\x93\x0c\x97\xe9\x1b\xdd\x12\xc7\x71\x13\x60\xdb\xfa\x37\x20\xe1\xc6\xfd\xad\x77\xdb\x55\xe1\xe9\x54\x05\xa7\x1f\xab\x4a\x32\x4c\x4d\xea\x1a\xdc\x62\x0a\x21\x9e\xe3\x42\x5c\x69\x4e\x05\x5a\xa3\xec\xb4\x91\x7b\x75\x97\x46\x4e\x16\xd4\x4f\xe2\xea\x9f\x8f\x80\x11\xf4\xa3\xf8\xf0\xc7\xce\xe7\xf1\xe7\xf1\x67\x71\x18\x7d\xbe\xea\x76\xba\x9f\xc5\xe1\xe7\xc9\xe7\x09\x76\xf4\x67\xc3\x0a\x5a\x2c\xb5\x44\x70\x62\x26\xc6\x5a\x98\xcd\x97\xd3\x98\xae\x68\x82\x94\x3a\xf5\x55\x84\x19\x62\xfe\xe8\xea\x2f\x69\xc7\x27\x13\xf5\x27\x72\x33\xd6\x2d\x0f\x27\x93\xaa\xf7\x91\x57\xb3\x73\x5f\x8f\x6d\x7e\x58\x55\xd5\xc1\x38\xbf\x6f\xa4\xe0\x2a\x59\xfe\xcc\x2e\x69\x5e\xe7\x7b\x6d\xf6\xc4\xd6\xab\x3c\x7d\xff\xda\xfe\x22\x94\x5a\xfb\xa4\x2c\x79\x51\x72\x46\x24\xad\xa4\xa6\xb0\xc8\xc2\x02\x95\x59\x21\x91\x6c\xb3\xda\x77\xf3\xae\xa0\xfd\xfe\xa4\xdf\x87\x9f\xd6\xb6\x6c\xb1\x67\x6a\x0a\x15\xb5\x2c\x33\xb2\xd0\xd5\x40\x8d\x4b\x0d\x07\x19\x44\x7e\x1a\xde\xd4\x04\xe9\xc6\xf8\xec\x4c\xbd\x9f\x9d\xa9\x48\xea\x6b\xd0\xb8\xa9\xd0\x26\xc3\xf2\x8d\x44\xbe\x12\x31\x76\x3a\xdf\xae\x1f\xf7\x1e\xe2\xcf\x14\x06\x67\x67\x9e\x83\x4a\x8a\x5c\xb2\x7c\x49\x9b\x5e\x08\xf9\xe8\x8e\x0c\x91\x2e\x04\xa3\x30\xa8\x15\x8c\xad\x4a\xbb\x41\xd8\x0b\xdc\xca\x26\x47\x95\xaa\xf7\x1a\x3b\xf1\xf3\xf7\x03\x5b\x35\x59\xe4\xd9\x1a\x8a\x9c\x1a\xd4\x97\x84\x33\x2a\x7a\x55\x3d\x66\x5d\x7b\x5a\xcd\xb1\xfa\x75\x80\xaf\xd7\xc3\xdf\x32\x6f\xbf\x29\xe9\xdd\xc9\xee\xc6\x29\xfa\x7e\x54\x8d\x73\xa6\xd1\xf1\x8f\xd4\x4e\x8f\x95\xaa\x9d\xa7\xaf\x90\x36\xd0\xf1\x4e\x7e\x0c\x90\x42\x78\xd2\x76\x83\x82\x3a\xc1\x2f\xd8\x96\x99\x64\x88\x18\x13\x15\x2d\x9f\x9c\xb7\x4e\xc4\xa9\x11\xfc\x05\x77\xbe\xf8\x82\xae\x45\xb4\xc9\x66\xa7\xce\x51\x3b\x3f\x92\xd9\xa4\xaa\x93\xc5\x38\xa2\xb3\x59\x33\xb8\x01\x6d\x50\x8e\x9c\xdf\x0f\x6b\x59\x5e\x51\x53\x35\xc6\x40\xad\xa3\x6a\x60\x1d\x1f\x4f\x6c\xbd\x62\xc3\x13\x59\xdc\x0d\x5f\x54\x57\xdd\xd2\xaa\xae\x5f\xf4\xa0\xe4\x45\xba\x4c\xb4\x33\x30\x35\x69\x2a\xdc\x56\xf2\x94\x73\xba\x68\xfb\xb6\xa0\x59\x88\xd1\x3c\x1b\x0a\xef\xc3\x4c\xb2\xa9\x23\xc7\xc2\x11\xbe\xed\x78\x80\x76\xa2\x93\xf2\xa1\x02\x0a\x07\x1a\x16\xaf\xf0\x42\x49\xce\xc3\x01\x1c\x5f\x77\x1a\x73\x6f\x6e\xb7\xc8\xef\xef\xc2\xbd\x7e\x2c\x04\x7d\x65\x67\x78\xa0\xc4\xf6\x3f\x01\x00\x00\xff\xff\xe0\xde\x55\x28\x07\x57\x00\x00") +var _webUiStaticJsProm_consoleJs = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xdc\x3c\x7f\x77\xdb\xb8\x91\x7f\xc7\x9f\x62\xc2\xb6\x21\x65\xc9\x94\x9d\xec\xee\x5d\xa5\x28\xfb\xb2\xf9\xb1\xc9\x5d\x92\xcd\x25\x4e\xdb\xad\xa2\xf3\x83\x49\x48\x42\x4c\x91\x2c\x00\xd9\x52\x13\x7f\xf7\x7b\x18\x00\x24\x40\x51\xb2\xec\x5e\xf7\xde\x35\x7f\x30\x26\x30\x18\x0c\x66\x06\x83\x99\xc1\x50\xfd\xc3\x03\x38\x84\x97\xcb\x3c\x91\xac\xc8\x05\xc8\x02\x16\xe4\x82\x02\x93\x40\x89\x60\x94\xab\x96\x2b\xce\x24\x85\x92\x17\x0b\x2a\xe7\x74\x29\x20\x29\x72\x51\x64\x54\xf4\x40\x2c\x93\xb9\xc2\x40\x04\xcc\x38\x29\xe7\x22\x3e\x00\x85\xb2\x7f\x70\xf0\x9e\x17\x8b\x67\x1a\x10\x46\xf0\xf5\x7a\xe8\x35\xc5\xef\x96\x8b\x73\xca\x5f\x16\x7c\x41\xa4\xa4\xdc\x80\xec\x80\x88\x4b\x4e\xa7\x6c\x45\xc5\x4f\x6c\x06\x23\x18\x07\x17\x41\x0f\x82\xb7\xea\xf1\xb3\x7a\x9c\xaa\xc7\x7b\xf5\x78\xa1\x1e\x7f\x55\x8f\x5f\x83\xc9\xde\x38\x4f\x8e\x1f\x7e\xa7\xf1\x32\x44\x8c\xcf\x9f\xf1\x79\x8a\xcf\xf7\xf8\x7c\x81\xcf\xbf\xe2\xf3\x57\xb6\x2f\xfe\x8f\x0b\x92\x65\x88\x7d\xa1\x06\x2e\xd5\x23\x57\x8f\x52\x3d\xa6\xea\x41\xd4\xe3\xef\xea\xb1\x56\x58\x3d\xb4\x67\x42\x72\x56\x9e\x72\xc2\x32\x96\xcf\xfe\x4a\x79\x01\x23\x98\x1a\xa9\x45\xab\x0e\x7c\x3d\x00\x00\x60\x53\x88\x56\x31\xcb\x53\xba\xfa\x65\x1a\x05\x34\xe8\xc0\x68\x04\x47\x27\xb6\x1f\xa0\xdf\x87\xd7\x32\x14\x90\x17\x12\x04\x99\x52\x25\x5e\xc4\xad\xc6\x32\xd5\x23\x12\x46\x73\xc9\xa6\x2c\x51\x40\x44\x4d\x10\x9b\xc1\x9c\xca\x25\xcf\x61\x15\x73\x5a\x66\x24\xa1\x51\xff\x73\xfc\xe3\xf1\xe1\xef\xfb\x3d\x08\xc3\xce\x10\xa1\xae\x0f\x5c\xc8\xe1\x81\x12\x7b\xbf\x0f\xaf\x96\x0b\x92\xb3\xbf\x53\x20\x90\x23\x8b\xe2\x9d\x6c\x9b\x5b\xf0\xcd\x55\x5e\x12\xae\xd0\xc3\x08\x76\x21\x38\xb3\x18\x22\xa4\x67\xd5\xdb\x09\xed\x68\x41\x0f\xe1\xf7\x16\x69\x0f\x4e\x8e\x8f\x8f\x71\xed\x2b\x18\x29\xc2\xc6\xc7\x93\xa1\x21\x53\x43\x9a\xe6\x13\x6c\x56\x12\x7a\x4b\xe4\x3c\x26\xe7\x42\xad\xe8\x31\x54\xc2\xa9\xb8\x2b\x8b\x17\xab\xb2\xc8\x95\x14\x48\x16\x3d\xea\x40\xd7\x60\x52\x08\x14\x7f\x0d\xe4\x6e\x05\x89\x14\xa2\x97\x6c\x45\xd3\xe8\x51\xc7\xc5\xb1\x4d\x22\x3d\x48\x8b\x3c\x94\xb0\x14\x14\x16\x2c\xcb\x58\x7f\xc1\x12\x5e\xf4\xa9\x4c\x62\xb0\x8b\xde\x4f\x6c\xef\x0a\x64\xce\x7b\xbb\xfe\xa6\x0c\x6f\xe6\xc2\x1e\x6b\x7b\xcf\x69\xc2\x84\xc2\xfa\xa8\xd3\xb1\xac\xf9\x4d\xb4\x63\x3c\xb9\xad\xd8\xff\x39\x12\x83\x2b\x26\xe7\x80\x76\x8b\x08\x90\x73\x0a\xe7\x44\xd0\x1e\x70\x22\xe7\xca\x72\xcf\x49\x8e\x74\xee\x27\x34\x63\xff\x7e\xe3\xfd\xa6\x66\x75\xb9\xfa\xf0\xbb\x7f\x91\xcd\xa4\xf1\xb2\x7c\x06\x24\x07\xba\x22\x89\x04\x4e\x4b\x4e\x05\xcd\xad\x55\xdd\x47\x2a\x2f\x70\xe4\xff\x23\x33\x68\xf8\xa9\x85\x07\xdd\x4a\x5c\x37\x9c\xff\x35\xa9\xde\x62\x7b\xe0\x12\x05\x8d\x49\xa7\x24\x91\x05\xaf\x19\x52\xe9\x48\x10\x58\xfd\x58\xc1\x68\x34\x82\x63\xab\x17\xfd\x43\x78\x5e\xa8\x83\x6d\xce\xf2\x59\xac\xfc\x14\x80\x6b\xa0\x99\xa0\x1b\xda\xf4\x64\x54\xab\xd3\xb4\xe0\x10\xa9\x19\xd8\xe8\x78\x08\x0c\x1e\xbb\x64\xc5\x19\xcd\x67\x72\x0e\x0f\x1e\x40\x63\xbc\xa6\x6f\x08\xdd\x2e\xab\x8f\xe0\x15\xf4\xab\x1e\xd3\x54\xd1\xed\x60\x1d\xb3\x49\x7d\xa2\x1a\x12\x6f\x22\x06\xd9\xb2\x85\x9c\xc7\x70\xb2\x41\xc8\xe1\x8d\x84\x20\x46\x9f\x94\x5a\xc6\xe3\x4a\x3c\x46\xbe\x9e\x80\x4f\xd9\x82\x3e\x2b\x72\xc9\x8b\xcc\x15\xa9\x9e\x3f\x2d\x92\xe5\x82\xe6\x32\x9e\x51\xf9\x22\xa3\xea\xcf\x9f\xd6\xaf\xd3\x28\x50\x5e\xe6\x19\xba\x92\x67\xe9\x92\xe3\x46\x39\x13\x73\xce\xf2\x8b\xa0\x13\x17\x79\x92\xb1\xe4\x02\x46\x20\xe7\x4c\xc4\x29\x4d\x38\x25\x82\x3e\x37\x80\xf1\x39\xcb\xd3\x48\x75\xa1\x26\xde\x6a\x8e\x19\x2f\xae\x36\x67\x60\xf9\x3f\x3c\x83\x64\x0b\x7a\x76\x4e\x92\x1d\xf4\xbf\xc8\xd3\xbb\x22\x9e\x16\xfc\x8a\xf0\x74\x3b\xe5\x77\xc3\xcd\xe9\x94\x53\x31\x3f\x3b\x5f\x4a\x59\xe4\x9b\xd8\x4d\x7f\x03\xb3\x5e\x94\x61\x95\x41\x0d\xa3\x5b\xc9\x21\xa8\x11\xd1\x3c\xbd\x1d\x0e\x64\x08\xcd\xd3\x60\x2b\x31\x71\x91\xb3\xbc\x5c\xca\x4a\x00\x4c\x94\x44\x26\xad\xeb\xa8\xa7\xff\xe7\x8f\x32\xec\xfc\x13\xc9\x96\xf4\x76\x6b\xf6\x05\x75\x76\xa9\x30\xa8\xf5\x57\x27\x04\x76\xbf\x61\xe2\xb6\x08\x59\x2e\x29\xbf\x24\x99\xd0\xdc\x74\x90\xbd\xb6\x3d\x18\xce\xfc\x32\xc5\xe0\xe5\x04\xc3\x9a\xef\xf1\x79\x62\xfe\x9b\x07\x68\x36\x36\xcd\x55\x13\x91\xb1\x58\x9e\x79\x52\x03\x32\xe6\x12\xad\xf4\x59\x5a\xf6\x44\x41\xc6\x02\x13\x72\x64\xac\xa9\x9e\x82\xca\x0f\x4d\x0d\xed\x6d\x4c\x3b\x66\x93\x1a\x83\xa4\x2b\xa9\xac\x95\x66\x7d\x0b\xe8\xd0\xf8\x15\x15\x43\x63\x52\x96\x34\x4f\x9f\xcd\x59\x96\x46\x19\x33\x2e\xe8\x36\xcd\x43\xc9\x34\x4e\x6b\xc7\x42\xc6\x25\x2f\x64\x21\xd7\x25\x55\xc2\x41\x77\xc2\xda\x9c\x68\xe3\x28\x76\xc7\x9d\xb1\x9c\x29\xd7\x06\x75\xa7\x9e\xb6\x63\xcf\xbf\xfb\x7b\x0e\xa4\x79\xaa\x7a\xdf\x15\x57\x56\x02\x4d\x7d\xbe\xc3\x0a\x88\x34\x8e\x07\x40\x4e\xaf\x00\xdf\x6f\x47\x0f\x1c\x6a\xcf\xc2\x70\xb7\xe9\x44\xb8\x08\xd4\xf6\x7f\x89\xa7\x99\xd2\x4c\xb5\x86\x60\x1d\x0c\xe0\x87\x63\x38\xd4\x8f\x87\xdf\xc1\x21\x3c\xfa\xe1\x7b\xe5\xdb\x04\x57\x9b\x5d\xff\x86\x1d\x69\xa3\x03\x1b\xe7\x75\x23\xbe\x2f\xf0\x1d\xff\x14\xc1\x00\x4e\x76\x12\x26\x24\x2d\xf5\xaa\xd4\x8e\x51\x63\x4e\x8e\xc5\x96\x4d\xf3\xe8\xd8\xee\x9d\x1e\x04\x0f\xf1\xf9\x03\x3e\x4f\xf4\xcb\x49\x8a\x1d\x69\x80\x73\x9f\x5c\xe1\x1b\x3e\xbf\xc3\xe7\xbf\xe3\xf3\x64\x8d\xed\xeb\xe0\xa0\x99\x48\x68\x17\xd8\x99\xa0\xf2\x15\x11\xf3\xcd\x73\x5a\x6d\x43\xab\x53\x76\x77\x95\x84\xd7\x27\x62\xb4\x5d\xdb\x2b\xc3\x61\x65\x69\xc6\x2b\xeb\x93\xa7\xa8\x0c\x1d\xe8\xa3\x7c\x15\xe4\x15\xcb\xd3\xe2\x2a\xce\x8a\x44\x1f\xb5\x73\x4d\x50\xf0\xbb\x32\x91\x49\x00\x5d\xa0\x79\x52\xa4\xf4\xd3\x87\xd7\xcf\x8a\x85\x76\xe9\xa3\xff\xf8\xf8\xcb\xbb\x58\x79\xeb\xf9\x8c\x4d\xd7\x5a\xd7\xbe\x5a\x62\x06\x15\xe5\x3d\x4b\xc2\xc0\xfe\x71\xad\x34\x6a\x97\xd0\x7c\x75\x6c\x67\x8c\xa1\xb0\x8d\x70\xbb\x74\x64\x84\xb0\x9b\x51\xf5\x54\xe9\x99\x10\x17\x16\x76\x7c\x07\xf5\xd2\xce\x87\x4b\x43\x56\x47\x29\xdd\x58\x38\x62\x12\xcb\x73\xbd\xf6\xe8\xfb\x8e\xd9\x21\xae\x9f\x58\xa1\x72\x38\xf2\xe8\x87\xe3\x63\x87\x1b\xc7\xd7\x36\x0c\x52\xe4\x5d\xfa\x5b\x6f\x93\xac\xba\xab\xde\xcf\x1d\x25\x4f\xd5\xe8\x09\xb3\x39\xe2\x5d\x71\xa5\xc4\xcf\x97\xb4\x11\x77\x59\x06\x5d\x47\x9d\xbd\x54\xd5\x53\x3e\x57\x2c\x76\x8d\xa7\x74\x25\x37\x75\xf7\xc3\x0b\x43\xf3\x07\x3a\x7b\xb1\x2a\xa3\xe0\xbf\xa3\xf1\xf1\xd1\x1f\x27\xdd\x4e\x34\x5e\x5f\xa5\xf3\x85\x98\xfc\xd8\xf9\x7d\x7d\xd6\x2d\xd4\x51\x8d\xcc\x73\xf1\xc6\xd8\x1c\xd5\x48\x6b\x33\x6b\x06\x74\xe0\xab\x5d\x99\x62\xf5\xb0\x4a\x4a\x58\xeb\x89\xf4\xbf\xce\x65\x64\x06\x8c\x4f\x26\xd5\xa4\xcb\x9c\xa9\xc3\xc7\xf6\x3c\x9c\xc0\xb7\x6f\x10\x8a\x70\xd8\x60\x17\x1c\x6e\x35\xc2\x8e\x11\x1c\x2b\x74\x2d\x81\xd7\x7e\xa7\x4e\x1b\x6b\x6b\xb6\x2a\xd4\x68\xcd\xfc\x13\xfe\x82\xae\x81\xe5\xfb\x10\x67\xf5\x0a\x11\xc5\xe5\x52\xcc\xa3\xf1\x3e\x6b\xba\xa0\xeb\x49\x4f\xcd\x33\xa9\x52\x3e\x1a\x85\x28\xb8\x8c\x2a\x8a\x49\x0f\xce\x1d\x51\x9c\xab\x50\xf4\x08\xc8\xf8\x78\x32\x84\xeb\x8e\xef\x95\xc0\x08\x8c\x5f\xa2\x31\xb5\x38\x23\x4a\xc2\x95\x15\xfc\x83\x86\x1b\xb3\x89\xc2\xea\x6d\xde\x4a\x4c\x35\x74\xdf\x85\xee\x40\xb7\x7e\x3d\x69\x0f\xaa\xec\xc8\x7d\x05\xd7\x0c\x51\x76\xdb\xf0\x8f\x34\x29\xf2\x54\xdc\xc9\x94\xb7\xb1\xec\xe6\x33\xaf\xe2\x27\xeb\x76\xdb\xf8\x69\x29\x7a\xdc\x46\xd1\xcd\xe8\x95\x13\x57\xb3\xdf\x7a\x7f\xb7\x44\x30\x74\x87\x5b\x47\x3d\xaa\x9a\xb5\x64\x5c\x69\xed\x27\x9a\x66\x7c\xfa\x1b\x89\x66\x6f\x99\xc0\x11\x9c\x28\x31\x3e\xd1\xe2\x3c\x3a\xda\x25\x9f\x27\xff\x7a\xf2\x71\x08\xd9\x6e\xee\x76\x7a\xf3\xf5\x66\x35\x80\xd6\x93\x8a\x6e\x70\x2f\x3c\xc3\x6b\xbc\xa1\x4d\xf5\x50\x72\xd8\xe2\x86\x8f\x46\x10\x86\x8d\x6c\x67\xbe\xcc\x32\x37\x11\x9e\x12\x49\xdf\x13\x2e\x2b\x9d\x6a\xa2\x89\x45\x99\x31\x19\xf5\xc7\x47\x30\x98\xf4\x3b\xb5\x11\x52\xe4\xc4\x9f\x4e\x9f\x45\x15\x8a\xf1\xf1\xa4\x57\x23\x1c\x9f\x28\x7b\x7a\xe2\xb6\x3c\xf4\xfa\x1f\x79\x6f\xdf\x4d\x6e\xc3\x8e\x5f\xf8\xc7\x1d\x3c\xb1\x0b\x6b\xf3\x26\xed\x69\xac\xfa\x1b\xbc\x51\x4d\x96\x37\x66\x78\xed\xc2\x54\xe2\x13\x35\x32\xc4\xe1\x9c\xbc\xea\xbd\x76\x75\x6e\x7d\xac\x36\xd6\x52\x53\x88\x8e\x64\xb1\xc4\xa0\xc5\xce\xf1\xe9\xf4\xd9\x2b\xd5\x14\x61\xda\xee\x18\x7e\x84\xf0\x38\x84\x6e\x5b\xff\xa0\xa5\xb1\x72\x62\x58\xbe\x94\xb4\x81\xf8\xad\x6e\xdc\x81\xba\x86\x18\xb4\x36\xb7\x30\xe5\xd3\xe9\xb3\x97\xcb\x2c\xfb\x95\x12\x1e\xa9\x43\x2e\x38\x52\x0e\x7b\xe4\x8e\x2e\x72\x39\x8f\x3a\xdd\x93\xba\xdb\xe9\x35\xc1\x40\x17\x02\x08\xa0\x6b\xb6\xb5\xe6\x4a\x17\x82\x81\x82\x36\x8b\xd9\x97\xf1\xa2\x55\x85\x6a\xb6\x37\xf2\x04\x11\x26\x32\x5a\xf3\x38\x76\xaf\x5b\x6d\xab\x43\xdb\x4a\x45\xee\xb8\xf5\x9d\x1c\xdd\xa6\x9e\xf7\xfb\xf0\xda\xf4\xd7\x11\xd8\xc3\xef\xff\x00\x9c\xe4\x33\x0a\x0f\x20\x29\xf2\x4b\xca\x25\x2c\xf0\xd6\x5e\xc4\x2d\x3a\x5c\x69\xb8\xa5\xdd\xdd\x5a\xc8\xef\xdb\x1d\x35\x26\x1a\xef\x7f\x07\x1d\x27\xc7\xe6\xd8\xe3\xdb\x9d\x8b\xad\xeb\xbe\xed\x1a\x8e\xfe\x6f\xd6\x60\x12\x41\x5b\xe8\x6f\x51\x9f\x30\x6c\xd5\x94\xbb\x33\xd1\x8c\xf8\xe7\x39\x15\x26\x74\xdf\x65\x68\xb1\x7b\x34\xc2\x93\xc7\x1a\x5c\x3d\xa4\x2d\x3e\xb4\xf6\x77\xc3\x91\xf4\xfd\xc8\x2a\x13\x39\x63\x42\xf2\x75\x9b\x03\xa9\x06\x23\x54\xc3\xdd\x69\x0c\xad\xd2\x76\xd8\xac\x56\x4f\x16\xf5\x8a\x9d\xf3\xdb\xb0\xa9\x05\xb8\x8e\x78\xd5\xba\xdc\x00\x57\x83\xf9\xde\xc8\xbe\x9e\xc7\x59\x23\xc1\x08\x23\x73\x78\xef\x67\xd9\x3e\x6c\x2a\x9f\xef\xb4\x54\x8e\xc3\xc6\x44\xf7\x1b\xd2\x32\xc9\x8b\x24\xa3\x84\x5b\xa0\xf6\xa1\xc6\xdd\x6a\x47\x3b\xf2\x9c\x0f\x2f\x5e\xba\x3f\x02\x6d\x5c\x1d\xe7\xb2\x7d\x93\xdc\xf7\x9c\x1a\x3f\x37\x1e\x79\xf5\x25\x7b\xab\xb8\x97\x0f\xdd\x4e\xbc\xe1\x82\xa0\xd2\xe7\x41\x4b\xd2\xbe\xb7\x31\xf1\x61\x7d\xf9\x79\xbd\x23\xa3\xdf\x48\x31\xfb\x71\x5e\xbf\x0f\x98\xa4\x2f\xa6\x40\xb2\xcc\xd4\x52\xf5\x60\x29\x68\x0a\xe7\x6b\x50\x21\xb0\x32\xf8\x4a\x15\x1a\x35\x18\x0d\x95\x37\x41\xb9\x07\x82\x10\xcf\xe9\x94\x2c\x33\x69\x73\xa3\x74\x55\xf2\x01\x0a\xad\x67\x0b\x83\x5e\xac\x4a\x4e\x85\x50\x32\x93\x85\x51\x6f\x78\x46\x72\x38\xa7\x40\x20\x33\xe4\xe9\x8c\x13\x1e\x37\x79\x91\xd2\x06\x8e\xe7\xbf\xbc\xc5\x66\x85\x01\x6b\x84\xcc\x36\x5d\xe6\x29\xe5\xb6\x8e\xc8\xfd\xd7\xef\xc3\xab\xe2\x0a\xb2\x22\x9f\x61\x05\x83\x06\x67\x02\x8a\x4b\xca\x7b\xc0\x72\x10\x9a\xcd\x6a\x70\x9d\xc7\xba\x65\x3a\xbc\xd7\x3e\xf3\xe9\x9c\xaa\x78\x7c\x85\xec\xad\x67\xa7\x4a\xaa\x44\xaa\x19\xab\x4c\xd9\xbe\x33\x9a\x01\x3d\x4c\x68\xa6\x72\xee\xf0\x47\x2d\x95\xb2\xd9\x1c\xd9\x58\xcf\x96\xb2\xcb\x1e\xd0\x55\x92\x2d\x53\xa6\x98\xc0\x64\x46\x05\x90\x3c\x85\x8c\xce\xa8\x59\x79\x0b\xf1\x95\x40\x65\x01\x64\x29\x8b\xa3\x94\x4a\x9a\xd8\x7a\xad\x39\xce\x34\x80\x87\xc7\xc7\xff\xf0\xe4\x0b\x96\x0f\x20\x50\x73\x04\x16\xd7\x5b\x96\xb3\xc5\x72\x01\xbf\x1e\x91\x15\x13\x3a\x2d\xd5\x83\xd4\x21\x29\x2b\xae\xa8\x90\xca\xc9\x23\xba\x1b\x31\x91\xd5\x00\x75\x61\xca\x72\x9a\xf6\x10\x13\x59\xdd\x80\x69\xce\x66\xf3\x4d\x54\x9c\x2a\x95\xa2\x7c\x00\x61\xc6\x72\x1a\xf6\xb4\x44\xd7\x25\x55\x2b\xb4\x1b\xa8\x28\x75\x5d\x23\xe1\xd4\xc0\xe1\xe2\x42\xc2\x29\x09\x51\x87\xc9\xa2\xa9\xc3\x7f\x9e\x13\xa9\xe6\x4d\xd4\x4e\x2c\xb3\x42\x0a\x9f\x1e\xc9\xd7\xc8\xab\x02\xd2\xa2\x5d\x34\x02\x2b\x25\x15\x90\xf2\x73\x8a\x9c\x9c\x67\x74\x8b\x14\x5f\x4f\x81\x98\x3d\xd5\x03\x26\xc3\x2c\xc3\x02\x2c\x39\x27\x32\x86\xf1\x18\x32\x72\x4e\x33\x98\x4c\xe0\x8a\x65\x99\xda\x89\x98\xf4\x65\x72\x29\x69\xba\x0b\xa5\x3d\x18\x0c\xce\x73\x8a\xcb\xa1\xa9\xae\x19\x22\xb0\x20\xa5\xe2\xd3\x05\x5d\xe3\x9a\x74\x1a\x76\xcb\x36\x51\x1c\x13\xf3\x62\x99\xa5\xd6\xef\x57\x0a\xa4\x38\xa7\x86\x2e\xc5\xb6\xb5\x6d\xb3\x1d\x7d\x4b\x9c\xe8\x01\x25\xc9\x1c\xa8\xb6\x90\xed\x58\xec\xc2\x49\x59\x66\x8c\xa6\x28\x81\x39\xd5\x82\x81\x29\x2f\x16\xf8\x9a\x14\x9c\x53\x51\x16\xb9\xd2\xe3\x76\x44\x66\x16\xbb\x01\x94\x05\x44\xca\x14\xf5\xab\x53\xa5\xf9\x03\x08\xd4\xe6\x0d\x7a\xae\x81\xc0\x3d\x61\x07\xad\x40\x69\xa9\x1a\xb1\xfe\x94\x33\x29\x06\x10\xf8\xd0\x3a\x33\x6a\xa0\xd7\x35\xb4\xc5\xbf\x03\x77\x0d\xdd\xef\x83\x2e\x8f\x51\xae\x92\xa9\x8f\x55\x4e\x93\x83\xef\xe9\x8a\x89\xaa\x78\x66\xb0\xb3\x52\xc7\x16\xd6\xf4\x76\x62\x36\xb7\x05\x73\x65\x77\x21\xa5\x92\xb0\x0c\x27\x7a\xa5\x1a\x6e\x39\x13\x16\x2d\x99\xe9\x9e\x15\x59\xc1\x41\x24\x73\xaa\xd5\xe5\x9c\xd6\xa7\x9a\x15\x63\x75\xcc\x50\x86\x95\x6b\xb5\xc6\xcc\xe9\x0a\x12\x85\x41\x23\x4b\x8a\x94\x0a\x28\x38\x14\x79\xc5\xb6\xc4\x9d\x40\x29\xa5\x00\xb1\x2c\xcb\x82\x4b\x3d\xcb\x07\x96\x5c\x88\x39\xb9\x52\xab\x41\xd8\x8f\x08\x6a\x36\xfd\x86\xc3\xf6\xb3\x71\x2b\x2b\xcf\x4a\x3b\x82\xda\x2b\xa9\x33\xdd\xcd\x3c\xb7\x77\xc6\xba\xae\xce\xfd\x08\x61\x0d\x96\xda\xb9\xd1\x0d\xe3\x8b\x49\xc3\x85\xf5\x10\x8d\x2f\x1a\x49\x62\x74\x9e\xd6\x25\x2d\xa6\x60\x1d\x54\xa5\xc6\xa3\x11\x04\x7a\x73\x55\x6e\x96\xd7\x0d\x63\xe7\x75\x32\xdc\x8a\x0c\xf7\xb4\x83\x0c\xbe\x7d\x83\x2d\x10\x96\x3f\x81\xeb\x93\xeb\x5e\x73\x2d\xd0\x9e\x31\x76\x08\x69\xf3\xec\xb5\x45\xd6\x37\x02\xce\x94\x9e\xf7\xe7\x91\x82\xf0\xfe\xdd\xbb\xee\xd7\x97\x2d\x64\x21\x9c\x32\x0b\x3c\x32\xd2\x33\x3c\x49\x6a\x97\xb5\xdf\x87\xff\xa4\xb4\x04\x02\x9c\x4e\x29\xa7\x79\x42\x41\x14\x68\x83\x61\xba\xe4\xa8\x92\xcb\x52\x45\xfb\x02\x22\x1a\xcf\x62\x20\xb9\xad\x8d\x16\x1d\x48\xb4\xee\x2e\x48\x4a\x35\x32\xa3\xda\x4b\x41\xb9\x12\xbd\x9c\x53\xc6\x41\xd2\x45\x99\x29\x14\x55\xa0\xce\x8d\x62\x5a\x8d\xb3\xe4\xec\x8a\x85\x90\x2f\xa6\x78\x44\x4d\x76\xa8\x18\x72\x08\xa7\xea\x84\x81\x8c\xac\x8b\xa5\x1c\xe8\xa6\x6f\xc6\xe6\xc0\x37\xd0\x13\xc0\x37\xdb\x61\xfe\x7d\x33\x56\xaf\xee\xe8\x6b\xa7\xe0\x1b\xbc\xc1\xc3\xdf\x74\xf4\x4d\x2c\x28\x71\x92\xed\x15\x19\xd8\x6f\x72\x28\x78\xe2\x25\x19\x11\xe2\x9d\x96\x92\x57\xa8\x83\x80\x0a\xce\x4a\xb2\x48\xa9\x57\x4e\x81\x10\x55\x10\x2a\xf9\xae\x59\xb9\x3b\xa5\x87\x84\x57\x18\x34\x2b\x4e\xd3\x5d\x78\x6c\xdd\x10\xf7\x90\xd8\x91\x0d\x54\xcf\xd9\xe5\x1e\xb8\xec\xe0\x16\x8c\xcf\xd9\xa5\x03\xf2\x9c\x5d\x6e\xe5\xd6\x1a\x0f\x89\xc0\x07\xf6\x63\x09\xc3\x46\x23\xf0\x2e\xd8\x9d\xa3\xcf\x28\xf8\x11\x02\x88\x02\xe8\x82\xd7\x1c\x4b\xce\x16\x3a\xe9\xd6\x09\x40\x1d\x4d\x5a\xa7\x74\xb0\xaf\xa6\xbe\x0b\xbf\xdc\xd1\x75\x7a\xc3\x34\xf8\x6b\xb4\xfa\xaf\xd7\x19\x6c\x00\xa3\xff\x5c\xaf\x0e\x5f\x37\x80\xb4\x9f\x5b\x43\xe9\x77\xbd\x90\x7f\x48\x6d\x1a\xeb\xda\xc5\x86\x4a\x37\x56\x77\x56\xb3\x95\xab\x66\xf6\x65\xab\x4a\xac\x6a\x95\xa8\x60\x5b\x35\x42\xf7\xfe\x2f\x70\xa3\x4a\xb8\xbc\x61\xf9\xc5\x5d\x16\xe8\x0c\xde\x44\xf8\x74\x07\x3e\xa2\xd1\x39\xe3\xdb\xf1\x3e\xf5\xc1\x9e\x6e\x65\x5e\xc6\xf2\x8b\xa0\x01\xeb\x33\x2f\xe8\x36\xfb\xe7\x9c\x4e\x5b\x53\x4d\xe2\xb4\xf8\x98\x11\x31\x47\x13\xfb\xe9\xc3\x9b\xc8\x39\xde\xaa\x75\xea\x50\xea\x2e\x5c\xb3\x23\xeb\x9d\xa4\x5b\x76\x9b\x9f\x94\x5d\x6a\x6c\x76\xf8\xd6\xad\x54\x01\x6c\x6c\xe1\x6a\x1e\x6d\x14\x4c\x82\x84\xa4\xe9\x8b\x4b\x9a\xcb\x37\x4c\x48\x9a\x53\x1e\x85\x9c\x0a\xf6\x77\x15\x7d\x35\x92\x90\xca\xbb\x88\x5a\x4e\xdd\x66\xfe\xa9\xce\xc9\x28\xa8\x96\x11\xce\xc9\x7f\xed\xa4\x61\x1c\x5b\xb5\x2b\x77\xfa\xb3\xce\xe5\xd5\x89\x37\x4c\x0f\xfd\xc9\xe4\x64\x2b\x9a\x4d\x6a\xf8\x6b\x5d\xac\x61\x4b\x35\x5e\x66\x05\x91\x51\x9d\x14\x55\x3e\x13\x13\xef\xc8\x3b\xd5\x56\xb9\x73\xfd\x3e\x04\xdd\xd7\x39\x96\x42\x1e\x99\xff\xf1\xbd\x8a\x5e\x10\x59\x0a\x2c\x97\x05\xbc\x23\xef\x94\x8f\xe0\xe0\xef\xc4\x2a\x1c\xb0\xa8\x12\x92\x87\x52\x0d\x42\x15\x53\x71\xb2\x28\x54\x00\x76\xa5\x5c\x89\x05\x7e\x6b\x47\x4a\x01\x11\xf2\x31\xde\x76\x03\x58\x57\x8c\xec\xc1\x16\x2a\x12\x52\xd2\x57\xa7\x6f\xdf\xb8\x6c\xd1\x5e\x60\xcd\x17\x9a\x4b\x26\xd7\x6f\x49\x69\x92\x48\x00\xc1\x83\x60\x00\xc1\x03\xb2\x28\x87\x81\x8e\x1e\x83\xc7\xd8\x92\xc9\xaa\xe1\x09\x36\xcc\xaa\x86\x30\x08\x07\x10\x3e\xf8\xdb\xb2\x90\xc3\xd0\xc0\x84\x81\x6a\xfa\xdd\xa3\x3f\x56\x2d\x7d\xdd\xb2\x7a\xf8\x72\x18\xaa\x15\xa1\xbc\xcd\x9a\x34\x5d\xf5\x67\x68\xe3\x07\x8f\x9f\x04\xe1\xe7\xfe\xa4\x3f\xab\x15\x11\x22\xd1\xb8\x03\xac\xc8\x1f\x0b\xed\x03\xef\xa3\x30\x5a\x19\x1b\x97\x48\xa4\xe6\x89\xa0\xd9\xd4\xe4\x1e\xab\x4f\x55\x48\x46\x65\x75\xc5\x58\xc5\x1f\x18\x09\xc5\xef\x75\x67\xf4\x55\x98\x30\xc4\x71\x59\x63\x27\x3e\xb9\xae\xcc\x87\xa0\x9c\x51\x5b\x6d\x73\x60\x62\x47\x26\x2a\xd5\xc2\x70\xaa\xc8\x41\x6f\xc5\x78\x9b\xb7\xab\xfe\x1b\x1e\xd8\xca\x60\xe5\x35\xbf\x5c\xe6\x49\x5d\xc5\x53\xe5\x65\x7d\x4f\xdf\xdf\xae\x6a\x68\x32\x2f\x0a\x81\x2c\xf1\xec\xa1\x6e\x7e\x67\xf0\xd6\x9c\xda\x1e\x0a\xb8\xb3\xed\x8e\x07\x90\x52\xed\xfc\x9a\xd9\x3b\x37\x7e\x1c\xd1\x3e\x0f\x46\x17\xad\xf3\x38\xd1\x50\x73\xc0\x98\x4d\xda\x42\xac\x16\xea\x2a\x25\x61\x3d\x58\x50\xc9\x59\xe2\x02\xb7\x7f\x6d\x84\xa5\xd6\x65\xa1\x82\x03\xc5\xbd\x0d\x21\x8c\xd9\xa4\x42\x36\xac\x70\x5d\xbb\xa5\xcd\xac\x53\xf5\x78\xdc\x68\xa1\xb0\x05\x7b\x3d\xd6\x89\x35\xb5\xa2\xfd\x4c\x25\xc6\x32\xa8\x43\x68\xbc\xd4\x1b\x47\x9f\x4b\x67\x10\x62\x4f\x4b\xdf\xd0\x1c\xf9\x7e\xe0\x06\xcb\x54\x8b\x82\xc2\x63\xc4\x53\xb1\x9f\xd6\xec\x6f\x13\x9b\x82\x1d\xd3\x49\x8c\x63\x38\x15\xcb\x4c\xb6\x4b\x4e\x4f\x3d\xae\x28\x98\x54\xe6\xc9\xfe\x53\x28\x06\x6d\x08\xc7\x6c\x12\x9b\x4a\xc5\x05\x29\x6b\xf1\xb9\x85\x7c\x5f\x57\x03\xd0\xf5\x0f\xeb\x01\x6e\x77\xf7\x14\x89\xb0\x82\xef\x7a\x08\xd7\x1d\x3f\x7b\x86\x5b\x79\x60\x6d\x81\xde\xd9\x51\x03\x46\x27\x1f\x35\xca\xda\x02\x47\x95\xc4\xc6\x74\x12\x6d\x21\xda\xe8\x43\x85\xf0\x7a\x78\x70\xef\xde\x3d\xbc\x34\x16\x94\x4b\xdc\xb4\x02\xd9\x4a\xb2\x0c\x16\x4c\x08\x96\xcf\x40\x48\x5a\x8a\x58\x41\xa2\x0d\xa0\x57\x1f\x5d\xdb\x62\x9a\xcb\x42\x68\x19\x9a\x77\x21\x09\x57\x6e\x11\xd2\xd9\xb8\x16\x3b\xf2\x5a\xdd\x72\x18\x6b\x2d\xd4\x94\x8d\xc1\x4e\x71\x9c\xe7\xcb\x17\xd3\xa9\xa0\xf2\xcf\xda\x39\xb9\x77\xef\x5e\xa5\x14\x38\xbb\xa2\x62\x08\x12\x1e\xb7\x52\xa2\x7a\xba\x23\x9c\x4d\x29\xc6\x3d\xcd\x8c\xa7\x59\x56\x5c\x21\x17\xa6\xea\x9c\x55\x2c\x28\x0b\x96\x4b\x60\x39\x49\x92\x25\x27\xc9\x1a\xb9\x71\x4f\x6d\xfe\x0d\x35\x8a\x1d\x6d\x85\x27\xc8\x97\x07\x0f\x36\xb5\x0d\xc1\xc6\x65\x21\x26\xf1\x4a\x59\x1b\xe8\xea\x45\xe3\x65\xa1\x25\xe6\x5e\xc5\x6c\xbd\x0d\x77\x60\xe9\x0c\xf5\x88\xb2\x10\xdd\xae\xfe\xbb\xda\xd4\x6d\xa8\x94\x7e\x4a\x54\x4e\x25\xf4\x6b\x33\xfc\xfa\xc0\x3e\xda\xa7\xd2\xa7\x93\xc6\x33\xf4\x36\xd2\x1b\x9a\xab\x79\xdd\xb4\x93\xf6\xd1\xf0\x92\x10\x0f\xc8\xfa\x06\xf8\xbe\x1e\x63\xb8\xe4\x1e\x13\x94\xf3\x82\x9f\xd2\x95\xdc\xc7\x53\x85\x1a\xdc\x73\xdc\x43\xc7\x71\x47\x88\xb0\x09\xed\xbb\xee\xe1\xbb\x02\x2f\xcb\xcc\x99\xa9\x77\x30\x4d\x43\xe7\xfa\xcf\x6a\x9b\xeb\xf2\x56\xe8\x3a\x43\xc7\x61\xb0\x9e\x54\xbf\x0f\x1f\xa8\xbd\xc0\x72\xaf\x9e\xbd\xe3\x5d\x33\xc6\xb5\x3b\xb5\x61\xc7\x3b\xab\x20\x63\x39\x25\x3c\x70\x6d\x80\xb9\x23\xda\xb6\x0d\x5c\x50\x7b\xa3\xe3\x1a\x70\xdd\xe6\x42\x99\x24\xb7\x8f\xb2\xe7\x9d\x40\xf6\xde\xc4\x45\x64\x5b\x5d\x48\xbc\xac\x71\x81\x16\x64\xe5\xf5\xb3\xbc\xd1\xcf\xbc\x8b\x36\x2d\x83\x81\xf9\xdf\xf8\x5b\xb6\xe0\xe9\x92\xf2\xe7\x98\x64\x6e\x65\x63\xfc\xaa\x06\xa8\x58\x8a\x8b\x19\xe8\xff\xec\x3c\x45\xae\x25\x33\xd8\x8c\x3f\xac\x1e\xae\xde\xe0\x15\x8a\x2d\x81\x33\x97\xb1\xf5\x27\x50\xe2\xa7\xf5\x33\xab\x71\x51\xb0\x3a\xc3\x1b\x97\xa0\x63\x3e\x3d\xae\xf1\x30\x49\x17\xfb\x62\x51\xb0\x0d\x14\xf8\x31\x2a\x92\xe2\x0a\x18\xba\xe0\x35\xbe\xa1\x53\x69\xcb\x72\xec\x24\x4e\xcf\x13\x73\x2d\xeb\x77\x69\x4c\xdf\xbe\xb9\xaa\x27\xe9\xa2\x31\x8f\xd3\x74\xf7\x59\x7c\x6f\xc6\x90\x8e\x1b\x56\x7f\x12\x95\xfa\x5f\x93\xa1\x9c\xcf\xa6\x19\x2b\x4b\x9a\x06\x8e\xf7\x62\x28\xbc\xc3\xc8\x0d\xff\xa6\x85\x0c\x4e\x17\xc5\x25\xbd\x23\x25\xb7\x19\x7c\x6d\x4f\x5f\xab\x8f\x6b\xe7\xa6\xa4\xd2\xc8\xb5\xcb\x35\xa5\x07\xeb\x0d\xbf\xda\xee\x4d\x74\x38\xf4\xd7\xcb\xfe\x0c\x50\x5f\xbd\xd5\x1b\xae\x71\x39\xa3\x26\xea\xfa\x00\x98\xe9\xab\xdc\x3b\x27\x7e\xf6\xb6\x23\xde\x26\xb5\x6f\x44\xd5\x13\xff\xba\x73\x0f\x4a\x96\x5c\x68\x1a\x7c\x73\xe0\xdf\x51\x79\x13\xae\x6e\x98\x10\xeb\x85\xb6\xcd\x79\xdd\x48\xac\xb4\xe3\xd1\x29\xec\x9d\x84\xfb\xb6\xb2\xca\x78\x54\x53\x20\x95\xc6\x34\xea\x13\x6f\xbd\xd1\xa2\x77\x4a\xdd\xb2\x2d\xb9\x8f\x70\x7b\x84\x9b\xf5\x19\xbb\x59\xd8\x75\x35\x67\x19\x05\x2f\xc5\x1a\x67\x44\x48\x3c\xc3\xbc\xcf\xf6\x6c\xaf\xd6\xe5\xcd\xcc\xac\x33\xcc\x1e\x72\x2e\xf2\x8a\x15\x5b\xd0\xd7\xfd\x1b\x13\xb4\x0d\xf5\x2b\x63\x5a\x6f\x3d\x6e\xe4\xcb\x6a\xce\x45\x5b\x6d\x4b\x13\xf0\x7c\xc9\xb2\xf4\xbf\x96\x94\xaf\x3f\x71\xef\xbb\x73\xcc\xc8\xd5\xbf\x14\xe0\x94\x0b\x99\x2b\x22\x1b\x9a\x3d\x3d\x7d\x75\xf6\xfe\xc3\x8b\x97\xaf\xff\x02\x5d\x08\xfa\xa4\x64\xfd\xcb\x93\xfe\xdf\x14\xca\x33\xac\xbd\xfc\x11\xff\x1e\xd9\x42\xd5\x96\xcf\xd2\xf4\x5c\x5d\x93\x21\x51\xce\xe0\x08\xd3\xef\xfb\x78\xbe\xce\x30\xc2\x25\x8e\x8b\x4a\xc7\xdf\xae\x91\x60\xea\xfe\x01\xcd\x53\x83\xdc\x7a\xc2\x37\x32\x73\x7b\xe9\x60\xe5\x71\x7f\xd1\x61\xd8\x17\x1b\x3d\x23\xff\xab\xe8\xeb\x4b\x1d\x7d\xd5\xbd\xe3\x2f\x93\x98\x9c\x17\x5c\x46\xde\xaf\xb1\x90\x2c\x3b\xab\xfd\x4d\x78\xca\x39\x59\x47\x5b\x22\x7f\xa7\x98\xd6\xc8\x7b\xbf\x21\x28\x51\x8a\x57\xff\x67\x9c\xfe\x6d\x49\x85\x14\xbe\x80\xbd\xfc\xc2\x96\x6f\x59\xb6\xa6\x23\x1a\x9f\x25\x37\x3e\x67\x6c\xc4\x21\x15\xd8\x92\x57\x4e\x87\xa7\x94\x1b\x2b\xa9\x23\x70\x34\x8d\x73\x6e\xd6\xfd\x97\xb7\x6f\x5e\x49\x59\x7e\xd0\x0b\xb2\x05\x70\xab\x39\x8f\x8b\x92\xe6\x51\x38\xa3\x32\xec\xa9\x69\x7a\xf8\x61\x9d\xd3\xaf\x2b\x21\x04\xc5\x6a\x98\x11\x84\x5f\x44\x91\x87\xce\xf0\x1c\xfd\x5d\xef\x87\x36\xe6\xbc\x07\xac\x99\x94\x6d\x3a\xfc\x70\x37\xd7\xfe\xb6\xce\xfd\x0e\xf7\xfe\x05\x12\x9e\x15\x04\xcb\x95\x94\x5e\x85\xde\xc7\x21\xfb\x38\xf7\x60\x7f\xbf\x2c\xce\x8a\x59\xd4\x82\x12\xb5\x23\x6c\x1c\xa5\xbe\xa4\xa0\x4d\xdf\x8e\x6d\x5f\xbf\x0f\x45\x8e\x7b\x01\x66\x54\x0a\x20\xf9\x1a\xf0\xb5\xaa\xe5\x6a\xdb\x68\x4d\x8c\xde\x3e\xdb\xb9\xd7\x6a\x47\xc1\xcb\x0a\x19\xa1\xba\x82\x57\xcb\xdc\x25\x77\xe5\x9d\x6c\xae\xcc\xff\xc6\x4d\x27\x86\x0a\x89\x3f\x6c\x83\xcc\x3b\xa7\xd3\x82\x53\xa4\x0f\xc4\x32\x49\xa8\x70\x8a\xd6\xdc\xaf\x73\x6a\x7f\xc6\x7c\xc6\xa1\xcc\x82\xab\xb1\xc3\xcd\x64\x5c\x75\x6d\x10\x14\xe7\x5f\x68\x22\xbd\xf4\x9b\x41\xe1\x7c\x2c\xeb\xe9\xbf\x2b\xf4\xeb\x6d\x82\x3b\x1a\xc1\x89\x05\xb2\xd6\x0a\x33\x7e\x26\x65\x7a\x1b\xce\x78\xc6\x6b\xec\xb8\xff\xde\x2d\x87\x9d\xe5\x56\xc2\x13\xca\x9d\xf1\xea\x58\x51\x13\x90\xd0\xd5\x9c\x57\x25\x10\xe8\x18\x69\x6d\x7e\xbd\x98\xed\xd8\xa1\x6c\x31\x33\xd7\x44\x15\x74\x2c\x78\x02\xa3\xc6\x19\x18\xf6\x85\x24\x92\x25\x7d\xb6\x98\xf5\xc9\x17\xb2\x3a\x52\x03\x28\x8f\x67\x6c\x1a\x36\xc6\x93\x0c\xb7\xe9\x1b\xdd\x12\xc7\x71\x13\x60\xdb\xfe\x37\x20\xe1\xc6\x05\xaf\x77\x1d\x56\xe1\xe9\x54\x65\xb3\x1f\xab\x7a\x38\x4c\x4d\xea\x4a\xe2\x62\x0a\x21\xc6\x71\x21\xee\x34\xa7\x8e\xae\x51\x3c\xdb\xc8\xbd\xba\x5b\x23\x27\x0b\xea\x27\x71\xf5\x8f\x60\xc0\x08\xfa\x51\x7c\xf8\x63\xe7\xf3\xf8\xf3\xf8\xb3\x38\x8c\x3e\x5f\x75\x3b\xdd\xcf\xe2\xf0\xf3\xe4\xf3\x04\x3b\xfa\xb3\x61\x05\x2d\x96\x9a\x23\xb8\x30\xe3\x63\x2d\xcc\xe1\xcb\x69\x4c\x57\x34\xc1\x99\x3a\xf5\x5d\x85\x19\x62\xfe\xe8\xea\xef\x81\xc7\x27\x13\xf5\x27\x52\x33\xd6\x2d\x0f\x27\x93\xaa\xf7\x91\x57\xd4\x73\x5f\x8f\x6d\x7e\x1e\x56\x15\xca\x38\xbf\xd2\xa4\xe0\x2a\x5e\xfe\xcc\x2e\x69\x5e\xe7\x7b\x6d\xf6\xc4\x16\xb4\x3c\x7d\xff\xda\xfe\xae\x95\xda\xfb\xa4\x2c\x79\x51\x72\x46\x24\xad\xb8\xa6\xb0\xc8\xc2\x02\x95\x59\x21\x75\x49\x56\x83\xed\x9b\x77\x05\xed\x17\x2c\xfd\x3e\xfc\xb4\xb6\xc5\x97\x3d\x53\x19\xa9\x66\xcb\x32\xc3\x0b\x5d\x2e\xd4\xb8\xd4\x70\x90\x41\xe4\xa7\xe1\x4d\xd1\x90\x6e\x8c\xcf\xce\xd4\xfb\xd9\x99\xf2\xa4\xbe\x06\x8d\x9b\x0a\xad\x32\x2c\xdf\x48\xe4\x2b\x16\x63\xa7\xf3\x05\xfe\x71\xef\x21\xfe\xd8\x62\x70\x76\xe6\x19\xa8\xa4\xc8\x25\xcb\x97\xb4\x69\x85\x90\x8e\xee\xc8\x4c\xd2\x85\x60\x14\x06\xb5\x80\xb1\x55\x49\x37\x08\x7b\x81\x5b\xfa\xe4\x88\x52\xf5\x5e\x63\x27\x7e\xc4\x7f\x60\x6b\x3f\x8b\x3c\x5b\x63\x7d\x9c\x46\x7d\x49\x38\xa3\xa2\x57\x55\x95\xd6\x15\xb4\xd5\x1a\xab\xdf\x38\xf8\x7a\x3d\xfc\x2d\xf3\xf6\x9b\x9c\xde\x9d\xec\x6e\x44\xd1\xf7\xa3\x6a\x9c\xb3\x8c\x8e\x1f\x52\x3b\x3d\x96\xab\x76\x9d\xbe\x40\xda\x40\xc7\x3b\xe9\x31\x40\x0a\xe1\x49\xdb\x0d\x0a\xca\x04\xbf\xc3\x5b\x66\x92\x21\x62\x4c\x54\xb4\x7c\x38\xdf\xba\x10\xa7\x88\xf0\x17\x3c\xf9\xe2\x0b\xba\x16\xd1\x26\x99\x9d\x3a\x47\xed\xfc\xd4\x67\x73\x56\x9d\x2c\xc6\x11\x9d\xcd\xa2\xc2\x0d\x68\x83\x72\xe4\xfc\x0a\x5a\xcb\xf6\x8a\x9a\xa2\x31\x0a\x6a\x0d\x55\x03\xeb\xf8\x78\x62\x0b\x1a\x1b\x96\xc8\xe2\x6e\xd8\xa2\xba\x12\x94\x56\x5f\x27\x88\x1e\x94\xbc\x48\x97\x89\x36\x06\xa6\x68\x4d\xb9\xdb\x8a\x9f\x72\x4e\x17\x6d\x5f\x48\x34\x2b\x35\x9a\xb1\xa1\xf0\x3e\x2f\x25\x9b\x32\x72\x34\x1c\xe1\xdb\xc2\x03\xd4\x13\x9d\x94\x0f\x15\x50\x38\xd0\xb0\x78\x85\x17\x4a\x72\x1e\x0e\xe0\xf8\xba\xd3\x58\x7b\xf3\xb8\x45\x7a\x7f\x17\xee\xf5\x93\x27\x68\x2b\x3b\xc3\x03\xc5\xb6\xff\x09\x00\x00\xff\xff\x61\xe9\xbe\x39\xcd\x57\x00\x00") func webUiStaticJsProm_consoleJsBytes() ([]byte, error) { return bindataRead( @@ -461,7 +461,7 @@ func webUiStaticJsProm_consoleJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/static/js/prom_console.js", size: 22279, mode: os.FileMode(420), modTime: time.Unix(1497884603, 0)} + info := bindataFileInfo{name: "web/ui/static/js/prom_console.js", size: 22477, mode: os.FileMode(420), modTime: time.Unix(1499174554, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -481,7 +481,7 @@ func webUiStaticVendorBootstrap331CssBootstrapThemeMinCss() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/static/vendor/bootstrap-3.3.1/css/bootstrap-theme.min.css", size: 19835, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/vendor/bootstrap-3.3.1/css/bootstrap-theme.min.css", size: 19835, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -501,7 +501,7 @@ func webUiStaticVendorBootstrap331CssBootstrapMinCss() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/static/vendor/bootstrap-3.3.1/css/bootstrap.min.css", size: 113498, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/vendor/bootstrap-3.3.1/css/bootstrap.min.css", size: 113498, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -521,7 +521,7 @@ func webUiStaticVendorBootstrap331FontsGlyphiconsHalflingsRegularEot() (*asset, return nil, err } - info := bindataFileInfo{name: "web/ui/static/vendor/bootstrap-3.3.1/fonts/glyphicons-halflings-regular.eot", size: 20335, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/vendor/bootstrap-3.3.1/fonts/glyphicons-halflings-regular.eot", size: 20335, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -541,7 +541,7 @@ func webUiStaticVendorBootstrap331FontsGlyphiconsHalflingsRegularSvg() (*asset, return nil, err } - info := bindataFileInfo{name: "web/ui/static/vendor/bootstrap-3.3.1/fonts/glyphicons-halflings-regular.svg", size: 62926, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/vendor/bootstrap-3.3.1/fonts/glyphicons-halflings-regular.svg", size: 62926, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -561,7 +561,7 @@ func webUiStaticVendorBootstrap331FontsGlyphiconsHalflingsRegularTtf() (*asset, return nil, err } - info := bindataFileInfo{name: "web/ui/static/vendor/bootstrap-3.3.1/fonts/glyphicons-halflings-regular.ttf", size: 41280, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/vendor/bootstrap-3.3.1/fonts/glyphicons-halflings-regular.ttf", size: 41280, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -581,7 +581,7 @@ func webUiStaticVendorBootstrap331FontsGlyphiconsHalflingsRegularWoff() (*asset, return nil, err } - info := bindataFileInfo{name: "web/ui/static/vendor/bootstrap-3.3.1/fonts/glyphicons-halflings-regular.woff", size: 23320, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/vendor/bootstrap-3.3.1/fonts/glyphicons-halflings-regular.woff", size: 23320, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -601,7 +601,7 @@ func webUiStaticVendorBootstrap331JsBootstrapMinJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/static/vendor/bootstrap-3.3.1/js/bootstrap.min.js", size: 35601, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/vendor/bootstrap-3.3.1/js/bootstrap.min.js", size: 35601, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -621,7 +621,7 @@ func webUiStaticVendorBootstrap331JsNpmJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/static/vendor/bootstrap-3.3.1/js/npm.js", size: 484, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/vendor/bootstrap-3.3.1/js/npm.js", size: 484, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -641,7 +641,7 @@ func webUiStaticVendorBootstrap3TypeaheadBootstrap3TypeaheadMinJs() (*asset, err return nil, err } - info := bindataFileInfo{name: "web/ui/static/vendor/bootstrap3-typeahead/bootstrap3-typeahead.min.js", size: 7856, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/vendor/bootstrap3-typeahead/bootstrap3-typeahead.min.js", size: 7856, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -661,7 +661,7 @@ func webUiStaticVendorEonasdanBootstrapDatetimepickerBootstrapDatetimepickerMinC return nil, err } - info := bindataFileInfo{name: "web/ui/static/vendor/eonasdan-bootstrap-datetimepicker/bootstrap-datetimepicker.min.css", size: 7771, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/vendor/eonasdan-bootstrap-datetimepicker/bootstrap-datetimepicker.min.css", size: 7771, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -681,7 +681,7 @@ func webUiStaticVendorEonasdanBootstrapDatetimepickerBootstrapDatetimepickerMinJ return nil, err } - info := bindataFileInfo{name: "web/ui/static/vendor/eonasdan-bootstrap-datetimepicker/bootstrap-datetimepicker.min.js", size: 48881, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/vendor/eonasdan-bootstrap-datetimepicker/bootstrap-datetimepicker.min.js", size: 48881, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -701,7 +701,7 @@ func webUiStaticVendorFuzzyFuzzyJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/static/vendor/fuzzy/fuzzy.js", size: 5669, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/vendor/fuzzy/fuzzy.js", size: 5669, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -721,7 +721,7 @@ func webUiStaticVendorJsJqueryHotkeysJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/static/vendor/js/jquery.hotkeys.js", size: 3283, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/vendor/js/jquery.hotkeys.js", size: 3283, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -741,7 +741,7 @@ func webUiStaticVendorJsJqueryMinJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/static/vendor/js/jquery.min.js", size: 95935, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/vendor/js/jquery.min.js", size: 95935, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -761,7 +761,7 @@ func webUiStaticVendorJsJquerySelectionJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/static/vendor/js/jquery.selection.js", size: 13320, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/vendor/js/jquery.selection.js", size: 13320, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -781,7 +781,7 @@ func webUiStaticVendorMomentMomentMinJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/static/vendor/moment/moment.min.js", size: 61281, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/vendor/moment/moment.min.js", size: 61281, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -801,7 +801,7 @@ func webUiStaticVendorMustacheMustacheMinJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/static/vendor/mustache/mustache.min.js", size: 9528, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/vendor/mustache/mustache.min.js", size: 9528, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -821,7 +821,7 @@ func webUiStaticVendorRickshawRickshawMinCss() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/static/vendor/rickshaw/rickshaw.min.css", size: 6102, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/vendor/rickshaw/rickshaw.min.css", size: 6102, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -841,7 +841,7 @@ func webUiStaticVendorRickshawRickshawMinJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/static/vendor/rickshaw/rickshaw.min.js", size: 76322, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/vendor/rickshaw/rickshaw.min.js", size: 76322, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -861,7 +861,7 @@ func webUiStaticVendorRickshawVendorD3LayoutMinJs() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/static/vendor/rickshaw/vendor/d3.layout.min.js", size: 17514, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/vendor/rickshaw/vendor/d3.layout.min.js", size: 17514, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } @@ -881,7 +881,7 @@ func webUiStaticVendorRickshawVendorD3V3Js() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "web/ui/static/vendor/rickshaw/vendor/d3.v3.js", size: 144718, mode: os.FileMode(420), modTime: time.Unix(1490957917, 0)} + info := bindataFileInfo{name: "web/ui/static/vendor/rickshaw/vendor/d3.v3.js", size: 144718, mode: os.FileMode(420), modTime: time.Unix(1499168114, 0)} a := &asset{bytes: bytes, info: info} return a, nil } diff --git a/web/ui/static/js/prom_console.js b/web/ui/static/js/prom_console.js index 505627b5d..c1657d0a7 100644 --- a/web/ui/static/js/prom_console.js +++ b/web/ui/static/js/prom_console.js @@ -311,6 +311,9 @@ PromConsole.graphDefaults = { yAxisFormatter: PromConsole.NumberFormatter.humanize, // Number formatter for y values hover detail. yHoverFormatter: PromConsole.NumberFormatter.humanizeExact, + // Color scheme to be used by the plots. Can be either a list of hex color + // codes or one of the color scheme names supported by Rickshaw. + colorScheme: null, }; PromConsole.Graph = function(params) { @@ -420,7 +423,7 @@ PromConsole.Graph.prototype._escapeHTML = function(string) { PromConsole.Graph.prototype._render = function(data) { var self = this; - var palette = new Rickshaw.Color.Palette(); + var palette = new Rickshaw.Color.Palette({scheme: this.params.colorScheme}); var series = []; // This will be used on resize. From 13c6e4a4bcdc07cf63a01ee6e59511f20a78bac3 Mon Sep 17 00:00:00 2001 From: Matt Bostock Date: Tue, 4 Jul 2017 20:48:52 +0100 Subject: [PATCH 03/13] Remote queue manager: Fix typo Change 'send' to 'sent'. --- storage/remote/queue_manager.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage/remote/queue_manager.go b/storage/remote/queue_manager.go index 40c5a5eb4..9891546f5 100644 --- a/storage/remote/queue_manager.go +++ b/storage/remote/queue_manager.go @@ -303,7 +303,7 @@ func (t *QueueManager) calculateDesiredShards() { // We use the number of incoming samples as a prediction of how much work we // will need to do next iteration. We add to this any pending samples - // (received - send) so we can catch up with any backlog. We use the average + // (received - sent) so we can catch up with any backlog. We use the average // outgoing batch latency to work out how many shards we need. var ( samplesIn = t.samplesIn.rate() From 98d20d588081a97cfffd7fadefdc2289cc5c5b34 Mon Sep 17 00:00:00 2001 From: Goutham Veeramachaneni Date: Wed, 5 Jul 2017 16:09:29 +0200 Subject: [PATCH 04/13] Make sure rendering config produces valid config Fixes #2899 Signed-off-by: Goutham Veeramachaneni --- config/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/config.go b/config/config.go index 93d2ecd4d..ca1a1d57d 100644 --- a/config/config.go +++ b/config/config.go @@ -1278,7 +1278,7 @@ func (a *RelabelAction) UnmarshalYAML(unmarshal func(interface{}) error) error { type RelabelConfig struct { // A list of labels from which values are taken and concatenated // with the configured separator in order. - SourceLabels model.LabelNames `yaml:"source_labels,flow"` + SourceLabels model.LabelNames `yaml:"source_labels,flow,omitempty"` // Separator is the string between concatenated values from the source labels. Separator string `yaml:"separator,omitempty"` // Regex against which the concatenation is matched. From a607873ad26d46a85ca136a506c4f211a827be8e Mon Sep 17 00:00:00 2001 From: Goutham Veeramachaneni Date: Thu, 6 Jul 2017 11:32:37 +0200 Subject: [PATCH 05/13] Log the stopping of TargetManager in Info Fixes #2715 Signed-off-by: Goutham Veeramachaneni --- retrieval/targetmanager.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/retrieval/targetmanager.go b/retrieval/targetmanager.go index 791d59a05..6d39b3c80 100644 --- a/retrieval/targetmanager.go +++ b/retrieval/targetmanager.go @@ -86,7 +86,7 @@ func (tm *TargetManager) Stop() { // Wait for all scrape inserts to complete. tm.wg.Wait() - tm.logger.Debugln("Target manager stopped") + tm.logger.Infoln("Target manager stopped.") } func (tm *TargetManager) reload() { From 835eb8c653fb642473b41c2c0296f3c0a944a812 Mon Sep 17 00:00:00 2001 From: Tom Wilkie Date: Fri, 7 Jul 2017 15:37:16 +0100 Subject: [PATCH 06/13] Add _test.go suffix to promql/{bench.go, test.go} to prevent importing the testing package in a normal binary. --- promql/{bench.go => bench_test.go} | 0 promql/test.go | 26 ------------------- promql/test_test.go | 40 ++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 26 deletions(-) rename promql/{bench.go => bench_test.go} (100%) create mode 100644 promql/test_test.go diff --git a/promql/bench.go b/promql/bench_test.go similarity index 100% rename from promql/bench.go rename to promql/bench_test.go diff --git a/promql/test.go b/promql/test.go index 8b10d450f..e65982713 100644 --- a/promql/test.go +++ b/promql/test.go @@ -419,32 +419,6 @@ func (cmd clearCmd) String() string { return "clear" } -// RunAsBenchmark runs the test in benchmark mode. -// This will not count any loads or non eval functions. -func (t *Test) RunAsBenchmark(b *Benchmark) error { - for _, cmd := range t.cmds { - - switch cmd.(type) { - // Only time the "eval" command. - case *evalCmd: - err := t.exec(cmd) - if err != nil { - return err - } - default: - if b.iterCount == 0 { - b.b.StopTimer() - err := t.exec(cmd) - if err != nil { - return err - } - b.b.StartTimer() - } - } - } - return nil -} - // Run executes the command sequence of the test. Until the maximum error number // is reached, evaluation errors do not terminate execution. func (t *Test) Run() error { diff --git a/promql/test_test.go b/promql/test_test.go new file mode 100644 index 000000000..5de250749 --- /dev/null +++ b/promql/test_test.go @@ -0,0 +1,40 @@ +// Copyright 2015 The Prometheus Authors +// 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, softwar +// 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 promql + +// RunAsBenchmark runs the test in benchmark mode. +// This will not count any loads or non eval functions. +func (t *Test) RunAsBenchmark(b *Benchmark) error { + for _, cmd := range t.cmds { + + switch cmd.(type) { + // Only time the "eval" command. + case *evalCmd: + err := t.exec(cmd) + if err != nil { + return err + } + default: + if b.iterCount == 0 { + b.b.StopTimer() + err := t.exec(cmd) + if err != nil { + return err + } + b.b.StartTimer() + } + } + } + return nil +} From 902fafb8e7216d0f5064667452b49dbc0d267e99 Mon Sep 17 00:00:00 2001 From: "Fuente, Pablo Andres" Date: Sun, 9 Jul 2017 01:34:50 -0300 Subject: [PATCH 07/13] Fixing tests for Windows Fixing the config/config_test, the discovery/file/file_test and the promql/promql_test tests for Windows. For most of the tests, the fix involved correct handling of path separators. In the case of the promql tests, the issue was related to the removal of the temporal directories used by the storage. The issue is that the RemoveAll() call returns an error when it tries to remove a directory which is not empty, which seems to be true due to some kind of process that is still running after closing the storage. To fix it I added some retries to the remove of the temporal directories. Adding tags file from Universal Ctags to .gitignore --- .gitignore | 1 + config/config_non_windows_test.go | 27 +++++++++++ config/config_test.go | 45 ++++++++++++++----- config/config_windows_test.go | 25 +++++++++++ config/testdata/conf.good.yml | 1 - config/testdata/rules_abs_path.good.yml | 4 ++ .../testdata/rules_abs_path_windows.good.yml | 4 ++ discovery/file/file_test.go | 5 ++- util/testutil/directory.go | 14 ++++-- 9 files changed, 109 insertions(+), 17 deletions(-) create mode 100644 config/config_non_windows_test.go create mode 100644 config/config_windows_test.go create mode 100644 config/testdata/rules_abs_path.good.yml create mode 100644 config/testdata/rules_abs_path_windows.good.yml diff --git a/.gitignore b/.gitignore index 2fe870e94..4d417605a 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ .*.swo *.iml .idea +tags /prometheus /promtool diff --git a/config/config_non_windows_test.go b/config/config_non_windows_test.go new file mode 100644 index 000000000..8e0be7243 --- /dev/null +++ b/config/config_non_windows_test.go @@ -0,0 +1,27 @@ +// Copyright 2015 The Prometheus Authors +// 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. + +// +build !windows + +package config + +const ruleFilesConfigFile = "testdata/rules_abs_path.good.yml" +var ruleFilesExpectedConf = &Config{ + GlobalConfig: DefaultGlobalConfig, + RuleFiles: []string{ + "testdata/first.rules", + "testdata/rules/second.rules", + "/absolute/third.rules", + }, + original: "", +} diff --git a/config/config_test.go b/config/config_test.go index 0282deb0e..8071d7258 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -17,6 +17,7 @@ import ( "encoding/json" "io/ioutil" "net/url" + "path/filepath" "reflect" "regexp" "strings" @@ -48,9 +49,8 @@ var expectedConf = &Config{ }, RuleFiles: []string{ - "testdata/first.rules", - "/absolute/second.rules", - "testdata/my/*.rules", + filepath.FromSlash("testdata/first.rules"), + filepath.FromSlash("testdata/my/*.rules"), }, RemoteWriteConfigs: []*RemoteWriteConfig{ @@ -85,7 +85,7 @@ var expectedConf = &Config{ Scheme: DefaultScrapeConfig.Scheme, HTTPClientConfig: HTTPClientConfig{ - BearerTokenFile: "testdata/valid_token_file", + BearerTokenFile: filepath.FromSlash("testdata/valid_token_file"), }, ServiceDiscoveryConfig: ServiceDiscoveryConfig{ @@ -252,9 +252,9 @@ var expectedConf = &Config{ TagSeparator: DefaultConsulSDConfig.TagSeparator, Scheme: "https", TLSConfig: TLSConfig{ - CertFile: "testdata/valid_cert_file", - KeyFile: "testdata/valid_key_file", - CAFile: "testdata/valid_ca_file", + CertFile: filepath.FromSlash("testdata/valid_cert_file"), + KeyFile: filepath.FromSlash("testdata/valid_key_file"), + CAFile: filepath.FromSlash("testdata/valid_ca_file"), InsecureSkipVerify: false, }, }, @@ -283,8 +283,8 @@ var expectedConf = &Config{ HTTPClientConfig: HTTPClientConfig{ TLSConfig: TLSConfig{ - CertFile: "testdata/valid_cert_file", - KeyFile: "testdata/valid_key_file", + CertFile: filepath.FromSlash("testdata/valid_cert_file"), + KeyFile: filepath.FromSlash("testdata/valid_key_file"), }, BearerToken: "mysecret", @@ -354,8 +354,8 @@ var expectedConf = &Config{ Timeout: model.Duration(30 * time.Second), RefreshInterval: model.Duration(30 * time.Second), TLSConfig: TLSConfig{ - CertFile: "testdata/valid_cert_file", - KeyFile: "testdata/valid_key_file", + CertFile: filepath.FromSlash("testdata/valid_cert_file"), + KeyFile: filepath.FromSlash("testdata/valid_key_file"), }, }, }, @@ -549,6 +549,29 @@ func TestLoadConfig(t *testing.T) { } +func TestLoadConfigRuleFilesAbsolutePath(t *testing.T) { + // Parse a valid file that sets a rule files with an absolute path + c, err := LoadFile(ruleFilesConfigFile) + if err != nil { + t.Errorf("Error parsing %s: %s", ruleFilesConfigFile, err) + } + + bgot, err := yaml.Marshal(c) + if err != nil { + t.Fatalf("%s", err) + } + + bexp, err := yaml.Marshal(ruleFilesExpectedConf) + if err != nil { + t.Fatalf("%s", err) + } + ruleFilesExpectedConf.original = c.original + + if !reflect.DeepEqual(c, ruleFilesExpectedConf) { + t.Fatalf("%s: unexpected config result: \n\n%s\n expected\n\n%s", ruleFilesConfigFile, bgot, bexp) + } +} + var expectedErrors = []struct { filename string errMsg string diff --git a/config/config_windows_test.go b/config/config_windows_test.go new file mode 100644 index 000000000..cb8dcebfb --- /dev/null +++ b/config/config_windows_test.go @@ -0,0 +1,25 @@ +// Copyright 2015 The Prometheus Authors +// 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 config + +const ruleFilesConfigFile = "testdata/rules_abs_path_windows.good.yml" +var ruleFilesExpectedConf = &Config{ + GlobalConfig: DefaultGlobalConfig, + RuleFiles: []string{ + "testdata\\first.rules", + "testdata\\rules\\second.rules", + "c:\\absolute\\third.rules", + }, + original: "", +} diff --git a/config/testdata/conf.good.yml b/config/testdata/conf.good.yml index 69c9cdc88..34da77d4e 100644 --- a/config/testdata/conf.good.yml +++ b/config/testdata/conf.good.yml @@ -10,7 +10,6 @@ global: rule_files: - "first.rules" -- "/absolute/second.rules" - "my/*.rules" remote_write: diff --git a/config/testdata/rules_abs_path.good.yml b/config/testdata/rules_abs_path.good.yml new file mode 100644 index 000000000..e9d3cf7f9 --- /dev/null +++ b/config/testdata/rules_abs_path.good.yml @@ -0,0 +1,4 @@ +rule_files: + - 'first.rules' + - 'rules/second.rules' + - '/absolute/third.rules' diff --git a/config/testdata/rules_abs_path_windows.good.yml b/config/testdata/rules_abs_path_windows.good.yml new file mode 100644 index 000000000..667411ff5 --- /dev/null +++ b/config/testdata/rules_abs_path_windows.good.yml @@ -0,0 +1,4 @@ +rule_files: + - 'first.rules' + - 'rules\second.rules' + - 'c:\absolute\third.rules' diff --git a/discovery/file/file_test.go b/discovery/file/file_test.go index f977e3b22..65c53c23b 100644 --- a/discovery/file/file_test.go +++ b/discovery/file/file_test.go @@ -17,6 +17,7 @@ import ( "fmt" "io" "os" + "path/filepath" "testing" "time" @@ -89,12 +90,12 @@ retry: if _, ok := tg.Labels["foo"]; !ok { t.Fatalf("Label not parsed") } - if tg.String() != fmt.Sprintf("fixtures/_test%s:0", ext) { + if tg.String() != filepath.FromSlash(fmt.Sprintf("fixtures/_test%s:0", ext)) { t.Fatalf("Unexpected target group %s", tg) } tg = tgs[1] - if tg.String() != fmt.Sprintf("fixtures/_test%s:1", ext) { + if tg.String() != filepath.FromSlash(fmt.Sprintf("fixtures/_test%s:1", ext)) { t.Fatalf("Unexpected target groups %s", tg) } break retry diff --git a/util/testutil/directory.go b/util/testutil/directory.go index 1672c5b01..d3c9c926f 100644 --- a/util/testutil/directory.go +++ b/util/testutil/directory.go @@ -26,6 +26,9 @@ const ( // NilCloser is a no-op Closer. NilCloser = nilCloser(true) + + // The number of times that a TemporaryDirectory will retry its removal + temporaryDirectoryRemoveRetries = 2 ) type ( @@ -84,15 +87,20 @@ func NewCallbackCloser(fn func()) Closer { } func (t temporaryDirectory) Close() { + retries := temporaryDirectoryRemoveRetries err := os.RemoveAll(t.path) - if err != nil { + for err != nil && retries > 0 { switch { case os.IsNotExist(err): - return + err = nil default: - t.tester.Fatal(err) + retries-- + err = os.RemoveAll(t.path) } } + if err != nil { + t.tester.Fatal(err) + } } func (t temporaryDirectory) Path() string { From 193dc472309c0c7a50222db46590d7288c27380e Mon Sep 17 00:00:00 2001 From: "Fuente, Pablo Andres" Date: Sun, 9 Jul 2017 02:43:33 -0300 Subject: [PATCH 08/13] Fixing code style to adhere gofmt --- config/config_non_windows_test.go | 3 ++- config/config_windows_test.go | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/config/config_non_windows_test.go b/config/config_non_windows_test.go index 8e0be7243..932643b88 100644 --- a/config/config_non_windows_test.go +++ b/config/config_non_windows_test.go @@ -1,4 +1,4 @@ -// Copyright 2015 The Prometheus Authors +// Copyright 2017 The Prometheus Authors // 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 @@ -16,6 +16,7 @@ package config const ruleFilesConfigFile = "testdata/rules_abs_path.good.yml" + var ruleFilesExpectedConf = &Config{ GlobalConfig: DefaultGlobalConfig, RuleFiles: []string{ diff --git a/config/config_windows_test.go b/config/config_windows_test.go index cb8dcebfb..ac97d3105 100644 --- a/config/config_windows_test.go +++ b/config/config_windows_test.go @@ -1,4 +1,4 @@ -// Copyright 2015 The Prometheus Authors +// Copyright 2017 The Prometheus Authors // 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 @@ -14,6 +14,7 @@ package config const ruleFilesConfigFile = "testdata/rules_abs_path_windows.good.yml" + var ruleFilesExpectedConf = &Config{ GlobalConfig: DefaultGlobalConfig, RuleFiles: []string{ From fe73de94525d70ea3a044f82123381e775910e54 Mon Sep 17 00:00:00 2001 From: "Fuente, Pablo Andres" Date: Mon, 10 Jul 2017 00:02:08 -0300 Subject: [PATCH 09/13] Renaming config test file to fix build tags Renaming the name of a file of the config tests, in order to properly use the Go build tags feature. --- config/{config_non_windows_test.go => config_notwin_test.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename config/{config_non_windows_test.go => config_notwin_test.go} (100%) diff --git a/config/config_non_windows_test.go b/config/config_notwin_test.go similarity index 100% rename from config/config_non_windows_test.go rename to config/config_notwin_test.go From 9eb8c6e1d2f0c52e4f9b3a6a5362970a043c08d3 Mon Sep 17 00:00:00 2001 From: "Fuente, Pablo Andres" Date: Mon, 10 Jul 2017 11:08:16 -0300 Subject: [PATCH 10/13] Renaming the config_notwin test to config_default --- config/{config_notwin_test.go => config_default_test.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename config/{config_notwin_test.go => config_default_test.go} (100%) diff --git a/config/config_notwin_test.go b/config/config_default_test.go similarity index 100% rename from config/config_notwin_test.go rename to config/config_default_test.go From 6861b3d03d57d112a778c0449ae5b680caa22eb8 Mon Sep 17 00:00:00 2001 From: Fabian Reinartz Date: Wed, 12 Jul 2017 13:49:23 +0200 Subject: [PATCH 11/13] Delete remote file --- storage/remote/queue_manager.go | 512 -------------------------------- 1 file changed, 512 deletions(-) delete mode 100644 storage/remote/queue_manager.go diff --git a/storage/remote/queue_manager.go b/storage/remote/queue_manager.go deleted file mode 100644 index 9891546f5..000000000 --- a/storage/remote/queue_manager.go +++ /dev/null @@ -1,512 +0,0 @@ -// Copyright 2013 The Prometheus Authors -// 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 remote - -import ( - "math" - "sync" - "time" - - "golang.org/x/time/rate" - - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/common/log" - "github.com/prometheus/common/model" - "github.com/prometheus/prometheus/config" - "github.com/prometheus/prometheus/relabel" -) - -// String constants for instrumentation. -const ( - namespace = "prometheus" - subsystem = "remote_storage" - queue = "queue" - - // We track samples in/out and how long pushes take using an Exponentially - // Weighted Moving Average. - ewmaWeight = 0.2 - shardUpdateDuration = 10 * time.Second - - // Allow 30% too many shards before scaling down. - shardToleranceFraction = 0.3 - - // Limit to 1 log event every 10s - logRateLimit = 0.1 - logBurst = 10 -) - -var ( - succeededSamplesTotal = prometheus.NewCounterVec( - prometheus.CounterOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "succeeded_samples_total", - Help: "Total number of samples successfully sent to remote storage.", - }, - []string{queue}, - ) - failedSamplesTotal = prometheus.NewCounterVec( - prometheus.CounterOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "failed_samples_total", - Help: "Total number of samples which failed on send to remote storage.", - }, - []string{queue}, - ) - droppedSamplesTotal = prometheus.NewCounterVec( - prometheus.CounterOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "dropped_samples_total", - Help: "Total number of samples which were dropped due to the queue being full.", - }, - []string{queue}, - ) - sentBatchDuration = prometheus.NewHistogramVec( - prometheus.HistogramOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "sent_batch_duration_seconds", - Help: "Duration of sample batch send calls to the remote storage.", - Buckets: prometheus.DefBuckets, - }, - []string{queue}, - ) - queueLength = prometheus.NewGaugeVec( - prometheus.GaugeOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "queue_length", - Help: "The number of processed samples queued to be sent to the remote storage.", - }, - []string{queue}, - ) - queueCapacity = prometheus.NewGaugeVec( - prometheus.GaugeOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "queue_capacity", - Help: "The capacity of the queue of samples to be sent to the remote storage.", - }, - []string{queue}, - ) - numShards = prometheus.NewGaugeVec( - prometheus.GaugeOpts{ - Namespace: namespace, - Subsystem: subsystem, - Name: "shards", - Help: "The number of shards used for parallel sending to the remote storage.", - }, - []string{queue}, - ) -) - -func init() { - prometheus.MustRegister(succeededSamplesTotal) - prometheus.MustRegister(failedSamplesTotal) - prometheus.MustRegister(droppedSamplesTotal) - prometheus.MustRegister(sentBatchDuration) - prometheus.MustRegister(queueLength) - prometheus.MustRegister(queueCapacity) - prometheus.MustRegister(numShards) -} - -// QueueManagerConfig is the configuration for the queue used to write to remote -// storage. -type QueueManagerConfig struct { - // Number of samples to buffer per shard before we start dropping them. - QueueCapacity int - // Max number of shards, i.e. amount of concurrency. - MaxShards int - // Maximum number of samples per send. - MaxSamplesPerSend int - // Maximum time sample will wait in buffer. - BatchSendDeadline time.Duration - // Max number of times to retry a batch on recoverable errors. - MaxRetries int - // On recoverable errors, backoff exponentially. - MinBackoff time.Duration - MaxBackoff time.Duration -} - -// defaultQueueManagerConfig is the default remote queue configuration. -var defaultQueueManagerConfig = QueueManagerConfig{ - // With a maximum of 1000 shards, assuming an average of 100ms remote write - // time and 100 samples per batch, we will be able to push 1M samples/s. - MaxShards: 1000, - MaxSamplesPerSend: 100, - - // By default, buffer 1000 batches, which at 100ms per batch is 1:40mins. At - // 1000 shards, this will buffer 100M samples total. - QueueCapacity: 100 * 1000, - BatchSendDeadline: 5 * time.Second, - - // Max number of times to retry a batch on recoverable errors. - MaxRetries: 10, - MinBackoff: 30 * time.Millisecond, - MaxBackoff: 100 * time.Millisecond, -} - -// StorageClient defines an interface for sending a batch of samples to an -// external timeseries database. -type StorageClient interface { - // Store stores the given samples in the remote storage. - Store(model.Samples) error - // Name identifies the remote storage implementation. - Name() string -} - -// QueueManager manages a queue of samples to be sent to the Storage -// indicated by the provided StorageClient. -type QueueManager struct { - cfg QueueManagerConfig - externalLabels model.LabelSet - relabelConfigs []*config.RelabelConfig - client StorageClient - queueName string - logLimiter *rate.Limiter - - shardsMtx sync.Mutex - shards *shards - numShards int - reshardChan chan int - quit chan struct{} - wg sync.WaitGroup - - samplesIn, samplesOut, samplesOutDuration *ewmaRate - integralAccumulator float64 -} - -// NewQueueManager builds a new QueueManager. -func NewQueueManager(cfg QueueManagerConfig, externalLabels model.LabelSet, relabelConfigs []*config.RelabelConfig, client StorageClient) *QueueManager { - t := &QueueManager{ - cfg: cfg, - externalLabels: externalLabels, - relabelConfigs: relabelConfigs, - client: client, - queueName: client.Name(), - - logLimiter: rate.NewLimiter(logRateLimit, logBurst), - numShards: 1, - reshardChan: make(chan int), - quit: make(chan struct{}), - - samplesIn: newEWMARate(ewmaWeight, shardUpdateDuration), - samplesOut: newEWMARate(ewmaWeight, shardUpdateDuration), - samplesOutDuration: newEWMARate(ewmaWeight, shardUpdateDuration), - } - t.shards = t.newShards(t.numShards) - numShards.WithLabelValues(t.queueName).Set(float64(t.numShards)) - queueCapacity.WithLabelValues(t.queueName).Set(float64(t.cfg.QueueCapacity)) - - return t -} - -// Append queues a sample to be sent to the remote storage. It drops the -// sample on the floor if the queue is full. -// Always returns nil. -func (t *QueueManager) Append(s *model.Sample) error { - var snew model.Sample - snew = *s - snew.Metric = s.Metric.Clone() - - for ln, lv := range t.externalLabels { - if _, ok := s.Metric[ln]; !ok { - snew.Metric[ln] = lv - } - } - - snew.Metric = model.Metric( - relabel.Process(model.LabelSet(snew.Metric), t.relabelConfigs...)) - - if snew.Metric == nil { - return nil - } - - t.shardsMtx.Lock() - enqueued := t.shards.enqueue(&snew) - t.shardsMtx.Unlock() - - if enqueued { - queueLength.WithLabelValues(t.queueName).Inc() - } else { - droppedSamplesTotal.WithLabelValues(t.queueName).Inc() - if t.logLimiter.Allow() { - log.Warn("Remote storage queue full, discarding sample. Multiple subsequent messages of this kind may be suppressed.") - } - } - return nil -} - -// NeedsThrottling implements storage.SampleAppender. It will always return -// false as a remote storage drops samples on the floor if backlogging instead -// of asking for throttling. -func (*QueueManager) NeedsThrottling() bool { - return false -} - -// Start the queue manager sending samples to the remote storage. -// Does not block. -func (t *QueueManager) Start() { - t.wg.Add(2) - go t.updateShardsLoop() - go t.reshardLoop() - - t.shardsMtx.Lock() - defer t.shardsMtx.Unlock() - t.shards.start() -} - -// Stop stops sending samples to the remote storage and waits for pending -// sends to complete. -func (t *QueueManager) Stop() { - log.Infof("Stopping remote storage...") - close(t.quit) - t.wg.Wait() - - t.shardsMtx.Lock() - defer t.shardsMtx.Unlock() - t.shards.stop() - log.Info("Remote storage stopped.") -} - -func (t *QueueManager) updateShardsLoop() { - defer t.wg.Done() - - ticker := time.Tick(shardUpdateDuration) - for { - select { - case <-ticker: - t.calculateDesiredShards() - case <-t.quit: - return - } - } -} - -func (t *QueueManager) calculateDesiredShards() { - t.samplesIn.tick() - t.samplesOut.tick() - t.samplesOutDuration.tick() - - // We use the number of incoming samples as a prediction of how much work we - // will need to do next iteration. We add to this any pending samples - // (received - sent) so we can catch up with any backlog. We use the average - // outgoing batch latency to work out how many shards we need. - var ( - samplesIn = t.samplesIn.rate() - samplesOut = t.samplesOut.rate() - samplesPending = samplesIn - samplesOut - samplesOutDuration = t.samplesOutDuration.rate() - ) - - // We use an integral accumulator, like in a PID, to help dampen oscillation. - t.integralAccumulator = t.integralAccumulator + (samplesPending * 0.1) - - if samplesOut <= 0 { - return - } - - var ( - timePerSample = samplesOutDuration / samplesOut - desiredShards = (timePerSample * (samplesIn + samplesPending + t.integralAccumulator)) / float64(time.Second) - ) - log.Debugf("QueueManager.calculateDesiredShards samplesIn=%f, samplesOut=%f, samplesPending=%f, desiredShards=%f", - samplesIn, samplesOut, samplesPending, desiredShards) - - // Changes in the number of shards must be greater than shardToleranceFraction. - var ( - lowerBound = float64(t.numShards) * (1. - shardToleranceFraction) - upperBound = float64(t.numShards) * (1. + shardToleranceFraction) - ) - log.Debugf("QueueManager.updateShardsLoop %f <= %f <= %f", lowerBound, desiredShards, upperBound) - if lowerBound <= desiredShards && desiredShards <= upperBound { - return - } - - numShards := int(math.Ceil(desiredShards)) - if numShards > t.cfg.MaxShards { - numShards = t.cfg.MaxShards - } - if numShards == t.numShards { - return - } - - // Resharding can take some time, and we want this loop - // to stay close to shardUpdateDuration. - select { - case t.reshardChan <- numShards: - log.Infof("Remote storage resharding from %d to %d shards.", t.numShards, numShards) - t.numShards = numShards - default: - log.Infof("Currently resharding, skipping.") - } -} - -func (t *QueueManager) reshardLoop() { - defer t.wg.Done() - - for { - select { - case numShards := <-t.reshardChan: - t.reshard(numShards) - case <-t.quit: - return - } - } -} - -func (t *QueueManager) reshard(n int) { - numShards.WithLabelValues(t.queueName).Set(float64(n)) - - t.shardsMtx.Lock() - newShards := t.newShards(n) - oldShards := t.shards - t.shards = newShards - t.shardsMtx.Unlock() - - oldShards.stop() - - // We start the newShards after we have stopped (the therefore completely - // flushed) the oldShards, to guarantee we only every deliver samples in - // order. - newShards.start() -} - -type shards struct { - qm *QueueManager - queues []chan *model.Sample - done chan struct{} - wg sync.WaitGroup -} - -func (t *QueueManager) newShards(numShards int) *shards { - queues := make([]chan *model.Sample, numShards) - for i := 0; i < numShards; i++ { - queues[i] = make(chan *model.Sample, t.cfg.QueueCapacity) - } - s := &shards{ - qm: t, - queues: queues, - done: make(chan struct{}), - } - s.wg.Add(numShards) - return s -} - -func (s *shards) len() int { - return len(s.queues) -} - -func (s *shards) start() { - for i := 0; i < len(s.queues); i++ { - go s.runShard(i) - } -} - -func (s *shards) stop() { - for _, shard := range s.queues { - close(shard) - } - s.wg.Wait() -} - -func (s *shards) enqueue(sample *model.Sample) bool { - s.qm.samplesIn.incr(1) - - fp := sample.Metric.FastFingerprint() - shard := uint64(fp) % uint64(len(s.queues)) - - select { - case s.queues[shard] <- sample: - return true - default: - return false - } -} - -func (s *shards) runShard(i int) { - defer s.wg.Done() - queue := s.queues[i] - - // Send batches of at most MaxSamplesPerSend samples to the remote storage. - // If we have fewer samples than that, flush them out after a deadline - // anyways. - pendingSamples := model.Samples{} - - for { - select { - case sample, ok := <-queue: - if !ok { - if len(pendingSamples) > 0 { - log.Debugf("Flushing %d samples to remote storage...", len(pendingSamples)) - s.sendSamples(pendingSamples) - log.Debugf("Done flushing.") - } - return - } - - queueLength.WithLabelValues(s.qm.queueName).Dec() - pendingSamples = append(pendingSamples, sample) - - for len(pendingSamples) >= s.qm.cfg.MaxSamplesPerSend { - s.sendSamples(pendingSamples[:s.qm.cfg.MaxSamplesPerSend]) - pendingSamples = pendingSamples[s.qm.cfg.MaxSamplesPerSend:] - } - case <-time.After(s.qm.cfg.BatchSendDeadline): - if len(pendingSamples) > 0 { - s.sendSamples(pendingSamples) - pendingSamples = pendingSamples[:0] - } - } - } -} - -func (s *shards) sendSamples(samples model.Samples) { - begin := time.Now() - s.sendSamplesWithBackoff(samples) - - // These counters are used to calculate the dynamic sharding, and as such - // should be maintained irrespective of success or failure. - s.qm.samplesOut.incr(int64(len(samples))) - s.qm.samplesOutDuration.incr(int64(time.Since(begin))) -} - -// sendSamples to the remote storage with backoff for recoverable errors. -func (s *shards) sendSamplesWithBackoff(samples model.Samples) { - backoff := s.qm.cfg.MinBackoff - for retries := s.qm.cfg.MaxRetries; retries > 0; retries-- { - begin := time.Now() - err := s.qm.client.Store(samples) - - sentBatchDuration.WithLabelValues(s.qm.queueName).Observe(time.Since(begin).Seconds()) - if err == nil { - succeededSamplesTotal.WithLabelValues(s.qm.queueName).Add(float64(len(samples))) - return - } - - log.Warnf("Error sending %d samples to remote storage: %s", len(samples), err) - if _, ok := err.(recoverableError); !ok { - break - } - time.Sleep(backoff) - backoff = backoff * 2 - if backoff > s.qm.cfg.MaxBackoff { - backoff = s.qm.cfg.MaxBackoff - } - } - - failedSamplesTotal.WithLabelValues(s.qm.queueName).Add(float64(len(samples))) -} From 6aee36ac3ba0383e0125b1f24bef96dfd82c6f80 Mon Sep 17 00:00:00 2001 From: Fabian Reinartz Date: Wed, 12 Jul 2017 14:01:45 +0200 Subject: [PATCH 12/13] vendor: update prometheus/tsdb --- vendor/github.com/prometheus/tsdb/db.go | 2 +- vendor/github.com/prometheus/tsdb/head.go | 1 + vendor/vendor.json | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/vendor/github.com/prometheus/tsdb/db.go b/vendor/github.com/prometheus/tsdb/db.go index 17f3e5f5f..a4801bbf0 100644 --- a/vendor/github.com/prometheus/tsdb/db.go +++ b/vendor/github.com/prometheus/tsdb/db.go @@ -710,7 +710,7 @@ func (db *DB) ensureHead(t int64) error { } // Create another block of buffer in front if the DB is initialized or retrieving // new data after a long gap. - // This ensures we always have a full block width if append window. + // This ensures we always have a full block width of append window. if addBuffer { if _, err := db.createHeadBlock(mint-int64(db.opts.MinBlockDuration), mint); err != nil { return err diff --git a/vendor/github.com/prometheus/tsdb/head.go b/vendor/github.com/prometheus/tsdb/head.go index 90e03f727..cb8e7329a 100644 --- a/vendor/github.com/prometheus/tsdb/head.go +++ b/vendor/github.com/prometheus/tsdb/head.go @@ -302,6 +302,7 @@ func (h *HeadBlock) Snapshot(snapshotDir string) error { return errors.Wrap(err, "write snapshot") } meta.ULID = uid + meta.MaxTime = h.highTimestamp if err = writeMetaFile(tmp, meta); err != nil { return errors.Wrap(err, "write merged meta") diff --git a/vendor/vendor.json b/vendor/vendor.json index ce1255a59..f5b94fb39 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -853,10 +853,10 @@ "revisionTime": "2016-04-11T19:08:41Z" }, { - "checksumSHA1": "kT9X/dKXjFCoxV48N2C9NZhPRvA=", + "checksumSHA1": "GgHaU/6pJjJ7I8aTfaZXnV/OWxA=", "path": "github.com/prometheus/tsdb", - "revision": "d492bfd973c24026ab784c1c1821af426bc80e90", - "revisionTime": "2017-06-30T13:17:34Z" + "revision": "969c407335d68cbd8154dcd1bca6259786b27f53", + "revisionTime": "2017-07-12T11:54:31Z" }, { "checksumSHA1": "9EH3v+JdbikCUJAgD4VEOPIaWfs=", From 724505e53e839d5408bec06f97275db577f37c49 Mon Sep 17 00:00:00 2001 From: Fabian Reinartz Date: Wed, 12 Jul 2017 13:26:21 +0200 Subject: [PATCH 13/13] *: cut v2.0.0-beta.0 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 4640d5706..72e5fccd8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.0.0-alpha.3 +2.0.0-beta.0