Top Banner
Dive into Fluentd Plugin
72

Dive into Fluentd plugin v0.12

Jan 14, 2017

Download

Technology

N Masahiro
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Dive into Fluentd plugin v0.12

Dive into Fluentd Plugin

Page 2: Dive into Fluentd plugin v0.12

Site: repeatedly.github.com

Company: Treasure Data Inc.

Love plugins: input: tail buffer: memory output: mongo

Page 3: Dive into Fluentd plugin v0.12

developed by

The missing log collector

What's Fluentd?

Page 4: Dive into Fluentd plugin v0.12

Fluentd is a buffer router collector converter aggregator etc...

Page 5: Dive into Fluentd plugin v0.12

... but, Fluentd doesn’t have such features as a built-in.

Page 6: Dive into Fluentd plugin v0.12

Instead, Fluentd has flexible plugin architecture which consists of Input, Filter, Output and Buffer.

Page 7: Dive into Fluentd plugin v0.12

We can customize Fluentd using plugins :)

Page 8: Dive into Fluentd plugin v0.12

Agenda: This slide

talk about - an example of Fluentd plugins - Fluentd and libraries - how to develop a Fluentd plugin

don’t talk about - the details of each plugin - the experience of production

Page 9: Dive into Fluentd plugin v0.12

See also: http://docs.fluentd.org/articles/plugin-development

Page 10: Dive into Fluentd plugin v0.12

Examplebased on bit.ly/fluentd-with-mongo

Page 11: Dive into Fluentd plugin v0.12

Install

Plugin name is , and fluent-gem is included in Fluentd gem.

fluent-plugin-xxx

Page 12: Dive into Fluentd plugin v0.12

Let’s type!

$ fluent-gem install fluent-plugin-mongo

Page 13: Dive into Fluentd plugin v0.12

<source> type tail format apache path /path/to/log tag mongo.apache </source>

<match mongo.**> type mongo database apache collection access host otherhost </match>

Input Output

fluentd.conf

Page 14: Dive into Fluentd plugin v0.12

Start!

$ fluentd -c fluentd.conf2015-10-04 00:00:14 +0900: starting fluentd-0.12.16 2015-10-04 00:00:14 +0900: reading config file path="fluentd.conf" 2015-10-04 00:00:14 +0900: adding source type="tail" 2015-10-04 00:00:14 +0900: adding match pattern="mongo.**" type="mongo" █

Page 15: Dive into Fluentd plugin v0.12

Attack!

$ ab -n 100 -c 10 http://localhost/

Page 16: Dive into Fluentd plugin v0.12

$ mongo --host otherhost > use apache > db.access.find() { "type": "127.0.0.1", "method": "GET", "path": "/", "code": "200", "size": "44", "time": ISODate("2015-10-04T00:01:00Z") ... } has more...

Page 17: Dive into Fluentd plugin v0.12

Mongo

Apache

Fluentd

write

tail

insert

I’m a log!

event buffering

Page 18: Dive into Fluentd plugin v0.12

Warming up

Page 19: Dive into Fluentd plugin v0.12

Ruby

Fluentd Stack

OS

Cool.io

MessagePack

BufferInput

Outpu

Page 20: Dive into Fluentd plugin v0.12

Rubyruby-lang.org

Page 21: Dive into Fluentd plugin v0.12

Fluentd and plugins are written in Ruby.

Page 22: Dive into Fluentd plugin v0.12

Fluentd works on Ruby 1.9.3 or later

Page 23: Dive into Fluentd plugin v0.12

Note that Fluentd v0.14 works on Ruby 2.1 or later. We will remove 1.9 or 2.0 support.

Page 24: Dive into Fluentd plugin v0.12

MessagePackmsgpack.org

Page 25: Dive into Fluentd plugin v0.12

Serialization: JSON like fast and compact format.

RPC: Async and parallelism for high performance.

IDL: Easy to integrate and maintain the service.

Page 26: Dive into Fluentd plugin v0.12

Binary format, Header + Body, and Variable length.

Page 27: Dive into Fluentd plugin v0.12

