logstash-output-harbor_beacon 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/CHANGELOG.md +2 -0
 - data/CONTRIBUTORS +10 -0
 - data/Gemfile +3 -0
 - data/LICENSE +11 -0
 - data/README.md +86 -0
 - data/lib/logstash/outputs/harbor_beacon.rb +422 -0
 - data/logstash-output-harbor_beacon.gemspec +30 -0
 - data/spec/outputs/harbor_beacon_spec.rb +35 -0
 - metadata +118 -0
 
    
        checksums.yaml
    ADDED
    
    | 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            SHA256:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 12a689753ad344a88d1c675b3d3bbd4424b6e6aa054b9e9a4baf9db4d6cbb7ee
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: d5cc214c27a3b2b01f07339a2ebd824c3c0d4a7b3f3b1ef2a2e4097869e7c270
         
     | 
| 
      
 5 
     | 
    
         
            +
            SHA512:
         
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 9452adf6b1d1c049f24974a1d62f9b9e662ecf479309f27db9beb0ba2c6b11ac9e14bf8445254120606288aa04fb773975510ed07d922ab417a14459a7a315b8
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 1e980c6f23eef6be5bd1eb1799d58cea358f7a7927a1ff8d5367f53323c32a8cc684bfbeacbba6ea04e0b23434d02c527ff4a01fa58c27847c03dd591e8b29a0
         
     | 
    
        data/CHANGELOG.md
    ADDED
    
    
    
        data/CONTRIBUTORS
    ADDED
    
    | 
         @@ -0,0 +1,10 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            The following is a list of people who have contributed ideas, code, bug
         
     | 
| 
      
 2 
     | 
    
         
            +
            reports, or in general have helped logstash along its way.
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            Contributors:
         
     | 
| 
      
 5 
     | 
    
         
            +
            * Scott Matheson - scott@hrbr.io
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            Note: If you've sent us patches, bug reports, or otherwise contributed to
         
     | 
| 
      
 8 
     | 
    
         
            +
            Logstash, and you aren't on the list above and want to be, please let us know
         
     | 
| 
      
 9 
     | 
    
         
            +
            and we'll make sure you're here. Contributions from folks like you are what make
         
     | 
| 
      
 10 
     | 
    
         
            +
            open source awesome.
         
     | 
    
        data/Gemfile
    ADDED
    
    
    
        data/LICENSE
    ADDED
    
    | 
         @@ -0,0 +1,11 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Licensed under the Apache License, Version 2.0 (the "License");
         
     | 
| 
      
 2 
     | 
    
         
            +
            you may not use this file except in compliance with the License.
         
     | 
| 
      
 3 
     | 
    
         
            +
            You may obtain a copy of the License at
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                http://www.apache.org/licenses/LICENSE-2.0
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            Unless required by applicable law or agreed to in writing, software
         
     | 
| 
      
 8 
     | 
    
         
            +
            distributed under the License is distributed on an "AS IS" BASIS,
         
     | 
| 
      
 9 
     | 
    
         
            +
            WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
         
     | 
| 
      
 10 
     | 
    
         
            +
            See the License for the specific language governing permissions and
         
     | 
