diff --git a/CHANGELOG.md b/CHANGELOG.md index 078e600f5acc0..18a68ebf7b95e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,17 @@ -## v0.3.0 [unreleased] +## v0.10.1 [unreleased] + +### Features +- [#509](https://github.com/influxdb/telegraf/pull/509): Flatten JSON arrays with indices. Thanks @psilva261! +- [#512](https://github.com/influxdata/telegraf/pull/512): Python 3 build script, add lsof dep to package. Thanks @Ormod! +- [#475](https://github.com/influxdata/telegraf/pull/475): Add response time to httpjson plugin. Thanks @titilambert! +- [#519](https://github.com/influxdata/telegraf/pull/519): Added a sensors input based on lm-sensors. Thanks @md14454! +- [#467](https://github.com/influxdata/telegraf/issues/467): Add option to disable statsd measurement name conversion. + +### Bugfixes +- [#506](https://github.com/influxdb/telegraf/pull/506): Ping input doesn't return response time metric when timeout. Thanks @titilambert! +- [#508](https://github.com/influxdb/telegraf/pull/508): Fix prometheus cardinality issue with the `net` plugin + +## v0.10.0 [2016-01-12] ### Release Notes - Linux packages have been taken out of `opt`, the binary is now in `/usr/bin` @@ -23,7 +36,7 @@ aggregated). ### Packaging change note: -RHEL/CentOS users upgrading from 0.2 to 0.3 will probably have their +RHEL/CentOS users upgrading from 0.2.x to 0.10.0 will probably have their configurations overwritten by the upgrade. There is a backup stored at /etc/telegraf/telegraf.conf.$(date +%s).backup. diff --git a/Godeps b/Godeps index 2584179bd9c3c..1b427674a3ded 100644 --- a/Godeps +++ b/Godeps @@ -3,18 +3,18 @@ github.com/Shopify/sarama d37c73f2b2bce85f7fa16b6a550d26c5372892ef github.com/Sirupsen/logrus 446d1c146faa8ed3f4218f056fcd165f6bcfda81 github.com/amir/raidman 6a8e089bbe32e6b907feae5ba688841974b3c339 github.com/armon/go-metrics 345426c77237ece5dab0e1605c3e4b35c3f54757 -github.com/aws/aws-sdk-go f09322ae1e6468fe828c862542389bc45baf3c00 +github.com/aws/aws-sdk-go c4c1a1a2a076858fe18b2be674d833c796c45b09 github.com/beorn7/perks b965b613227fddccbfffe13eae360ed3fa822f8d -github.com/boltdb/bolt 34a0fa5307f7562980fb8e7ff4723f7987edf49b +github.com/boltdb/bolt 6465994716bf6400605746e79224cf1e7ed68725 github.com/cenkalti/backoff 4dc77674aceaabba2c7e3da25d4c823edfb73f99 -github.com/dancannon/gorethink a124c9663325ed9f7fb669d17c69961b59151e6e +github.com/dancannon/gorethink ff457cac6a529d9749d841a733d76e8305cba3c8 github.com/davecgh/go-spew 5215b55f46b2b919f50a1df0eaa5886afe4e3b3d github.com/eapache/go-resiliency b86b1ec0dd4209a588dc1285cdd471e73525c0b3 github.com/eapache/queue ded5959c0d4e360646dc9e9908cff48666781367 -github.com/fsouza/go-dockerclient 175e1df973274f04e9b459a62cffc49808f1a649 +github.com/fsouza/go-dockerclient 2fb7694010aa553998ed513dc8805ab00708077a github.com/go-ini/ini afbd495e5aaea13597b5e14fe514ddeaa4d76fc3 -github.com/go-sql-driver/mysql 7a8740a6bd8feb6af5786ab9a9f1513970019d8c -github.com/gogo/protobuf 7b1331554dbe882cb3613ee8f1824a5583627963 +github.com/go-sql-driver/mysql 6fd058ce0d6b7ee43174e80d5a3e7f483c4dfbe5 +github.com/gogo/protobuf c57e439bad574c2e0877ff18d514badcfced004d github.com/golang/protobuf 2402d76f3d41f928c7902a765dfc872356dd3aad github.com/golang/snappy 723cc1e459b8eea2dea4583200fd60757d40097a github.com/gonuts/go-shellquote e842a11b24c6abfb3dd27af69a17f482e4b483c2 @@ -22,31 +22,31 @@ github.com/hailocab/go-hostpool 50839ee41f32bfca8d03a183031aa634b2dc1c64 github.com/hashicorp/go-msgpack fa3f63826f7c23912c15263591e65d54d080b458 github.com/hashicorp/raft d136cd15dfb7876fd7c89cad1995bc4f19ceb294 github.com/hashicorp/raft-boltdb d1e82c1ec3f15ee991f7cc7ffd5b67ff6f5bbaee -github.com/influxdb/influxdb bd63489ef0faae2465ae5b1f0a28bd7e71e02e38 +github.com/influxdb/influxdb db84a6ed76353905432ff8bd91527c68b3ea1be6 github.com/jmespath/go-jmespath c01cf91b011868172fdcd9f41838e80c9d716264 -github.com/klauspost/crc32 a3b15ae34567abb20a22992b989cd76f48d09c47 -github.com/lib/pq 11fc39a580a008f1f39bb3d11d984fb34ed778d9 +github.com/klauspost/crc32 999f3125931f6557b991b2f8472172bdfa578d38 +github.com/lib/pq 8ad2b298cadd691a77015666a5372eae5dbfac8f github.com/matttproud/golang_protobuf_extensions d0c3fe89de86839aecf2e0579c40ba3bb336a453 github.com/mreiferson/go-snappystream 028eae7ab5c4c9e2d1cb4c4ca1e53259bbe7e504 github.com/naoina/go-stringutil 6b638e95a32d0c1131db0e7fe83775cbea4a0d0b github.com/naoina/toml 751171607256bb66e64c9f0220c00662420c38e9 github.com/nsqio/go-nsq 2118015c120962edc5d03325c680daf3163a8b5f github.com/pborman/uuid dee7705ef7b324f27ceb85a121c61f2c2e8ce988 -github.com/pmezard/go-difflib e8554b8641db39598be7f6342874b958f12ae1d4 +github.com/pmezard/go-difflib 792786c7400a136282c1664665ae0a8db921c6c2 github.com/prometheus/client_golang 67994f177195311c3ea3d4407ed0175e34a4256f github.com/prometheus/client_model fa8ad6fec33561be4280a8f0514318c79d7f6cb6 github.com/prometheus/common 0a3005bb37bc411040083a55372e77c405f6464c github.com/prometheus/procfs 406e5b7bfd8201a36e2bb5f7bdae0b03380c2ce8 github.com/samuel/go-zookeeper 218e9c81c0dd8b3b18172b2bbfad92cc7d6db55f -github.com/shirou/gopsutil ef151b7ff7fe76308f89a389447b7b78dfa02e0f +github.com/shirou/gopsutil 8850f58d7035653e1ab90711481954c8ca1b9813 github.com/streadway/amqp b4f3ceab0337f013208d31348b578d83c0064744 github.com/stretchr/objx 1a9d0bb9f541897e62256577b352fdbc1fb4fd94 -github.com/stretchr/testify c92828f29518bc633893affbce12904ba41a7cfa +github.com/stretchr/testify f390dcf405f7b83c997eac1b06768bb9f44dec18 github.com/wvanbergen/kafka 1a8639a45164fcc245d5c7b4bd3ccfbd1a0ffbf3 github.com/wvanbergen/kazoo-go 0f768712ae6f76454f987c3356177e138df258f8 -golang.org/x/crypto f23ba3a5ee43012fcb4b92e1a2a405a92554f4f2 -golang.org/x/net 520af5de654dc4dd4f0f65aa40e66dbbd9043df1 -gopkg.in/dancannon/gorethink.v1 a124c9663325ed9f7fb669d17c69961b59151e6e +golang.org/x/crypto 3760e016850398b85094c4c99e955b8c3dea5711 +golang.org/x/net 99ca920b6037ef77af8a11297150f7f0d8f4ef80 +gopkg.in/dancannon/gorethink.v1 e2cef022d0495329dfb0635991de76efcab5cf50 gopkg.in/fatih/pool.v2 cba550ebf9bce999a02e963296d4bc7a486cb715 gopkg.in/mgo.v2 e30de8ac9ae3b30df7065f766c71f88bba7d4e49 gopkg.in/yaml.v2 f7716cbe52baa25d2e9b0d0da546fcf909fc16b4 diff --git a/Makefile b/Makefile index b9de93ffbeedc..2ae4d12574ec8 100644 --- a/Makefile +++ b/Makefile @@ -21,18 +21,6 @@ dev: prepare "-X main.Version=$(VERSION)" \ ./cmd/telegraf/telegraf.go -# Build linux 64-bit, 32-bit and arm architectures -build-linux-bins: prepare - GOARCH=amd64 GOOS=linux go build -o telegraf_linux_amd64 \ - -ldflags "-X main.Version=$(VERSION)" \ - ./cmd/telegraf/telegraf.go - GOARCH=386 GOOS=linux go build -o telegraf_linux_386 \ - -ldflags "-X main.Version=$(VERSION)" \ - ./cmd/telegraf/telegraf.go - GOARCH=arm GOOS=linux go build -o telegraf_linux_arm \ - -ldflags "-X main.Version=$(VERSION)" \ - ./cmd/telegraf/telegraf.go - # Get dependencies and use gdm to checkout changesets prepare: go get ./... diff --git a/README.md b/README.md index e86750f184bb2..6b723787e1fd5 100644 --- a/README.md +++ b/README.md @@ -17,17 +17,18 @@ new plugins. ## Installation: -NOTE: Telegraf 0.3.x is **not** backwards-compatible with previous versions of -telegraf, both in the database layout and the configuration file. 0.2.x will -continue to be supported, see below for download links. +NOTE: Telegraf 0.10.x is **not** backwards-compatible with previous versions +of telegraf, both in the database layout and the configuration file. 0.2.x +will continue to be supported, see below for download links. -TODO: link to blog post about 0.3.x changes. +For more details on the differences between Telegraf 0.2.x and 0.10.x, see +the [release blog post](https://influxdata.com/blog/announcing-telegraf-0-10-0/). ### Linux deb and rpm packages: Latest: -* http://get.influxdb.org/telegraf/telegraf_0.3.0_amd64.deb -* http://get.influxdb.org/telegraf/telegraf-0.3.0-1.x86_64.rpm +* http://get.influxdb.org/telegraf/telegraf_0.10.0-1_amd64.deb +* http://get.influxdb.org/telegraf/telegraf-0.10.0-1.x86_64.rpm 0.2.x: * http://get.influxdb.org/telegraf/telegraf_0.2.4_amd64.deb @@ -45,9 +46,9 @@ controlled via `systemctl [action] telegraf` ### Linux binaries: Latest: -* http://get.influxdb.org/telegraf/telegraf_linux_amd64_0.3.0.tar.gz -* http://get.influxdb.org/telegraf/telegraf_linux_386_0.3.0.tar.gz -* http://get.influxdb.org/telegraf/telegraf_linux_arm_0.3.0.tar.gz +* http://get.influxdb.org/telegraf/telegraf-0.10.0_linux_amd64.tar.gz +* http://get.influxdb.org/telegraf/telegraf-0.10.0_linux_386.tar.gz +* http://get.influxdb.org/telegraf/telegraf-0.10.0_linux_arm.tar.gz 0.2.x: * http://get.influxdb.org/telegraf/telegraf_linux_amd64_0.2.4.tar.gz @@ -84,7 +85,7 @@ if you don't have it already. You also must build with golang version 1.4+. ```console $ telegraf -help -Telegraf, The plugin-driven server agent for reporting metrics into InfluxDB +Telegraf, The plugin-driven server agent for collecting and reporting metrics. Usage: @@ -99,6 +100,8 @@ The flags are: -input-filter filter the input plugins to enable, separator is : -output-filter filter the output plugins to enable, separator is : -usage print usage for a plugin, ie, 'telegraf -usage mysql' + -debug print metrics as they're generated to stdout + -quiet run in quiet mode -version print the version to stdout Examples: @@ -126,7 +129,11 @@ configuration options. ## Supported Input Plugins -Telegraf currently has support for collecting metrics from: +Telegraf currently has support for collecting metrics from many sources. For +more information on each, please look at the directory of the same name in +`plugins/inputs`. + +Currently implemented sources: * aerospike * apache @@ -157,6 +164,7 @@ Telegraf currently has support for collecting metrics from: * twemproxy * zfs * zookeeper +* sensors * system * cpu * mem diff --git a/agent.go b/agent.go index 1af2a1f7cc9c7..0c5d58db570aa 100644 --- a/agent.go +++ b/agent.go @@ -121,8 +121,10 @@ func (a *Agent) gatherParallel(pointChan chan *client.Point) error { wg.Wait() elapsed := time.Since(start) - log.Printf("Gathered metrics, (%s interval), from %d inputs in %s\n", - a.Config.Agent.Interval.Duration, counter, elapsed) + if !a.Config.Agent.Quiet { + log.Printf("Gathered metrics, (%s interval), from %d inputs in %s\n", + a.Config.Agent.Interval.Duration, counter, elapsed) + } return nil } @@ -149,8 +151,10 @@ func (a *Agent) gatherSeparate( } elapsed := time.Since(start) - log.Printf("Gathered metrics, (separate %s interval), from %s in %s\n", - input.Config.Interval, input.Name, elapsed) + if !a.Config.Agent.Quiet { + log.Printf("Gathered metrics, (separate %s interval), from %s in %s\n", + input.Config.Interval, input.Name, elapsed) + } if outerr != nil { return outerr @@ -235,8 +239,10 @@ func (a *Agent) writeOutput( if err == nil { // Write successful elapsed := time.Since(start) - log.Printf("Flushed %d metrics to output %s in %s\n", - len(filtered), ro.Name, elapsed) + if !a.Config.Agent.Quiet { + log.Printf("Flushed %d metrics to output %s in %s\n", + len(filtered), ro.Name, elapsed) + } return } @@ -327,12 +333,13 @@ func jitterInterval(ininterval, injitter time.Duration) time.Duration { func (a *Agent) Run(shutdown chan struct{}) error { var wg sync.WaitGroup - a.Config.Agent.FlushInterval.Duration = jitterInterval(a.Config.Agent.FlushInterval.Duration, + a.Config.Agent.FlushInterval.Duration = jitterInterval( + a.Config.Agent.FlushInterval.Duration, a.Config.Agent.FlushJitter.Duration) - log.Printf("Agent Config: Interval:%s, Debug:%#v, Hostname:%#v, "+ - "Flush Interval:%s\n", - a.Config.Agent.Interval.Duration, a.Config.Agent.Debug, + log.Printf("Agent Config: Interval:%s, Debug:%#v, Quiet:%#v, Hostname:%#v, "+ + "Flush Interval:%s \n", + a.Config.Agent.Interval.Duration, a.Config.Agent.Debug, a.Config.Agent.Quiet, a.Config.Agent.Hostname, a.Config.Agent.FlushInterval.Duration) // channel shared between all input threads for accumulating points diff --git a/build.py b/build.py index d6d6bee01543a..a5892f26a537e 100755 --- a/build.py +++ b/build.py @@ -92,31 +92,32 @@ def run(command, allow_failure=False, shell=False): out = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=shell) else: out = subprocess.check_output(command.split(), stderr=subprocess.STDOUT) + out = out.decode("utf8") except subprocess.CalledProcessError as e: - print "" - print "" - print "Executed command failed!" - print "-- Command run was: {}".format(command) - print "-- Failure was: {}".format(e.output) + print("") + print("") + print("Executed command failed!") + print("-- Command run was: {}".format(command)) + print("-- Failure was: {}".format(e.output)) if allow_failure: - print "Continuing..." + print("Continuing...") return None else: - print "" - print "Stopping." + print("") + print("Stopping.") sys.exit(1) except OSError as e: - print "" - print "" - print "Invalid command!" - print "-- Command run was: {}".format(command) - print "-- Failure was: {}".format(e) + print("") + print("") + print("Invalid command!") + print("-- Command run was: {}".format(command)) + print("-- Failure was: {}".format(e)) if allow_failure: - print "Continuing..." + print("Continuing...") return out else: - print "" - print "Stopping." + print("") + print("Stopping.") sys.exit(1) else: return out @@ -173,42 +174,42 @@ def is_exe(fpath): return full_path def check_environ(build_dir = None): - print "\nChecking environment:" + print("\nChecking environment:") for v in [ "GOPATH", "GOBIN", "GOROOT" ]: - print "\t- {} -> {}".format(v, os.environ.get(v)) + print("\t- {} -> {}".format(v, os.environ.get(v))) cwd = os.getcwd() if build_dir == None and os.environ.get("GOPATH") and os.environ.get("GOPATH") not in cwd: - print "\n!! WARNING: Your current directory is not under your GOPATH. This may lead to build failures." + print("\n!! WARNING: Your current directory is not under your GOPATH. This may lead to build failures.") def check_prereqs(): - print "\nChecking for dependencies:" + print("\nChecking for dependencies:") for req in prereqs: - print "\t- {} ->".format(req), + print("\t- {} ->".format(req),) path = check_path_for(req) if path: - print "{}".format(path) + print("{}".format(path)) else: - print "?" + print("?") for req in optional_prereqs: - print "\t- {} (optional) ->".format(req), + print("\t- {} (optional) ->".format(req)) path = check_path_for(req) if path: - print "{}".format(path) + print("{}".format(path)) else: - print "?" - print "" + print("?") + print("") def upload_packages(packages, nightly=False): - print "Uploading packages to S3..." - print "" + print("Uploading packages to S3...") + print("") c = boto.connect_s3() # TODO(rossmcdonald) - Set to different S3 bucket for release vs nightly - bucket = c.get_bucket('telegraf-nightly') + bucket = c.get_bucket('get.influxdb.org') for p in packages: - name = os.path.basename(p) + name = os.path.join('telegraf', os.path.basename(p)) if bucket.get_key(name) is None or nightly: - print "\t - Uploading {}...".format(name), + print("\t - Uploading {}...".format(name)) k = Key(bucket) k.key = name if nightly: @@ -216,41 +217,41 @@ def upload_packages(packages, nightly=False): else: n = k.set_contents_from_filename(p, replace=False) k.make_public() - print "[ DONE ]" + print("[ DONE ]") else: - print "\t - Not uploading {}, already exists.".format(p) - print "" + print("\t - Not uploading {}, already exists.".format(p)) + print("") def run_tests(race, parallel, timeout, no_vet): get_command = "go get -d -t ./..." - print "Retrieving Go dependencies...", + print("Retrieving Go dependencies...") sys.stdout.flush() run(get_command) - print "done." - print "Running tests:" - print "\tRace: ", race + print("done.") + print("Running tests:") + print("\tRace: ", race) if parallel is not None: - print "\tParallel:", parallel + print("\tParallel:", parallel) if timeout is not None: - print "\tTimeout:", timeout + print("\tTimeout:", timeout) sys.stdout.flush() p = subprocess.Popen(["go", "fmt", "./..."], stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = p.communicate() if len(out) > 0 or len(err) > 0: - print "Code not formatted. Please use 'go fmt ./...' to fix formatting errors." - print out - print err + print("Code not formatted. Please use 'go fmt ./...' to fix formatting errors.") + print(out) + print(err) return False if not no_vet: p = subprocess.Popen(["go", "tool", "vet", "-composites=false", "./"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = p.communicate() if len(out) > 0 or len(err) > 0: - print "Go vet failed. Please run 'go vet ./...' and fix any errors." - print out - print err + print("Go vet failed. Please run 'go vet ./...' and fix any errors.") + print(out) + print(err) return False else: - print "Skipping go vet ..." + print("Skipping go vet ...") sys.stdout.flush() test_command = "go test -v" if race: @@ -262,10 +263,10 @@ def run_tests(race, parallel, timeout, no_vet): test_command += " ./..." code = os.system(test_command) if code != 0: - print "Tests Failed" + print("Tests Failed") return False else: - print "Tests Passed" + print("Tests Passed") return True def build(version=None, @@ -279,26 +280,26 @@ def build(version=None, clean=False, outdir=".", goarm_version="6"): - print "-------------------------" - print "" - print "Build plan:" - print "\t- version: {}".format(version) + print("-------------------------") + print("") + print("Build plan:") + print("\t- version: {}".format(version)) if rc: - print "\t- release candidate: {}".format(rc) - print "\t- commit: {}".format(commit) - print "\t- branch: {}".format(branch) - print "\t- platform: {}".format(platform) - print "\t- arch: {}".format(arch) + print("\t- release candidate: {}".format(rc)) + print("\t- commit: {}".format(commit)) + print("\t- branch: {}".format(branch)) + print("\t- platform: {}".format(platform)) + print("\t- arch: {}".format(arch)) if arch == 'arm' and goarm_version: - print "\t- ARM version: {}".format(goarm_version) - print "\t- nightly? {}".format(str(nightly).lower()) - print "\t- race enabled? {}".format(str(race).lower()) - print "" + print("\t- ARM version: {}".format(goarm_version)) + print("\t- nightly? {}".format(str(nightly).lower())) + print("\t- race enabled? {}".format(str(race).lower())) + print("") if not os.path.exists(outdir): os.makedirs(outdir) elif clean and outdir != '/': - print "Cleaning build directory..." + print("Cleaning build directory...") shutil.rmtree(outdir) os.makedirs(outdir) @@ -306,14 +307,14 @@ def build(version=None, # If a release candidate, update the version information accordingly version = "{}rc{}".format(version, rc) - print "Starting build..." - for b, c in targets.iteritems(): - print "\t- Building '{}'...".format(os.path.join(outdir, b)), + print("Starting build...") + for b, c in targets.items(): + print("\t- Building '{}'...".format(os.path.join(outdir, b)),) build_command = "" build_command += "GOOS={} GOARCH={} ".format(platform, arch) if arch == "arm" and goarm_version: if goarm_version not in ["5", "6", "7", "arm64"]: - print "!! Invalid ARM build version: {}".format(goarm_version) + print("!! Invalid ARM build version: {}".format(goarm_version)) build_command += "GOARM={} ".format(goarm_version) build_command += "go build -o {} ".format(os.path.join(outdir, b)) if race: @@ -331,20 +332,20 @@ def build(version=None, build_command += "-X main.Commit={}\" ".format(get_current_commit()) build_command += c run(build_command, shell=True) - print "[ DONE ]" - print "" + print("[ DONE ]") + print("") def create_dir(path): try: os.makedirs(path) except OSError as e: - print e + print(e) def rename_file(fr, to): try: os.rename(fr, to) except OSError as e: - print e + print(e) # Return the original filename return fr else: @@ -355,27 +356,27 @@ def copy_file(fr, to): try: shutil.copy(fr, to) except OSError as e: - print e + print(e) def create_package_fs(build_root): - print "\t- Creating a filesystem hierarchy from directory: {}".format(build_root) + print("\t- Creating a filesystem hierarchy from directory: {}".format(build_root)) # Using [1:] for the path names due to them being absolute # (will overwrite previous paths, per 'os.path.join' documentation) dirs = [ INSTALL_ROOT_DIR[1:], LOG_DIR[1:], SCRIPT_DIR[1:], CONFIG_DIR[1:], LOGROTATE_DIR[1:] ] for d in dirs: create_dir(os.path.join(build_root, d)) - os.chmod(os.path.join(build_root, d), 0755) + os.chmod(os.path.join(build_root, d), 0o755) def package_scripts(build_root): - print "\t- Copying scripts and sample configuration to build directory" + print("\t- Copying scripts and sample configuration to build directory") shutil.copyfile(INIT_SCRIPT, os.path.join(build_root, SCRIPT_DIR[1:], INIT_SCRIPT.split('/')[1])) - os.chmod(os.path.join(build_root, SCRIPT_DIR[1:], INIT_SCRIPT.split('/')[1]), 0644) + os.chmod(os.path.join(build_root, SCRIPT_DIR[1:], INIT_SCRIPT.split('/')[1]), 0o644) shutil.copyfile(SYSTEMD_SCRIPT, os.path.join(build_root, SCRIPT_DIR[1:], SYSTEMD_SCRIPT.split('/')[1])) - os.chmod(os.path.join(build_root, SCRIPT_DIR[1:], SYSTEMD_SCRIPT.split('/')[1]), 0644) + os.chmod(os.path.join(build_root, SCRIPT_DIR[1:], SYSTEMD_SCRIPT.split('/')[1]), 0o644) shutil.copyfile(LOGROTATE_SCRIPT, os.path.join(build_root, LOGROTATE_DIR[1:], "telegraf")) - os.chmod(os.path.join(build_root, LOGROTATE_DIR[1:], "telegraf"), 0644) + os.chmod(os.path.join(build_root, LOGROTATE_DIR[1:], "telegraf"), 0o644) shutil.copyfile(DEFAULT_CONFIG, os.path.join(build_root, CONFIG_DIR[1:], "telegraf.conf")) - os.chmod(os.path.join(build_root, CONFIG_DIR[1:], "telegraf.conf"), 0644) + os.chmod(os.path.join(build_root, CONFIG_DIR[1:], "telegraf.conf"), 0o644) def go_get(update=False): get_command = None @@ -383,24 +384,27 @@ def go_get(update=False): get_command = "go get -u -f -d ./..." else: get_command = "go get -d ./..." - print "Retrieving Go dependencies...", + print("Retrieving Go dependencies...") run(get_command) - print "done.\n" + print("done.\n") def generate_md5_from_file(path): m = hashlib.md5() with open(path, 'rb') as f: - for chunk in iter(lambda: f.read(4096), b""): - m.update(chunk) + while True: + data = f.read(4096) + if not data: + break + m.update(data) return m.hexdigest() def build_packages(build_output, version, nightly=False, rc=None, iteration=1): outfiles = [] tmp_build_dir = create_temp_dir() try: - print "-------------------------" - print "" - print "Packaging..." + print("-------------------------") + print("") + print("Packaging...") for p in build_output: # Create top-level folder displaying which platform (linux, etc) create_dir(os.path.join(tmp_build_dir, p)) @@ -419,11 +423,11 @@ def build_packages(build_output, version, nightly=False, rc=None, iteration=1): b = b + '.exe' fr = os.path.join(current_location, b) to = os.path.join(build_root, INSTALL_ROOT_DIR[1:], b) - print "\t- [{}][{}] - Moving from '{}' to '{}'".format(p, a, fr, to) + print("\t- [{}][{}] - Moving from '{}' to '{}'".format(p, a, fr, to)) copy_file(fr, to) # Package the directory structure for package_type in supported_packages[p]: - print "\t- Packaging directory '{}' as '{}'...".format(build_root, package_type), + print("\t- Packaging directory '{}' as '{}'...".format(build_root, package_type)) name = "telegraf" package_version = version package_iteration = iteration @@ -448,52 +452,53 @@ def build_packages(build_output, version, nightly=False, rc=None, iteration=1): current_location) if package_type == "rpm": fpm_command += "--depends coreutils " + fpm_command += "--depends lsof" out = run(fpm_command, shell=True) matches = re.search(':path=>"(.*)"', out) outfile = None if matches is not None: outfile = matches.groups()[0] if outfile is None: - print "[ COULD NOT DETERMINE OUTPUT ]" + print("[ COULD NOT DETERMINE OUTPUT ]") else: # Strip nightly version (the unix epoch) from filename if nightly and package_type in ['deb', 'rpm']: outfile = rename_file(outfile, outfile.replace("{}-{}".format(version, iteration), "nightly")) outfiles.append(os.path.join(os.getcwd(), outfile)) - print "[ DONE ]" + print("[ DONE ]") # Display MD5 hash for generated package - print "\t\tMD5 = {}".format(generate_md5_from_file(outfile)) - print "" + print("\t\tMD5 = {}".format(generate_md5_from_file(outfile))) + print("") return outfiles finally: # Cleanup shutil.rmtree(tmp_build_dir) def print_usage(): - print "Usage: ./build.py [options]" - print "" - print "Options:" - print "\t --outdir= \n\t\t- Send build output to a specified path. Defaults to ./build." - print "\t --arch= \n\t\t- Build for specified architecture. Acceptable values: x86_64|amd64, 386, arm, or all" - print "\t --goarm= \n\t\t- Build for specified ARM version (when building for ARM). Default value is: 6" - print "\t --platform= \n\t\t- Build for specified platform. Acceptable values: linux, windows, darwin, or all" - print "\t --version= \n\t\t- Version information to apply to build metadata. If not specified, will be pulled from repo tag." - print "\t --commit= \n\t\t- Use specific commit for build (currently a NOOP)." - print "\t --branch= \n\t\t- Build from a specific branch (currently a NOOP)." - print "\t --rc= \n\t\t- Whether or not the build is a release candidate (affects version information)." - print "\t --iteration= \n\t\t- The iteration to display on the package output (defaults to 0 for RC's, and 1 otherwise)." - print "\t --race \n\t\t- Whether the produced build should have race detection enabled." - print "\t --package \n\t\t- Whether the produced builds should be packaged for the target platform(s)." - print "\t --nightly \n\t\t- Whether the produced build is a nightly (affects version information)." - print "\t --update \n\t\t- Whether dependencies should be updated prior to building." - print "\t --test \n\t\t- Run Go tests. Will not produce a build." - print "\t --parallel \n\t\t- Run Go tests in parallel up to the count specified." - print "\t --timeout \n\t\t- Timeout for Go tests. Defaults to 480s." - print "\t --clean \n\t\t- Clean the build output directory prior to creating build." - print "" + print("Usage: ./build.py [options]") + print("") + print("Options:") + print("\t --outdir= \n\t\t- Send build output to a specified path. Defaults to ./build.") + print("\t --arch= \n\t\t- Build for specified architecture. Acceptable values: x86_64|amd64, 386, arm, or all") + print("\t --goarm= \n\t\t- Build for specified ARM version (when building for ARM). Default value is: 6") + print("\t --platform= \n\t\t- Build for specified platform. Acceptable values: linux, windows, darwin, or all") + print("\t --version= \n\t\t- Version information to apply to build metadata. If not specified, will be pulled from repo tag.") + print("\t --commit= \n\t\t- Use specific commit for build (currently a NOOP).") + print("\t --branch= \n\t\t- Build from a specific branch (currently a NOOP).") + print("\t --rc= \n\t\t- Whether or not the build is a release candidate (affects version information).") + print("\t --iteration= \n\t\t- The iteration to display on the package output (defaults to 0 for RC's, and 1 otherwise).") + print("\t --race \n\t\t- Whether the produced build should have race detection enabled.") + print("\t --package \n\t\t- Whether the produced builds should be packaged for the target platform(s).") + print("\t --nightly \n\t\t- Whether the produced build is a nightly (affects version information).") + print("\t --update \n\t\t- Whether dependencies should be updated prior to building.") + print("\t --test \n\t\t- Run Go tests. Will not produce a build.") + print("\t --parallel \n\t\t- Run Go tests in parallel up to the count specified.") + print("\t --timeout \n\t\t- Timeout for Go tests. Defaults to 480s.") + print("\t --clean \n\t\t- Clean the build output directory prior to creating build.") + print("") def print_package_summary(packages): - print packages + print(packages) def main(): # Command-line arguments @@ -577,13 +582,13 @@ def main(): print_usage() return 0 else: - print "!! Unknown argument: {}".format(arg) + print("!! Unknown argument: {}".format(arg)) print_usage() return 1 if nightly: if rc: - print "!! Cannot be both nightly and a release candidate! Stopping." + print("!! Cannot be both nightly and a release candidate! Stopping.") return 1 # In order to support nightly builds on the repository, we are adding the epoch timestamp # to the version so that version numbers are always greater than the previous nightly. @@ -622,7 +627,7 @@ def main(): platforms = [] single_build = True if target_platform == 'all': - platforms = supported_builds.keys() + platforms = list(supported_builds.keys()) single_build = False else: platforms = [target_platform] @@ -655,7 +660,7 @@ def main(): # Build packages if package: if not check_path_for("fpm"): - print "!! Cannot package without command 'fpm'. Stopping." + print("!! Cannot package without command 'fpm'. Stopping.") return 1 packages = build_packages(build_output, version, nightly=nightly, rc=rc, iteration=iteration) # TODO(rossmcdonald): Add nice output for print_package_summary() @@ -667,4 +672,3 @@ def main(): if __name__ == '__main__': sys.exit(main()) - diff --git a/cmd/telegraf/telegraf.go b/cmd/telegraf/telegraf.go index 21e89ce04d04b..a2b5161bee979 100644 --- a/cmd/telegraf/telegraf.go +++ b/cmd/telegraf/telegraf.go @@ -16,6 +16,8 @@ import ( var fDebug = flag.Bool("debug", false, "show metrics as they're generated to stdout") +var fQuiet = flag.Bool("quiet", false, + "run in quiet mode") var fTest = flag.Bool("test", false, "gather metrics, print them out, and exit") var fConfig = flag.String("config", "", "configuration file to load") var fConfigDirectory = flag.String("config-directory", "", @@ -57,6 +59,8 @@ The flags are: -input-filter filter the input plugins to enable, separator is : -output-filter filter the output plugins to enable, separator is : -usage print usage for a plugin, ie, 'telegraf -usage mysql' + -debug print metrics as they're generated to stdout + -quiet run in quiet mode -version print the version to stdout Examples: @@ -173,6 +177,10 @@ func main() { ag.Config.Agent.Debug = true } + if *fQuiet { + ag.Config.Agent.Quiet = true + } + if *fTest { err = ag.Test() if err != nil { diff --git a/internal/config/config.go b/internal/config/config.go index 6c3d17750aa9f..ca4972b69793f 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -76,8 +76,11 @@ type AgentConfig struct { UTC bool `toml:"utc"` Precision string - // Option for running in debug mode - Debug bool + // Debug is the option for running in debug mode + Debug bool + + // Quiet is the option for running in quiet mode + Quiet bool Hostname string } @@ -279,6 +282,8 @@ var header = `# Telegraf configuration # Run telegraf in debug mode debug = false + # Run telegraf in quiet mode + quiet = false # Override default hostname, if empty use os.Hostname() hostname = "" diff --git a/internal/internal.go b/internal/internal.go index fc55ba5294a5f..8b0b33a4157b7 100644 --- a/internal/internal.go +++ b/internal/internal.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "os" + "strconv" "strings" "time" ) @@ -49,9 +50,17 @@ func (f *JSONFlattener) FlattenJSON( return err } } + case []interface{}: + for i, v := range t { + k := strconv.Itoa(i) + err := f.FlattenJSON(fieldname+"_"+k+"_", v) + if err != nil { + return nil + } + } case float64: f.Fields[fieldname] = t - case bool, string, []interface{}, nil: + case bool, string, nil: // ignored types return nil default: diff --git a/plugins/inputs/all/all.go b/plugins/inputs/all/all.go index fea1c7ca04a60..b6b1e74daa979 100644 --- a/plugins/inputs/all/all.go +++ b/plugins/inputs/all/all.go @@ -28,6 +28,7 @@ import ( _ "github.com/influxdb/telegraf/plugins/inputs/rabbitmq" _ "github.com/influxdb/telegraf/plugins/inputs/redis" _ "github.com/influxdb/telegraf/plugins/inputs/rethinkdb" + _ "github.com/influxdb/telegraf/plugins/inputs/sensors" _ "github.com/influxdb/telegraf/plugins/inputs/statsd" _ "github.com/influxdb/telegraf/plugins/inputs/system" _ "github.com/influxdb/telegraf/plugins/inputs/trig" diff --git a/plugins/inputs/elasticsearch/testdata_test.go b/plugins/inputs/elasticsearch/testdata_test.go index 03e512f815a76..bca1f9e45beff 100644 --- a/plugins/inputs/elasticsearch/testdata_test.go +++ b/plugins/inputs/elasticsearch/testdata_test.go @@ -562,6 +562,9 @@ var indicesExpected = map[string]interface{}{ } var osExpected = map[string]interface{}{ + "load_average_0": float64(0.01), + "load_average_1": float64(0.04), + "load_average_2": float64(0.05), "swap_used_in_bytes": float64(0), "swap_free_in_bytes": float64(487997440), "timestamp": float64(1436460392944), @@ -724,10 +727,13 @@ var threadPoolExpected = map[string]interface{}{ } var fsExpected = map[string]interface{}{ - "timestamp": float64(1436460392946), - "total_free_in_bytes": float64(16909316096), - "total_available_in_bytes": float64(15894814720), - "total_total_in_bytes": float64(19507089408), + "data_0_total_in_bytes": float64(19507089408), + "data_0_free_in_bytes": float64(16909316096), + "data_0_available_in_bytes": float64(15894814720), + "timestamp": float64(1436460392946), + "total_free_in_bytes": float64(16909316096), + "total_available_in_bytes": float64(15894814720), + "total_total_in_bytes": float64(19507089408), } var transportExpected = map[string]interface{}{ diff --git a/plugins/inputs/exec/README.md b/plugins/inputs/exec/README.md index 7aa52db33245d..bd78f0b3c414b 100644 --- a/plugins/inputs/exec/README.md +++ b/plugins/inputs/exec/README.md @@ -7,13 +7,13 @@ For example, if you have a json-returning command called mycollector, you could setup the exec plugin with: ``` -[[exec.commands]] -command = "/usr/bin/mycollector --output=json" -name = "mycollector" -interval = 10 +[[inputs.exec]] + command = "/usr/bin/mycollector --output=json" + name_suffix = "_mycollector" + interval = "10s" ``` -The name is used as a prefix for the measurements. +The name suffix is appended to exec as "exec_name_suffix" to identify the input stream. The interval is used to determine how often a particular command should be run. Each time the exec plugin runs, it will only run a particular command if it has been at least @@ -22,21 +22,24 @@ time the exec plugin runs, it will only run a particular command if it has been # Sample -Let's say that we have a command named "mycollector", which gives the following output: +Let's say that we have a command with the name_suffix "_mycollector", which gives the following output: ```json { "a": 0.5, "b": { - "c": "some text", - "d": 0.1, - "e": 5 + "c": 0.1, + "d": 5 } } ``` -The collected metrics will be: +The collected metrics will be stored as field values under the same measurement "exec_mycollector": ``` -exec_mycollector_a value=0.5 -exec_mycollector_b_d value=0.1 -exec_mycollector_b_e value=5 + exec_mycollector a=0.5,b_c=0.1,b_d=5 1452815002357578567 +``` + +Other options for modifying the measurement names are: +``` +name_override = "newname" +name_prefix = "prefix_" ``` diff --git a/plugins/inputs/exec/exec_test.go b/plugins/inputs/exec/exec_test.go index d3e54429dbb87..64fd69fce5f03 100644 --- a/plugins/inputs/exec/exec_test.go +++ b/plugins/inputs/exec/exec_test.go @@ -59,13 +59,17 @@ func TestExec(t *testing.T) { var acc testutil.Accumulator err := e.Gather(&acc) require.NoError(t, err) - assert.Equal(t, acc.NFields(), 4, "non-numeric measurements should be ignored") + assert.Equal(t, acc.NFields(), 8, "non-numeric measurements should be ignored") fields := map[string]interface{}{ "num_processes": float64(82), "cpu_used": float64(8234), "cpu_free": float64(32), "percent": float64(0.81), + "users_0": float64(0), + "users_1": float64(1), + "users_2": float64(2), + "users_3": float64(3), } acc.AssertContainsFields(t, "exec", fields) } diff --git a/plugins/inputs/httpjson/httpjson.go b/plugins/inputs/httpjson/httpjson.go index e31085e3ab4f8..5763fd6fab9b0 100644 --- a/plugins/inputs/httpjson/httpjson.go +++ b/plugins/inputs/httpjson/httpjson.go @@ -9,6 +9,7 @@ import ( "net/url" "strings" "sync" + "time" "github.com/influxdb/telegraf/internal" "github.com/influxdb/telegraf/plugins/inputs" @@ -119,7 +120,8 @@ func (h *HttpJson) gatherServer( acc inputs.Accumulator, serverURL string, ) error { - resp, err := h.sendRequest(serverURL) + resp, responseTime, err := h.sendRequest(serverURL) + if err != nil { return err } @@ -141,6 +143,9 @@ func (h *HttpJson) gatherServer( delete(jsonOut, tag) } + if responseTime >= 0 { + jsonOut["response_time"] = responseTime + } f := internal.JSONFlattener{} err = f.FlattenJSON("", jsonOut) if err != nil { @@ -164,11 +169,11 @@ func (h *HttpJson) gatherServer( // Returns: // string: body of the response // error : Any error that may have occurred -func (h *HttpJson) sendRequest(serverURL string) (string, error) { +func (h *HttpJson) sendRequest(serverURL string) (string, float64, error) { // Prepare URL requestURL, err := url.Parse(serverURL) if err != nil { - return "", fmt.Errorf("Invalid server URL \"%s\"", serverURL) + return "", -1, fmt.Errorf("Invalid server URL \"%s\"", serverURL) } params := url.Values{} @@ -180,19 +185,21 @@ func (h *HttpJson) sendRequest(serverURL string) (string, error) { // Create + send request req, err := http.NewRequest(h.Method, requestURL.String(), nil) if err != nil { - return "", err + return "", -1, err } + start := time.Now() resp, err := h.client.MakeRequest(req) if err != nil { - return "", err + return "", -1, err } - defer resp.Body.Close() defer resp.Body.Close() + responseTime := time.Since(start).Seconds() + body, err := ioutil.ReadAll(resp.Body) if err != nil { - return string(body), err + return string(body), responseTime, err } // Process response @@ -203,10 +210,10 @@ func (h *HttpJson) sendRequest(serverURL string) (string, error) { http.StatusText(resp.StatusCode), http.StatusOK, http.StatusText(http.StatusOK)) - return string(body), err + return string(body), responseTime, err } - return string(body), err + return string(body), responseTime, err } func init() { diff --git a/plugins/inputs/httpjson/httpjson_test.go b/plugins/inputs/httpjson/httpjson_test.go index 7e9ffd3312452..3f14290ffc9d8 100644 --- a/plugins/inputs/httpjson/httpjson_test.go +++ b/plugins/inputs/httpjson/httpjson_test.go @@ -14,17 +14,17 @@ import ( const validJSON = ` { "parent": { - "child": 3, + "child": 3.0, "ignored_child": "hi" }, "ignored_null": null, "integer": 4, - "ignored_list": [3, 4], + "list": [3, 4], "ignored_parent": { - "another_ignored_list": [4], "another_ignored_null": null, "ignored_string": "hello, world!" - } + }, + "another_list": [4] }` const validJSONTags = ` @@ -35,8 +35,11 @@ const validJSONTags = ` }` var expectedFields = map[string]interface{}{ - "parent_child": float64(3), - "integer": float64(4), + "parent_child": float64(3), + "list_0": float64(3), + "list_1": float64(4), + "another_list_0": float64(4), + "integer": float64(4), } const invalidJSON = "I don't think this is JSON" @@ -123,10 +126,16 @@ func TestHttpJson200(t *testing.T) { var acc testutil.Accumulator err := service.Gather(&acc) require.NoError(t, err) - assert.Equal(t, 4, acc.NFields()) + assert.Equal(t, 12, acc.NFields()) + // Set responsetime + for _, p := range acc.Points { + p.Fields["response_time"] = 1.0 + } + for _, srv := range service.Servers { tags := map[string]string{"server": srv} mname := "httpjson_" + service.Name + expectedFields["response_time"] = 1.0 acc.AssertContainsTaggedFields(t, mname, expectedFields, tags) } } @@ -185,11 +194,15 @@ func TestHttpJson200Tags(t *testing.T) { if service.Name == "other_webapp" { var acc testutil.Accumulator err := service.Gather(&acc) + // Set responsetime + for _, p := range acc.Points { + p.Fields["response_time"] = 1.0 + } require.NoError(t, err) - assert.Equal(t, 2, acc.NFields()) + assert.Equal(t, 4, acc.NFields()) for _, srv := range service.Servers { tags := map[string]string{"server": srv, "role": "master", "build": "123"} - fields := map[string]interface{}{"value": float64(15)} + fields := map[string]interface{}{"value": float64(15), "response_time": float64(1)} mname := "httpjson_" + service.Name acc.AssertContainsTaggedFields(t, mname, fields, tags) } diff --git a/plugins/inputs/ping/ping.go b/plugins/inputs/ping/ping.go index e03fc71e8bfa0..ff7cebb99cd4d 100644 --- a/plugins/inputs/ping/ping.go +++ b/plugins/inputs/ping/ping.go @@ -86,7 +86,9 @@ func (p *Ping) Gather(acc inputs.Accumulator) error { "packets_transmitted": trans, "packets_received": rec, "percent_packet_loss": loss, - "average_response_ms": avg, + } + if avg > 0 { + fields["average_response_ms"] = avg } acc.AddFields("ping", fields, tags) }(url, acc) diff --git a/plugins/inputs/ping/ping_test.go b/plugins/inputs/ping/ping_test.go index 7ae86534d3190..b98a08be81fe4 100644 --- a/plugins/inputs/ping/ping_test.go +++ b/plugins/inputs/ping/ping_test.go @@ -193,7 +193,6 @@ func TestBadPingGather(t *testing.T) { "packets_transmitted": 2, "packets_received": 0, "percent_packet_loss": 100.0, - "average_response_ms": 0.0, } acc.AssertContainsTaggedFields(t, "ping", fields, tags) } diff --git a/plugins/inputs/procstat/README.md b/plugins/inputs/procstat/README.md index d2322ab1f5b49..0c37af50924de 100644 --- a/plugins/inputs/procstat/README.md +++ b/plugins/inputs/procstat/README.md @@ -16,25 +16,19 @@ individual process specific measurements. Example: ``` - [procstat] +[[inputs.procstat]] + exe = "influxd" + prefix = "influxd" - [[procstat.specifications]] - exe = "influxd" - prefix = "influxd" - - [[procstat.specifications]] - pid_file = "/var/run/lxc/dnsmasq.pid" +[[inputs.procstat]] + pid_file = "/var/run/lxc/dnsmasq.pid" ``` The above configuration would result in output like: ``` -[...] -> [name="dnsmasq" pid="44979"] procstat_cpu_user value=0.14 -> [name="dnsmasq" pid="44979"] procstat_cpu_system value=0.07 -[...] -> [name="influxd" pid="34337"] procstat_influxd_cpu_user value=25.43 -> [name="influxd" pid="34337"] procstat_influxd_cpu_system value=21.82 +> procstat,name="dnsmasq",pid="44979" cpu_user=0.14,cpu_system=0.07 +> procstat,name="influxd",pid="34337" influxd_cpu_user=25.43,influxd_cpu_system=21.82 ``` # Measurements diff --git a/plugins/inputs/sensors/sensors.go b/plugins/inputs/sensors/sensors.go new file mode 100644 index 0000000000000..18e26278d44fc --- /dev/null +++ b/plugins/inputs/sensors/sensors.go @@ -0,0 +1,90 @@ +// +build linux,sensors + +package sensors + +import ( + "strings" + + "github.com/md14454/gosensors" + + "github.com/influxdb/telegraf/plugins/inputs" +) + +type Sensors struct { + Sensors []string +} + +func (_ *Sensors) Description() string { + return "Monitor sensors using lm-sensors package" +} + +var sensorsSampleConfig = ` + # By default, telegraf gathers stats from all sensors detected by the + # lm-sensors module. + # + # Only collect stats from the selected sensors. Sensors are listed as + # :. This information can be found by running the + # sensors command, e.g. sensors -u + # + # A * as the feature name will return all features of the chip + # + # sensors = ["coretemp-isa-0000:Core 0", "coretemp-isa-0001:*"] +` + +func (_ *Sensors) SampleConfig() string { + return sensorsSampleConfig +} + +func (s *Sensors) Gather(acc inputs.Accumulator) error { + gosensors.Init() + defer gosensors.Cleanup() + + for _, chip := range gosensors.GetDetectedChips() { + for _, feature := range chip.GetFeatures() { + chipName := chip.String() + featureLabel := feature.GetLabel() + + if len(s.Sensors) != 0 { + var found bool + + for _, sensor := range s.Sensors { + parts := strings.SplitN(":", sensor, 2) + + if parts[0] == chipName { + if parts[1] == "*" || parts[1] == featureLabel { + found = true + break + } + } + } + + if !found { + continue + } + } + + tags := map[string]string{ + "chip": chipName, + "adapter": chip.AdapterName(), + "feature-name": feature.Name, + "feature-label": featureLabel, + } + + fieldName := chipName + ":" + featureLabel + + fields := map[string]interface{}{ + fieldName: feature.GetValue(), + } + + acc.AddFields("sensors", fields, tags) + } + } + + return nil +} + +func init() { + inputs.Add("sensors", func() inputs.Input { + return &Sensors{} + }) +} diff --git a/plugins/inputs/sensors/sensors_nocompile.go b/plugins/inputs/sensors/sensors_nocompile.go new file mode 100644 index 0000000000000..5c38a437b1823 --- /dev/null +++ b/plugins/inputs/sensors/sensors_nocompile.go @@ -0,0 +1,3 @@ +// +build !linux !sensors + +package sensors diff --git a/plugins/inputs/statsd/statsd.go b/plugins/inputs/statsd/statsd.go index d210b55fa8413..a4b70ffe3e4d2 100644 --- a/plugins/inputs/statsd/statsd.go +++ b/plugins/inputs/statsd/statsd.go @@ -35,6 +35,7 @@ type Statsd struct { DeleteCounters bool DeleteSets bool DeleteTimings bool + ConvertNames bool sync.Mutex @@ -63,6 +64,8 @@ func NewStatsd() *Statsd { s.sets = make(map[string]cachedset) s.timings = make(map[string]cachedtimings) + s.ConvertNames = true + return &s } @@ -121,6 +124,9 @@ const sampleConfig = ` # Percentiles to calculate for timing & histogram stats percentiles = [90] + # convert measurement names, "." to "_" and "-" to "__" + convert_names = true + # templates = [ # "cpu.* measurement*" # ] @@ -389,8 +395,10 @@ func (s *Statsd) parseName(bucket string) (string, map[string]string) { if err == nil { name, tags, _, _ = p.ApplyTemplate(name) } - name = strings.Replace(name, ".", "_", -1) - name = strings.Replace(name, "-", "__", -1) + if s.ConvertNames { + name = strings.Replace(name, ".", "_", -1) + name = strings.Replace(name, "-", "__", -1) + } return name, tags } @@ -491,6 +499,6 @@ func (s *Statsd) Stop() { func init() { inputs.Add("statsd", func() inputs.Input { - return &Statsd{} + return &Statsd{ConvertNames: true} }) } diff --git a/plugins/inputs/statsd/statsd_test.go b/plugins/inputs/statsd/statsd_test.go index 4a97728f25acd..a8aae2e9e3a79 100644 --- a/plugins/inputs/statsd/statsd_test.go +++ b/plugins/inputs/statsd/statsd_test.go @@ -303,6 +303,64 @@ func TestParse_Tags(t *testing.T) { } } +// Test that statsd buckets are parsed to measurement names properly +func TestParseName(t *testing.T) { + s := NewStatsd() + + tests := []struct { + in_name string + out_name string + }{ + { + "foobar", + "foobar", + }, + { + "foo.bar", + "foo_bar", + }, + { + "foo.bar-baz", + "foo_bar__baz", + }, + } + + for _, test := range tests { + name, _ := s.parseName(test.in_name) + if name != test.out_name { + t.Errorf("Expected: %s, got %s", test.out_name, name) + } + } + + // Test with ConvertNames = false + s.ConvertNames = false + + tests = []struct { + in_name string + out_name string + }{ + { + "foobar", + "foobar", + }, + { + "foo.bar", + "foo.bar", + }, + { + "foo.bar-baz", + "foo.bar-baz", + }, + } + + for _, test := range tests { + name, _ := s.parseName(test.in_name) + if name != test.out_name { + t.Errorf("Expected: %s, got %s", test.out_name, name) + } + } +} + // Test that measurements with the same name, but different tags, are treated // as different outputs func TestParse_MeasurementsWithSameName(t *testing.T) { diff --git a/plugins/inputs/system/net.go b/plugins/inputs/system/net.go index 95df7a741ab94..42f0d5854d63d 100644 --- a/plugins/inputs/system/net.go +++ b/plugins/inputs/system/net.go @@ -94,7 +94,10 @@ func (s *NetIOStats) Gather(acc inputs.Accumulator) error { fields[name] = value } } - acc.AddFields("net", fields, nil) + tags := map[string]string{ + "interface": "all", + } + acc.AddFields("net", fields, tags) return nil } diff --git a/plugins/inputs/system/net_test.go b/plugins/inputs/system/net_test.go index ba71848d1a7ca..3ec2cb9904466 100644 --- a/plugins/inputs/system/net_test.go +++ b/plugins/inputs/system/net_test.go @@ -80,7 +80,10 @@ func TestNetStats(t *testing.T) { "udp_noports": int64(892592), "udp_indatagrams": int64(4655), } - acc.AssertContainsTaggedFields(t, "net", fields2, make(map[string]string)) + ntags = map[string]string{ + "interface": "all", + } + acc.AssertContainsTaggedFields(t, "net", fields2, ntags) acc.Points = nil diff --git a/plugins/outputs/all/all.go b/plugins/outputs/all/all.go index 8a0d24f9415dd..7eedb592a29ae 100644 --- a/plugins/outputs/all/all.go +++ b/plugins/outputs/all/all.go @@ -4,6 +4,7 @@ import ( _ "github.com/influxdb/telegraf/plugins/outputs/amon" _ "github.com/influxdb/telegraf/plugins/outputs/amqp" _ "github.com/influxdb/telegraf/plugins/outputs/datadog" + _ "github.com/influxdb/telegraf/plugins/outputs/graphite" _ "github.com/influxdb/telegraf/plugins/outputs/influxdb" _ "github.com/influxdb/telegraf/plugins/outputs/kafka" _ "github.com/influxdb/telegraf/plugins/outputs/kinesis" diff --git a/plugins/outputs/graphite/README.md b/plugins/outputs/graphite/README.md new file mode 100644 index 0000000000000..48313a886c323 --- /dev/null +++ b/plugins/outputs/graphite/README.md @@ -0,0 +1,13 @@ +# Graphite Output Plugin + +This plugin writes to [Graphite](http://graphite.readthedocs.org/en/latest/index.html) via raw TCP. + +Parameters: + + Servers []string + Prefix string + Timeout int + +* `servers`: List of strings, ["mygraphiteserver:2003"]. +* `prefix`: String use to prefix all sent metrics. +* `timeout`: Connection timeout in second. diff --git a/plugins/outputs/graphite/graphite.go b/plugins/outputs/graphite/graphite.go new file mode 100644 index 0000000000000..405b1fe7acda6 --- /dev/null +++ b/plugins/outputs/graphite/graphite.go @@ -0,0 +1,134 @@ +package graphite + +import ( + "errors" + "fmt" + "github.com/influxdb/influxdb/client/v2" + "github.com/influxdb/telegraf/plugins/outputs" + "log" + "math/rand" + "net" + "strings" + "time" +) + +type Graphite struct { + // URL is only for backwards compatability + Servers []string + Prefix string + Timeout int + conns []net.Conn +} + +var sampleConfig = ` + # TCP raw endpoint for your graphite instance. + servers = ["mygraphiteserver:2003"] # default "localhost:2003" + # Prefix metrics name + prefix = "" # default "" + # Connection timeout in second (for the connection with Carbon(Graphite)) + timeout = 2 # default 2s +` + +func (g *Graphite) Connect() error { + // Set default values + if g.Timeout <= 0 { + g.Timeout = 2 + } + if len(g.Servers) == 0 { + g.Servers = append(g.Servers, "localhost:2003") + } + // Get Connections + var conns []net.Conn + for _, server := range g.Servers { + conn, err := net.DialTimeout("tcp", server, time.Duration(g.Timeout)*time.Second) + if err == nil { + conns = append(conns, conn) + } + } + g.conns = conns + return nil +} + +func (g *Graphite) Close() error { + // Closing all connections + for _, conn := range g.conns { + conn.Close() + } + return nil +} + +func (g *Graphite) SampleConfig() string { + return sampleConfig +} + +func (g *Graphite) Description() string { + return "Configuration for Graphite server to send metrics to using TCP raw protocol" +} + +// Choose a random server in the cluster to write to until a successful write +// occurs, logging each unsuccessful. If all servers fail, return error. +func (g *Graphite) Write(points []*client.Point) error { + // Prepare data + var bp []string + for _, point := range points { + // Get name + name := point.Name() + // Convert UnixNano to Unix timestamps + timestamp := point.UnixNano() / 1000000000 + + for field_name, value := range point.Fields() { + // Convert value + value_str := fmt.Sprintf("%#v", value) + // Write graphite point + var graphitePoint string + if name == field_name { + graphitePoint = fmt.Sprintf("%s.%s %s %d\n", + strings.Replace(point.Tags()["host"], ".", "_", -1), + strings.Replace(name, ".", "_", -1), + value_str, + timestamp) + } else { + graphitePoint = fmt.Sprintf("%s.%s.%s %s %d\n", + strings.Replace(point.Tags()["host"], ".", "_", -1), + strings.Replace(name, ".", "_", -1), + strings.Replace(field_name, ".", "_", -1), + value_str, + timestamp) + } + if g.Prefix != "" { + graphitePoint = fmt.Sprintf("%s.%s", g.Prefix, graphitePoint) + } + bp = append(bp, graphitePoint) + //fmt.Printf(graphitePoint) + } + } + graphitePoints := strings.Join(bp, "") + + // This will get set to nil if a successful write occurs + err := errors.New("Could not write to any Graphite server in cluster\n") + + // Send data to a random server + p := rand.Perm(len(g.conns)) + for _, n := range p { + if _, e := fmt.Fprintf(g.conns[n], graphitePoints); e != nil { + // Error + log.Println("ERROR: " + err.Error()) + // Let's try the next one + } else { + // Success + err = nil + break + } + } + // try to reconnect + if err != nil { + g.Connect() + } + return err +} + +func init() { + outputs.Add("graphite", func() outputs.Output { + return &Graphite{} + }) +} diff --git a/plugins/outputs/graphite/graphite_test.go b/plugins/outputs/graphite/graphite_test.go new file mode 100644 index 0000000000000..e9000c3c7723c --- /dev/null +++ b/plugins/outputs/graphite/graphite_test.go @@ -0,0 +1,104 @@ +package graphite + +import ( + "bufio" + "net" + "net/textproto" + "sync" + "testing" + "time" + + "github.com/influxdb/influxdb/client/v2" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestGraphiteError(t *testing.T) { + // Init plugin + g := Graphite{ + Servers: []string{"127.0.0.1:2003", "127.0.0.1:12003"}, + Prefix: "my.prefix", + } + // Init points + pt1, _ := client.NewPoint( + "mymeasurement", + map[string]string{"host": "192.168.0.1"}, + map[string]interface{}{"mymeasurement": float64(3.14)}, + time.Date(2010, time.November, 10, 23, 0, 0, 0, time.UTC), + ) + // Prepare point list + var points []*client.Point + points = append(points, pt1) + // Error + err1 := g.Connect() + require.NoError(t, err1) + err2 := g.Write(points) + require.Error(t, err2) + assert.Equal(t, "Could not write to any Graphite server in cluster\n", err2.Error()) +} + +func TestGraphiteOK(t *testing.T) { + var wg sync.WaitGroup + // Init plugin + g := Graphite{ + Prefix: "my.prefix", + } + // Init points + pt1, _ := client.NewPoint( + "mymeasurement", + map[string]string{"host": "192.168.0.1"}, + map[string]interface{}{"mymeasurement": float64(3.14)}, + time.Date(2010, time.November, 10, 23, 0, 0, 0, time.UTC), + ) + pt2, _ := client.NewPoint( + "mymeasurement", + map[string]string{"host": "192.168.0.1"}, + map[string]interface{}{"value": float64(3.14)}, + time.Date(2010, time.November, 10, 23, 0, 0, 0, time.UTC), + ) + pt3, _ := client.NewPoint( + "my_measurement", + map[string]string{"host": "192.168.0.1"}, + map[string]interface{}{"value": float64(3.14)}, + time.Date(2010, time.November, 10, 23, 0, 0, 0, time.UTC), + ) + // Prepare point list + var points []*client.Point + points = append(points, pt1) + points = append(points, pt2) + points = append(points, pt3) + // Start TCP server + wg.Add(1) + go TCPServer(t, &wg) + wg.Wait() + // Connect + wg.Add(1) + err1 := g.Connect() + wg.Wait() + require.NoError(t, err1) + // Send Data + err2 := g.Write(points) + require.NoError(t, err2) + wg.Add(1) + // Waiting TCPserver + wg.Wait() + g.Close() +} + +func TCPServer(t *testing.T, wg *sync.WaitGroup) { + tcpServer, _ := net.Listen("tcp", "127.0.0.1:2003") + wg.Done() + conn, _ := tcpServer.Accept() + wg.Done() + reader := bufio.NewReader(conn) + tp := textproto.NewReader(reader) + data1, _ := tp.ReadLine() + assert.Equal(t, "my.prefix.192_168_0_1.mymeasurement 3.14 1289430000", data1) + data2, _ := tp.ReadLine() + assert.Equal(t, "my.prefix.192_168_0_1.mymeasurement.value 3.14 1289430000", data2) + data3, _ := tp.ReadLine() + assert.Equal(t, "my.prefix.192_168_0_1.my_measurement.value 3.14 1289430000", data3) + conn.Close() + wg.Done() +} diff --git a/scripts/package.sh b/scripts/package.sh deleted file mode 100755 index fbbf39eb83abd..0000000000000 --- a/scripts/package.sh +++ /dev/null @@ -1,365 +0,0 @@ -#!/usr/bin/env bash - -########################################################################### -# Packaging script which creates debian and RPM packages. It optionally -# tags the repo with the given version. -# -# Requirements: GOPATH must be set. 'fpm' must be on the path, and the AWS -# CLI tools must also be installed. -# -# https://github.com/jordansissel/fpm -# http://aws.amazon.com/cli/ -# -# Packaging process: to package a build, simply execute: -# -# package.sh -# -# The script will automatically determined the version number from git using -# `git describe --always --tags` -# -# AWS upload: the script will also offer to upload the packages to S3. If -# this option is selected, the credentials should be present in the file -# ~/aws.conf. The contents should be of the form: -# -# [default] -# aws_access_key_id= -# aws_secret_access_key= -# region = us-east-1 -# -# Trim the leading spaces when creating the file. The script will exit if -# S3 upload is requested, but this file does not exist. - -AWS_FILE=~/aws.conf - -INSTALL_ROOT_DIR=/opt/telegraf -TELEGRAF_LOG_DIR=/var/log/telegraf -CONFIG_ROOT_DIR=/etc/opt/telegraf -CONFIG_D_DIR=/etc/opt/telegraf/telegraf.d -LOGROTATE_DIR=/etc/logrotate.d - -SAMPLE_CONFIGURATION=etc/telegraf.conf -LOGROTATE_CONFIGURATION=etc/logrotate.d/telegraf -INITD_SCRIPT=scripts/init.sh -SYSTEMD_SCRIPT=scripts/telegraf.service - -TMP_WORK_DIR=`mktemp -d` -POST_INSTALL_PATH=`mktemp` -ARCH=`uname -i` -LICENSE=MIT -URL=influxdb.com -MAINTAINER=support@influxdb.com -VENDOR=InfluxDB -DESCRIPTION="InfluxDB Telegraf agent" -PKG_DEPS=(coreutils) -GO_VERSION="go1.5" -GOPATH_INSTALL= -BINS=( - telegraf - ) - -########################################################################### -# Helper functions. - -# usage prints simple usage information. -usage() { - echo -e "$0\n" - cleanup_exit $1 -} - -# make_dir_tree creates the directory structure within the packages. -make_dir_tree() { - work_dir=$1 - version=$2 - mkdir -p $work_dir/$INSTALL_ROOT_DIR/versions/$version/scripts - if [ $? -ne 0 ]; then - echo "Failed to create installation directory -- aborting." - cleanup_exit 1 - fi - mkdir -p $work_dir/$CONFIG_ROOT_DIR - if [ $? -ne 0 ]; then - echo "Failed to create configuration directory -- aborting." - cleanup_exit 1 - fi - mkdir -p $work_dir/$CONFIG_D_DIR - if [ $? -ne 0 ]; then - echo "Failed to create configuration subdirectory -- aborting." - cleanup_exit 1 - fi - mkdir -p $work_dir/$LOGROTATE_DIR - if [ $? -ne 0 ]; then - echo "Failed to create logrotate directory -- aborting." - cleanup_exit 1 - fi - -} - -# cleanup_exit removes all resources created during the process and exits with -# the supplied returned code. -cleanup_exit() { - rm -r $TMP_WORK_DIR - rm $POST_INSTALL_PATH - exit $1 -} - -# check_gopath sanity checks the value of the GOPATH env variable, and determines -# the path where build artifacts are installed. GOPATH may be a colon-delimited -# list of directories. -check_gopath() { - [ -z "$GOPATH" ] && echo "GOPATH is not set." && cleanup_exit 1 - GOPATH_INSTALL=`echo $GOPATH | cut -d ':' -f 1` - [ ! -d "$GOPATH_INSTALL" ] && echo "GOPATH_INSTALL is not a directory." && cleanup_exit 1 - echo "GOPATH ($GOPATH) looks sane, using $GOPATH_INSTALL for installation." -} - -# check_clean_tree ensures that no source file is locally modified. -check_clean_tree() { - modified=$(git ls-files --modified | wc -l) - if [ $modified -ne 0 ]; then - echo "The source tree is not clean -- aborting." - cleanup_exit 1 - fi - echo "Git tree is clean." -} - -# do_build builds the code. The version and commit must be passed in. -do_build() { - version=$1 - commit=`git rev-parse HEAD` - if [ $? -ne 0 ]; then - echo "Unable to retrieve current commit -- aborting" - cleanup_exit 1 - fi - - for b in ${BINS[*]}; do - rm -f $GOPATH_INSTALL/bin/$b - done - - gdm restore - go install -ldflags="-X main.Version $version" ./... - if [ $? -ne 0 ]; then - echo "Build failed, unable to create package -- aborting" - cleanup_exit 1 - fi - echo "Build completed successfully." -} - -# generate_postinstall_script creates the post-install script for the -# package. It must be passed the version. -generate_postinstall_script() { - version=$1 - cat <$POST_INSTALL_PATH -#!/bin/sh -rm -f $INSTALL_ROOT_DIR/telegraf -rm -f $INSTALL_ROOT_DIR/init.sh -ln -sfn $INSTALL_ROOT_DIR/versions/$version/telegraf $INSTALL_ROOT_DIR/telegraf - -if ! id telegraf >/dev/null 2>&1; then - useradd --help 2>&1| grep -- --system > /dev/null 2>&1 - old_useradd=\$? - if [ \$old_useradd -eq 0 ] - then - useradd --system -U -M telegraf - else - groupadd telegraf && useradd -M -g telegraf telegraf - fi -fi - -# Systemd -if which systemctl > /dev/null 2>&1 ; then - cp $INSTALL_ROOT_DIR/versions/$version/scripts/telegraf.service \ - /lib/systemd/system/telegraf.service - systemctl enable telegraf - - # restart on upgrade of package - if [ "$#" -eq 2 ]; then - systemctl restart telegraf - fi - -# Sysv -else - ln -sfn $INSTALL_ROOT_DIR/versions/$version/scripts/init.sh \ - $INSTALL_ROOT_DIR/init.sh - rm -f /etc/init.d/telegraf - ln -sfn $INSTALL_ROOT_DIR/init.sh /etc/init.d/telegraf - chmod +x /etc/init.d/telegraf - # update-rc.d sysv service: - if which update-rc.d > /dev/null 2>&1 ; then - update-rc.d -f telegraf remove - update-rc.d telegraf defaults - # CentOS-style sysv: - else - chkconfig --add telegraf - fi - - # restart on upgrade of package - if [ "$#" -eq 2 ]; then - /etc/init.d/telegraf restart - fi - - mkdir -p $TELEGRAF_LOG_DIR - chown -R -L telegraf:telegraf $TELEGRAF_LOG_DIR -fi - -chown -R -L telegraf:telegraf $INSTALL_ROOT_DIR -chmod -R a+rX $INSTALL_ROOT_DIR - -EOF - echo "Post-install script created successfully at $POST_INSTALL_PATH" -} - -########################################################################### -# Start the packaging process. - -if [ "$1" == "-h" ]; then - usage 0 -elif [ "$1" == "" ]; then - VERSION=`git describe --always --tags | tr -d v` -else - VERSION="$1" -fi - -cd `git rev-parse --show-toplevel` -echo -e "\nStarting package process, version: $VERSION\n" - -check_gopath -do_build $VERSION -make_dir_tree $TMP_WORK_DIR $VERSION - -########################################################################### -# Copy the assets to the installation directories. - -for b in ${BINS[*]}; do - cp $GOPATH_INSTALL/bin/$b $TMP_WORK_DIR/$INSTALL_ROOT_DIR/versions/$VERSION - if [ $? -ne 0 ]; then - echo "Failed to copy binaries to packaging directory -- aborting." - cleanup_exit 1 - fi -done - -echo "${BINS[*]} copied to $TMP_WORK_DIR/$INSTALL_ROOT_DIR/versions/$VERSION" - -cp $INITD_SCRIPT $TMP_WORK_DIR/$INSTALL_ROOT_DIR/versions/$VERSION/scripts -if [ $? -ne 0 ]; then - echo "Failed to copy init.d script to packaging directory -- aborting." - cleanup_exit 1 -fi -echo "$INITD_SCRIPT copied to $TMP_WORK_DIR/$INSTALL_ROOT_DIR/versions/$VERSION/scripts" - -cp $SYSTEMD_SCRIPT $TMP_WORK_DIR/$INSTALL_ROOT_DIR/versions/$VERSION/scripts -if [ $? -ne 0 ]; then - echo "Failed to copy systemd file to packaging directory -- aborting." - cleanup_exit 1 -fi -echo "$SYSTEMD_SCRIPT copied to $TMP_WORK_DIR/$INSTALL_ROOT_DIR/versions/$VERSION/scripts" - -cp $SAMPLE_CONFIGURATION $TMP_WORK_DIR/$CONFIG_ROOT_DIR/telegraf.conf -if [ $? -ne 0 ]; then - echo "Failed to copy $SAMPLE_CONFIGURATION to packaging directory -- aborting." - cleanup_exit 1 -fi - -cp $LOGROTATE_CONFIGURATION $TMP_WORK_DIR/$LOGROTATE_DIR/telegraf -if [ $? -ne 0 ]; then - echo "Failed to copy $LOGROTATE_CONFIGURATION to packaging directory -- aborting." - cleanup_exit 1 -fi - -generate_postinstall_script $VERSION - -########################################################################### -# Create the actual packages. - -if [ "$CIRCLE_BRANCH" == "" ]; then - echo -n "Commence creation of $ARCH packages, version $VERSION? [Y/n] " - read response - response=`echo $response | tr 'A-Z' 'a-z'` - if [ "x$response" == "xn" ]; then - echo "Packaging aborted." - cleanup_exit 1 - fi -fi - -if [ $ARCH == "i386" ]; then - rpm_package=telegraf-$VERSION-1.i686.rpm - debian_package=telegraf_${VERSION}_i686.deb - deb_args="-a i686" - rpm_args="setarch i686" -elif [ $ARCH == "arm" ]; then - rpm_package=telegraf-$VERSION-1.armel.rpm - debian_package=telegraf_${VERSION}_armel.deb -else - rpm_package=telegraf-$VERSION-1.x86_64.rpm - debian_package=telegraf_${VERSION}_amd64.deb -fi - -COMMON_FPM_ARGS="-C $TMP_WORK_DIR --vendor $VENDOR --url $URL --license $LICENSE \ - --maintainer $MAINTAINER --after-install $POST_INSTALL_PATH \ - --name telegraf --provides telegraf --version $VERSION --config-files $CONFIG_ROOT_DIR ." -$rpm_args fpm -s dir -t rpm --description "$DESCRIPTION" $COMMON_FPM_ARGS -if [ $? -ne 0 ]; then - echo "Failed to create RPM package -- aborting." - cleanup_exit 1 -fi -echo "RPM package created successfully." - -fpm -s dir -t deb $deb_args --description "$DESCRIPTION" $COMMON_FPM_ARGS -if [ $? -ne 0 ]; then - echo "Failed to create Debian package -- aborting." - cleanup_exit 1 -fi -echo "Debian package created successfully." - -########################################################################### -# Offer to publish the packages. - -if [ "$CIRCLE_BRANCH" == "" ]; then - echo -n "Publish packages to S3? [y/N] " - read response - response=`echo $response | tr 'A-Z' 'a-z'` - if [ "x$response" == "xy" ]; then - echo "Publishing packages to S3." - if [ ! -e "$AWS_FILE" ]; then - echo "$AWS_FILE does not exist -- aborting." - cleanup_exit 1 - fi - - # Upload .deb and .rpm packages - for filepath in `ls *.{deb,rpm}`; do - echo "Uploading $filepath to S3" - filename=`basename $filepath` - echo "Uploading $filename to s3://get.influxdb.org/telegraf/$filename" - AWS_CONFIG_FILE=$AWS_FILE aws s3 cp $filepath \ - s3://get.influxdb.org/telegraf/$filename \ - --acl public-read --region us-east-1 - if [ $? -ne 0 ]; then - echo "Upload failed -- aborting". - cleanup_exit 1 - fi - rm $filepath - done - - # Make and upload linux amd64, 386, and arm - make build-linux-bins - for b in `ls telegraf_*`; do - zippedbin=${b}_${VERSION}.tar.gz - # Zip the binary - tar -zcf $TMP_WORK_DIR/$zippedbin ./$b - echo "Uploading binary: $zippedbin to S3" - AWS_CONFIG_FILE=$AWS_FILE aws s3 cp $TMP_WORK_DIR/$zippedbin \ - s3://get.influxdb.org/telegraf/$zippedbin \ - --acl public-read --region us-east-1 - if [ $? -ne 0 ]; then - echo "Binary upload failed -- aborting". - cleanup_exit 1 - fi - done - else - echo "Not publishing packages to S3." - fi -fi - -########################################################################### -# All done. - -echo -e "\nPackaging process complete." -cleanup_exit 0 diff --git a/scripts/post-install.sh b/scripts/post-install.sh index 19b895808f8c5..bb4803f8d6936 100644 --- a/scripts/post-install.sh +++ b/scripts/post-install.sh @@ -56,7 +56,7 @@ if [[ -f /etc/redhat-release ]]; then install_init install_chkconfig fi -elif [[ -f /etc/lsb-release ]]; then +elif [[ -f /etc/debian_version ]]; then # Debian/Ubuntu logic which systemctl &>/dev/null if [[ $? -eq 0 ]]; then