Note that Ruby version can’t handle a Time object natively.

Page 28: Dive into Fluentd plugin v0.12

So, we use an Integer object , second unit, instead of a Time for now.

Page 29: Dive into Fluentd plugin v0.12

Since v0.14, Fluentd supports nano-second unit with new EventTime object. https://github.com/fluent/fluentd/pull/653

Page 30: Dive into Fluentd plugin v0.12

Source: github.com/msgpack

Wiki: wiki.msgpack.org/display/MSGPACK

Mailing List: groups.google.com/group/msgpack

Page 31: Dive into Fluentd plugin v0.12

Cool.iocoolio.github.com

Page 32: Dive into Fluentd plugin v0.12

Event driven framework built on top of libev.

Page 33: Dive into Fluentd plugin v0.12

Cool.io has Loop and Watchers with Transport wrappers. Lots of input plugins use cool.io.

Page 34: Dive into Fluentd plugin v0.12

Configuration

Page 35: Dive into Fluentd plugin v0.12

Fluentd loads plugins from $LOAD_PATH.

Page 36: Dive into Fluentd plugin v0.12

Input: $LOAD_PATH/fluent/plugin/in_<type>.rb

Buffer: $LOAD_PATH/fluent/plugin/buf_<type>.rb

Output: $LOAD_PATH/fluent/plugin/out_<type>.rb

Filter: $LOAD_PATH/fluent/plugin/filter_<type>.rb

Page 37: Dive into Fluentd plugin v0.12

We use ‘register_xxx’ to register a plugin. ’xxx’ is ’input’, ’filter’, ’buffer’ and ’output’

Page 38: Dive into Fluentd plugin v0.12

We can load the plugin configuration using config_param and configure method.config_param set config value to @<config name> automatically.

Supported types are below: http://docs.fluentd.org/articles/config-file#supported-data-types-for-values

Page 39: Dive into Fluentd plugin v0.12

class TailInput < Input Plugin.register_input(’tail’, self) config_param :path, :string ... end

<source> type tail path /path/to/log ... </source> fluentd.conf

in_tail.rb

Page 40: Dive into Fluentd plugin v0.12

One trick is here:

Fluentd’s configuration module does not verify a default value. So, we can use the nil like Tribool :)

config_param :tag, :string, :default => nil

Fluentd does not check the type

Page 41: Dive into Fluentd plugin v0.12

Fluentd provides some useful mixins for input and output plugins.

Page 42: Dive into Fluentd plugin v0.12

SetTagKeyMixin: Provide ‘tag_key’ and ‘include_tag_key’.

SetTimeKeyMixin: Provide ‘time_key’ and ‘include_time_key’.

HandleTagNameMixin: Provide ‘remove_tag_prefix’ and ‘add_tag_prefix’ ‘remove_tag_suffix’ and ‘add_tag_suffix’

Page 43: Dive into Fluentd plugin v0.12

Code Flow

Mixin usage

class MongoOutput < BufferedOutput ... include SetTagKeyMixin config_set_default :include_tag_key, false ... end MongoOutput

SetTagKeyMixin

BufferedOutput

super

super

super

Page 44: Dive into Fluentd plugin v0.12

Input

Page 45: Dive into Fluentd plugin v0.12

Default 3rd party

Available plugins

exec forward http syslog tail monitor_agent etc...

mongo_tail scribe msgpack dstat kafka amqp2 etc...

Page 46: Dive into Fluentd plugin v0.12

class NewInput < Input ... def configure(conf) # parse a configuration manually end

def start # invoke action end

def shutdown # cleanup resources end end

Page 47: Dive into Fluentd plugin v0.12

In action method, we use router.emit to input data.

tag = "app.tag" time = Engine.now record = {"key" => "value", ...} router.emit(tag, time, record)

Sample:

Page 48: Dive into Fluentd plugin v0.12

How to read an input in an efficient way? We use a thread and an event loop.

Page 49: Dive into Fluentd plugin v0.12

class ForwardInput < Fluent::Input ... def start ... @thread = Thread.new(&method(:run)) end