| 
      
 11 
     | 
    
         
            +
            limitations under the License.
         
     | 
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,86 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Logstash Plugin
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            This is a plugin for [Logstash](https://github.com/elastic/logstash).
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            It is fully free and fully open source. The license is Apache 2.0, meaning you are pretty much free to use it however you want in whatever way.
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            ## Documentation
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            Logstash provides infrastructure to automatically generate documentation for this plugin. We use the asciidoc format to write documentation so any comments in the source code will be first converted into asciidoc and then into html. All plugin documentation are placed under one [central location](http://www.elastic.co/guide/en/logstash/current/).
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            - For formatting code or config example, you can use the asciidoc `[source,ruby]` directive
         
     | 
| 
      
 12 
     | 
    
         
            +
            - For more asciidoc formatting tips, see the excellent reference here https://github.com/elastic/docs#asciidoc-guide
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            ## Need Help?
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            Need help? Try #logstash on freenode IRC or the https://discuss.elastic.co/c/logstash discussion forum.
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            ## Developing
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            ### 1. Plugin Developement and Testing
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            #### Code
         
     | 
| 
      
 23 
     | 
    
         
            +
            - To get started, you'll need JRuby with the Bundler gem installed.
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            - Create a new plugin or clone and existing from the GitHub [logstash-plugins](https://github.com/logstash-plugins) organization. We also provide [example plugins](https://github.com/logstash-plugins?query=example).
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            - Install dependencies
         
     | 
| 
      
 28 
     | 
    
         
            +
            ```sh
         
     | 
| 
      
 29 
     | 
    
         
            +
            bundle install
         
     | 
| 
      
 30 
     | 
    
         
            +
            ```
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            #### Test
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            - Update your dependencies
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            ```sh
         
     | 
| 
      
 37 
     | 
    
         
            +
            bundle install
         
     | 
| 
      
 38 
     | 
    
         
            +
            ```
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
            - Run tests
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
            ```sh
         
     | 
| 
      
 43 
     | 
    
         
            +
            bundle exec rspec
         
     | 
| 
      
 44 
     | 
    
         
            +
            ```
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
            ### 2. Running your unpublished Plugin in Logstash
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
            #### 2.1 Run in a local Logstash clone
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
            - Edit Logstash `Gemfile` and add the local plugin path, for example:
         
     | 
| 
      
 51 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 52 
     | 
    
         
            +
            gem "logstash-filter-awesome", :path => "/your/local/logstash-filter-awesome"
         
     | 
| 
      
 53 
     | 
    
         
            +
            ```
         
     | 
| 
      
 54 
     | 
    
         
            +
            - Install plugin
         
     | 
| 
      
 55 
     | 
    
         
            +
            ```sh
         
     | 
| 
      
 56 
     | 
    
         
            +
            bin/logstash-plugin install --no-verify
         
     | 
| 
      
 57 
     | 
    
         
            +
            ```
         
     | 
| 
      
 58 
     | 
    
         
            +
            - Run Logstash with your plugin
         
     | 
| 
      
 59 
     | 
    
         
            +
            ```sh
         
     | 
| 
      
 60 
     | 
    
         
            +
            bin/logstash -e 'filter {awesome {}}'
         
     | 
| 
      
 61 
     | 
    
         
            +
            ```
         
     | 
| 
      
 62 
     | 
    
         
            +
            At this point any modifications to the plugin code will be applied to this local Logstash setup. After modifying the plugin, simply rerun Logstash.
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
            #### 2.2 Run in an installed Logstash
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
            You can use the same **2.1** method to run your plugin in an installed Logstash by editing its `Gemfile` and pointing the `:path` to your local plugin development directory or you can build the gem and install it using:
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
            - Build your plugin gem
         
     | 
| 
      
 69 
     | 
    
         
            +
            ```sh
         
     | 
| 
      
 70 
     | 
    
         
            +
            gem build logstash-filter-awesome.gemspec
         
     | 
| 
      
 71 
     | 
    
         
            +
            ```
         
     | 
| 
      
 72 
     | 
    
         
            +
            - Install the plugin from the Logstash home
         
     | 
| 
      
 73 
     | 
    
         
            +
            ```sh
         
     | 
| 
      
 74 
     | 
    
         
            +
            bin/logstash-plugin install /your/local/plugin/logstash-filter-awesome.gem
         
     | 
| 
      
 75 
     | 
    
         
            +
            ```
         
     | 
| 
      
 76 
     | 
    
         
            +
            - Start Logstash and proceed to test the plugin
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
            ## Contributing
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
            All contributions are welcome: ideas, patches, documentation, bug reports, complaints, and even something you drew up on a napkin.
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
            Programming is not a required skill. Whatever you've seen about open source and maintainers or community members  saying "send patches or die" - you will not see that here.
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
            It is more important to the community that you are able to contribute.
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
            For more information about contributing, see the [CONTRIBUTING](https://github.com/elastic/logstash/blob/master/CONTRIBUTING.md) file.
         
     | 
| 
         @@ -0,0 +1,422 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # encoding: utf-8
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "logstash/outputs/base"
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "logstash/namespace"
         
     | 
| 
      
 4 
     | 
    
         
            +
            require "logstash/json"
         
     | 
| 
      
 5 
     | 
    
         
            +
            require "uri"
         
     | 
| 
      
 6 
     | 
    
         
            +
            require "logstash/plugin_mixins/http_client"
         
     | 
| 
      
 7 
     | 
    
         
            +
            require "zlib"
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            # An harbor_beacon output that does nothing.
         
     | 
| 
      
 10 
     | 
    
         
            +
            class LogStash::Outputs::HarborBeacon < LogStash::Outputs::Base
         
     | 
| 
      
 11 
     | 
    
         
            +
              include LogStash::PluginMixins::HttpClient
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              concurrency :shared
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              attr_accessor :is_batch
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              RETRYABLE_MANTICORE_EXCEPTIONS = [
         
     | 
| 
      
 18 
     | 
    
         
            +
                ::Manticore::Timeout,
         
     | 
| 
      
 19 
     | 
    
         
            +
                ::Manticore::SocketException,
         
     | 
| 
      
 20 
     | 
    
         
            +
                ::Manticore::ClientProtocolException,
         
     | 
| 
      
 21 
     | 
    
         
            +
                ::Manticore::ResolutionFailure,
         
     | 
| 
      
 22 
     | 
    
         
            +
                ::Manticore::SocketTimeout
         
     | 
| 
      
 23 
     | 
    
         
            +
              ]
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              # This output lets you send events to a
         
     | 
| 
      
 26 
     | 
    
         
            +
              # generic HTTP(S) endpoint
         
     | 
| 
      
 27 
     | 
    
         
            +
              #
         
     | 
| 
      
 28 
     | 
    
         
            +
              # This output will execute up to 'pool_max' requests in parallel for performance.
         
     | 
| 
      
 29 
     | 
    
         
            +
              # Consider this when tuning this plugin for performance.
         
     | 
| 
      
 30 
     | 
    
         
            +
              #
         
     | 
| 
      
 31 
     | 
    
         
            +
              # Additionally, note that when parallel execution is used strict ordering of events is not
         
     | 
| 
      
 32 
     | 
    
         
            +
              # guaranteed!
         
     | 
| 
      
 33 
     | 
    
         
            +
              #
         
     | 
| 
      
 34 
     | 
    
         
            +
              # Beware, this gem does not yet support codecs. Please use the 'format' option for now.
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              config_name "harbor_beacon"
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
              # URL to use
         
     | 
| 
      
 39 
     | 
    
         
            +
              @@url = "https://harbor-stream.hrbr.io/beacon"
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
              # The HTTP Verb. Must be "post"
         
     | 
| 
      
 42 
     | 
    
         
            +
              @@http_method = "post"
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
              # Content type
         
     | 
| 
      
 45 
     | 
    
         
            +
              @@content_type = "application/json"
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
              # Custom headers to use
         
     | 
| 
      
 49 
     | 
    
         
            +
              # format is `headers => ["X-My-Header", "%{host}"]`
         
     | 
| 
      
 50 
     | 
    
         
            +
              config :headers, :validate => :hash, :default => {}
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
              # API Key
         
     | 
| 
      
 53 
     | 
    
         
            +
              config :api_key, :validate => :string, :required => :true
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
              # App Version Id
         
     | 
| 
      
 56 
     | 
    
         
            +
              config :app_version_id, :validate => :string, :required => :true
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
              # Beacon Version Id
         
     | 
| 
      
 59 
     | 
    
         
            +
              config :beacon_version_id, :validate => :string, :required => :true
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
              # Beacon Message Type
         
     | 
| 
      
 62 
     | 
    
         
            +
              config :beacon_message_type, :validate => :string, :required => :true
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
              # Beacon Instance ID
         
     | 
| 
      
 65 
     | 
    
         
            +
              config :beacon_instance_id, :validate => :string
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
              # Data Timestamp
         
     | 
| 
      
 68 
     | 
    
         
            +
              config :data_timestamp, :validate => :string
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
              # Set this to false if you don't want this output to retry failed requests
         
     | 
| 
      
 71 
     | 
    
         
            +
              config :retry_failed, :validate => :boolean, :default => true
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
              # If encountered as response codes this plugin will retry these requests
         
     | 
| 
      
 74 
     | 
    
         
            +
              config :retryable_codes, :validate => :number, :list => true, :default => [429, 500, 502, 503, 504]
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
              # If you would like to consider some non-2xx codes to be successes
         
     | 
| 
      
 77 
     | 
    
         
            +
              # enumerate them here. Responses returning these codes will be considered successes
         
     | 
| 
      
 78 
     | 
    
         
            +
              config :ignorable_codes, :validate => :number, :list => true
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
              # This lets you choose the structure and parts of the event that are sent.
         
     | 
| 
      
 81 
     | 
    
         
            +
              #
         
     | 
| 
      
 82 
     | 
    
         
            +
              #
         
     | 
| 
      
 83 
     | 
    
         
            +
              # For example:
         
     | 
| 
      
 84 
     | 
    
         
            +
              # [source,ruby]
         
     | 
| 
      
 85 
     | 
    
         
            +
              #    mapping => {"foo" => "%{host}"
         
     | 
| 
      
 86 
     | 
    
         
            +
              #               "bar" => "%{type}"}
         
     | 
| 
      
 87 
     | 
    
         
            +
              config :mapping, :validate => :hash
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
              # Set the format of the http body.
         
     | 
| 
      
 90 
     | 
    
         
            +
              #
         
     | 
| 
      
 91 
     | 
    
         
            +
              # If message, then the body will be the result of formatting the event according to message
         
     | 
| 
      
 92 
     | 
    
         
            +
              #
         
     | 
| 
      
 93 
     | 
    
         
            +
              # Otherwise, the event is sent as json.
         
     | 
| 
      
 94 
     | 
    
         
            +
              config :format, :validate => ["json", "message"], :default => "json"
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
              # Set this to true if you want to enable gzip compression for your http requests
         
     | 
| 
      
 97 
     | 
    
         
            +
              #
         
     | 
| 
      
 98 
     | 
    
         
            +
              # Compression is not supported at this time
         
     | 
| 
      
 99 
     | 
    
         
            +
              #
         
     | 
| 
      
 100 
     | 
    
         
            +
              # config :http_compression, :validate => :boolean, :default => false
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
              config :message, :validate => :string
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
              public
         
     | 
| 
      
 105 
     | 
    
         
            +
              def register
         
     | 
| 
      
 106 
     | 
    
         
            +
             
     | 
| 
      
 107 
     | 
    
         
            +
                # We count outstanding requests with this queue
         
     | 
| 
      
 108 
     | 
    
         
            +
                # This queue tracks the requests to create backpressure
         
     | 
| 
      
 109 
     | 
    
         
            +
                # When this queue is empty no new requests may be sent,
         
     | 
| 
      
 110 
     | 
    
         
            +
                # tokens must be added back by the client on success
         
     | 
| 
      
 111 
     | 
    
         
            +
                @request_tokens = SizedQueue.new(@pool_max)
         
     | 
| 
      
 112 
     | 
    
         
            +
                @pool_max.times {|t| @request_tokens << true }
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                @requests = Array.new
         
     | 
| 
      
 115 
     | 
    
         
            +
             
     | 
| 
      
 116 
     | 
    
         
            +
                # Compression is not supported at this time
         
     | 
| 
      
 117 
     | 
    
         
            +
                #
         
     | 
| 
      
 118 
     | 
    
         
            +
                @http_compression = false
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
                @is_batch = false
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                @headers["Content-Type"] = @@content_type
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
                validate_api_required!
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                @headers["apiKey"] = @api_key
         
     | 
| 
      
 127 
     | 
    
         
            +
                @headers["appVersionId"] = @app_version_id
         
     | 
| 
      
 128 
     | 
    
         
            +
                @headers["beaconVersionId"] = @beacon_version_id
         
     | 
| 
      
 129 
     | 
    
         
            +
                @headers["beaconMessageType"] = @beacon_message_type
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                if !@beacon_instance_id.nil?
         
     | 
| 
      
 132 
     | 
    
         
            +
                  @headers["beaconInstanceId"] = @beacon_instance_id.to_s
         
     | 
| 
      
 133 
     | 
    
         
            +
                end
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                if !@data_timestamp.nil?
         
     | 
| 
      
 136 
     | 
    
         
            +
                  @headers["dataTimestamp"] = @data_timestamp.to_s
         
     | 
| 
      
 137 
     | 
    
         
            +
                end
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
                validate_format!
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                # Run named Timer as daemon thread
         
     | 
| 
      
 142 
     | 
    
         
            +
                @timer = java.util.Timer.new("HTTP Output #{self.params['id']}", true)
         
     | 
| 
      
 143 
     | 
    
         
            +
              end # def register
         
     | 
| 
      
 144 
     | 
    
         
            +
             
     | 
| 
      
 145 
     | 
    
         
            +
              def multi_receive(events)
         
     | 
| 
      
 146 
     | 
    
         
            +
                return if events.empty?
         
     | 
| 
      
 147 
     | 
    
         
            +
                send_events(events)
         
     | 
| 
      
 148 
     | 
    
         
            +
              end
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
              class RetryTimerTask < java.util.TimerTask
         
     | 
| 
      
 151 
     | 
    
         
            +
                def initialize(pending, event, attempt)
         
     | 
| 
      
 152 
     | 
    
         
            +
                  @pending = pending
         
     | 
| 
      
 153 
     | 
    
         
            +
                  @event = event
         
     | 
| 
      
 154 
     | 
    
         
            +
                  @attempt = attempt
         
     | 
| 
      
 155 
     | 
    
         
            +
                  super()
         
     | 
| 
      
 156 
     | 
    
         
            +
                end
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
                def run
         
     | 
| 
      
 159 
     | 
    
         
            +
                  @pending << [@event, @attempt]
         
     | 
| 
      
 160 
     | 
    
         
            +
                end
         
     | 
| 
      
 161 
     | 
    
         
            +
              end
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
              def log_retryable_response(response)
         
     | 
| 
      
 164 
     | 
    
         
            +
                if (response.code == 429)
         
     | 
| 
      
 165 
     | 
    
         
            +
                  @logger.debug? && @logger.debug("Encountered a 429 response, will retry. This is not serious, just flow control via HTTP")
         
     | 
| 
      
 166 
     | 
    
         
            +
                else
         
     | 
| 
      
 167 
     | 
    
         
            +
                  @logger.warn("Encountered a retryable HTTP request in HTTP output, will retry", :code => response.code, :body => response.body)
         
     | 
| 
      
 168 
     | 
    
         
            +
                end
         
     | 
| 
      
 169 
     | 
    
         
            +
              end
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
              def log_error_response(response, url, event)
         
     | 
| 
      
 172 
     | 
    
         
            +
                log_failure(
         
     | 
| 
      
 173 
     | 
    
         
            +
                          "Encountered non-2xx HTTP code #{response.code}",
         
     | 
| 
      
 174 
     | 
    
         
            +
                          :response_code => response.code,
         
     | 
| 
      
 175 
     | 
    
         
            +
                          :url => url,
         
     | 
| 
      
 176 
     | 
    
         
            +
                          :event => event
         
     | 
| 
      
 177 
     | 
    
         
            +
                        )
         
     | 
| 
      
 178 
     | 
    
         
            +
              end
         
     | 
| 
      
 179 
     | 
    
         
            +
             
     | 
| 
      
 180 
     | 
    
         
            +
              def send_events(events)
         
     | 
| 
      
 181 
     | 
    
         
            +
                successes = java.util.concurrent.atomic.AtomicInteger.new(0)
         
     | 
| 
      
 182 
     | 
    
         
            +
                failures  = java.util.concurrent.atomic.AtomicInteger.new(0)
         
     | 
| 
      
 183 
     | 
    
         
            +
                retries = java.util.concurrent.atomic.AtomicInteger.new(0)
         
     | 
| 
      
 184 
     | 
    
         
            +
                event_count = @is_batch ? 1 : events.size
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
                pending = Queue.new
         
     | 
| 
      
 187 
     | 
    
         
            +
                if @is_batch
         
     | 
| 
      
 188 
     | 
    
         
            +
                  pending << [events, 0]
         
     | 
| 
      
 189 
     | 
    
         
            +
                else
         
     | 
| 
      
 190 
     | 
    
         
            +
                  events.each {|e| pending << [e, 0]}
         
     | 
| 
      
 191 
     | 
    
         
            +
                end
         
     | 
| 
      
 192 
     | 
    
         
            +
             
     | 
| 
      
 193 
     | 
    
         
            +
                while popped = pending.pop
         
     | 
| 
      
 194 
     | 
    
         
            +
                  break if popped == :done
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
      
 196 
     | 
    
         
            +
                  event, attempt = popped
         
     | 
| 
      
 197 
     | 
    
         
            +
             
     | 
| 
      
 198 
     | 
    
         
            +
                  action, event, attempt = send_event(event, attempt)
         
     | 
| 
      
 199 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 200 
     | 
    
         
            +
                    action = :failure if action == :retry && !@retry_failed
         
     | 
| 
      
 201 
     | 
    
         
            +
             
     | 
| 
      
 202 
     | 
    
         
            +
                    case action
         
     | 
| 
      
 203 
     | 
    
         
            +
                    when :success
         
     | 
| 
      
 204 
     | 
    
         
            +
                      successes.incrementAndGet
         
     | 
| 
      
 205 
     | 
    
         
            +
                    when :retry
         
     | 
| 
      
 206 
     | 
    
         
            +
                      retries.incrementAndGet
         
     | 
| 
      
 207 
     | 
    
         
            +
             
     | 
| 
      
 208 
     | 
    
         
            +
                      next_attempt = attempt+1
         
     | 
| 
      
 209 
     | 
    
         
            +
                      sleep_for = sleep_for_attempt(next_attempt)
         
     | 
| 
      
 210 
     | 
    
         
            +
                      @logger.info("Retrying http request, will sleep for #{sleep_for} seconds")
         
     | 
| 
      
 211 
     | 
    
         
            +
                      timer_task = RetryTimerTask.new(pending, event, next_attempt)
         
     | 
| 
      
 212 
     | 
    
         
            +
                      @timer.schedule(timer_task, sleep_for*1000)
         
     | 
| 
      
 213 
     | 
    
         
            +
                    when :failure
         
     | 
| 
      
 214 
     | 
    
         
            +
                      failures.incrementAndGet
         
     | 
| 
      
 215 
     | 
    
         
            +
                    else
         
     | 
| 
      
 216 
     | 
    
         
            +
                      raise "Unknown action #{action}"
         
     | 
| 
      
 217 
     | 
    
         
            +
                    end
         
     | 
| 
      
 218 
     | 
    
         
            +
             
     | 
| 
      
 219 
     | 
    
         
            +
                    if action == :success || action == :failure
         
     | 
| 
      
 220 
     | 
    
         
            +
                      if successes.get+failures.get == event_count
         
     | 
| 
      
 221 
     | 
    
         
            +
                        pending << :done
         
     | 
| 
      
 222 
     | 
    
         
            +
                      end
         
     | 
| 
      
 223 
     | 
    
         
            +
                    end
         
     | 
| 
      
 224 
     | 
    
         
            +
                  rescue => e
         
     | 
| 
      
 225 
     | 
    
         
            +
                    # This should never happen unless there's a flat out bug in the code
         
     | 
| 
      
 226 
     | 
    
         
            +
                    @logger.error("Error sending HTTP Request",
         
     | 
| 
      
 227 
     | 
    
         
            +
                      :class => e.class.name,
         
     | 
| 
      
 228 
     | 
    
         
            +
                      :message => e.message,
         
     | 
| 
      
 229 
     | 
    
         
            +
                      :backtrace => e.backtrace)
         
     | 
| 
      
 230 
     | 
    
         
            +
                    failures.incrementAndGet
         
     | 
| 
      
 231 
     | 
    
         
            +
                    raise e
         
     | 
| 
      
 232 
     | 
    
         
            +
                  end
         
     | 
| 
      
 233 
     | 
    
         
            +
                end
         
     | 
| 
      
 234 
     | 
    
         
            +
              rescue => e
         
     | 
| 
      
 235 
     | 
    
         
            +
                @logger.error("Error in http output loop",
         
     | 
| 
      
 236 
     | 
    
         
            +
                        :class => e.class.name,
         
     | 
| 
      
 237 
     | 
    
         
            +
                        :message => e.message,
         
     | 
| 
      
 238 
     | 
    
         
            +
                        :backtrace => e.backtrace)
         
     | 
| 
      
 239 
     | 
    
         
            +
                raise e
         
     | 
| 
      
 240 
     | 
    
         
            +
              end
         
     | 
| 
      
 241 
     | 
    
         
            +
             
     | 
| 
      
 242 
     | 
    
         
            +
              def sleep_for_attempt(attempt)
         
     | 
| 
      
 243 
     | 
    
         
            +
                sleep_for = attempt**2
         
     | 
| 
      
 244 
     | 
    
         
            +
                sleep_for = sleep_for <= 60 ? sleep_for : 60
         
     | 
| 
      
 245 
     | 
    
         
            +
                (sleep_for/2) + (rand(0..sleep_for)/2)
         
     | 
| 
      
 246 
     | 
    
         
            +
              end
         
     | 
| 
      
 247 
     | 
    
         
            +
             
     | 
| 
      
 248 
     | 
    
         
            +
              def send_event(event, attempt)
         
     | 
| 
      
 249 
     | 
    
         
            +
                body = event_body(event)
         
     | 
| 
      
 250 
     | 
    
         
            +
             
     | 
| 
      
 251 
     | 
    
         
            +
                # Send the request
         
     | 
| 
      
 252 
     | 
    
         
            +
                url = @is_batch ? @@url : event.sprintf(@@url)
         
     | 
| 
      
 253 
     | 
    
         
            +
                headers = @is_batch ? @headers : event_headers(event)
         
     | 
| 
      
 254 
     | 
    
         
            +
             
     | 
| 
      
 255 
     | 
    
         
            +
                # Compress the body and add appropriate header
         
     | 
| 
      
 256 
     | 
    
         
            +
                if @http_compression == true
         
     | 
| 
      
 257 
     | 
    
         
            +
                  headers["Content-Encoding"] = "gzip"
         
     | 
| 
      
 258 
     | 
    
         
            +
                  body = gzip(body)
         
     | 
| 
      
 259 
     | 
    
         
            +
                end
         
     | 
| 
      
 260 
     | 
    
         
            +
             
     | 
| 
      
 261 
     | 
    
         
            +
                # Create an async request
         
     | 
| 
      
 262 
     | 
    
         
            +
                response = client.send(@@http_method, url, :body => body, :headers => headers).call
         
     | 
| 
      
 263 
     | 
    
         
            +
             
     | 
| 
      
 264 
     | 
    
         
            +
                if !response_success?(response)
         
     | 
| 
      
 265 
     | 
    
         
            +
                  if retryable_response?(response)
         
     | 
| 
      
 266 
     | 
    
         
            +
                    log_retryable_response(response)
         
     | 
| 
      
 267 
     | 
    
         
            +
                    return :retry, event, attempt
         
     | 
| 
      
 268 
     | 
    
         
            +
                  else
         
     | 
| 
      
 269 
     | 
    
         
            +
                    log_error_response(response, url, event)
         
     | 
| 
      
 270 
     | 
    
         
            +
                    return :failure, event, attempt
         
     | 
| 
      
 271 
     | 
    
         
            +
                  end
         
     | 
| 
      
 272 
     | 
    
         
            +
                else
         
     | 
| 
      
 273 
     | 
    
         
            +
                  return :success, event, attempt
         
     | 
| 
      
 274 
     | 
    
         
            +
                end
         
     | 
| 
      
 275 
     | 
    
         
            +
             
     | 
| 
      
 276 
     | 
    
         
            +
              rescue => exception
         
     | 
| 
      
 277 
     | 
    
         
            +
                will_retry = retryable_exception?(exception)
         
     | 
| 
      
 278 
     | 
    
         
            +
                log_failure("Could not fetch URL",
         
     | 
| 
      
 279 
     | 
    
         
            +
                            :url => url,
         
     | 
| 
      
 280 
     | 
    
         
            +
                            :method => @@http_method,
         
     | 
| 
      
 281 
     | 
    
         
            +
                            :body => body,
         
     | 
| 
      
 282 
     | 
    
         
            +
                            :headers => headers,
         
     | 
| 
      
 283 
     | 
    
         
            +
                            :message => exception.message,
         
     | 
| 
      
 284 
     | 
    
         
            +
                            :class => exception.class.name,
         
     | 
| 
      
 285 
     | 
    
         
            +
                            :backtrace => exception.backtrace,
         
     | 
| 
      
 286 
     | 
    
         
            +
                            :will_retry => will_retry
         
     | 
| 
      
 287 
     | 
    
         
            +
                )
         
     | 
| 
      
 288 
     | 
    
         
            +
             
     | 
| 
      
 289 
     | 
    
         
            +
                if will_retry
         
     | 
| 
      
 290 
     | 
    
         
            +
                  return :retry, event, attempt
         
     | 
| 
      
 291 
     | 
    
         
            +
                else
         
     | 
| 
      
 292 
     | 
    
         
            +
                  return :failure, event, attempt
         
     | 
| 
      
 293 
     | 
    
         
            +
                end
         
     | 
| 
      
 294 
     | 
    
         
            +
              end
         
     | 
| 
      
 295 
     | 
    
         
            +
             
     | 
| 
      
 296 
     | 
    
         
            +
              def close
         
     | 
| 
      
 297 
     | 
    
         
            +
                @timer.cancel
         
     | 
| 
      
 298 
     | 
    
         
            +
                client.close
         
     | 
| 
      
 299 
     | 
    
         
            +
              end
         
     | 
| 
      
 300 
     | 
    
         
            +
             
     | 
| 
      
 301 
     | 
    
         
            +
              private
         
     | 
| 
      
 302 
     | 
    
         
            +
             
     | 
| 
      
 303 
     | 
    
         
            +
              def response_success?(response)
         
     | 
| 
      
 304 
     | 
    
         
            +
                code = response.code
         
     | 
| 
      
 305 
     | 
    
         
            +
                return true if @ignorable_codes && @ignorable_codes.include?(code)
         
     | 
| 
      
 306 
     | 
    
         
            +
                return code >= 200 && code <= 299
         
     | 
| 
      
 307 
     | 
    
         
            +
              end
         
     | 
| 
      
 308 
     | 
    
         
            +
             
     | 
| 
      
 309 
     | 
    
         
            +
              def retryable_response?(response)
         
     | 
| 
      
 310 
     | 
    
         
            +
                @retryable_codes && @retryable_codes.include?(response.code)
         
     | 
| 
      
 311 
     | 
    
         
            +
              end
         
     | 
| 
      
 312 
     | 
    
         
            +
             
     | 
| 
      
 313 
     | 
    
         
            +
              def retryable_exception?(exception)
         
     | 
| 
      
 314 
     | 
    
         
            +
                RETRYABLE_MANTICORE_EXCEPTIONS.any? {|me| exception.is_a?(me) }
         
     | 
| 
      
 315 
     | 
    
         
            +
              end
         
     | 
| 
      
 316 
     | 
    
         
            +
             
     | 
| 
      
 317 
     | 
    
         
            +
              # This is split into a separate method mostly to help testing
         
     | 
| 
      
 318 
     | 
    
         
            +
              def log_failure(message, opts)
         
     | 
| 
      
 319 
     | 
    
         
            +
                @logger.error("[HTTP Output Failure] #{message}", opts)
         
     | 
| 
      
 320 
     | 
    
         
            +
              end
         
     | 
| 
      
 321 
     | 
    
         
            +
             
     | 
| 
      
 322 
     | 
    
         
            +
              # Format the HTTP body
         
     | 
| 
      
 323 
     | 
    
         
            +
              def event_body(event)
         
     | 
| 
      
 324 
     | 
    
         
            +
                # TODO: Create an HTTP post data codec, use that here
         
     | 
| 
      
 325 
     | 
    
         
            +
                if @format == "json"
         
     | 
| 
      
 326 
     | 
    
         
            +
                  LogStash::Json.dump(map_event(event))
         
     | 
| 
      
 327 
     | 
    
         
            +
                elsif @format == "message"
         
     | 
| 
      
 328 
     | 
    
         
            +
                  event.sprintf(@message)
         
     | 
| 
      
 329 
     | 
    
         
            +
                else
         
     | 
| 
      
 330 
     | 
    
         
            +
                  encode(map_event(event))
         
     | 
| 
      
 331 
     | 
    
         
            +
                end
         
     | 
| 
      
 332 
     | 
    
         
            +
              end
         
     | 
| 
      
 333 
     | 
    
         
            +
             
     | 
| 
      
 334 
     | 
    
         
            +
              # gzip data
         
     | 
| 
      
 335 
     | 
    
         
            +
              def gzip(data)
         
     | 
| 
      
 336 
     | 
    
         
            +
                gz = StringIO.new
         
     | 
| 
      
 337 
     | 
    
         
            +
                gz.set_encoding("BINARY")
         
     | 
| 
      
 338 
     | 
    
         
            +
                z = Zlib::GzipWriter.new(gz)
         
     | 
| 
      
 339 
     | 
    
         
            +
                z.write(data)
         
     | 
| 
      
 340 
     | 
    
         
            +
                z.close
         
     | 
| 
      
 341 
     | 
    
         
            +
                gz.string
         
     | 
| 
      
 342 
     | 
    
         
            +
              end
         
     | 
| 
      
 343 
     | 
    
         
            +
             
     | 
| 
      
 344 
     | 
    
         
            +
              def convert_mapping(mapping, event)
         
     | 
| 
      
 345 
     | 
    
         
            +
                if mapping.is_a?(Hash)
         
     | 
| 
      
 346 
     | 
    
         
            +
                  mapping.reduce({}) do |acc, kv|
         
     | 
| 
      
 347 
     | 
    
         
            +
                    k, v = kv
         
     | 
| 
      
 348 
     | 
    
         
            +
                    acc[k] = convert_mapping(v, event)
         
     | 
| 
      
 349 
     | 
    
         
            +
                    acc
         
     | 
| 
      
 350 
     | 
    
         
            +
                  end
         
     | 
| 
      
 351 
     | 
    
         
            +
                elsif mapping.is_a?(Array)
         
     | 
| 
      
 352 
     | 
    
         
            +
                  mapping.map { |elem| convert_mapping(elem, event) }
         
     | 
| 
      
 353 
     | 
    
         
            +
                else
         
     | 
| 
      
 354 
     | 
    
         
            +
                  event.sprintf(mapping)
         
     | 
| 
      
 355 
     | 
    
         
            +
                end
         
     | 
| 
      
 356 
     | 
    
         
            +
              end
         
     | 
| 
      
 357 
     | 
    
         
            +
             
     | 
| 
      
 358 
     | 
    
         
            +
              def map_event(event)
         
     | 
| 
      
 359 
     | 
    
         
            +
                if @mapping
         
     | 
| 
      
 360 
     | 
    
         
            +
                  convert_mapping(@mapping, event)
         
     | 
| 
      
 361 
     | 
    
         
            +
                else
         
     | 
| 
      
 362 
     | 
    
         
            +
                  event.to_hash
         
     | 
| 
      
 363 
     | 
    
         
            +
                end
         
     | 
| 
      
 364 
     | 
    
         
            +
              end
         
     | 
| 
      
 365 
     | 
    
         
            +
             
     | 
| 
      
 366 
     | 
    
         
            +
              def event_headers(event)
         
     | 
| 
      
 367 
     | 
    
         
            +
                custom_headers(event) || {}
         
     | 
| 
      
 368 
     | 
    
         
            +
              end
         
     | 
| 
      
 369 
     | 
    
         
            +
             
     | 
| 
      
 370 
     | 
    
         
            +
              def custom_headers(event)
         
     | 
| 
      
 371 
     | 
    
         
            +
                return nil unless @headers
         
     | 
| 
      
 372 
     | 
    
         
            +
             
     | 
| 
      
 373 
     | 
    
         
            +
                @headers.reduce({}) do |acc,kv|
         
     | 
| 
      
 374 
     | 
    
         
            +
                  k,v = kv
         
     | 
| 
      
 375 
     | 
    
         
            +
                  acc[k] = event.sprintf(v)
         
     | 
| 
      
 376 
     | 
    
         
            +
                  acc
         
     | 
| 
      
 377 
     | 
    
         
            +
                end
         
     | 
| 
      
 378 
     | 
    
         
            +
              end
         
     | 
| 
      
 379 
     | 
    
         
            +
             
     | 
| 
      
 380 
     | 
    
         
            +
              #TODO Extract this to a codec
         
     | 
| 
      
 381 
     | 
    
         
            +
              def encode(hash)
         
     | 
| 
      
 382 
     | 
    
         
            +
                return hash.collect do |key, value|
         
     | 
| 
      
 383 
     | 
    
         
            +
                  CGI.escape(key) + "=" + CGI.escape(value.to_s)
         
     | 
| 
      
 384 
     | 
    
         
            +
                end.join("&")
         
     | 
| 
      
 385 
     | 
    
         
            +
              end
         
     | 
| 
      
 386 
     | 
    
         
            +
             
     | 
| 
      
 387 
     | 
    
         
            +
             
     | 
| 
      
 388 
     | 
    
         
            +
              def validate_format!
         
     | 
| 
      
 389 
     | 
    
         
            +
                if @format == "message"
         
     | 
| 
      
 390 
     | 
    
         
            +
                  if @message.nil?
         
     | 
| 
      
 391 
     | 
    
         
            +
                    raise "message must be set if message format is used"
         
     | 
| 
      
 392 
     | 
    
         
            +
                  end
         
     | 
| 
      
 393 
     | 
    
         
            +
             
     | 
| 
      
 394 
     | 
    
         
            +
                  unless @mapping.nil?
         
     | 
| 
      
 395 
     | 
    
         
            +
                    @logger.warn "mapping is not supported and will be ignored if message format is used"
         
     | 
| 
      
 396 
     | 
    
         
            +
                  end
         
     | 
| 
      
 397 
     | 
    
         
            +
                end
         
     | 
| 
      
 398 
     | 
    
         
            +
              end
         
     | 
| 
      
 399 
     | 
    
         
            +
             
     | 
| 
      
 400 
     | 
    
         
            +
              def validate_api_required!
         
     | 
| 
      
 401 
     | 
    
         
            +
                if @api_key.nil?
         
     | 
| 
      
 402 
     | 
    
         
            +
                  raise "api_key must be set"
         
     | 
| 
      
 403 
     | 
    
         
            +
                end
         
     | 
| 
      
 404 
     | 
    
         
            +
             
     | 
| 
      
 405 
     | 
    
         
            +
                if @app_version_id.nil?
         
     | 
| 
      
 406 
     | 
    
         
            +
                  raise "app_version_id must be set"
         
     | 
| 
      
 407 
     | 
    
         
            +
                end
         
     | 
| 
      
 408 
     | 
    
         
            +
             
     | 
| 
      
 409 
     | 
    
         
            +
                if @beacon_version_id.nil?
         
     | 
| 
      
 410 
     | 
    
         
            +
                  raise "beacon_version_id must be set"
         
     | 
| 
      
 411 
     | 
    
         
            +
                end
         
     | 
| 
      
 412 
     | 
    
         
            +
             
     | 
| 
      
 413 
     | 
    
         
            +
                if @beacon_message_type.nil?
         
     | 
| 
      
 414 
     | 
    
         
            +
                  raise "beacon_message_type must be set"
         
     | 
| 
      
 415 
     | 
    
         
            +
                end
         
     | 
| 
      
 416 
     | 
    
         
            +
             
     | 
| 
      
 417 
     | 
    
         
            +
              #  # unless @mapping.nil?
         
     | 
| 
      
 418 
     | 
    
         
            +
              #  #   @logger.warn "mapping is not supported and will be ignored if message format is used"
         
     | 
| 
      
 419 
     | 
    
         
            +
              #  # end
         
     | 
| 
      
 420 
     | 
    
         
            +
              end
         
     | 
| 
      
 421 
     | 
    
         
            +
             
     | 
| 
      
 422 
     | 
    
         
            +
            end # class LogStash::Outputs::HarborBeacon
         
     | 
| 
         @@ -0,0 +1,30 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Gem::Specification.new do |s|
         
     | 
| 
      
 2 
     | 
    
         
            +
              s.name          = 'logstash-output-harbor_beacon'
         
     | 
| 
      
 3 
     | 
    
         
            +
              s.version       = '0.3.0'
         
     | 
| 
      
 4 
     | 
    
         
            +
              s.licenses      = ['Apache-2.0']
         
     | 
| 
      
 5 
     | 
    
         
            +
              s.summary       = 'Emit output messages (beacons) to Harbor Beacon service.'
         
     | 
| 
      
 6 
     | 
    
         
            +
              s.description   = 'This gem is a Logstash output plugin to be installed on top of the Logstash'\
         
     | 
| 
      
 7 
     | 
    
         
            +
                                'core  pipeline using $LS_HOME/bin/logstash-plugin install gemname.'\
         
     | 
| 
      
 8 
     | 
    
         
            +
                                'This gem is not a stand-alone program.'
         
     | 
| 
      
 9 
     | 
    
         
            +
              s.homepage      = 'https://docs.hrbr.io/'
         
     | 
| 
      
 10 
     | 
    
         
            +
              s.authors       = ['Harbor']
         
     | 
| 
      
 11 
     | 
    
         
            +
              s.email         = 'info@hrbr.io'
         
     | 
| 
      
 12 
     | 
    
         
            +
              s.require_paths = ['lib']
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              # Files
         
     | 
| 
      
 15 
     | 
    
         
            +
              s.files = Dir['lib/**/*','spec/**/*','vendor/**/*','*.gemspec','*.md','CONTRIBUTORS','Gemfile','LICENSE','NOTICE.TXT']
         
     | 
| 
      
 16 
     | 
    
         
            +
               # Tests
         
     | 
| 
      
 17 
     | 
    
         
            +
              s.test_files = s.files.grep(%r{^(test|spec|features)/})
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              # Special flag to let us know this is actually a logstash plugin
         
     | 
| 
      
 20 
     | 
    
         
            +
              s.metadata = { "logstash_plugin" => "true", "logstash_group" => "output" }
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              # Gem dependencies
         
     | 
| 
      
 23 
     | 
    
         
            +
              s.add_runtime_dependency "logstash-core-plugin-api", "~> 2.0"
         
     | 
| 
      
 24 
     | 
    
         
            +
              s.add_runtime_dependency "logstash-mixin-http_client", ">= 6.0.0", "< 7.0.0"
         
     | 
| 
      
 25 
     | 
    
         
            +
              s.add_runtime_dependency "logstash-codec-plain", "~> 3.0"
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              s.add_development_dependency "logstash-devutils", "~> 1.3"
         
     | 
| 
      
 28 
     | 
    
         
            +
              # s.add_development_dependency 'sinatra', '~> 1.4'
         
     | 
| 
      
 29 
     | 
    
         
            +
              # s.add_development_dependency 'webrick', '~> 1.4'
         
     | 
| 
      
 30 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,35 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "logstash/devutils/rspec/spec_helper"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "logstash/outputs/harbor_beacon"
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "logstash/codecs/plain"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            class LogStash::Outputs::HarborBeacon
         
     | 
| 
      
 7 
     | 
    
         
            +
              attr_writer :agent
         
     | 
| 
      
 8 
     | 
    
         
            +
              attr_reader :request_tokens
         
     | 
| 
      
 9 
     | 
    
         
            +
            end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            describe LogStash::Outputs::HarborBeacon do
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              let(:sample_event) { LogStash::Event.new({"message" => "hi"}) }
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              let(:api_key) { "ABC" }
         
     | 
| 
      
 16 
     | 
    
         
            +
              let(:app_version_id) { "DEF" }
         
     | 
| 
      
 17 
     | 
    
         
            +
              let(:beacon_version_id) { "GHI" }
         
     | 
| 
      
 18 
     | 
    
         
            +
              let(:beacon_message_type) { "JKL" }
         
     | 
| 
      
 19 
     | 
    
         
            +
              let(:sample_config) { {"api_key" => api_key, "app_version_id" => app_version_id, "beacon_version_id" => beacon_version_id, "beacon_message_type" => beacon_message_type } }
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              let(:output) { LogStash::Outputs::HarborBeacon.new(sample_config) }
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              before do
         
     | 
| 
      
 24 
     | 
    
         
            +
                  output.register
         
     | 
| 
      
 25 
     | 
    
         
            +
              end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
              describe "receive message" do
         
     | 
| 
      
 28 
     | 
    
         
            +
                subject { output.receive(sample_event) }
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                it "returns a string" do
         
     | 
| 
      
 31 
     | 
    
         
            +
                  #expect(subject).to eq("Event received")
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,118 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: logstash-output-harbor_beacon
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version
         
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.3.0
         
     | 
| 
      
 5 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 6 
     | 
    
         
            +
            authors:
         
     | 
| 
      
 7 
     | 
    
         
            +
            - Harbor
         
     | 
| 
      
 8 
     | 
    
         
            +
            autorequire:
         
     | 
| 
      
 9 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 10 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2018-12-21 00:00:00.000000000 Z
         
     | 
| 
      
 12 
     | 
    
         
            +
            dependencies:
         
     | 
| 
      
 13 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 14 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 15 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 16 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 17 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 18 
     | 
    
         
            +
                    version: '2.0'
         
     | 
| 
      
 19 
     | 
    
         
            +
              name: logstash-core-plugin-api
         
     | 
| 
      
 20 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 21 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 22 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 23 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 24 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 25 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 26 
     | 
    
         
            +
                    version: '2.0'
         
     | 
| 
      
 27 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 28 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 29 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 30 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 31 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 32 
     | 
    
         
            +
                    version: 6.0.0
         
     | 
| 
      
 33 
     | 
    
         
            +
                - - "<"
         
     | 
| 
      
 34 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 35 
     | 
    
         
            +
                    version: 7.0.0
         
     | 
| 
      
 36 
     | 
    
         
            +
              name: logstash-mixin-http_client
         
     | 
| 
      
 37 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 38 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 39 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 40 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 41 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 42 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 43 
     | 
    
         
            +
                    version: 6.0.0
         
     | 
| 
      
 44 
     | 
    
         
            +
                - - "<"
         
     | 
| 
      
 45 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 46 
     | 
    
         
            +
                    version: 7.0.0
         
     | 
| 
      
 47 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 48 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 49 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 50 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 51 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 52 
     | 
    
         
            +
                    version: '3.0'
         
     | 
| 
      
 53 
     | 
    
         
            +
              name: logstash-codec-plain
         
     | 
| 
      
 54 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 55 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 56 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 57 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 58 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 59 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 60 
     | 
    
         
            +
                    version: '3.0'
         
     | 
| 
      
 61 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency
         
     | 
| 
      
 62 
     | 
    
         
            +
              requirement: !ruby/object:Gem::Requirement
         
     | 
| 
      
 63 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 64 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 65 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 66 
     | 
    
         
            +
                    version: '1.3'
         
     | 
| 
      
 67 
     | 
    
         
            +
              name: logstash-devutils
         
     | 
| 
      
 68 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 69 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 70 
     | 
    
         
            +
              version_requirements: !ruby/object:Gem::Requirement
         
     | 
| 
      
 71 
     | 
    
         
            +
                requirements:
         
     | 
| 
      
 72 
     | 
    
         
            +
                - - "~>"
         
     | 
| 
      
 73 
     | 
    
         
            +
                  - !ruby/object:Gem::Version
         
     | 
| 
      
 74 
     | 
    
         
            +
                    version: '1.3'
         
     | 
| 
      
 75 
     | 
    
         
            +
            description: This gem is a Logstash output plugin to be installed on top of the Logstashcore  pipeline
         
     | 
| 
      
 76 
     | 
    
         
            +
              using $LS_HOME/bin/logstash-plugin install gemname.This gem is not a stand-alone
         
     | 
| 
      
 77 
     | 
    
         
            +
              program.
         
     | 
| 
      
 78 
     | 
    
         
            +
            email: info@hrbr.io
         
     | 
| 
      
 79 
     | 
    
         
            +
            executables: []
         
     | 
| 
      
 80 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 81 
     | 
    
         
            +
            extra_rdoc_files: []
         
     | 
| 
      
 82 
     | 
    
         
            +
            files:
         
     | 
| 
      
 83 
     | 
    
         
            +
            - CHANGELOG.md
         
     | 
| 
      
 84 
     | 
    
         
            +
            - CONTRIBUTORS
         
     | 
| 
      
 85 
     | 
    
         
            +
            - Gemfile
         
     | 
| 
      
 86 
     | 
    
         
            +
            - LICENSE
         
     | 
| 
      
 87 
     | 
    
         
            +
            - README.md
         
     | 
| 
      
 88 
     | 
    
         
            +
            - lib/logstash/outputs/harbor_beacon.rb
         
     | 
| 
      
 89 
     | 
    
         
            +
            - logstash-output-harbor_beacon.gemspec
         
     | 
| 
      
 90 
     | 
    
         
            +
            - spec/outputs/harbor_beacon_spec.rb
         
     | 
| 
      
 91 
     | 
    
         
            +
            homepage: https://docs.hrbr.io/
         
     | 
| 
      
 92 
     | 
    
         
            +
            licenses:
         
     | 
| 
      
 93 
     | 
    
         
            +
            - Apache-2.0
         
     | 
| 
      
 94 
     | 
    
         
            +
            metadata:
         
     | 
| 
      
 95 
     | 
    
         
            +
              logstash_plugin: 'true'
         
     | 
| 
      
 96 
     | 
    
         
            +
              logstash_group: output
         
     | 
| 
      
 97 
     | 
    
         
            +
            post_install_message:
         
     | 
| 
      
 98 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 99 
     | 
    
         
            +
            require_paths:
         
     | 
| 
      
 100 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 101 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 102 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 103 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 104 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 105 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 106 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         
     | 
| 
      
 107 
     | 
    
         
            +
              requirements:
         
     | 
| 
      
 108 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 109 
     | 
    
         
            +
                - !ruby/object:Gem::Version
         
     | 
| 
      
 110 
     | 
    
         
            +
                  version: '0'
         
     | 
| 
      
 111 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 112 
     | 
    
         
            +
            rubyforge_project:
         
     | 
| 
      
 113 
     | 
    
         
            +
            rubygems_version: 2.7.6
         
     | 
| 
      
 114 
     | 
    
         
            +
            signing_key:
         
     | 
| 
      
 115 
     | 
    
         
            +
            specification_version: 4
         
     | 
| 
      
 116 
     | 
    
         
            +
            summary: Emit output messages (beacons) to Harbor Beacon service.
         
     | 
| 
      
 117 
     | 
    
         
            +
            test_files:
         
     | 
| 
      
 118 
     | 
    
         
            +
            - spec/outputs/harbor_beacon_spec.rb
         
     |