├── .gitignore ├── .gitmodules ├── LICENSE ├── Makefile ├── README.md ├── go.mod ├── go.sum ├── lib ├── cloudwatchlogs │ ├── client.go │ ├── init.go │ ├── region.go │ └── writer.go ├── datadog │ ├── init.go │ └── writer.go ├── destination.go ├── error.go ├── group.go ├── journald │ ├── init.go │ └── reader.go ├── log.go ├── logdna │ ├── init.go │ └── writer.go ├── loggly │ ├── init.go │ └── writer.go ├── message.go ├── message_test.go ├── reader.go ├── source.go ├── statsd │ ├── init.go │ ├── writer.go │ └── writer_test.go ├── store.go ├── stream.go ├── stream_test.go ├── syslog │ ├── init.go │ ├── pool │ │ ├── pool.go │ │ └── pool_test.go │ ├── writer.go │ └── writer_test.go └── writer.go ├── main.go └── main_linux.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | vendor/*/ 10 | bin/ 11 | 12 | # Architecture specific extensions/prefixes 13 | *.[568vq] 14 | [568vq].out 15 | 16 | *.cgo1.go 17 | *.cgo2.c 18 | _cgo_defun.c 19 | _cgo_gotypes.go 20 | _cgo_export.* 21 | 22 | _testmain.go 23 | 24 | *.exe 25 | *.test 26 | *.prof 27 | 28 | /ecs-logs 29 | 30 | # Emacs 31 | *~ 32 | 33 | # Packages 34 | *.deb 35 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "vendor/github.com/aws/aws-sdk-go"] 2 | path = vendor/github.com/aws/aws-sdk-go 3 | url = https://github.com/aws/aws-sdk-go 4 | [submodule "vendor/github.com/coreos/go-systemd"] 5 | path = vendor/github.com/coreos/go-systemd 6 | url = https://github.com/coreos/go-systemd 7 | [submodule "vendor/github.com/statsd/client"] 8 | path = vendor/github.com/statsd/client 9 | url = https://github.com/statsd/client 10 | [submodule "vendor/github.com/statsd/datadog"] 11 | path = vendor/github.com/statsd/datadog 12 | url = https://github.com/statsd/datadog 13 | [submodule "vendor/github.com/visionmedia/go-debug"] 14 | path = vendor/github.com/visionmedia/go-debug 15 | url = https://github.com/visionmedia/go-debug 16 | [submodule "vendor/github.com/segmentio/ecs-logs-go"] 17 | path = vendor/github.com/segmentio/ecs-logs-go 18 | url = https://github.com/segmentio/ecs-logs-go 19 | [submodule "vendor/github.com/apex/log"] 20 | path = vendor/github.com/apex/log 21 | url = https://github.com/apex/log 22 | [submodule "vendor/github.com/go-ini/ini"] 23 | path = vendor/github.com/go-ini/ini 24 | url = https://github.com/go-ini/ini 25 | [submodule "vendor/github.com/jmespath/go-jmespath"] 26 | path = vendor/github.com/jmespath/go-jmespath 27 | url = https://github.com/jmespath/go-jmespath 28 | [submodule "vendor/github.com/coreos/pkg"] 29 | path = vendor/github.com/coreos/pkg 30 | url = https://github.com/coreos/pkg 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Segment 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | VERSION := unmaintained 2 | LDFLAGS := "-X main.version=$(VERSION)" 3 | REPO := github.com/segmentio/ecs-logs 4 | SOURCES := $(git ls-files *.go) 5 | DOCKER_TAG := segment/ecs-logs:v$(VERSION) 6 | 7 | default: bin/ecs-logs-linux-amd64 8 | 9 | bin/ecs-logs-linux-amd64: $(SOURCES) 10 | env GOOS=linux GOARCH=amd64 go build -ldflags $(LDFLAGS) -o $@ $(REPO) 11 | 12 | vendor: 13 | go mod vendor 14 | 15 | test: 16 | go test $(shell go list ./...) 17 | 18 | image: 19 | docker build -t $(DOCKER_TAG) -t segment/ecs-logs:latest . 20 | 21 | push_image: 22 | docker push $(DOCKER_TAG) 23 | docker push segment/ecs-logs:latest 24 | 25 | clean: 26 | -rm -f bin/* *.deb 27 | 28 | .PHONY: test clean deb upload_deb image push_image 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ⚠️ Unmaintained ⚠️ 2 | 3 | This repository is unmaintained, but left as a historical relic for any wishing to adapt it. Godspeed! 4 | 5 | # ecs-logs 6 | ecs-logs was a log forwarder for services ran by ecs-agent. 7 | 8 | ## Quick Start 9 | 10 | The simplest way to use ecs-logs is to run it as a docker container, you'll want 11 | to configure the ecs-agent to forward services logs to journald first, here's 12 | how to do it: 13 | 14 | - run ecs-agent with `ECS_AVAILABLE_LOGGING_DRIVERS=["journald"]` set in the 15 | environment variables. 16 | 17 | - configure the task definitions of your services to use the journald driver by 18 | adding the following: 19 | ```js 20 | "logConfiguration": { 21 | "logDriver": "journald", 22 | "options": { 23 | "tag": "" 24 | } 25 | } 26 | ``` 27 | *Note: The tag is important here since it will be used as the group name for the 28 | CloudWatch logs* 29 | 30 | Once you have ecs-agent properly configured (you should be able to see your ECS 31 | services logs in the journal), you can start ecs-logs this way: 32 | ``` 33 | docker run -t -i -v /run/log/journal:/run/log/journal:ro \ 34 | segment/ecs-logs:latest -src journald -dst cloudwatchlogs 35 | ``` 36 | That's it! The services logs should now be showing up in CloudWatch Logs. 37 | 38 | ### Docker Image 39 | 40 | - https://hub.docker.com/r/segment/ecs-logs 41 | 42 | ### Sources 43 | 44 | Sources are log streams from which events are read by ecs-logs and forwarded to 45 | the destinations. 46 | The log events can be JSON formatted with the following structure: 47 | ```js 48 | { 49 | "level": "", 50 | "time": "", 51 | "info": { 52 | "host": "", 53 | "source": "", 54 | "id": "", 55 | "pid": , 56 | "gid": , 57 | "uid": , 58 | "errors": [ 59 | { 60 | "type": "", 61 | "error": "", 62 | "errno": , 63 | "stack": [...] 64 | }, 65 | ... 66 | ] 67 | }, 68 | "data": { 69 | ... 70 | }, 71 | "message": "" 72 | } 73 | ``` 74 | All fields are optional and ecs-logs will assume defaults if some are missing. 75 | 76 | - **stdin** 77 | 78 | The default source that ecs-logs uses is *stdin*, in most cases this is not what 79 | will be used in production but can be useful for development and testing 80 | purposes. 81 | Because no metadata can be passed to log messages read from *stdin*, this source 82 | expects a to read a stream of JSON-formatted objects with this following 83 | structure: 84 | ```js 85 | { 86 | "group": "", 87 | "stream": "", 88 | "event": { 89 | ... 90 | } 91 | } 92 | ``` 93 | Where *group* and *stream* will be used to identify where the log event belong 94 | and *event* must be a JSON object with the structure defined above. 95 | 96 | - **journald** 97 | 98 | This journald source is what is usually used for production deployments since 99 | ECS can be easily configured to send docker containers logs to the journal which 100 | then acts as a centralize logging system on host. 101 | 102 | The journald source expects to find the *CONTAINER_TAG* and *CONTAINER_NAME* 103 | metadata on log events, which it uses to set the group and stream to which the 104 | log event will be sent. 105 | 106 | You can override the stream name by setting the `JOURNALD_STREAM_NAME` environment 107 | variable with a different journald metadata field to read the stream name from. 108 | 109 | The log message can be either plain text or JSON formatted. When ecs-logs fails 110 | to parse a JSON message, either because the content is not JSON or because the 111 | format is not something it understands, it will generate a log event where the 112 | *message* field is set to the full log message, for example: 113 | 114 | *log message:* 115 | ``` 116 | 2016-07-05T09:08:12.123Z - INFO - hello! 117 | ``` 118 | *log event:* 119 | ```js 120 | { 121 | "level": "NONE", 122 | "time": "