def run ... end end

Thread

Page 50: Dive into Fluentd plugin v0.12

class ForwardInput < Fluent::Input ... def start @loop = Coolio::Loop.new @lsock = listen @loop.attach(@lsock) ... end ... end

Event loop

Page 51: Dive into Fluentd plugin v0.12

Note that We must use Engine.now instead of Time.now

Page 52: Dive into Fluentd plugin v0.12

Filter

Page 53: Dive into Fluentd plugin v0.12

Default 3rd party

Available plugins

grep stdout record_transformer

parser geoip record_map typecast record_modifier etc...

Page 54: Dive into Fluentd plugin v0.12

class NewFilter < Filter # configure, start and shutdown # are same as input plugin

def filter(tag, time, record) # Modify record and return it. # If returns nil, that records are ignored record end end

Page 55: Dive into Fluentd plugin v0.12

Buffer

Page 56: Dive into Fluentd plugin v0.12

Default 3rd party

Available plugins

memory file

Page 57: Dive into Fluentd plugin v0.12

In most cases, Memory and File are enough.

Page 58: Dive into Fluentd plugin v0.12

Memory type is default. It’s fast but can’t resume data.

Page 59: Dive into Fluentd plugin v0.12

File type is persistent type. It can resume data from file. TimeSlicedOutput’s default is file.

Page 60: Dive into Fluentd plugin v0.12

Output

Page 61: Dive into Fluentd plugin v0.12

Default 3rd party

Available plugins

copy exec file forward null stdout etc...

mongo s3 scribe elasticsearch webhdfs kafka Norikra etc...

Page 62: Dive into Fluentd plugin v0.12

class NewOutput < BufferedOutput # configure, start and shutdown # are same as input plugin

def format(tag, time, record) # convert event to raw string end

def write(chunk) # write chunk to target # chunk has multiple formatted data end end

Page 63: Dive into Fluentd plugin v0.12

Output has 3 buffering modes. None Buffered ObjectBuffered Time sliced

Page 64: Dive into Fluentd plugin v0.12

Buffered Time sliced

Buffering type

chunk

go out

chunk

chunk

from in

chunk limit

queue limit

Buffer has an internal map to manage a chunk. A key is “” in Buffered, but a key is time slice in TimeSliced buffer.

def write(chunk) # chunk.key is time slice end

Page 65: Dive into Fluentd plugin v0.12

Test

Page 66: Dive into Fluentd plugin v0.12

Input: Fluent::Test::InputTestDriver

Buffer: Fluent::Test::BufferedOutputTestDriver

Output: Fluent::Test::OutputTestDriver

Filter: Fluent::Test::FilterTestDriver

Page 67: Dive into Fluentd plugin v0.12

class MongoOutputTest < Test::Unit::TestCase def setup Fluent::Test.setup require 'fluent/plugin/out_mongo' end

def create_driver(conf = CONFIG) Fluent::Test::BufferedOutputTestDriver.new (Fluent::MongoOutput) { def start # prevent external access super end ... }.configure(conf) end

Page 68: Dive into Fluentd plugin v0.12

...

def test_format # test format using emit and expect_format

end

def test_write d = create_driver t = emit_documents(d)

# return a result of write method collection_name, documents = d.run assert_equal([{...}, {...}, ...], documents) assert_equal('test', collection_name) end ...

end

Page 69: Dive into Fluentd plugin v0.12

Release

Page 70: Dive into Fluentd plugin v0.12

Gem StructurePlugin root |-- lib/ | |-- fluent/ | |-- plugin/ | |- out_<name>.rb |- Gemfile |- fluent-plugin-<name>.gemspec |- Rakefile |- README.md(rdoc) |- VERSION

Page 71: Dive into Fluentd plugin v0.12

Bundle with git

$ edit lib/fluent/plugin/out_<name>.rb

$ git add / commit

$ cat VERSION 0.1.0

$ bunlde exec rake release

See: rubygems.org/gems/fluent-plugin-<name>

Page 72: Dive into Fluentd plugin v0.12

See released plugins for more details about each file.