logstash-filter-fix_protocol 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 01e4c787451d2df8a4d094719f6773f41dc32b48
4
+ data.tar.gz: 59d92aec02f3566804710507b42e046814817100
5
+ SHA512:
6
+ metadata.gz: 1c20c43d362899f2423da2799621d48c5af3f9c2775313a33ddac837ca68d93098b34ed098aa2a214235f0d931a0aa615699a5c22651fd455ff2ef16cb0681fb
7
+ data.tar.gz: 27940ad87626f23d13428a78fc243ede4f453551d35404f5af3592a8ec75b508aaaf494769b0a108424864ce0c1db1d7bbf8be701661e60654ff287c39d98c09
@@ -0,0 +1,13 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4
+
5
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.
6
+
7
+ Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
8
+
9
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
10
+
11
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
12
+
13
+ This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,34 @@
1
+ # Contributing to FIX Message Logstash Filter
2
+
3
+ Thanks for taking the time to contribute to FIX Message Logstash Filter!
4
+
5
+ If you come across any issues, please [tell us](https://github.com/connamara/logstash-filter-fix_protocol/issues).
6
+ Pull requests (with tests) are appreciated. No pull request is too small. Please help with:
7
+
8
+ * Reporting bugs
9
+ * Suggesting features
10
+ * Writing or improving documentation
11
+ * Fixing typos
12
+ * Cleaning whitespace
13
+ * Refactoring code
14
+ * Adding tests
15
+ * Closing [issues](https://github.com/connamara/logstash-filter-fix_protocol/issues)
16
+
17
+
18
+ ## Before you contribute
19
+
20
+ * Did you find a bug? **Ensure the bug was not already reported** by searching on Github under [Issues](https://github.com/connamara/logstash-filter-fix_protocol/issues).
21
+
22
+ ## Steps to Contribute:
23
+
24
+ 1. Fork the [official repository](https://github.com/connamara/logstash-filter-fix_protocol/).
25
+ 2. Make your changes in a topic branch.
26
+ 3. Send a pull request.
27
+ 4. If you are new contributor to this project, sign the CLA
28
+
29
+ ### Notes:
30
+
31
+ * If you report a bug and don't include a fix, please include a failing test.
32
+ * Contributions without a signed CLA won't be accepted.
33
+ * Generally, contributions without tests won't be accepted.
34
+ * Contributions that fail the automated build won't be accepted.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fix_logstash_plugin.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2016 Connamara Systems, llc
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.
@@ -0,0 +1,46 @@
1
+ The QuickFIX Software License, Version 1.0
2
+
3
+ Copyright (c) 2001-2010 quickfixengine.org All rights
4
+ reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions
8
+ are met:
9
+
10
+ 1. Redistributions of source code must retain the above copyright
11
+ notice, this list of conditions and the following disclaimer.
12
+
13
+ 2. Redistributions in binary form must reproduce the above copyright
14
+ notice, this list of conditions and the following disclaimer in
15
+ the documentation and/or other materials provided with the
16
+ distribution.
17
+
18
+ 3. The end-user documentation included with the redistribution,
19
+ if any, must include the following acknowledgment:
20
+ "This product includes software developed by
21
+ quickfixengine.org (http://www.quickfixengine.org/)."
22
+ Alternately, this acknowledgment may appear in the software itself,
23
+ if and wherever such third-party acknowledgments normally appear.
24
+
25
+ 4. The names "QuickFIX" and "quickfixengine.org" must
26
+ not be used to endorse or promote products derived from this
27
+ software without prior written permission. For written
28
+ permission, please contact ask@quickfixengine.org
29
+
30
+ 5. Products derived from this software may not be called "QuickFIX",
31
+ nor may "QuickFIX" appear in their name, without prior written
32
+ permission of quickfixengine.org
33
+
34
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
35
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
36
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
37
+ DISCLAIMED. IN NO EVENT SHALL QUICKFIXENGINE.ORG OR
38
+ ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
39
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
40
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
41
+ USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
42
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
43
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
44
+ OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45
+ SUCH DAMAGE.
46
+
data/README.md ADDED
@@ -0,0 +1,151 @@
1
+ # FIX Protocol Logstash Filter [![Build Status](https://travis-ci.org/connamara/logstash-filter-fix_protocol.svg?branch=master)](https://travis-ci.org/connamara/logstash-filter-fix_protocol)
2
+
3
+ A LogStash filter plugin for FIX Message parsing
4
+
5
+ Given a FIX log file that looks like this:
6
+
7
+ ```
8
+ 2015-08-26 23:08:38,096 FIX.4.2:DUMMY_INC->ANOTHER_INC: 8=FIX.4.29=18435=F34=249=ANOTHER_INC50=DefaultSenderSubID52=20150826-23:08:38.09456=DUMMY_INC1=DefaultAccount11=clordid_of_cancel41=15101256954=155=ITER60=20250407-13:14:15167=FUT200=20151210=147
9
+ 2015-08-31 17:48:20,890 FIXT.1.1:DUMMY_INC->ANOTHER_INC: 8=FIXT.1.19=14035=W34=249=DUMMY_INC52=20150831-17:48:20.89056=ANOTHER_INC22=9948=.AQUA-W262=golden_path_test268=1269=3270=640754272=20150831273=17:48:20.88210=070
10
+ 2015-08-31 20:48:26,536 FIXT.1.1:DUMMY_INC->ANOTHER_INC: 8=FIXT.1.19=18935=W34=549=DUMMY_INC52=20150831-20:48:26.53556=ANOTHER_INC22=9948=ITRZ21262=req_A268=2269=0270=0.01005271=10272=20150831273=20:48:26.514269=1270=0.0101271=2272=20150831273=20:48:26.51410=123
11
+ ```
12
+
13
+ The FIX Message filter plugin can read the FIX log as an input and turn it into something like this:
14
+
15
+ ![alt tag](http://i.imgur.com/gkeStss.png)
16
+
17
+ ## Installation
18
+ ```
19
+ $ /opt/logstash/bin/plugin install logstash-filter-fix_protocol
20
+ ```
21
+
22
+ ## Plugin Configuration
23
+
24
+ | Setting | Input type | Required | Default Value |
25
+ | ----------------------- | ----------------| ---------| ------------------ |
26
+ | message | string/variable | Yes | "Fix String" |
27
+ | data_dictionary_path | string | Yes | "/PATH/TO/YOUR/DD" |
28
+ | session_dictionary_path | string | No | nil |
29
+
30
+ **message**
31
+ + value type is a string
32
+ + required
33
+
34
+ Should be the actual fix message passed to the filter. You might need to use a separate filter, like grok, to parse a log and set a fix string variable.
35
+
36
+ **data_dictionary_path**
37
+ + value type is a string
38
+ + required
39
+
40
+ Should be the absolute path to your data dictionary xml file.
41
+
42
+ **session_dictionary_path**
43
+ + value type is a string
44
+ + Not required
45
+
46
+ Should be the absolute path to your session dictionary xml file for FIX versions > 5.0. Note, if you do not set this but are using FIX 5.0, the filter will still work, but admin messages won't be correctly parsed - you'll lose data. The filter ignores key-value pairs that it doesn't parse correctly.
47
+
48
+ **Sample Config File**
49
+
50
+ *Note: For FIX < 5.0, simply omit the `session_dictionary_path`.*
51
+
52
+ ```
53
+ input {
54
+ file {
55
+ path => "/PATH/TO/YOUR/FIX-MESSAGE.log"
56
+ start_position => "beginning"
57
+ }
58
+ }
59
+ filter {
60
+ grok {
61
+ match => ["message","%{TIMESTAMP_ISO8601:timestamp} %{GREEDYDATA:fix_string}: %{GREEDYDATA:fix_message}"]
62
+ }
63
+ fix_protocol {
64
+ message => fix_message
65
+ session_dictionary_path => "/PATH/TO/FIX/5.0/SESSION/DICTIONARY/FIX.xml"
66
+ data_dictionary_path => "/PATH/TO/FIX/5.0/DATA/DICTIONARY/FIX.xml"
67
+ }
68
+ }
69
+ output {
70
+ stdout { codec => rubydebug }
71
+ }
72
+
73
+ ```
74
+
75
+ Notice, we're using the Grok filter to create a `fix_message` variable from a theoretical FIX Message log file. Then, we're passing that variable to our filter. You can see this emulated behavior in our specs.
76
+
77
+ ## Development Environment
78
+
79
+ To get set up quickly, we recommend using Vagrant with the Ansible provisioning available in this source repository.
80
+
81
+ ### Setup with Vagrant
82
+
83
+ * Install [Ansible](http://www.ansible.com/)
84
+ * Install [VirtualBox](https://www.virtualbox.org)
85
+ * Install [Vagrant](http://www.vagrantup.com/)
86
+
87
+ Then,
88
+
89
+ ```
90
+ vagrant up
91
+ ```
92
+
93
+ ### Manual Setup (OSX)
94
+ + `rvm install jruby`
95
+ + `rvm use jruby`
96
+ + `bundle install`
97
+ + `brew install logstash`
98
+
99
+ Then, run `bin/console` for an interactive prompt that will allow you to experiment.
100
+
101
+ To release a new version, update the **version number** in `logstash-filter-fix_protocol.gemspec`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
102
+
103
+ *Note: If you get an error message about metadata, you'll need to update to ruby gems > 2.0. Run `gem update --system`*
104
+
105
+ ### Running Tests
106
+
107
+ ```
108
+ $ ./bin/rspec rspec
109
+ ```
110
+
111
+ ### Development Logstash Installation
112
+
113
+ 1. Add the filter to your installation of LogStash
114
+
115
+ ```ruby
116
+ # /opt/logstash/Gemfile
117
+ #...
118
+ gem "logstash-output-kafka"
119
+ gem "logstash-input-http_poller"
120
+ gem "logstash-filter-fix_protocol", :path => "/PATH/TO/YOUR/FORK"
121
+ ```
122
+
123
+ 2. Install the filter plugin
124
+
125
+ ```
126
+ $ /opt/logstash/bin/plugin install --no-verify
127
+ ```
128
+
129
+ 3. Start logstash installation with a LogStash configuration file.
130
+
131
+ ```
132
+ $ /opt/logstash/bin/logstash -f /PATH/TO/logstash.conf
133
+ ```
134
+
135
+ ## Contributing
136
+
137
+ Contributions are welcome! Please see the [Contribution Guidelines](CONTRIBUTING.md) for details.
138
+
139
+ ![Connamara Systems](http://www.connamara.com/wp-content/uploads/2016/01/connamara_logo_dark.png)
140
+
141
+ FIX Message Logstash Filter is maintained and funded by [Connamara Systems, llc](http://connamara.com).
142
+
143
+ The names and logos for Connamara Systems are trademarks of Connamara Systems, llc.
144
+
145
+ ## Licensing
146
+
147
+ FIX Message Logstash Filter is Copyright © 2016 Connamara Systems, llc.
148
+
149
+ This software is available under the Apache license and a commercial license. Please see the [LICENSE](LICENSE.txt) file for the terms specified by the Apache license. The commercial license offers more flexible licensing terms compared to the Apache license, and includes support services. [Contact us](mailto:info@connamara.com) for more information on the Connamara commercial license, what it enables, and how you can start commercial development with it.
150
+
151
+ This product includes software developed by quickfixengine.org ([http://www.quickfixengine.org/](http://www.quickfixengine.org/)). Please see the [QuickFIX Software LICENSE](QUICKFIX_LICENSE.txt) for the terms specified by the QuickFIX Software License.
@@ -0,0 +1,16 @@
1
+ require 'quickfix'
2
+
3
+ module LogStash
4
+ module Filters
5
+ class DataDictionary < quickfix.DataDictionary
6
+ attr_reader :file
7
+
8
+ def initialize(file_path)
9
+ @file = ::File.new(file_path) # throw an exception if the file isn't found
10
+
11
+ super(file_path)
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,91 @@
1
+ require 'quickfix'
2
+ require 'active_support/core_ext'
3
+
4
+ module LogStash
5
+ module Filters
6
+ class FixMessage < quickfix.Message
7
+ attr_reader :type, :msg_string, :session_dictionary, :data_dictionary, :all_dictionaries
8
+
9
+ def initialize(msg_string, data_dictionary, session_dictionary)
10
+ @session_dictionary = session_dictionary
11
+ @data_dictionary = data_dictionary
12
+ @msg_string = msg_string
13
+ @type = quickfix.MessageUtils.getMessageType(msg_string)
14
+
15
+ @all_dictionaries = [@data_dictionary, @session_dictionary]
16
+
17
+ super(msg_string, data_dictionary, false)
18
+ end
19
+
20
+ def to_hash
21
+ # TODO: This logic / parsing might make sense in quickfix-j / java world
22
+ # Then, from here, we could inherit from quickfix.Message and call `JSON.parse(self.to_json)`
23
+ # OR: Might want to move all this to ruby
24
+ # dd = Hash.from_xml(load_fixture("FIX50SP1.xml")) || https://github.com/jnunemaker/crack
25
+ header_msg = field_map_to_hash(self.header)
26
+ body_msg = field_map_to_hash(self, type)
27
+ trailer_msg = field_map_to_hash(self.trailer)
28
+
29
+ header_msg.merge(body_msg).merge(trailer_msg)
30
+ end
31
+
32
+ private
33
+
34
+ def field_type(tag)
35
+ @all_dictionaries.each do |dd|
36
+ enum = dd.get_field_type_enum(tag)
37
+ value = enum.get_name unless enum.nil?
38
+ return value if value.present?
39
+ end
40
+ end
41
+
42
+ def field_name(tag)
43
+ @all_dictionaries.each do |dd|
44
+ value = dd.get_field_name(tag)
45
+ return value if value.present?
46
+ end
47
+ end
48
+
49
+ def field_map_to_hash(field_map, msg_type = nil)
50
+ hash = {}
51
+ # java TreeMap: https://github.com/quickfix-j/quickfixj/blob/master/quickfixj-core/src/main/java/quickfix/FieldMap.java#L395
52
+ iter = field_map.iterator
53
+
54
+ while iter.has_next
55
+ field = iter.next
56
+ tag = field.get_tag
57
+ value = field.get_value
58
+
59
+ # IF GROUP
60
+ if msg_type.present? and @data_dictionary.is_group(msg_type, tag)
61
+ groups = []
62
+
63
+ for i in 1..value.to_i
64
+ group_map = field_map.get_group(i, tag)
65
+ groups << field_map_to_hash(group_map, msg_type)
66
+ end
67
+
68
+ value = groups
69
+ # IF FIELD
70
+ elsif @data_dictionary.is_field(tag)
71
+ value =
72
+ case field_type(tag)
73
+ when "INT", "DAYOFMONTH" then value.to_i
74
+ when "PRICE", "FLOAT", "QTY" then value.to_f
75
+ when "BOOLEAN" then value == "Y"
76
+ when "NUMINGROUP" then field_map.to_hash(value)
77
+ else
78
+ value_name = @data_dictionary.get_value_name(tag, value)
79
+ value_name.presence || value
80
+ end
81
+ end
82
+
83
+ hash[field_name(tag)] = value
84
+ end
85
+
86
+ hash
87
+ end
88
+
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,61 @@
1
+ # encoding: utf-8
2
+ require "logstash/filters/base"
3
+ require "logstash/namespace"
4
+ require "logstash/filters/data_dictionary"
5
+ require "logstash/filters/fix_message"
6
+
7
+ module LogStash
8
+ module Filters
9
+ class FixProtocol < LogStash::Filters::Base
10
+
11
+ attr_reader :data_dictionary, :session_dictionary
12
+
13
+ config_name "fix_protocol"
14
+
15
+ config :message, validate: :string, default: "Hello"
16
+
17
+ config :data_dictionary_path, validate: :string, default: "/PATH/TO/YOUR/DD"
18
+ config :session_dictionary_path, validate: :string, default: nil
19
+
20
+ def initialize(options = {})
21
+ super(options)
22
+
23
+ fail "Need to configure a valid data dictionary path" unless config["data_dictionary_path"]
24
+
25
+ @data_dictionary = DataDictionary.new(config["data_dictionary_path"])
26
+
27
+ # Set session data dictionary variable if using > FIX 5.0
28
+ session_dict = config["session_dictionary_path"]
29
+ @session_dictionary = session_dict.present? ? DataDictionary.new(session_dict) : @data_dictionary
30
+ end
31
+
32
+ def register
33
+ # just here because you complain otherwise
34
+ end
35
+
36
+ def filter(event)
37
+ if event["fix_message"]
38
+ fix_message = FixMessage.new(event["fix_message"], data_dictionary, session_dictionary)
39
+
40
+ fix_hash = fix_message.to_hash
41
+
42
+ fix_hash.each do |key, value|
43
+ begin
44
+ event[key] = value
45
+ rescue NoMethodError => e
46
+ puts "********"
47
+ puts "WARNING: Could not correctly parse #{event["fix_message"]}"
48
+ puts JSON.pretty_generate(fix_hash)
49
+ puts "Message: #{e.message}"
50
+ puts "********"
51
+ ensure
52
+ next
53
+ end
54
+ end
55
+ end
56
+ # filter_matched should go in the last line of our successful code
57
+ filter_matched(event)
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,34 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "logstash-filter-fix_protocol"
7
+ s.version = "0.1.1"
8
+ s.authors = ["Connamara Systems"]
9
+ s.email = ["info@connamara.com"]
10
+
11
+ s.summary = "FIX Protocol Logstash Filter"
12
+ s.description = "Put your financial application logs to work with logstash FIX filtering"
13
+ s.homepage = "https://github.com/connamara/logstash-filter-fix_protocol"
14
+ s.licenses = ['Apache License (2.0)']
15
+
16
+ s.files = Dir['lib/**/*','vendor/**/*','*.gemspec','*.md','CONTRIBUTORS','Gemfile','LICENSE.txt','QUICKFIX_LICENSE.txt','NOTICE.TXT', 'spec/**/*', 'features/**/*']
17
+
18
+ s.test_files = s.files.grep(%r{^(spec|features)/})
19
+
20
+ s.require_paths = ["lib"]
21
+
22
+ s.metadata = { "logstash_plugin" => "true", "logstash_group" => "filter" }
23
+
24
+ s.add_runtime_dependency "logstash-core", ">= 2.0.0.beta2", "< 3.0.0"
25
+ s.add_runtime_dependency "logstash-input-generator"
26
+ s.add_runtime_dependency "activesupport"
27
+ s.add_runtime_dependency "quickfix-jruby"
28
+
29
+ s.add_development_dependency "logstash-devutils"
30
+ s.add_development_dependency "bundler", "~> 1.8"
31
+ s.add_development_dependency "rake", "~> 10.0"
32
+ s.add_development_dependency "rspec"
33
+ s.add_development_dependency "pry"
34
+ end