├── .arcconfig ├── .gitignore ├── .travis.yml ├── CONTRIBUTORS ├── Dockerfile ├── Godeps ├── Godeps.json └── Readme ├── LICENSE ├── NOTICE ├── README.md ├── build-pkg.sh ├── clicktail.conf ├── clicktail.service ├── clicktail.upstart ├── event └── event.go ├── httime ├── httime.go ├── httime_test.go └── httimetest │ └── fake_nower.go ├── leash.go ├── leash_test.go ├── main.go ├── parsers ├── arangodb │ ├── arangodb.go │ └── arangodb_test.go ├── extregexp.go ├── htjson │ ├── htjson.go │ └── htjson_test.go ├── keyval │ ├── keyval.go │ └── keyval_test.go ├── mongodb │ ├── mongodb.go │ └── mongodb_test.go ├── mysql │ ├── mysql.go │ └── mysql_test.go ├── mysqlaudit │ └── mysqlaudit.go ├── nginx │ ├── nginx.go │ └── nginx_test.go ├── parsers.go ├── postgresql │ ├── postgresql.go │ └── postgresql_test.go └── regex │ ├── README.md │ ├── regex.go │ └── regex_test.go ├── pkg-test ├── Dockerfile.deb ├── Dockerfile.rpm └── test.sh ├── preinstall ├── response_stats.go ├── schema ├── db.sql ├── mysql.sql ├── mysqlaudit.sql └── nginx.sql ├── tail ├── tail.go └── tail_test.go └── vendor ├── github.com ├── Sirupsen │ └── logrus │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── CHANGELOG.md │ │ ├── LICENSE │ │ ├── README.md │ │ ├── doc.go │ │ ├── entry.go │ │ ├── exported.go │ │ ├── formatter.go │ │ ├── hooks.go │ │ ├── json_formatter.go │ │ ├── logger.go │ │ ├── logrus.go │ │ ├── terminal_bsd.go │ │ ├── terminal_linux.go │ │ ├── terminal_notwindows.go │ │ ├── terminal_solaris.go │ │ ├── terminal_windows.go │ │ ├── text_formatter.go │ │ └── writer.go ├── davecgh │ └── go-spew │ │ ├── LICENSE │ │ └── spew │ │ ├── bypass.go │ │ ├── bypasssafe.go │ │ ├── common.go │ │ ├── config.go │ │ ├── doc.go │ │ ├── dump.go │ │ ├── format.go │ │ └── spew.go ├── facebookgo │ ├── clock │ │ ├── LICENSE │ │ ├── README.md │ │ └── clock.go │ ├── limitgroup │ │ ├── .travis.yml │ │ ├── license │ │ ├── limitgroup.go │ │ ├── patents │ │ └── readme.md │ └── muster │ │ ├── .travis.yml │ │ ├── license │ │ ├── muster.go │ │ ├── patents │ │ └── readme.md ├── go-sql-driver │ └── mysql │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── AUTHORS │ │ ├── CHANGELOG.md │ │ ├── CONTRIBUTING.md │ │ ├── ISSUE_TEMPLATE.md │ │ ├── LICENSE │ │ ├── PULL_REQUEST_TEMPLATE.md │ │ ├── README.md │ │ ├── appengine.go │ │ ├── buffer.go │ │ ├── collations.go │ │ ├── connection.go │ │ ├── const.go │ │ ├── driver.go │ │ ├── dsn.go │ │ ├── errors.go │ │ ├── infile.go │ │ ├── packets.go │ │ ├── result.go │ │ ├── rows.go │ │ ├── statement.go │ │ ├── transaction.go │ │ └── utils.go ├── honeycombio │ ├── dynsampler-go │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── NOTICE │ │ ├── README.md │ │ ├── avgsamplerate.go │ │ ├── avgsamplewithmin.go │ │ ├── doc.go │ │ ├── dynsampler.go │ │ ├── onlyonce.go │ │ ├── perkeythroughput.go │ │ ├── static.go │ │ └── totalthroughput.go │ ├── gonx │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── CHANGELOG.md │ │ ├── LICENSE │ │ ├── Makefile │ │ ├── README.md │ │ ├── entry.go │ │ ├── filter.go │ │ ├── mapreduce.go │ │ ├── parser.go │ │ ├── reader.go │ │ └── reducer.go │ ├── mongodbtools │ │ ├── LICENSE │ │ ├── logparser │ │ │ ├── internal │ │ │ │ └── logparser │ │ │ │ │ └── log_line.go │ │ │ └── log_line.go │ │ └── queryshape │ │ │ ├── internal │ │ │ └── queryshape │ │ │ │ └── shape.go │ │ │ └── shape.go │ ├── mysqltools │ │ ├── LICENSE │ │ └── query │ │ │ └── normalizer │ │ │ ├── ast_transformer.go │ │ │ ├── parser.go │ │ │ └── scanner.go │ ├── sqlparser │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── LICENSE.md │ │ ├── Makefile │ │ ├── analyzer.go │ │ ├── ast.go │ │ ├── parsed_query.go │ │ ├── readme.md │ │ ├── rewriter.go │ │ ├── sql.go │ │ ├── sql.y │ │ ├── token.go │ │ └── tracked_buffer.go │ └── urlshaper │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── doc.go │ │ └── urlshaper.go ├── hpcloud │ └── tail │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── CHANGES.md │ │ ├── Dockerfile │ │ ├── LICENSE.txt │ │ ├── Makefile │ │ ├── README.md │ │ ├── appveyor.yml │ │ ├── ratelimiter │ │ ├── Licence │ │ ├── leakybucket.go │ │ ├── memory.go │ │ └── storage.go │ │ ├── tail.go │ │ ├── tail_posix.go │ │ ├── tail_windows.go │ │ ├── util │ │ └── util.go │ │ ├── vendor │ │ └── gopkg.in │ │ │ ├── fsnotify.v1 │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ ├── AUTHORS │ │ │ ├── CHANGELOG.md │ │ │ ├── CONTRIBUTING.md │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── fsnotify.go │ │ │ ├── inotify.go │ │ │ ├── inotify_poller.go │ │ │ ├── kqueue.go │ │ │ ├── open_mode_bsd.go │ │ │ ├── open_mode_darwin.go │ │ │ └── windows.go │ │ │ └── tomb.v1 │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ └── tomb.go │ │ ├── watch │ │ ├── filechanges.go │ │ ├── inotify.go │ │ ├── inotify_tracker.go │ │ ├── polling.go │ │ └── watch.go │ │ └── winfile │ │ └── winfile.go ├── jessevdk │ └── go-flags │ │ ├── .travis.yml │ │ ├── LICENSE │ │ ├── README.md │ │ ├── arg.go │ │ ├── check_crosscompile.sh │ │ ├── closest.go │ │ ├── command.go │ │ ├── completion.go │ │ ├── convert.go │ │ ├── error.go │ │ ├── flags.go │ │ ├── group.go │ │ ├── help.go │ │ ├── ini.go │ │ ├── man.go │ │ ├── multitag.go │ │ ├── option.go │ │ ├── optstyle_other.go │ │ ├── optstyle_windows.go │ │ ├── parser.go │ │ ├── termsize.go │ │ ├── termsize_linux.go │ │ ├── termsize_nosysioctl.go │ │ ├── termsize_other.go │ │ └── termsize_unix.go ├── kr │ └── logfmt │ │ ├── .gitignore │ │ ├── Readme │ │ ├── decode.go │ │ ├── scanner.go │ │ └── unquote.go ├── pmezard │ └── go-difflib │ │ ├── LICENSE │ │ └── difflib │ │ └── difflib.go ├── stretchr │ └── testify │ │ ├── LICENCE.txt │ │ ├── LICENSE │ │ └── assert │ │ ├── assertions.go │ │ ├── doc.go │ │ ├── errors.go │ │ ├── forward_assertions.go │ │ └── http_assertions.go └── xwb1989 │ └── sqlparser │ ├── LICENSE.md │ └── dependency │ ├── bson │ ├── common.go │ ├── marshal.go │ ├── marshal_util.go │ ├── unmarshal.go │ └── unmarshal_util.go │ ├── bytes2 │ └── chunked_writer.go │ ├── hack │ └── hack.go │ └── sqltypes │ └── sqltypes.go ├── golang.org └── x │ └── sys │ ├── LICENSE │ ├── PATENTS │ └── unix │ ├── .gitignore │ ├── asm.s │ ├── asm_darwin_386.s │ ├── asm_darwin_amd64.s │ ├── asm_darwin_arm.s │ ├── asm_darwin_arm64.s │ ├── asm_dragonfly_386.s │ ├── asm_dragonfly_amd64.s │ ├── asm_freebsd_386.s │ ├── asm_freebsd_amd64.s │ ├── asm_freebsd_arm.s │ ├── asm_linux_386.s │ ├── asm_linux_amd64.s │ ├── asm_linux_arm.s │ ├── asm_linux_arm64.s │ ├── asm_linux_mips64x.s │ ├── asm_linux_ppc64x.s │ ├── asm_netbsd_386.s │ ├── asm_netbsd_amd64.s │ ├── asm_netbsd_arm.s │ ├── asm_openbsd_386.s │ ├── asm_openbsd_amd64.s │ ├── asm_solaris_amd64.s │ ├── constants.go │ ├── env_unix.go │ ├── env_unset.go │ ├── flock.go │ ├── flock_linux_32bit.go │ ├── gccgo.go │ ├── gccgo_c.c │ ├── gccgo_linux_amd64.go │ ├── mkall.sh │ ├── mkerrors.sh │ ├── mksyscall.pl │ ├── mksyscall_solaris.pl │ ├── mksysctl_openbsd.pl │ ├── mksysnum_darwin.pl │ ├── mksysnum_dragonfly.pl │ ├── mksysnum_freebsd.pl │ ├── mksysnum_linux.pl │ ├── mksysnum_netbsd.pl │ ├── mksysnum_openbsd.pl │ ├── race.go │ ├── race0.go │ ├── sockcmsg_linux.go │ ├── sockcmsg_unix.go │ ├── str.go │ ├── syscall.go │ ├── syscall_bsd.go │ ├── syscall_darwin.go │ ├── syscall_darwin_386.go │ ├── syscall_darwin_amd64.go │ ├── syscall_darwin_arm.go │ ├── syscall_darwin_arm64.go │ ├── syscall_dragonfly.go │ ├── syscall_dragonfly_386.go │ ├── syscall_dragonfly_amd64.go │ ├── syscall_freebsd.go │ ├── syscall_freebsd_386.go │ ├── syscall_freebsd_amd64.go │ ├── syscall_freebsd_arm.go │ ├── syscall_linux.go │ ├── syscall_linux_386.go │ ├── syscall_linux_amd64.go │ ├── syscall_linux_arm.go │ ├── syscall_linux_arm64.go │ ├── syscall_linux_mips64x.go │ ├── syscall_linux_ppc64x.go │ ├── syscall_netbsd.go │ ├── syscall_netbsd_386.go │ ├── syscall_netbsd_amd64.go │ ├── syscall_netbsd_arm.go │ ├── syscall_no_getwd.go │ ├── syscall_openbsd.go │ ├── syscall_openbsd_386.go │ ├── syscall_openbsd_amd64.go │ ├── syscall_solaris.go │ ├── syscall_solaris_amd64.go │ ├── syscall_unix.go │ ├── types_darwin.go │ ├── types_dragonfly.go │ ├── types_freebsd.go │ ├── types_linux.go │ ├── types_netbsd.go │ ├── types_openbsd.go │ ├── types_solaris.go │ ├── zerrors_darwin_386.go │ ├── zerrors_darwin_amd64.go │ ├── zerrors_darwin_arm.go │ ├── zerrors_darwin_arm64.go │ ├── zerrors_dragonfly_386.go │ ├── zerrors_dragonfly_amd64.go │ ├── zerrors_freebsd_386.go │ ├── zerrors_freebsd_amd64.go │ ├── zerrors_freebsd_arm.go │ ├── zerrors_linux_386.go │ ├── zerrors_linux_amd64.go │ ├── zerrors_linux_arm.go │ ├── zerrors_linux_arm64.go │ ├── zerrors_linux_mips64.go │ ├── zerrors_linux_mips64le.go │ ├── zerrors_linux_ppc64.go │ ├── zerrors_linux_ppc64le.go │ ├── zerrors_netbsd_386.go │ ├── zerrors_netbsd_amd64.go │ ├── zerrors_netbsd_arm.go │ ├── zerrors_openbsd_386.go │ ├── zerrors_openbsd_amd64.go │ ├── zerrors_solaris_amd64.go │ ├── zsyscall_darwin_386.go │ ├── zsyscall_darwin_amd64.go │ ├── zsyscall_darwin_arm.go │ ├── zsyscall_darwin_arm64.go │ ├── zsyscall_dragonfly_386.go │ ├── zsyscall_dragonfly_amd64.go │ ├── zsyscall_freebsd_386.go │ ├── zsyscall_freebsd_amd64.go │ ├── zsyscall_freebsd_arm.go │ ├── zsyscall_linux_386.go │ ├── zsyscall_linux_amd64.go │ ├── zsyscall_linux_arm.go │ ├── zsyscall_linux_arm64.go │ ├── zsyscall_linux_mips64.go │ ├── zsyscall_linux_mips64le.go │ ├── zsyscall_linux_ppc64.go │ ├── zsyscall_linux_ppc64le.go │ ├── zsyscall_netbsd_386.go │ ├── zsyscall_netbsd_amd64.go │ ├── zsyscall_netbsd_arm.go │ ├── zsyscall_openbsd_386.go │ ├── zsyscall_openbsd_amd64.go │ ├── zsyscall_solaris_amd64.go │ ├── zsysctl_openbsd.go │ ├── zsysnum_darwin_386.go │ ├── zsysnum_darwin_amd64.go │ ├── zsysnum_darwin_arm.go │ ├── zsysnum_darwin_arm64.go │ ├── zsysnum_dragonfly_386.go │ ├── zsysnum_dragonfly_amd64.go │ ├── zsysnum_freebsd_386.go │ ├── zsysnum_freebsd_amd64.go │ ├── zsysnum_freebsd_arm.go │ ├── zsysnum_linux_386.go │ ├── zsysnum_linux_amd64.go │ ├── zsysnum_linux_arm.go │ ├── zsysnum_linux_arm64.go │ ├── zsysnum_linux_mips64.go │ ├── zsysnum_linux_mips64le.go │ ├── zsysnum_linux_ppc64.go │ ├── zsysnum_linux_ppc64le.go │ ├── zsysnum_netbsd_386.go │ ├── zsysnum_netbsd_amd64.go │ ├── zsysnum_netbsd_arm.go │ ├── zsysnum_openbsd_386.go │ ├── zsysnum_openbsd_amd64.go │ ├── zsysnum_solaris_amd64.go │ ├── ztypes_darwin_386.go │ ├── ztypes_darwin_amd64.go │ ├── ztypes_darwin_arm.go │ ├── ztypes_darwin_arm64.go │ ├── ztypes_dragonfly_386.go │ ├── ztypes_dragonfly_amd64.go │ ├── ztypes_freebsd_386.go │ ├── ztypes_freebsd_amd64.go │ ├── ztypes_freebsd_arm.go │ ├── ztypes_linux_386.go │ ├── ztypes_linux_amd64.go │ ├── ztypes_linux_arm.go │ ├── ztypes_linux_arm64.go │ ├── ztypes_linux_mips64.go │ ├── ztypes_linux_mips64le.go │ ├── ztypes_linux_ppc64.go │ ├── ztypes_linux_ppc64le.go │ ├── ztypes_netbsd_386.go │ ├── ztypes_netbsd_amd64.go │ ├── ztypes_netbsd_arm.go │ ├── ztypes_openbsd_386.go │ ├── ztypes_openbsd_amd64.go │ └── ztypes_solaris_amd64.go └── gopkg.in ├── alexcesaro └── statsd.v2 │ ├── .travis.yml │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── conn.go │ ├── doc.go │ ├── options.go │ └── statsd.go ├── fsnotify.v1 ├── .gitignore ├── .travis.yml ├── AUTHORS ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── fsnotify.go ├── inotify.go ├── inotify_poller.go ├── kqueue.go ├── open_mode_bsd.go ├── open_mode_darwin.go └── windows.go └── tomb.v1 ├── LICENSE ├── README.md └── tomb.go /.arcconfig: -------------------------------------------------------------------------------- 1 | { 2 | "phabricator.uri" : "https://honeycomb.phacility.com/" 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | honeytail 2 | *.swp 3 | .DS_Store 4 | *.tar.gz 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: 2 | - linux 3 | 4 | language: go 5 | 6 | addons: 7 | artifacts: 8 | debug: true 9 | paths: 10 | - $GOPATH/bin 11 | 12 | dist: trusty 13 | 14 | go: 15 | - 1.8 16 | 17 | script: 18 | - set -e 19 | # Run tests 20 | # - go test github.com/Altinity/clicktail/... 21 | # Build binary and packages 22 | - go install -ldflags "-X main.BuildID=1.${TRAVIS_BUILD_NUMBER}" github.com/Altinity/clicktail/... 23 | - $GOPATH/bin/clicktail --write_default_config > ./clicktail.conf 24 | - ./build-pkg.sh -v "1.${TRAVIS_BUILD_NUMBER}" -t deb 25 | - ./build-pkg.sh -v "1.${TRAVIS_BUILD_NUMBER}" -t rpm 26 | # Check that packages install 27 | - pkg-test/test.sh "1.${TRAVIS_BUILD_NUMBER}" 28 | 29 | before_install: 30 | # Install fpm for deb/rpm package building 31 | - sudo apt-get -qq update 32 | - sudo apt-get install -y build-essential rpm 33 | - gem install fpm 34 | 35 | install: 36 | - true # HACK: fixes travis-CI lack of support for vendor/ + godeps 37 | -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | Honeytail contributors: 2 | 3 | Ben Hartshorne 4 | Charity Majors 5 | Chris Toshok 6 | Christine Yen 7 | Conrad Irwin 8 | Ian Wilkes 9 | Justin Hennessy 10 | Max Neunhoeffer 11 | Rick Branson 12 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # This builds the binary inside an Alpine Linux container, which is small 2 | FROM alpine:3.3 3 | MAINTAINER Andrey Monakhov 4 | 5 | # Set us up so we can build the binary 6 | ENV GOROOT /usr/lib/go 7 | ENV GOPATH /gopath 8 | ENV GOBIN /gopath/bin 9 | ENV PATH $PATH:$GOROOT/bin:$GOPATH/bin 10 | 11 | WORKDIR /gopath/src/github.com/Altinity/clicktail 12 | COPY . /gopath/src/github.com/Altinity/clicktail/ 13 | 14 | # Does the package, build, and cleanup as one step to keep size small 15 | RUN apk add --update \ 16 | coreutils \ 17 | go \ 18 | git \ 19 | openssl \ 20 | ca-certificates \ 21 | && ver=$(git rev-parse --short HEAD) \ 22 | && git clean -f \ 23 | && rm -rf .git \ 24 | && go get -ldflags="-X main.BuildID=${ver}" github.com/Altinity/clicktail \ 25 | && apk del git go \ 26 | && rm -rf /var/cache/apk/* 27 | 28 | ENV HONEYCOMB_WRITE_KEY NULL 29 | ENV NGINX_LOG_FORMAT_NAME combined 30 | ENV NGINX_CONF /etc/nginx.conf 31 | ENV HONEYCOMB_SAMPLE_RATE 1 32 | ENV NGINX_ACCESS_LOG_FILENAME access.log 33 | 34 | CMD [ "/bin/sh", "-c", "clicktail \ 35 | --parser nginx \ 36 | --file /var/log/nginx/$NGINX_ACCESS_LOG_FILENAME \ 37 | --dataset clicktail.nginx_logs \ 38 | --samplerate $HONEYCOMB_SAMPLE_RATE \ 39 | --nginx.conf $NGINX_CONF \ 40 | --nginx.format $NGINX_LOG_FORMAT_NAME \ 41 | --tail.read_from end" ] 42 | -------------------------------------------------------------------------------- /Godeps/Readme: -------------------------------------------------------------------------------- 1 | This directory tree is generated automatically by godep. 2 | 3 | Please do not edit. 4 | 5 | See https://github.com/tools/godep for more information. 6 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016-Present Honeycomb, Hound Technology, Inc. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /build-pkg.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Build deb or rpm packages for clicktail. 4 | set -e 5 | 6 | function usage() { 7 | echo "Usage: build-pkg.sh -v -t " 8 | exit 2 9 | } 10 | 11 | while getopts "v:t:" opt; do 12 | case "$opt" in 13 | v) 14 | version=$OPTARG 15 | ;; 16 | t) 17 | pkg_type=$OPTARG 18 | ;; 19 | esac 20 | done 21 | 22 | if [ -z "$version" ] || [ -z "$pkg_type" ]; then 23 | usage 24 | fi 25 | 26 | fpm -s dir -n clicktail \ 27 | -m "Support " \ 28 | -p $GOPATH/bin \ 29 | -v $version \ 30 | -t $pkg_type \ 31 | --pre-install=./preinstall \ 32 | $GOPATH/bin/clicktail=/usr/bin/clicktail \ 33 | ./clicktail.upstart=/etc/init/clicktail.conf \ 34 | ./clicktail.service=/lib/systemd/system/clicktail.service \ 35 | ./clicktail.conf=/etc/clicktail/clicktail-example.conf 36 | -------------------------------------------------------------------------------- /clicktail.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=ClickHouse log tailer clicktail by Altinity 3 | After=network.target 4 | 5 | [Service] 6 | ExecStart=/usr/bin/clicktail -c /etc/clicktail/clicktail.conf 7 | KillMode=process 8 | Restart=on-failure 9 | User=root 10 | Group=root 11 | 12 | [Install] 13 | Alias=clicktail clicktail.service 14 | -------------------------------------------------------------------------------- /clicktail.upstart: -------------------------------------------------------------------------------- 1 | # Upstart job for clicktail, the log tailer for ClickHouse by Altinity 2 | # https://altinity.com/ 3 | 4 | description "Clicktail Daemon" 5 | author "Andrey Monakhov " 6 | 7 | start on runlevel [2345] 8 | stop on runlevel [!2345] 9 | 10 | respawn 11 | 12 | exec su -s /bin/sh -c 'exec "$0" "$@"' root -- /usr/bin/clicktail -c /etc/clicktail/clicktail.conf 13 | -------------------------------------------------------------------------------- /event/event.go: -------------------------------------------------------------------------------- 1 | // Package event contains the struct used to pass events between parsers and 2 | // the libclick module. 3 | package event 4 | 5 | import "time" 6 | 7 | // Event is a single log event 8 | type Event struct { 9 | // Timestamp is the time of the event (may be different from current time) 10 | Timestamp time.Time 11 | // SampleRate is the rate at which this event is sampled. If it is positive, 12 | // the event should be sent with that sample rate. If it is -1 the event 13 | // should be dropped instead of getting sent. Zero value should be treated as 14 | // unset and the event sent with a sample rate of 1 15 | SampleRate int 16 | // Data is a map[string]interface{} containing key/value pairs for all the 17 | // metrics to submit in this event 18 | Data map[string]interface{} 19 | } 20 | -------------------------------------------------------------------------------- /httime/httimetest/fake_nower.go: -------------------------------------------------------------------------------- 1 | package httimetest 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type FakeNower struct { 8 | FakeNow time.Time 9 | } 10 | 11 | func (f *FakeNower) Now() time.Time { 12 | if !f.FakeNow.IsZero() { 13 | return f.FakeNow 14 | } 15 | 16 | // default fake time to return 17 | fakeNow, _ := time.Parse(time.RFC3339, "2010-06-21T15:04:05Z") 18 | f.FakeNow = fakeNow 19 | return f.FakeNow 20 | } 21 | -------------------------------------------------------------------------------- /parsers/extregexp.go: -------------------------------------------------------------------------------- 1 | package parsers 2 | 3 | import "regexp" 4 | 5 | // ExtRegexp is a Regexp with one additional method to make it easier to work 6 | // with named groups 7 | type ExtRegexp struct { 8 | *regexp.Regexp 9 | } 10 | 11 | // FindStringSubmatchMap behaves the same as FindStringSubmatch except instead 12 | // of a list of matches with the names separate, it returns the full match and a 13 | // map of named submatches 14 | func (r *ExtRegexp) FindStringSubmatchMap(s string) (string, map[string]string) { 15 | match := r.FindStringSubmatch(s) 16 | if match == nil { 17 | return "", nil 18 | } 19 | 20 | captures := make(map[string]string) 21 | for i, name := range r.SubexpNames() { 22 | if i == 0 { 23 | continue 24 | } 25 | if name != "" { 26 | // ignore unnamed matches 27 | captures[name] = match[i] 28 | } 29 | } 30 | return match[0], captures 31 | } 32 | -------------------------------------------------------------------------------- /parsers/htjson/htjson_test.go: -------------------------------------------------------------------------------- 1 | package htjson 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | ) 7 | 8 | type testLineMap struct { 9 | input string 10 | expected map[string]interface{} 11 | } 12 | 13 | var tlms = []testLineMap{ 14 | { // strings, floats, and ints 15 | input: `{"mystr": "myval", "myint": 3, "myfloat": 4.234}`, 16 | expected: map[string]interface{}{ 17 | "mystr": "myval", 18 | "myint": float64(3), 19 | "myfloat": 4.234, 20 | }, 21 | }, 22 | { // time 23 | input: `{"time": "2014-03-10 19:57:38.123456789 -0800 PST", "myint": 3, "myfloat": 4.234}`, 24 | expected: map[string]interface{}{ 25 | "time": "2014-03-10 19:57:38.123456789 -0800 PST", 26 | "myint": float64(3), 27 | "myfloat": 4.234, 28 | }, 29 | }, 30 | { // non-flat json object 31 | input: `{"array": [3, 4, 6], "obj": {"subkey":"subval"}, "myfloat": 4.234}`, 32 | expected: map[string]interface{}{ 33 | "array": []interface{}{float64(3), float64(4), float64(6)}, 34 | "obj": map[string]interface{}{"subkey": "subval"}, 35 | "myfloat": 4.234, 36 | }, 37 | }, 38 | } 39 | 40 | func TestParseLine(t *testing.T) { 41 | jlp := JSONLineParser{} 42 | for _, tlm := range tlms { 43 | resp, err := jlp.ParseLine(tlm.input) 44 | if err != nil { 45 | t.Error("jlp.ParseLine unexpectedly returned error ", err) 46 | } 47 | if !reflect.DeepEqual(resp, tlm.expected) { 48 | t.Errorf("response %+v didn't match expected %+v", resp, tlm.expected) 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /parsers/parsers.go: -------------------------------------------------------------------------------- 1 | // Package parsers provides an interface for different log parsing engines. 2 | // 3 | // Each module in here takes care of a specific log type, providing 4 | // any necessary or relevant smarts for that style of logs. 5 | package parsers 6 | 7 | import "github.com/honeycombio/honeytail/event" 8 | 9 | type Parser interface { 10 | // Init does any initialization necessary for the module 11 | Init(options interface{}) error 12 | // ProcessLines consumes log lines from the lines channel and sends log events 13 | // to the send channel. prefixRegex, if not nil, will be stripped from the 14 | // line prior to parsing. Any named groups will be added to the event. 15 | ProcessLines(lines <-chan string, send chan<- event.Event, prefixRegex *ExtRegexp) 16 | } 17 | 18 | type LineParser interface { 19 | ParseLine(line string) (map[string]interface{}, error) 20 | } 21 | -------------------------------------------------------------------------------- /parsers/regex/README.md: -------------------------------------------------------------------------------- 1 | Golang `regexp` package uses the [RE2 syntax](https://github.com/google/re2/wiki/Syntax). 2 | 3 | Example CLI usage (from honeytail root) 4 | ``` 5 | honeytail -p regex -k $HONEYTAIL_WRITEKEY \ 6 | -f some/path/system.log \ 7 | --dataset 'MY_TEST_DATASET' \ 8 | --backfill \ 9 | --regex.line_regex="(?P