Skip to content

Commit 2237eec

Browse files
AstroProfundisLinuxGit
authored andcommitted
Use a Go tool to improve importing performance (#37)
1 parent 4aac229 commit 2237eec

File tree

174 files changed

+18687
-1692
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

174 files changed

+18687
-1692
lines changed

.travis.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ language: go
55
go:
66
- "1.9.x"
77
- "1.10.x"
8+
- "1.11.x"
89
- master
910

1011
matrix:

Gopkg.lock

Lines changed: 45 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Gopkg.toml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,15 @@
3131

3232
[[constraint]]
3333
name = "github.com/shirou/gopsutil"
34-
version = "2.18.06"
34+
version = "2.18.07"
35+
36+
[[constraint]]
37+
name = "github.com/influxdata/influxdb"
38+
version = "v1.6.2"
39+
40+
[[constraint]]
41+
branch = "master"
42+
name = "github.com/prometheus/common"
3543

3644
[prune]
3745
go-tests = true

Makefile

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
### Makefile for tidb-insight
2-
.PHONY: collector vmtouch
2+
.PHONY: collector tools
33

4-
default: collector vmtouch
4+
default: collector tools
55

6-
debug: collector vmtouch
6+
debug: collector tools
77

88
all: default
99

1010
collector:
1111
$(MAKE) -C collector $(MAKECMDGOALS)
1212

13-
vmtouch:
13+
tools:
14+
$(MAKE) -C tools $(MAKECMDGOALS)
1415
$(MAKE) -C tools/vmtouch $(MAKECMDGOALS)
1516
install -Dm755 tools/vmtouch/vmtouch bin/
1617

file/configfiles.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def save_sysconf(self):
2525
fileopt.write_file(os.path.join(
2626
self.outdir, "sysctl.conf"), stdout)
2727
if stderr:
28-
logging.warn("Reading limits.conf returned error: %s" % stderr)
28+
logging.warning("Reading limits.conf returned error: %s" % stderr)
2929

3030
def find_tidb_configfiles(self, cmdline=None):
3131
cmd_opts = util.parse_cmdline(cmdline)

insight.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ def get_lsof_tidb(self):
238238
def save_logfiles(self, args):
239239
# reading logs requires root priviledge
240240
if not util.is_root_privilege():
241-
logging.warn("It's required to read logs with root priviledge.")
241+
logging.warning("It's required to read logs with root priviledge.")
242242
# return
243243

244244
self.insight_logfiles = logfiles.InsightLogFiles(

metric/importer/prometheus.py

Lines changed: 33 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,11 @@
55
# for futher analysis.
66

77
import datetime
8-
import influxdb
98
import json
109
import logging
1110
import os
1211
import random
1312
import string
14-
import zlib
1513

1614
from utils import fileopt
1715
from utils import util
@@ -41,7 +39,26 @@ def unique_dbname(self):
4139

4240
return '_'.join(dbname)
4341

44-
def load_dump(self):
42+
def exec_importer(self, file=None, chunk_size=2000):
43+
if not file:
44+
logging.fatal("No file specified.")
45+
return (None, "No metric dump file specified to load.")
46+
base_dir = os.path.join(util.pwd(), "../")
47+
importer = os.path.join(base_dir, "bin/prom2influx")
48+
cmd = [importer,
49+
"-db", self.db_name,
50+
"-host", self.host,
51+
"-port", "%s" % self.port,
52+
"-chunk", "%s" % chunk_size, # chunk size of one write request
53+
"-file", file
54+
]
55+
logging.debug("Running cmd: %s" % ' '.join(cmd))
56+
return util.run_cmd(cmd)
57+
58+
def run_importing(self):
59+
logging.info("Metrics will be imported to database '%s'." %
60+
self.db_name)
61+
4562
def file_list(dir=None):
4663
f_list = []
4764
for file in fileopt.list_dir(dir):
@@ -52,58 +69,17 @@ def file_list(dir=None):
5269
return f_list
5370

5471
for file in file_list(self.datadir):
55-
if file.endswith('.json'):
56-
raw = fileopt.read_file(file)
57-
elif file.endswith('.dat'):
58-
raw = zlib.decompress(fileopt.read_file(file, 'rb'))
59-
else:
60-
logging.debug("Skipped unrecorgnized file '%s'" % file)
72+
# all dumped files are in 'prometheus' sub-directory
73+
if not file or not file.endswith('.json') or 'prometheus' not in file:
6174
continue
62-
yield json.loads(raw)
63-
64-
def build_series(self):
65-
def format_prom_metric(key=None):
66-
points = []
67-
point = {'fields': {}}
68-
# build point header
69-
for metric in key:
70-
point['measurement'] = metric['metric']['__name__']
71-
point['tags'] = {
72-
'cluster': self.db_name,
73-
'monitor': 'prometheus',
74-
}
75-
for k, v in metric['metric'].items():
76-
point['tags'][k] = v
77-
# build point values
78-
for value in metric['values']:
79-
point['time'] = datetime.datetime.utcfromtimestamp(
80-
value[0]).strftime('%Y-%m-%dT%H:%M:%SZ')
81-
try:
82-
point['fields']['value'] = float(value[1])
83-
except ValueError:
84-
point['fields']['value'] = value[1]
85-
points.append(point.copy())
86-
return points
87-
88-
for key in self.load_dump():
89-
yield format_prom_metric(key)
90-
91-
def write2influxdb(self):
92-
client = influxdb.InfluxDBClient(
93-
host=self.host, port=self.port, username=self.user, password=self.passwd,
94-
database=self.db_name, timeout=30)
95-
# create_database has no effect if the database already exist
96-
client.create_database(self.db_name)
97-
logging.info("Metrics will be imported to database '%s'." %
98-
self.db_name)
99-
100-
for series in self.build_series():
101-
try:
102-
client.write_points(series, batch_size=2000)
103-
except influxdb.exceptions.InfluxDBClientError as e:
104-
logging.warn(
105-
"Write error for key '%s', data may be empty." % series[0]['measurement'])
106-
logging.debug(e)
107-
108-
def run_importing(self):
109-
self.write2influxdb()
75+
stderr = self.exec_importer(file)[1]
76+
if stderr and "Request Entity Too Large" in stderr.decode('utf-8'):
77+
logging.info("Write to DB failed, retry for once...")
78+
retry_stderr = self.exec_importer(file, chunk_size=100)[1]
79+
if not retry_stderr:
80+
logging.info("Retry succeeded.")
81+
else:
82+
logging.warning("Retry failed, stderr is: '%s'" %
83+
retry_stderr)
84+
elif stderr:
85+
logging.warning(stderr)

metric/prometheus.py

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import json
77
import logging
88
import os
9-
import zlib
109

1110
from metric.base import MetricBase
1211
from utils import fileopt
@@ -36,7 +35,7 @@ def get_label_names(self):
3635

3736
def run_collecting(self):
3837
if self.resolution < 15.0:
39-
logging.warn(
38+
logging.warning(
4039
"Sampling resolution < 15s don't increase accuracy but data size.")
4140
for metric in self.get_label_names():
4241
url = '%s/query_range?query=%s&start=%s&end=%s&step=%s' % (
@@ -46,14 +45,8 @@ def run_collecting(self):
4645
logging.info("Error querying for key '%s'." % metric)
4746
logging.debug("Output is:\n%s" % matrix)
4847
continue
49-
if self.options.compress:
50-
metric_filename = '%s_%s_to_%s_%ss.dat' % (
51-
metric, self.start_time, self.end_time, self.resolution)
52-
fileopt.write_file(os.path.join(self.outdir, metric_filename), zlib.compress(
53-
json.dumps(matrix['data']['result'])))
54-
else:
55-
metric_filename = '%s_%s_to_%s_%ss.json' % (
56-
metric, self.start_time, self.end_time, self.resolution)
57-
fileopt.write_file(os.path.join(
58-
self.outdir, metric_filename), json.dumps(matrix['data']['result']))
48+
metric_filename = '%s_%s_to_%s_%ss.json' % (
49+
metric, self.start_time, self.end_time, self.resolution)
50+
fileopt.write_file(os.path.join(
51+
self.outdir, metric_filename), json.dumps(matrix['data']['result']))
5952
logging.debug("Saved data for key '%s'." % metric)

package.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ else
1111
fi
1212
RELPATH=${PKGNAME}-${RELVER}
1313

14-
GO_RELEASE_BIN=go1.10.3.linux-amd64
14+
GO_RELEASE_BIN=go1.11.linux-amd64
1515

1616
BUILD_ROOT="`pwd`/.build"
1717
mkdir -p ${BUILD_ROOT}
@@ -38,6 +38,8 @@ ln -sfv vendor src
3838
# compile a static binary
3939
cd ${BUILD_ROOT}/${PKGNAME}/collector/
4040
GOBIN=${GOROOT}/bin/go make static || exit 1
41+
cd ${BUILD_ROOT}/${PKGNAME}/tools/
42+
GOBIN=${GOROOT}/bin/go make static || exit 1
4143

4244
# compile other tools
4345
cd ${BUILD_ROOT}/${PKGNAME}/tools/vmtouch

runtime/perf.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,13 @@ def run_collecting(self):
8282
fileopt.write_file(
8383
path.join(self.outdir, "%s.stdout" % pname), stdout)
8484
if stderr:
85-
logging.warn(
85+
logging.warning(
8686
"Command '%s' returned error: %s" % (cmd, stderr))
8787
if self.options.archive:
8888
cmd = self.build_archive_cmd(pid, pname)
8989
stdout, stderr = util.run_cmd(cmd)
9090
if stderr:
91-
logging.warn(
91+
logging.warning(
9292
"Command '%s' returned error: %s" % (cmd, stderr))
9393
else:
9494
# perf the entire system
@@ -98,10 +98,11 @@ def run_collecting(self):
9898
fileopt.write_file(
9999
path.join(self.outdir, "perf.stdout"), stdout)
100100
if stderr:
101-
logging.warn("Command '%s' returned error: %s" % (cmd, stderr))
101+
logging.warning("Command '%s' returned error: %s" %
102+
(cmd, stderr))
102103
if self.options.archive:
103104
cmd = self.build_archive_cmd()
104105
stdout, stderr = util.run_cmd(cmd)
105106
if stderr:
106-
logging.warn(
107+
logging.warning(
107108
"Command '%s' returned error: %s" % (cmd, stderr))

0 commit comments

Comments
 (0)