waterdrop 2.0.5 → 2.2.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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.github/workflows/ci.yml +5 -4
- data/.ruby-version +1 -1
- data/CHANGELOG.md +25 -0
- data/Gemfile +0 -2
- data/Gemfile.lock +23 -26
- data/README.md +40 -12
- data/config/errors.yml +1 -0
- data/lib/{water_drop → waterdrop}/config.rb +5 -14
- data/lib/waterdrop/contracts/base.rb +23 -0
- data/lib/{water_drop → waterdrop}/contracts/config.rb +12 -8
- data/lib/{water_drop → waterdrop}/contracts/message.rb +2 -4
- data/lib/{water_drop → waterdrop}/contracts.rb +0 -0
- data/lib/{water_drop → waterdrop}/errors.rb +0 -0
- data/lib/{water_drop → waterdrop}/instrumentation/callbacks/delivery.rb +0 -0
- data/lib/{water_drop → waterdrop}/instrumentation/callbacks/error.rb +4 -3
- data/lib/{water_drop → waterdrop}/instrumentation/callbacks/statistics.rb +0 -0
- data/lib/{water_drop → waterdrop}/instrumentation/callbacks/statistics_decorator.rb +0 -0
- data/lib/{water_drop → waterdrop}/instrumentation/callbacks_manager.rb +5 -1
- data/lib/{water_drop → waterdrop}/instrumentation/monitor.rb +1 -3
- data/lib/{water_drop → waterdrop}/instrumentation/stdout_listener.rb +15 -24
- data/lib/waterdrop/instrumentation/vendors/datadog/dashboard.json +1 -0
- data/lib/waterdrop/instrumentation/vendors/datadog/listener.rb +197 -0
- data/lib/{water_drop → waterdrop}/instrumentation.rb +0 -1
- data/lib/{water_drop → waterdrop}/patches/rdkafka/bindings.rb +0 -0
- data/lib/{water_drop → waterdrop}/patches/rdkafka/producer.rb +0 -0
- data/lib/{water_drop → waterdrop}/producer/async.rb +2 -2
- data/lib/{water_drop → waterdrop}/producer/buffer.rb +15 -8
- data/lib/{water_drop → waterdrop}/producer/builder.rb +0 -0
- data/lib/{water_drop → waterdrop}/producer/dummy_client.rb +0 -0
- data/lib/{water_drop → waterdrop}/producer/status.rb +0 -0
- data/lib/{water_drop → waterdrop}/producer/sync.rb +2 -2
- data/lib/{water_drop → waterdrop}/producer.rb +2 -8
- data/lib/{water_drop → waterdrop}/version.rb +1 -1
- data/lib/waterdrop.rb +35 -2
- data/waterdrop.gemspec +8 -3
- data.tar.gz.sig +0 -0
- metadata +34 -30
- metadata.gz.sig +0 -0
- data/lib/water_drop.rb +0 -36
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: db36e5203312e482d0d98a83d3bfb4fd5e274c342e5b3c63829d6bb5f616b52e
         | 
| 4 | 
            +
              data.tar.gz: 6e49baf2f5ebd33aded769899fc0eb7f3c130ac97d9a6156fd491d000fd04306
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 426d9f910ca5e24a7e86db1ceec672f895186ace830554708e8741d21bb83f929c9278ed5018bff6468b354523ac7cc790cba0b91b8c13dd2bb28e58f8a52dc6
         | 
| 7 | 
            +
              data.tar.gz: b3871df6868ce287daf0765f522031cfdd566b96d0e5f8bf3ca1cd9724a7a68d5b3e4e1a33e0bdcc9b65063150d48cfc213e19348d19a6268a309b1c69dcab50
         | 
    
        checksums.yaml.gz.sig
    CHANGED
    
    | Binary file | 
    
        data/.github/workflows/ci.yml
    CHANGED
    
    | @@ -1,5 +1,7 @@ | |
| 1 1 | 
             
            name: ci
         | 
| 2 2 |  | 
| 3 | 
            +
            concurrency: ci-${{ github.ref }}
         | 
| 4 | 
            +
             | 
| 3 5 | 
             
            on:
         | 
| 4 6 | 
             
              pull_request:
         | 
| 5 7 | 
             
              push:
         | 
| @@ -14,12 +16,11 @@ jobs: | |
| 14 16 | 
             
                  fail-fast: false
         | 
| 15 17 | 
             
                  matrix:
         | 
| 16 18 | 
             
                    ruby:
         | 
| 19 | 
            +
                      - '3.1'
         | 
| 17 20 | 
             
                      - '3.0'
         | 
| 18 21 | 
             
                      - '2.7'
         | 
| 19 | 
            -
                      - '2.6'
         | 
| 20 | 
            -
                      - 'jruby-9.3.1.0'
         | 
| 21 22 | 
             
                    include:
         | 
| 22 | 
            -
                      - ruby: '3. | 
| 23 | 
            +
                      - ruby: '3.1'
         | 
| 23 24 | 
             
                        coverage: 'true'
         | 
| 24 25 | 
             
                steps:
         | 
| 25 26 | 
             
                  - uses: actions/checkout@v2
         | 
| @@ -59,7 +60,7 @@ jobs: | |
| 59 60 | 
             
                  - name: Set up Ruby
         | 
| 60 61 | 
             
                    uses: ruby/setup-ruby@v1
         | 
| 61 62 | 
             
                    with:
         | 
| 62 | 
            -
                      ruby-version: 3. | 
| 63 | 
            +
                      ruby-version: 3.1
         | 
| 63 64 | 
             
                  - name: Install latest bundler
         | 
| 64 65 | 
             
                    run: gem install bundler --no-document
         | 
| 65 66 | 
             
                  - name: Install Diffend plugin
         | 
    
        data/.ruby-version
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            3.0 | 
| 1 | 
            +
            3.1.0
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,5 +1,30 @@ | |
| 1 1 | 
             
            # WaterDrop changelog
         | 
| 2 2 |  | 
| 3 | 
            +
            ## 2.2.0 (2022-02-18)
         | 
| 4 | 
            +
            - Add Datadog listener for metrics + errors publishing
         | 
| 5 | 
            +
            - Add Datadog example dashboard template
         | 
| 6 | 
            +
            - Update Readme to show Dd instrumentation usage
         | 
| 7 | 
            +
            - Align the directory namespace convention with gem name (waterdrop => WaterDrop)
         | 
| 8 | 
            +
            - Introduce a common base for validation contracts
         | 
| 9 | 
            +
            - Drop CI support for ruby 2.6
         | 
| 10 | 
            +
            - Require all `kafka` settings to have symbol keys (compatibility with Karafka 2.0 and rdkafka)
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            ## 2.1.0 (2022-01-03)
         | 
| 13 | 
            +
            - Ruby 3.1 support
         | 
| 14 | 
            +
            - Change the error notification key from `error.emitted` to `error.occurred`.
         | 
| 15 | 
            +
            - Normalize error tracking and make all the places publish errors into the same notification endpoint (`error.occurred`).
         | 
| 16 | 
            +
            - Start semantic versioning WaterDrop.
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            ## 2.0.7 (2021-12-03)
         | 
| 19 | 
            +
            - Source code metadata url added to the gemspec
         | 
| 20 | 
            +
            - Replace `:producer` with `:producer_id` in events and update `StdoutListener` accordingly. This change aligns all the events in terms of not publishing the whole producer object in the events.
         | 
| 21 | 
            +
            - Add `error.emitted` into the `StdoutListener`.
         | 
| 22 | 
            +
            - Enable `StdoutLogger` in specs for additional integration coverage.
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            ## 2.0.6 (2021-12-01)
         | 
| 25 | 
            +
            - #218 - Fixes a case, where dispatch of callbacks the same moment a new producer was created could cause a concurrency issue in the manager.
         | 
| 26 | 
            +
            - Fix some unstable specs.
         | 
| 27 | 
            +
             | 
| 3 28 | 
             
            ## 2.0.5 (2021-11-28)
         | 
| 4 29 |  | 
| 5 30 | 
             
            ### Bug fixes
         | 
    
        data/Gemfile
    CHANGED
    
    
    
        data/Gemfile.lock
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            PATH
         | 
| 2 2 | 
             
              remote: .
         | 
| 3 3 | 
             
              specs:
         | 
| 4 | 
            -
                waterdrop (2.0 | 
| 4 | 
            +
                waterdrop (2.2.0)
         | 
| 5 5 | 
             
                  concurrent-ruby (>= 1.1)
         | 
| 6 6 | 
             
                  dry-configurable (~> 0.13)
         | 
| 7 7 | 
             
                  dry-monitor (~> 0.5)
         | 
| @@ -12,17 +12,16 @@ PATH | |
| 12 12 | 
             
            GEM
         | 
| 13 13 | 
             
              remote: https://rubygems.org/
         | 
| 14 14 | 
             
              specs:
         | 
| 15 | 
            -
                activesupport ( | 
| 15 | 
            +
                activesupport (7.0.2)
         | 
| 16 16 | 
             
                  concurrent-ruby (~> 1.0, >= 1.0.2)
         | 
| 17 17 | 
             
                  i18n (>= 1.6, < 2)
         | 
| 18 18 | 
             
                  minitest (>= 5.1)
         | 
| 19 19 | 
             
                  tzinfo (~> 2.0)
         | 
| 20 | 
            -
                  zeitwerk (~> 2.3)
         | 
| 21 20 | 
             
                byebug (11.1.3)
         | 
| 22 21 | 
             
                concurrent-ruby (1.1.9)
         | 
| 23 | 
            -
                diff-lcs (1. | 
| 22 | 
            +
                diff-lcs (1.5.0)
         | 
| 24 23 | 
             
                docile (1.4.0)
         | 
| 25 | 
            -
                dry-configurable (0. | 
| 24 | 
            +
                dry-configurable (0.14.0)
         | 
| 26 25 | 
             
                  concurrent-ruby (~> 1.0)
         | 
| 27 26 | 
             
                  dry-core (~> 0.6)
         | 
| 28 27 | 
             
                dry-container (0.9.0)
         | 
| @@ -34,7 +33,7 @@ GEM | |
| 34 33 | 
             
                  concurrent-ruby (~> 1.0)
         | 
| 35 34 | 
             
                  dry-core (~> 0.5, >= 0.5)
         | 
| 36 35 | 
             
                dry-inflector (0.2.1)
         | 
| 37 | 
            -
                dry-initializer (3. | 
| 36 | 
            +
                dry-initializer (3.1.1)
         | 
| 38 37 | 
             
                dry-logic (1.2.0)
         | 
| 39 38 | 
             
                  concurrent-ruby (~> 1.0)
         | 
| 40 39 | 
             
                  dry-core (~> 0.5, >= 0.5)
         | 
| @@ -63,29 +62,29 @@ GEM | |
| 63 62 | 
             
                  dry-schema (~> 1.8, >= 1.8.0)
         | 
| 64 63 | 
             
                factory_bot (6.2.0)
         | 
| 65 64 | 
             
                  activesupport (>= 5.0.0)
         | 
| 66 | 
            -
                ffi (1.15. | 
| 67 | 
            -
                i18n (1. | 
| 65 | 
            +
                ffi (1.15.5)
         | 
| 66 | 
            +
                i18n (1.9.1)
         | 
| 68 67 | 
             
                  concurrent-ruby (~> 1.0)
         | 
| 69 68 | 
             
                mini_portile2 (2.7.1)
         | 
| 70 | 
            -
                minitest (5. | 
| 69 | 
            +
                minitest (5.15.0)
         | 
| 71 70 | 
             
                rake (13.0.6)
         | 
| 72 | 
            -
                rdkafka (0.11. | 
| 71 | 
            +
                rdkafka (0.11.1)
         | 
| 73 72 | 
             
                  ffi (~> 1.15)
         | 
| 74 | 
            -
                  mini_portile2 (~> 2. | 
| 73 | 
            +
                  mini_portile2 (~> 2.6)
         | 
| 75 74 | 
             
                  rake (> 12)
         | 
| 76 | 
            -
                rspec (3. | 
| 77 | 
            -
                  rspec-core (~> 3. | 
| 78 | 
            -
                  rspec-expectations (~> 3. | 
| 79 | 
            -
                  rspec-mocks (~> 3. | 
| 80 | 
            -
                rspec-core (3. | 
| 81 | 
            -
                  rspec-support (~> 3. | 
| 82 | 
            -
                rspec-expectations (3. | 
| 75 | 
            +
                rspec (3.11.0)
         | 
| 76 | 
            +
                  rspec-core (~> 3.11.0)
         | 
| 77 | 
            +
                  rspec-expectations (~> 3.11.0)
         | 
| 78 | 
            +
                  rspec-mocks (~> 3.11.0)
         | 
| 79 | 
            +
                rspec-core (3.11.0)
         | 
| 80 | 
            +
                  rspec-support (~> 3.11.0)
         | 
| 81 | 
            +
                rspec-expectations (3.11.0)
         | 
| 83 82 | 
             
                  diff-lcs (>= 1.2.0, < 2.0)
         | 
| 84 | 
            -
                  rspec-support (~> 3. | 
| 85 | 
            -
                rspec-mocks (3. | 
| 83 | 
            +
                  rspec-support (~> 3.11.0)
         | 
| 84 | 
            +
                rspec-mocks (3.11.0)
         | 
| 86 85 | 
             
                  diff-lcs (>= 1.2.0, < 2.0)
         | 
| 87 | 
            -
                  rspec-support (~> 3. | 
| 88 | 
            -
                rspec-support (3. | 
| 86 | 
            +
                  rspec-support (~> 3.11.0)
         | 
| 87 | 
            +
                rspec-support (3.11.0)
         | 
| 89 88 | 
             
                simplecov (0.21.2)
         | 
| 90 89 | 
             
                  docile (~> 1.1)
         | 
| 91 90 | 
             
                  simplecov-html (~> 0.11)
         | 
| @@ -94,19 +93,17 @@ GEM | |
| 94 93 | 
             
                simplecov_json_formatter (0.1.3)
         | 
| 95 94 | 
             
                tzinfo (2.0.4)
         | 
| 96 95 | 
             
                  concurrent-ruby (~> 1.0)
         | 
| 97 | 
            -
                zeitwerk (2.5. | 
| 96 | 
            +
                zeitwerk (2.5.4)
         | 
| 98 97 |  | 
| 99 98 | 
             
            PLATFORMS
         | 
| 100 | 
            -
              x86_64-darwin
         | 
| 101 99 | 
             
              x86_64-linux
         | 
| 102 100 |  | 
| 103 101 | 
             
            DEPENDENCIES
         | 
| 104 102 | 
             
              byebug
         | 
| 105 103 | 
             
              factory_bot
         | 
| 106 | 
            -
              rdkafka
         | 
| 107 104 | 
             
              rspec
         | 
| 108 105 | 
             
              simplecov
         | 
| 109 106 | 
             
              waterdrop!
         | 
| 110 107 |  | 
| 111 108 | 
             
            BUNDLED WITH
         | 
| 112 | 
            -
               2. | 
| 109 | 
            +
               2.3.7
         | 
    
        data/README.md
    CHANGED
    
    | @@ -2,7 +2,7 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            **Note**: Documentation presented here refers to WaterDrop `2.0.0`.
         | 
| 4 4 |  | 
| 5 | 
            -
            WaterDrop `2.0` does **not** work with Karafka `1.*` and aims to either work as a standalone producer outside of Karafka `1.*` ecosystem or as a part of  | 
| 5 | 
            +
            WaterDrop `2.0` does **not** work with Karafka `1.*` and aims to either work as a standalone producer outside of Karafka `1.*` ecosystem or as a part of soon to be released Karafka `2.0.*`.
         | 
| 6 6 |  | 
| 7 7 | 
             
            Please refer to [this](https://github.com/karafka/waterdrop/tree/1.4) branch and its documentation for details about WaterDrop `1.*` usage.
         | 
| 8 8 |  | 
| @@ -36,16 +36,13 @@ It: | |
| 36 36 | 
             
            - [Instrumentation](#instrumentation)
         | 
| 37 37 | 
             
              * [Usage statistics](#usage-statistics)
         | 
| 38 38 | 
             
              * [Error notifications](#error-notifications)
         | 
| 39 | 
            +
              * [Datadog and StatsD integration](#datadog-and-statsd-integration)
         | 
| 39 40 | 
             
              * [Forking and potential memory problems](#forking-and-potential-memory-problems)
         | 
| 40 41 | 
             
            - [Note on contributions](#note-on-contributions)
         | 
| 41 42 |  | 
| 42 43 | 
             
            ## Installation
         | 
| 43 44 |  | 
| 44 | 
            -
             | 
| 45 | 
            -
            gem install waterdrop
         | 
| 46 | 
            -
            ```
         | 
| 47 | 
            -
             | 
| 48 | 
            -
            or add this to your Gemfile:
         | 
| 45 | 
            +
            Add this to your Gemfile:
         | 
| 49 46 |  | 
| 50 47 | 
             
            ```ruby
         | 
| 51 48 | 
             
            gem 'waterdrop'
         | 
| @@ -201,7 +198,7 @@ producer.setup do |config| | |
| 201 198 | 
             
              config.kafka = {
         | 
| 202 199 | 
             
                'bootstrap.servers': 'localhost:9092',
         | 
| 203 200 | 
             
                # Accumulate messages for at most 10 seconds
         | 
| 204 | 
            -
                'queue.buffering.max.ms'  | 
| 201 | 
            +
                'queue.buffering.max.ms': 10_000
         | 
| 205 202 | 
             
              }
         | 
| 206 203 | 
             
            end
         | 
| 207 204 |  | 
| @@ -288,9 +285,40 @@ producer.close | |
| 288 285 |  | 
| 289 286 | 
             
            Note: The metrics returned may not be completely consistent between brokers, toppars and totals, due to the internal asynchronous nature of librdkafka. E.g., the top level tx total may be less than the sum of the broker tx values which it represents.
         | 
| 290 287 |  | 
| 288 | 
            +
            ### Datadog and StatsD integration
         | 
| 289 | 
            +
             | 
| 290 | 
            +
            WaterDrop comes with (optional) full Datadog and StatsD integration that you can use. To use it:
         | 
| 291 | 
            +
             | 
| 292 | 
            +
            ```ruby
         | 
| 293 | 
            +
            # require datadog/statsd and the listener as it is not loaded by default
         | 
| 294 | 
            +
            require 'datadog/statsd'
         | 
| 295 | 
            +
            require 'waterdrop/instrumentation/vendors/datadog/listener'
         | 
| 296 | 
            +
             | 
| 297 | 
            +
            # initialize your producer with statistics.interval.ms enabled so the metrics are published
         | 
| 298 | 
            +
            producer = WaterDrop::Producer.new do |config|
         | 
| 299 | 
            +
              config.deliver = true
         | 
| 300 | 
            +
              config.kafka = {
         | 
| 301 | 
            +
                'bootstrap.servers': 'localhost:9092',
         | 
| 302 | 
            +
                'statistics.interval.ms': 1_000
         | 
| 303 | 
            +
              }
         | 
| 304 | 
            +
            end
         | 
| 305 | 
            +
             | 
| 306 | 
            +
            # initialize the listener with statsd client
         | 
| 307 | 
            +
            listener = ::WaterDrop::Instrumentation::Vendors::Datadog::Listener.new do |config|
         | 
| 308 | 
            +
              config.client = Datadog::Statsd.new('localhost', 8125)
         | 
| 309 | 
            +
              # Publish host as a tag alongside the rest of tags
         | 
| 310 | 
            +
              config.default_tags = ["host:#{Socket.gethostname}"]
         | 
| 311 | 
            +
            end
         | 
| 312 | 
            +
             | 
| 313 | 
            +
            # Subscribe with your listener to your producer and you should be ready to go!
         | 
| 314 | 
            +
            producer.monitor.subscribe(listener)
         | 
| 315 | 
            +
            ```
         | 
| 316 | 
            +
             | 
| 317 | 
            +
            You can also find a ready to import DataDog dashboard configuration file that you can use to monitor all of your producer.
         | 
| 318 | 
            +
             | 
| 291 319 | 
             
            ### Error notifications
         | 
| 292 320 |  | 
| 293 | 
            -
             | 
| 321 | 
            +
            WaterDrop allows you to listen to all errors that occur while producing messages and in its internal background threads. Things like reconnecting to Kafka upon network errors and others unrelated to publishing messages are all available under `error.occurred` notification key. You can subscribe to this event to ensure your setup is healthy and without any problems that would otherwise go unnoticed as long as messages are delivered.
         | 
| 294 322 |  | 
| 295 323 | 
             
            ```ruby
         | 
| 296 324 | 
             
            producer = WaterDrop::Producer.new do |config|
         | 
| @@ -298,10 +326,10 @@ producer = WaterDrop::Producer.new do |config| | |
| 298 326 | 
             
              config.kafka = { 'bootstrap.servers': 'localhost:9090' }
         | 
| 299 327 | 
             
            end
         | 
| 300 328 |  | 
| 301 | 
            -
            producer.monitor.subscribe('error. | 
| 329 | 
            +
            producer.monitor.subscribe('error.occurred') do |event|
         | 
| 302 330 | 
             
              error = event[:error]
         | 
| 303 331 |  | 
| 304 | 
            -
              p " | 
| 332 | 
            +
              p "WaterDrop error occurred: #{error}"
         | 
| 305 333 | 
             
            end
         | 
| 306 334 |  | 
| 307 335 | 
             
            # Run this code without Kafka cluster
         | 
| @@ -313,9 +341,9 @@ end | |
| 313 341 |  | 
| 314 342 | 
             
            # After you stop your Kafka cluster, you will see a lot of those:
         | 
| 315 343 | 
             
            #
         | 
| 316 | 
            -
            #  | 
| 344 | 
            +
            # WaterDrop error occurred: Local: Broker transport failure (transport)
         | 
| 317 345 | 
             
            #
         | 
| 318 | 
            -
            #  | 
| 346 | 
            +
            # WaterDrop error occurred: Local: Broker transport failure (transport)
         | 
| 319 347 | 
             
            ```
         | 
| 320 348 |  | 
| 321 349 | 
             
            ### Forking and potential memory problems
         | 
    
        data/config/errors.yml
    CHANGED
    
    
| @@ -9,7 +9,7 @@ module WaterDrop | |
| 9 9 |  | 
| 10 10 | 
             
                # Defaults for kafka settings, that will be overwritten only if not present already
         | 
| 11 11 | 
             
                KAFKA_DEFAULTS = {
         | 
| 12 | 
            -
                  'client.id'  | 
| 12 | 
            +
                  'client.id': 'waterdrop'
         | 
| 13 13 | 
             
                }.freeze
         | 
| 14 14 |  | 
| 15 15 | 
             
                private_constant :KAFKA_DEFAULTS
         | 
| @@ -17,7 +17,8 @@ module WaterDrop | |
| 17 17 | 
             
                # WaterDrop options
         | 
| 18 18 | 
             
                #
         | 
| 19 19 | 
             
                # option [String] id of the producer. This can be helpful when building producer specific
         | 
| 20 | 
            -
                #   instrumentation or loggers. It is not the kafka  | 
| 20 | 
            +
                #   instrumentation or loggers. It is not the kafka client id. It is an id that should be
         | 
| 21 | 
            +
                #   unique for each of the producers
         | 
| 21 22 | 
             
                setting(
         | 
| 22 23 | 
             
                  :id,
         | 
| 23 24 | 
             
                  default: false,
         | 
| @@ -62,7 +63,8 @@ module WaterDrop | |
| 62 63 | 
             
                    yield(config)
         | 
| 63 64 |  | 
| 64 65 | 
             
                    merge_kafka_defaults!(config)
         | 
| 65 | 
            -
             | 
| 66 | 
            +
             | 
| 67 | 
            +
                    Contracts::Config.new.validate!(config.to_h, Errors::ConfigurationInvalidError)
         | 
| 66 68 |  | 
| 67 69 | 
             
                    ::Rdkafka::Config.logger = config.logger
         | 
| 68 70 | 
             
                  end
         | 
| @@ -81,16 +83,5 @@ module WaterDrop | |
| 81 83 | 
             
                    config.kafka[key] = value
         | 
| 82 84 | 
             
                  end
         | 
| 83 85 | 
             
                end
         | 
| 84 | 
            -
             | 
| 85 | 
            -
                # Validates the configuration and if anything is wrong, will raise an exception
         | 
| 86 | 
            -
                # @param config_hash [Hash] config hash with setup details
         | 
| 87 | 
            -
                # @raise [WaterDrop::Errors::ConfigurationInvalidError] raised when something is wrong with
         | 
| 88 | 
            -
                #   the configuration
         | 
| 89 | 
            -
                def validate!(config_hash)
         | 
| 90 | 
            -
                  result = Contracts::Config.new.call(config_hash)
         | 
| 91 | 
            -
                  return true if result.success?
         | 
| 92 | 
            -
             | 
| 93 | 
            -
                  raise Errors::ConfigurationInvalidError, result.errors.to_h
         | 
| 94 | 
            -
                end
         | 
| 95 86 | 
             
              end
         | 
| 96 87 | 
             
            end
         | 
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module WaterDrop
         | 
| 4 | 
            +
              module Contracts
         | 
| 5 | 
            +
                # Base for all the contracts in WaterDrop
         | 
| 6 | 
            +
                class Base < Dry::Validation::Contract
         | 
| 7 | 
            +
                  config.messages.load_paths << File.join(WaterDrop.gem_root, 'config', 'errors.yml')
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  # @param data [Hash] data for validation
         | 
| 10 | 
            +
                  # @param error_class [Class] error class that should be used when validation fails
         | 
| 11 | 
            +
                  # @return [Boolean] true
         | 
| 12 | 
            +
                  # @raise [StandardError] any error provided in the error_class that inherits from the
         | 
| 13 | 
            +
                  #   standard error
         | 
| 14 | 
            +
                  def validate!(data, error_class)
         | 
| 15 | 
            +
                    result = call(data)
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                    return true if result.success?
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                    raise error_class, result.errors.to_h
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
            end
         | 
| @@ -3,12 +3,7 @@ | |
| 3 3 | 
             
            module WaterDrop
         | 
| 4 4 | 
             
              module Contracts
         | 
| 5 5 | 
             
                # Contract with validation rules for WaterDrop configuration details
         | 
| 6 | 
            -
                class Config <  | 
| 7 | 
            -
                  # Ensure valid format of each seed broker so that rdkafka doesn't fail silently
         | 
| 8 | 
            -
                  SEED_BROKER_FORMAT_REGEXP = %r{\A([^:/,]+:[0-9]+)(,[^:/,]+:[0-9]+)*\z}.freeze
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                  private_constant :SEED_BROKER_FORMAT_REGEXP
         | 
| 11 | 
            -
             | 
| 6 | 
            +
                class Config < Base
         | 
| 12 7 | 
             
                  params do
         | 
| 13 8 | 
             
                    required(:id).filled(:str?)
         | 
| 14 9 | 
             
                    required(:logger).filled
         | 
| @@ -16,9 +11,18 @@ module WaterDrop | |
| 16 11 | 
             
                    required(:max_payload_size).filled(:int?, gteq?: 1)
         | 
| 17 12 | 
             
                    required(:max_wait_timeout).filled(:number?, gteq?: 0)
         | 
| 18 13 | 
             
                    required(:wait_timeout).filled(:number?, gt?: 0)
         | 
| 14 | 
            +
                    required(:kafka).filled(:hash?)
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  # rdkafka allows both symbols and strings as keys for config but then casts them to strings
         | 
| 18 | 
            +
                  # This can be confusing, so we expect all keys to be symbolized
         | 
| 19 | 
            +
                  rule(:kafka) do
         | 
| 20 | 
            +
                    next unless value.is_a?(Hash)
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                    value.each_key do |key|
         | 
| 23 | 
            +
                      next if key.is_a?(Symbol)
         | 
| 19 24 |  | 
| 20 | 
            -
             | 
| 21 | 
            -
                      required(:'bootstrap.servers').filled(:str?, format?: SEED_BROKER_FORMAT_REGEXP)
         | 
| 25 | 
            +
                      key(:"kafka.#{key}").failure(:kafka_key_must_be_a_symbol)
         | 
| 22 26 | 
             
                    end
         | 
| 23 27 | 
             
                  end
         | 
| 24 28 | 
             
                end
         | 
| @@ -4,17 +4,15 @@ module WaterDrop | |
| 4 4 | 
             
              module Contracts
         | 
| 5 5 | 
             
                # Contract with validation rules for validating that all the message options that
         | 
| 6 6 | 
             
                # we provide to producer ale valid and usable
         | 
| 7 | 
            -
                class Message <  | 
| 7 | 
            +
                class Message < Base
         | 
| 8 8 | 
             
                  # Regex to check that topic has a valid format
         | 
| 9 | 
            -
                  TOPIC_REGEXP = /\A(\w|-|\.)+\z | 
| 9 | 
            +
                  TOPIC_REGEXP = /\A(\w|-|\.)+\z/
         | 
| 10 10 |  | 
| 11 11 | 
             
                  # Checks, that the given value is a string
         | 
| 12 12 | 
             
                  STRING_ASSERTION = ->(value) { value.is_a?(String) }.to_proc
         | 
| 13 13 |  | 
| 14 14 | 
             
                  private_constant :TOPIC_REGEXP, :STRING_ASSERTION
         | 
| 15 15 |  | 
| 16 | 
            -
                  config.messages.load_paths << File.join(WaterDrop.gem_root, 'config', 'errors.yml')
         | 
| 17 | 
            -
             | 
| 18 16 | 
             
                  option :max_payload_size
         | 
| 19 17 |  | 
| 20 18 | 
             
                  params do
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| @@ -17,16 +17,17 @@ module WaterDrop | |
| 17 17 | 
             
                    # Runs the instrumentation monitor with error
         | 
| 18 18 | 
             
                    # @param client_name [String] rdkafka client name
         | 
| 19 19 | 
             
                    # @param error [Rdkafka::Error] error that occurred
         | 
| 20 | 
            -
                    # @note  | 
| 20 | 
            +
                    # @note It will only instrument on errors of the client of our producer
         | 
| 21 21 | 
             
                    def call(client_name, error)
         | 
| 22 22 | 
             
                      # Emit only errors related to our client
         | 
| 23 23 | 
             
                      # Same as with statistics (mor explanation there)
         | 
| 24 24 | 
             
                      return unless @client_name == client_name
         | 
| 25 25 |  | 
| 26 26 | 
             
                      @monitor.instrument(
         | 
| 27 | 
            -
                        'error. | 
| 27 | 
            +
                        'error.occurred',
         | 
| 28 | 
            +
                        error: error,
         | 
| 28 29 | 
             
                        producer_id: @producer_id,
         | 
| 29 | 
            -
                         | 
| 30 | 
            +
                        type: 'librdkafka.error'
         | 
| 30 31 | 
             
                      )
         | 
| 31 32 | 
             
                    end
         | 
| 32 33 | 
             
                  end
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| @@ -13,8 +13,12 @@ module WaterDrop | |
| 13 13 | 
             
                  # Invokes all the callbacks registered one after another
         | 
| 14 14 | 
             
                  #
         | 
| 15 15 | 
             
                  # @param args [Object] any args that should go to the callbacks
         | 
| 16 | 
            +
                  # @note We do not use `#each_value` here on purpose. With it being used, we cannot dispatch
         | 
| 17 | 
            +
                  #   callbacks and add new at the same time. Since we don't know when and in what thread
         | 
| 18 | 
            +
                  #   things are going to be added to the manager, we need to extract values into an array and
         | 
| 19 | 
            +
                  #   run it. That way we can add new things the same time.
         | 
| 16 20 | 
             
                  def call(*args)
         | 
| 17 | 
            -
                    @callbacks. | 
| 21 | 
            +
                    @callbacks.values.each { |callback| callback.call(*args) }
         | 
| 18 22 | 
             
                  end
         | 
| 19 23 |  | 
| 20 24 | 
             
                  # Adds a callback to the manager
         | 
| @@ -24,13 +24,11 @@ module WaterDrop | |
| 24 24 | 
             
                    messages.buffered
         | 
| 25 25 |  | 
| 26 26 | 
             
                    buffer.flushed_async
         | 
| 27 | 
            -
                    buffer.flushed_async.error
         | 
| 28 27 | 
             
                    buffer.flushed_sync
         | 
| 29 | 
            -
                    buffer.flushed_sync.error
         | 
| 30 28 |  | 
| 31 29 | 
             
                    statistics.emitted
         | 
| 32 30 |  | 
| 33 | 
            -
                    error. | 
| 31 | 
            +
                    error.occurred
         | 
| 34 32 | 
             
                  ].freeze
         | 
| 35 33 |  | 
| 36 34 | 
             
                  private_constant :EVENTS
         | 
| @@ -51,7 +51,7 @@ module WaterDrop | |
| 51 51 | 
             
                    message = event[:message]
         | 
| 52 52 |  | 
| 53 53 | 
             
                    info(event, "Buffering of a message to '#{message[:topic]}' topic")
         | 
| 54 | 
            -
                    debug(event, [message | 
| 54 | 
            +
                    debug(event, [message])
         | 
| 55 55 | 
             
                  end
         | 
| 56 56 |  | 
| 57 57 | 
             
                  # @param event [Dry::Events::Event] event that happened with the details
         | 
| @@ -59,7 +59,7 @@ module WaterDrop | |
| 59 59 | 
             
                    messages = event[:messages]
         | 
| 60 60 |  | 
| 61 61 | 
             
                    info(event, "Buffering of #{messages.size} messages")
         | 
| 62 | 
            -
                    debug(event, [messages,  | 
| 62 | 
            +
                    debug(event, [messages, messages.size])
         | 
| 63 63 | 
             
                  end
         | 
| 64 64 |  | 
| 65 65 | 
             
                  # @param event [Dry::Events::Event] event that happened with the details
         | 
| @@ -70,15 +70,6 @@ module WaterDrop | |
| 70 70 | 
             
                    debug(event, messages)
         | 
| 71 71 | 
             
                  end
         | 
| 72 72 |  | 
| 73 | 
            -
                  # @param event [Dry::Events::Event] event that happened with the details
         | 
| 74 | 
            -
                  def on_buffer_flushed_async_error(event)
         | 
| 75 | 
            -
                    messages = event[:messages]
         | 
| 76 | 
            -
                    error = event[:error]
         | 
| 77 | 
            -
             | 
| 78 | 
            -
                    error(event, "Async flushing of #{messages.size} failed due to: #{error}")
         | 
| 79 | 
            -
                    debug(event, messages)
         | 
| 80 | 
            -
                  end
         | 
| 81 | 
            -
             | 
| 82 73 | 
             
                  # @param event [Dry::Events::Event] event that happened with the details
         | 
| 83 74 | 
             
                  def on_buffer_flushed_sync(event)
         | 
| 84 75 | 
             
                    messages = event[:messages]
         | 
| @@ -87,19 +78,19 @@ module WaterDrop | |
| 87 78 | 
             
                    debug(event, messages)
         | 
| 88 79 | 
             
                  end
         | 
| 89 80 |  | 
| 90 | 
            -
                  # @param event [Dry::Events::Event] event that happened with the details
         | 
| 91 | 
            -
                  def on_buffer_flushed_sync_error(event)
         | 
| 92 | 
            -
                    messages = event[:dispatched]
         | 
| 93 | 
            -
                    error = event[:error]
         | 
| 94 | 
            -
             | 
| 95 | 
            -
                    error(event, "Sync flushing of #{messages.size} failed due to: #{error}")
         | 
| 96 | 
            -
                    debug(event, messages)
         | 
| 97 | 
            -
                  end
         | 
| 98 | 
            -
             | 
| 99 81 | 
             
                  # @param event [Dry::Events::Event] event that happened with the details
         | 
| 100 82 | 
             
                  def on_producer_closed(event)
         | 
| 101 83 | 
             
                    info event, 'Closing producer'
         | 
| 102 | 
            -
                    debug event,  | 
| 84 | 
            +
                    debug event, ''
         | 
| 85 | 
            +
                  end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                  # @param event [Dry::Events::Event] event that happened with the error details
         | 
| 88 | 
            +
                  def on_error_occurred(event)
         | 
| 89 | 
            +
                    error = event[:error]
         | 
| 90 | 
            +
                    type = event[:type]
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                    error(event, "Error occurred: #{error} - #{type}")
         | 
| 93 | 
            +
                    debug(event, '')
         | 
| 103 94 | 
             
                  end
         | 
| 104 95 |  | 
| 105 96 | 
             
                  private
         | 
| @@ -107,19 +98,19 @@ module WaterDrop | |
| 107 98 | 
             
                  # @param event [Dry::Events::Event] event that happened with the details
         | 
| 108 99 | 
             
                  # @param log_message [String] message we want to publish
         | 
| 109 100 | 
             
                  def debug(event, log_message)
         | 
| 110 | 
            -
                    @logger.debug("[#{event[: | 
| 101 | 
            +
                    @logger.debug("[#{event[:producer_id]}] #{log_message}")
         | 
| 111 102 | 
             
                  end
         | 
| 112 103 |  | 
| 113 104 | 
             
                  # @param event [Dry::Events::Event] event that happened with the details
         | 
| 114 105 | 
             
                  # @param log_message [String] message we want to publish
         | 
| 115 106 | 
             
                  def info(event, log_message)
         | 
| 116 | 
            -
                    @logger.info("[#{event[: | 
| 107 | 
            +
                    @logger.info("[#{event[:producer_id]}] #{log_message} took #{event[:time]} ms")
         | 
| 117 108 | 
             
                  end
         | 
| 118 109 |  | 
| 119 110 | 
             
                  # @param event [Dry::Events::Event] event that happened with the details
         | 
| 120 111 | 
             
                  # @param log_message [String] message we want to publish
         | 
| 121 112 | 
             
                  def error(event, log_message)
         | 
| 122 | 
            -
                    @logger.error("[#{event[: | 
| 113 | 
            +
                    @logger.error("[#{event[:producer_id]}] #{log_message}")
         | 
| 123 114 | 
             
                  end
         | 
| 124 115 | 
             
                end
         | 
| 125 116 | 
             
              end
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            {"title":"WaterDrop producer example dashboard","description":"This dashboard include example setup for monitoring activity of your WaterDrop producer","widgets":[{"id":243951318,"definition":{"title":"Messages produced","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"produced sync","formula":"query1"},{"alias":"produced async","formula":"query2"},{"alias":"flushed sync","formula":"query3"},{"alias":"flushed async","formula":"query4"},{"alias":"acknowledged","formula":"query5"}],"response_format":"timeseries","queries":[{"query":"sum:waterdrop.produced_sync{*}.as_count()","data_source":"metrics","name":"query1"},{"query":"sum:waterdrop.produced_async{*}.as_count()","data_source":"metrics","name":"query2"},{"query":"sum:waterdrop.flushed_sync{*}.as_count()","data_source":"metrics","name":"query3"},{"query":"sum:waterdrop.flushed_async{*}.as_count()","data_source":"metrics","name":"query4"},{"query":"sum:waterdrop.acknowledged{*}.as_count()","data_source":"metrics","name":"query5"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}],"yaxis":{"include_zero":true,"scale":"linear","label":"","min":"auto","max":"auto"}}},{"id":1979626566852990,"definition":{"title":"Messages buffer size","title_size":"16","title_align":"left","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"max","formula":"query1"}],"response_format":"timeseries","queries":[{"query":"avg:waterdrop.buffer.size.max{*}","data_source":"metrics","name":"query1"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}]}},{"id":243951221,"definition":{"title":"Kafka broker API calls","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"API calls","formula":"query1"}],"response_format":"timeseries","queries":[{"query":"sum:waterdrop.calls{*}","data_source":"metrics","name":"query1"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}],"yaxis":{"include_zero":true,"scale":"linear","label":"","min":"auto","max":"auto"}}},{"id":243951952,"definition":{"title":"Producer queue size","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"Queue size average","formula":"query1"}],"response_format":"timeseries","queries":[{"query":"max:waterdrop.queue.size.avg{*}","data_source":"metrics","name":"query1"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"},{"formulas":[{"alias":"Queue size max","formula":"query1"}],"response_format":"timeseries","queries":[{"query":"max:waterdrop.queue.size.max{*}","data_source":"metrics","name":"query1"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}],"yaxis":{"include_zero":true,"scale":"linear","label":"","min":"auto","max":"auto"}}},{"id":243951263,"definition":{"title":"Producer queue latency","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"Average latency","formula":"query1"}],"response_format":"timeseries","queries":[{"query":"avg:waterdrop.queue.latency.avg{*}","data_source":"metrics","name":"query1"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"},{"formulas":[{"alias":"Latency p95","formula":"query1"}],"response_format":"timeseries","queries":[{"query":"avg:waterdrop.queue.latency.p95{*}","data_source":"metrics","name":"query1"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"},{"formulas":[{"alias":"Latency p99","formula":"query1"}],"response_format":"timeseries","queries":[{"query":"avg:waterdrop.queue.latency.p99{*}","data_source":"metrics","name":"query1"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}],"yaxis":{"include_zero":true,"scale":"linear","label":"","min":"auto","max":"auto"}}},{"id":243951276,"definition":{"title":"Producer network latency","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"alias":"Average latency","formula":"query1"}],"response_format":"timeseries","queries":[{"query":"avg:waterdrop.request_size.avg{*}","data_source":"metrics","name":"query1"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"},{"formulas":[{"alias":"Latency p95","formula":"query1"}],"response_format":"timeseries","queries":[{"query":"avg:waterdrop.network.latency.p95{*}","data_source":"metrics","name":"query1"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"},{"formulas":[{"alias":"Latency p99","formula":"query1"}],"response_format":"timeseries","queries":[{"query":"avg:waterdrop.network.latency.p99{*}","data_source":"metrics","name":"query1"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}],"yaxis":{"include_zero":true,"scale":"linear","label":"","min":"auto","max":"auto"}}},{"id":243954928,"definition":{"title":"Producer errors","show_legend":true,"legend_layout":"auto","legend_columns":["avg","min","max","value","sum"],"type":"timeseries","requests":[{"formulas":[{"formula":"query1"}],"response_format":"timeseries","queries":[{"query":"sum:waterdrop.error_occurred{*}.as_count()","data_source":"metrics","name":"query1"}],"style":{"palette":"dog_classic","line_type":"solid","line_width":"normal"},"display_type":"line"}],"yaxis":{"include_zero":true,"scale":"linear","label":"","min":"auto","max":"auto"}}}],"template_variables":[],"layout_type":"ordered","is_read_only":false,"notify_list":[],"reflow_type":"auto","id":"rnr-kgh-dna"}
         | 
| @@ -0,0 +1,197 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module WaterDrop
         | 
| 4 | 
            +
              module Instrumentation
         | 
| 5 | 
            +
                # Namespace for vendor specific instrumentation
         | 
| 6 | 
            +
                module Vendors
         | 
| 7 | 
            +
                  # Datadog specific instrumentation
         | 
| 8 | 
            +
                  module Datadog
         | 
| 9 | 
            +
                    # Listener that can be used to subscribe to WaterDrop producer to receive stats via StatsD
         | 
| 10 | 
            +
                    # and/or Datadog
         | 
| 11 | 
            +
                    #
         | 
| 12 | 
            +
                    # @note You need to setup the `dogstatsd-ruby` client and assign it
         | 
| 13 | 
            +
                    class Listener
         | 
| 14 | 
            +
                      include Dry::Configurable
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                      # Value object for storing a single rdkafka metric publishing details
         | 
| 17 | 
            +
                      RdKafkaMetric = Struct.new(:type, :scope, :name, :key_location)
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                      # Namespace under which the DD metrics should be published
         | 
| 20 | 
            +
                      setting :namespace, default: 'waterdrop', reader: true
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                      # Datadog client that we should use to publish the metrics
         | 
| 23 | 
            +
                      setting :client, reader: true
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                      # Default tags we want to publish (for example hostname)
         | 
| 26 | 
            +
                      # Format as followed (example for hostname): `["host:#{Socket.gethostname}"]`
         | 
| 27 | 
            +
                      setting :default_tags, default: [], reader: true
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                      # All the rdkafka metrics we want to publish
         | 
| 30 | 
            +
                      #
         | 
| 31 | 
            +
                      # By default we publish quite a lot so this can be tuned
         | 
| 32 | 
            +
                      # Note, that the once with `_d` come from WaterDrop, not rdkafka or Kafka
         | 
| 33 | 
            +
                      setting :rd_kafka_metrics, reader: true, default: [
         | 
| 34 | 
            +
                        # Client metrics
         | 
| 35 | 
            +
                        RdKafkaMetric.new(:count, :root, 'calls', 'tx_d'),
         | 
| 36 | 
            +
                        RdKafkaMetric.new(:histogram, :root, 'queue.size', 'msg_cnt_d'),
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                        # Broker metrics
         | 
| 39 | 
            +
                        RdKafkaMetric.new(:count, :brokers, 'deliver.attempts', 'txretries_d'),
         | 
| 40 | 
            +
                        RdKafkaMetric.new(:count, :brokers, 'deliver.errors', 'txerrs_d'),
         | 
| 41 | 
            +
                        RdKafkaMetric.new(:count, :brokers, 'receive.errors', 'rxerrs_d'),
         | 
| 42 | 
            +
                        RdKafkaMetric.new(:gauge, :brokers, 'queue.latency.avg', %w[outbuf_latency avg]),
         | 
| 43 | 
            +
                        RdKafkaMetric.new(:gauge, :brokers, 'queue.latency.p95', %w[outbuf_latency p95]),
         | 
| 44 | 
            +
                        RdKafkaMetric.new(:gauge, :brokers, 'queue.latency.p99', %w[outbuf_latency p99]),
         | 
| 45 | 
            +
                        RdKafkaMetric.new(:gauge, :brokers, 'network.latency.avg', %w[rtt avg]),
         | 
| 46 | 
            +
                        RdKafkaMetric.new(:gauge, :brokers, 'network.latency.p95', %w[rtt p95]),
         | 
| 47 | 
            +
                        RdKafkaMetric.new(:gauge, :brokers, 'network.latency.p99', %w[rtt p99])
         | 
| 48 | 
            +
                      ].freeze
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                      # @param block [Proc] configuration block
         | 
| 51 | 
            +
                      def initialize(&block)
         | 
| 52 | 
            +
                        setup(&block) if block
         | 
| 53 | 
            +
                      end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                      # @param block [Proc] configuration block
         | 
| 56 | 
            +
                      # @note We define this alias to be consistent with `WaterDrop#setup`
         | 
| 57 | 
            +
                      def setup(&block)
         | 
| 58 | 
            +
                        configure(&block)
         | 
| 59 | 
            +
                      end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                      # Hooks up to WaterDrop instrumentation for emitted statistics
         | 
| 62 | 
            +
                      #
         | 
| 63 | 
            +
                      # @param event [Dry::Events::Event]
         | 
| 64 | 
            +
                      def on_statistics_emitted(event)
         | 
| 65 | 
            +
                        statistics = event[:statistics]
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                        rd_kafka_metrics.each do |metric|
         | 
| 68 | 
            +
                          report_metric(metric, statistics)
         | 
| 69 | 
            +
                        end
         | 
| 70 | 
            +
                      end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                      # Increases the errors count by 1
         | 
| 73 | 
            +
                      #
         | 
| 74 | 
            +
                      # @param _event [Dry::Events::Event]
         | 
| 75 | 
            +
                      def on_error_occurred(_event)
         | 
| 76 | 
            +
                        client.count(
         | 
| 77 | 
            +
                          namespaced_metric('error_occurred'),
         | 
| 78 | 
            +
                          1,
         | 
| 79 | 
            +
                          tags: default_tags
         | 
| 80 | 
            +
                        )
         | 
| 81 | 
            +
                      end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                      # Increases acknowledged messages counter
         | 
| 84 | 
            +
                      # @param _event [Dry::Events::Event]
         | 
| 85 | 
            +
                      def on_message_acknowledged(_event)
         | 
| 86 | 
            +
                        client.increment(
         | 
| 87 | 
            +
                          namespaced_metric('acknowledged'),
         | 
| 88 | 
            +
                          tags: default_tags
         | 
| 89 | 
            +
                        )
         | 
| 90 | 
            +
                      end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                      %i[
         | 
| 93 | 
            +
                        produced_sync
         | 
| 94 | 
            +
                        produced_async
         | 
| 95 | 
            +
                      ].each do |event_scope|
         | 
| 96 | 
            +
                        class_eval <<~METHODS, __FILE__, __LINE__ + 1
         | 
| 97 | 
            +
                          # @param event [Dry::Events::Event]
         | 
| 98 | 
            +
                          def on_message_#{event_scope}(event)
         | 
| 99 | 
            +
                            report_message(event[:message][:topic], :#{event_scope})
         | 
| 100 | 
            +
                          end
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                          # @param event [Dry::Events::Event]
         | 
| 103 | 
            +
                          def on_messages_#{event_scope}(event)
         | 
| 104 | 
            +
                            event[:messages].each do |message|
         | 
| 105 | 
            +
                              report_message(message[:topic], :#{event_scope})
         | 
| 106 | 
            +
                            end
         | 
| 107 | 
            +
                          end
         | 
| 108 | 
            +
                        METHODS
         | 
| 109 | 
            +
                      end
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                      # Reports the buffer usage when anything is added to the buffer
         | 
| 112 | 
            +
                      %i[
         | 
| 113 | 
            +
                        message_buffered
         | 
| 114 | 
            +
                        messages_buffered
         | 
| 115 | 
            +
                      ].each do |event_scope|
         | 
| 116 | 
            +
                        class_eval <<~METHODS, __FILE__, __LINE__ + 1
         | 
| 117 | 
            +
                          # @param event [Dry::Events::Event]
         | 
| 118 | 
            +
                          def on_#{event_scope}(event)
         | 
| 119 | 
            +
                            client.histogram(
         | 
| 120 | 
            +
                              namespaced_metric('buffer.size'),
         | 
| 121 | 
            +
                              event[:buffer].size,
         | 
| 122 | 
            +
                              tags: default_tags
         | 
| 123 | 
            +
                            )
         | 
| 124 | 
            +
                          end
         | 
| 125 | 
            +
                        METHODS
         | 
| 126 | 
            +
                      end
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                      # Events that support many messages only
         | 
| 129 | 
            +
                      # Reports data flushing operation (production from the buffer)
         | 
| 130 | 
            +
                      %i[
         | 
| 131 | 
            +
                        flushed_sync
         | 
| 132 | 
            +
                        flushed_async
         | 
| 133 | 
            +
                      ].each do |event_scope|
         | 
| 134 | 
            +
                        class_eval <<~METHODS, __FILE__, __LINE__ + 1
         | 
| 135 | 
            +
                          # @param event [Dry::Events::Event]
         | 
| 136 | 
            +
                          def on_buffer_#{event_scope}(event)
         | 
| 137 | 
            +
                            event[:messages].each do |message|
         | 
| 138 | 
            +
                              report_message(message[:topic], :#{event_scope})
         | 
| 139 | 
            +
                            end
         | 
| 140 | 
            +
                          end
         | 
| 141 | 
            +
                        METHODS
         | 
| 142 | 
            +
                      end
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                      private
         | 
| 145 | 
            +
             | 
| 146 | 
            +
                      # Report that a message has been produced to a topic.
         | 
| 147 | 
            +
                      # @param topic [String] Kafka topic
         | 
| 148 | 
            +
                      # @param method_name [Symbol] method from which this message operation comes
         | 
| 149 | 
            +
                      def report_message(topic, method_name)
         | 
| 150 | 
            +
                        client.increment(
         | 
| 151 | 
            +
                          namespaced_metric(method_name),
         | 
| 152 | 
            +
                          tags: default_tags + ["topic:#{topic}"]
         | 
| 153 | 
            +
                        )
         | 
| 154 | 
            +
                      end
         | 
| 155 | 
            +
             | 
| 156 | 
            +
                      # Wraps metric name in listener's namespace
         | 
| 157 | 
            +
                      # @param metric_name [String] RdKafkaMetric name
         | 
| 158 | 
            +
                      # @return [String]
         | 
| 159 | 
            +
                      def namespaced_metric(metric_name)
         | 
| 160 | 
            +
                        "#{namespace}.#{metric_name}"
         | 
| 161 | 
            +
                      end
         | 
| 162 | 
            +
             | 
| 163 | 
            +
                      # Reports a given metric statistics to Datadog
         | 
| 164 | 
            +
                      # @param metric [RdKafkaMetric] metric value object
         | 
| 165 | 
            +
                      # @param statistics [Hash] hash with all the statistics emitted
         | 
| 166 | 
            +
                      def report_metric(metric, statistics)
         | 
| 167 | 
            +
                        case metric.scope
         | 
| 168 | 
            +
                        when :root
         | 
| 169 | 
            +
                          client.public_send(
         | 
| 170 | 
            +
                            metric.type,
         | 
| 171 | 
            +
                            namespaced_metric(metric.name),
         | 
| 172 | 
            +
                            statistics.fetch(*metric.key_location),
         | 
| 173 | 
            +
                            tags: default_tags
         | 
| 174 | 
            +
                          )
         | 
| 175 | 
            +
                        when :brokers
         | 
| 176 | 
            +
                          statistics.fetch('brokers').each_value do |broker_statistics|
         | 
| 177 | 
            +
                            # Skip bootstrap nodes
         | 
| 178 | 
            +
                            # Bootstrap nodes have nodeid -1, other nodes have positive
         | 
| 179 | 
            +
                            # node ids
         | 
| 180 | 
            +
                            next if broker_statistics['nodeid'] == -1
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                            client.public_send(
         | 
| 183 | 
            +
                              metric.type,
         | 
| 184 | 
            +
                              namespaced_metric(metric.name),
         | 
| 185 | 
            +
                              broker_statistics.dig(*metric.key_location),
         | 
| 186 | 
            +
                              tags: default_tags + ["broker:#{broker_statistics['nodename']}"]
         | 
| 187 | 
            +
                            )
         | 
| 188 | 
            +
                          end
         | 
| 189 | 
            +
                        else
         | 
| 190 | 
            +
                          raise ArgumentError, metric.scope
         | 
| 191 | 
            +
                        end
         | 
| 192 | 
            +
                      end
         | 
| 193 | 
            +
                    end
         | 
| 194 | 
            +
                  end
         | 
| 195 | 
            +
                end
         | 
| 196 | 
            +
              end
         | 
| 197 | 
            +
            end
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| @@ -19,7 +19,7 @@ module WaterDrop | |
| 19 19 |  | 
| 20 20 | 
             
                    @monitor.instrument(
         | 
| 21 21 | 
             
                      'message.produced_async',
         | 
| 22 | 
            -
                       | 
| 22 | 
            +
                      producer_id: id,
         | 
| 23 23 | 
             
                      message: message
         | 
| 24 24 | 
             
                    ) { client.produce(**message) }
         | 
| 25 25 | 
             
                  end
         | 
| @@ -40,7 +40,7 @@ module WaterDrop | |
| 40 40 |  | 
| 41 41 | 
             
                    @monitor.instrument(
         | 
| 42 42 | 
             
                      'messages.produced_async',
         | 
| 43 | 
            -
                       | 
| 43 | 
            +
                      producer_id: id,
         | 
| 44 44 | 
             
                      messages: messages
         | 
| 45 45 | 
             
                    ) do
         | 
| 46 46 | 
             
                      messages.map { |message| client.produce(**message) }
         | 
| @@ -23,8 +23,9 @@ module WaterDrop | |
| 23 23 |  | 
| 24 24 | 
             
                    @monitor.instrument(
         | 
| 25 25 | 
             
                      'message.buffered',
         | 
| 26 | 
            -
                       | 
| 27 | 
            -
                      message: message
         | 
| 26 | 
            +
                      producer_id: id,
         | 
| 27 | 
            +
                      message: message,
         | 
| 28 | 
            +
                      buffer: @messages
         | 
| 28 29 | 
             
                    ) { @messages << message }
         | 
| 29 30 | 
             
                  end
         | 
| 30 31 |  | 
| @@ -40,8 +41,9 @@ module WaterDrop | |
| 40 41 |  | 
| 41 42 | 
             
                    @monitor.instrument(
         | 
| 42 43 | 
             
                      'messages.buffered',
         | 
| 43 | 
            -
                       | 
| 44 | 
            -
                      messages: messages
         | 
| 44 | 
            +
                      producer_id: id,
         | 
| 45 | 
            +
                      messages: messages,
         | 
| 46 | 
            +
                      buffer: @messages
         | 
| 45 47 | 
             
                    ) do
         | 
| 46 48 | 
             
                      messages.each { |message| @messages << message }
         | 
| 47 49 | 
             
                      messages
         | 
| @@ -56,7 +58,7 @@ module WaterDrop | |
| 56 58 |  | 
| 57 59 | 
             
                    @monitor.instrument(
         | 
| 58 60 | 
             
                      'buffer.flushed_async',
         | 
| 59 | 
            -
                       | 
| 61 | 
            +
                      producer_id: id,
         | 
| 60 62 | 
             
                      messages: @messages
         | 
| 61 63 | 
             
                    ) { flush(false) }
         | 
| 62 64 | 
             
                  end
         | 
| @@ -69,7 +71,7 @@ module WaterDrop | |
| 69 71 |  | 
| 70 72 | 
             
                    @monitor.instrument(
         | 
| 71 73 | 
             
                      'buffer.flushed_sync',
         | 
| 72 | 
            -
                       | 
| 74 | 
            +
                      producer_id: id,
         | 
| 73 75 | 
             
                      messages: @messages
         | 
| 74 76 | 
             
                    ) { flush(true) }
         | 
| 75 77 | 
             
                  end
         | 
| @@ -103,8 +105,13 @@ module WaterDrop | |
| 103 105 | 
             
                      )
         | 
| 104 106 | 
             
                    end
         | 
| 105 107 | 
             
                  rescue *RESCUED_ERRORS => e
         | 
| 106 | 
            -
                     | 
| 107 | 
            -
             | 
| 108 | 
            +
                    @monitor.instrument(
         | 
| 109 | 
            +
                      'error.occurred',
         | 
| 110 | 
            +
                      error: e,
         | 
| 111 | 
            +
                      producer_id: id,
         | 
| 112 | 
            +
                      dispatched: dispatched,
         | 
| 113 | 
            +
                      type: sync ? 'buffer.flushed_sync.error' : 'buffer.flush_async.error'
         | 
| 114 | 
            +
                    )
         | 
| 108 115 |  | 
| 109 116 | 
             
                    raise Errors::FlushFailureError.new(dispatched)
         | 
| 110 117 | 
             
                  end
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| 
            File without changes
         | 
| @@ -21,7 +21,7 @@ module WaterDrop | |
| 21 21 |  | 
| 22 22 | 
             
                    @monitor.instrument(
         | 
| 23 23 | 
             
                      'message.produced_sync',
         | 
| 24 | 
            -
                       | 
| 24 | 
            +
                      producer_id: id,
         | 
| 25 25 | 
             
                      message: message
         | 
| 26 26 | 
             
                    ) do
         | 
| 27 27 | 
             
                      client
         | 
| @@ -49,7 +49,7 @@ module WaterDrop | |
| 49 49 | 
             
                    ensure_active!
         | 
| 50 50 | 
             
                    messages.each { |message| validate_message!(message) }
         | 
| 51 51 |  | 
| 52 | 
            -
                    @monitor.instrument('messages.produced_sync',  | 
| 52 | 
            +
                    @monitor.instrument('messages.produced_sync', producer_id: id, messages: messages) do
         | 
| 53 53 | 
             
                      messages
         | 
| 54 54 | 
             
                        .map { |message| client.produce(**message) }
         | 
| 55 55 | 
             
                        .map! do |handler|
         | 
| @@ -106,7 +106,7 @@ module WaterDrop | |
| 106 106 |  | 
| 107 107 | 
             
                    @monitor.instrument(
         | 
| 108 108 | 
             
                      'producer.closed',
         | 
| 109 | 
            -
                       | 
| 109 | 
            +
                      producer_id: id
         | 
| 110 110 | 
             
                    ) do
         | 
| 111 111 | 
             
                      @status.closing!
         | 
| 112 112 |  | 
| @@ -150,13 +150,7 @@ module WaterDrop | |
| 150 150 | 
             
                # @param message [Hash] message we want to send
         | 
| 151 151 | 
             
                # @raise [Karafka::Errors::MessageInvalidError]
         | 
| 152 152 | 
             
                def validate_message!(message)
         | 
| 153 | 
            -
                   | 
| 154 | 
            -
                  return if result.success?
         | 
| 155 | 
            -
             | 
| 156 | 
            -
                  raise Errors::MessageInvalidError, [
         | 
| 157 | 
            -
                    result.errors.to_h,
         | 
| 158 | 
            -
                    message
         | 
| 159 | 
            -
                  ]
         | 
| 153 | 
            +
                  @contract.validate!(message, Errors::MessageInvalidError)
         | 
| 160 154 | 
             
                end
         | 
| 161 155 | 
             
              end
         | 
| 162 156 | 
             
            end
         | 
    
        data/lib/waterdrop.rb
    CHANGED
    
    | @@ -1,4 +1,37 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            -
            #  | 
| 4 | 
            -
             | 
| 3 | 
            +
            # External components
         | 
| 4 | 
            +
            # delegate should be removed because we don't need it, we just add it because of ruby-kafka
         | 
| 5 | 
            +
            %w[
         | 
| 6 | 
            +
              concurrent/array
         | 
| 7 | 
            +
              dry-configurable
         | 
| 8 | 
            +
              dry/monitor/notifications
         | 
| 9 | 
            +
              dry-validation
         | 
| 10 | 
            +
              rdkafka
         | 
| 11 | 
            +
              json
         | 
| 12 | 
            +
              zeitwerk
         | 
| 13 | 
            +
              securerandom
         | 
| 14 | 
            +
            ].each { |lib| require lib }
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            # WaterDrop library
         | 
| 17 | 
            +
            module WaterDrop
         | 
| 18 | 
            +
              class << self
         | 
| 19 | 
            +
                # @return [String] root path of this gem
         | 
| 20 | 
            +
                def gem_root
         | 
| 21 | 
            +
                  Pathname.new(File.expand_path('..', __dir__))
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
            end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            loader = Zeitwerk::Loader.for_gem
         | 
| 27 | 
            +
            loader.inflector.inflect('waterdrop' => 'WaterDrop')
         | 
| 28 | 
            +
            # Do not load vendors instrumentation components. Those need to be required manually if needed
         | 
| 29 | 
            +
            loader.ignore("#{__dir__}/waterdrop/instrumentation/vendors/**/*.rb")
         | 
| 30 | 
            +
            loader.setup
         | 
| 31 | 
            +
            loader.eager_load
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            # Rdkafka uses a single global callback for things. We bypass that by injecting a manager for
         | 
| 34 | 
            +
            # each callback type. Callback manager allows us to register more than one callback
         | 
| 35 | 
            +
            # @note Those managers are also used by Karafka for consumer related statistics
         | 
| 36 | 
            +
            Rdkafka::Config.statistics_callback = WaterDrop::Instrumentation.statistics_callbacks
         | 
| 37 | 
            +
            Rdkafka::Config.error_callback = WaterDrop::Instrumentation.error_callbacks
         | 
    
        data/waterdrop.gemspec
    CHANGED
    
    | @@ -3,7 +3,7 @@ | |
| 3 3 | 
             
            lib = File.expand_path('lib', __dir__)
         | 
| 4 4 | 
             
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         | 
| 5 5 |  | 
| 6 | 
            -
            require ' | 
| 6 | 
            +
            require 'waterdrop/version'
         | 
| 7 7 |  | 
| 8 8 | 
             
            Gem::Specification.new do |spec|
         | 
| 9 9 | 
             
              spec.name          = 'waterdrop'
         | 
| @@ -11,7 +11,7 @@ Gem::Specification.new do |spec| | |
| 11 11 | 
             
              spec.platform      = Gem::Platform::RUBY
         | 
| 12 12 | 
             
              spec.authors       = ['Maciej Mensfeld']
         | 
| 13 13 | 
             
              spec.email         = %w[maciej@mensfeld.pl]
         | 
| 14 | 
            -
              spec.homepage      = 'https:// | 
| 14 | 
            +
              spec.homepage      = 'https://karafka.io'
         | 
| 15 15 | 
             
              spec.summary       = 'Kafka messaging made easy!'
         | 
| 16 16 | 
             
              spec.description   = spec.summary
         | 
| 17 17 | 
             
              spec.license       = 'MIT'
         | 
| @@ -23,7 +23,7 @@ Gem::Specification.new do |spec| | |
| 23 23 | 
             
              spec.add_dependency 'rdkafka', '>= 0.10'
         | 
| 24 24 | 
             
              spec.add_dependency 'zeitwerk', '~> 2.3'
         | 
| 25 25 |  | 
| 26 | 
            -
              spec.required_ruby_version = '>= 2. | 
| 26 | 
            +
              spec.required_ruby_version = '>= 2.7'
         | 
| 27 27 |  | 
| 28 28 | 
             
              if $PROGRAM_NAME.end_with?('gem')
         | 
| 29 29 | 
             
                spec.signing_key = File.expand_path('~/.ssh/gem-private_key.pem')
         | 
| @@ -33,4 +33,9 @@ Gem::Specification.new do |spec| | |
| 33 33 | 
             
              spec.files         = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec)/}) }
         | 
| 34 34 | 
             
              spec.executables   = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
         | 
| 35 35 | 
             
              spec.require_paths = %w[lib]
         | 
| 36 | 
            +
             | 
| 37 | 
            +
              spec.metadata = {
         | 
| 38 | 
            +
                'source_code_uri' => 'https://github.com/karafka/waterdrop',
         | 
| 39 | 
            +
                'rubygems_mfa_required' => 'true'
         | 
| 40 | 
            +
              }
         | 
| 36 41 | 
             
            end
         | 
    
        data.tar.gz.sig
    CHANGED
    
    | Binary file | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: waterdrop
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 2.0 | 
| 4 | 
            +
              version: 2.2.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Maciej Mensfeld
         | 
| @@ -34,7 +34,7 @@ cert_chain: | |
| 34 34 | 
             
              R2P11bWoCtr70BsccVrN8jEhzwXngMyI2gVt750Y+dbTu1KgRqZKp/ECe7ZzPzXj
         | 
| 35 35 | 
             
              pIy9vHxTANKYVyI4qj8OrFdEM5BQNu8oQpL0iQ==
         | 
| 36 36 | 
             
              -----END CERTIFICATE-----
         | 
| 37 | 
            -
            date:  | 
| 37 | 
            +
            date: 2022-02-18 00:00:00.000000000 Z
         | 
| 38 38 | 
             
            dependencies:
         | 
| 39 39 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 40 40 | 
             
              name: concurrent-ruby
         | 
| @@ -142,37 +142,41 @@ files: | |
| 142 142 | 
             
            - certs/mensfeld.pem
         | 
| 143 143 | 
             
            - config/errors.yml
         | 
| 144 144 | 
             
            - docker-compose.yml
         | 
| 145 | 
            -
            - lib/water_drop.rb
         | 
| 146 | 
            -
            - lib/water_drop/config.rb
         | 
| 147 | 
            -
            - lib/water_drop/contracts.rb
         | 
| 148 | 
            -
            - lib/water_drop/contracts/config.rb
         | 
| 149 | 
            -
            - lib/water_drop/contracts/message.rb
         | 
| 150 | 
            -
            - lib/water_drop/errors.rb
         | 
| 151 | 
            -
            - lib/water_drop/instrumentation.rb
         | 
| 152 | 
            -
            - lib/water_drop/instrumentation/callbacks/delivery.rb
         | 
| 153 | 
            -
            - lib/water_drop/instrumentation/callbacks/error.rb
         | 
| 154 | 
            -
            - lib/water_drop/instrumentation/callbacks/statistics.rb
         | 
| 155 | 
            -
            - lib/water_drop/instrumentation/callbacks/statistics_decorator.rb
         | 
| 156 | 
            -
            - lib/water_drop/instrumentation/callbacks_manager.rb
         | 
| 157 | 
            -
            - lib/water_drop/instrumentation/monitor.rb
         | 
| 158 | 
            -
            - lib/water_drop/instrumentation/stdout_listener.rb
         | 
| 159 | 
            -
            - lib/water_drop/patches/rdkafka/bindings.rb
         | 
| 160 | 
            -
            - lib/water_drop/patches/rdkafka/producer.rb
         | 
| 161 | 
            -
            - lib/water_drop/producer.rb
         | 
| 162 | 
            -
            - lib/water_drop/producer/async.rb
         | 
| 163 | 
            -
            - lib/water_drop/producer/buffer.rb
         | 
| 164 | 
            -
            - lib/water_drop/producer/builder.rb
         | 
| 165 | 
            -
            - lib/water_drop/producer/dummy_client.rb
         | 
| 166 | 
            -
            - lib/water_drop/producer/status.rb
         | 
| 167 | 
            -
            - lib/water_drop/producer/sync.rb
         | 
| 168 | 
            -
            - lib/water_drop/version.rb
         | 
| 169 145 | 
             
            - lib/waterdrop.rb
         | 
| 146 | 
            +
            - lib/waterdrop/config.rb
         | 
| 147 | 
            +
            - lib/waterdrop/contracts.rb
         | 
| 148 | 
            +
            - lib/waterdrop/contracts/base.rb
         | 
| 149 | 
            +
            - lib/waterdrop/contracts/config.rb
         | 
| 150 | 
            +
            - lib/waterdrop/contracts/message.rb
         | 
| 151 | 
            +
            - lib/waterdrop/errors.rb
         | 
| 152 | 
            +
            - lib/waterdrop/instrumentation.rb
         | 
| 153 | 
            +
            - lib/waterdrop/instrumentation/callbacks/delivery.rb
         | 
| 154 | 
            +
            - lib/waterdrop/instrumentation/callbacks/error.rb
         | 
| 155 | 
            +
            - lib/waterdrop/instrumentation/callbacks/statistics.rb
         | 
| 156 | 
            +
            - lib/waterdrop/instrumentation/callbacks/statistics_decorator.rb
         | 
| 157 | 
            +
            - lib/waterdrop/instrumentation/callbacks_manager.rb
         | 
| 158 | 
            +
            - lib/waterdrop/instrumentation/monitor.rb
         | 
| 159 | 
            +
            - lib/waterdrop/instrumentation/stdout_listener.rb
         | 
| 160 | 
            +
            - lib/waterdrop/instrumentation/vendors/datadog/dashboard.json
         | 
| 161 | 
            +
            - lib/waterdrop/instrumentation/vendors/datadog/listener.rb
         | 
| 162 | 
            +
            - lib/waterdrop/patches/rdkafka/bindings.rb
         | 
| 163 | 
            +
            - lib/waterdrop/patches/rdkafka/producer.rb
         | 
| 164 | 
            +
            - lib/waterdrop/producer.rb
         | 
| 165 | 
            +
            - lib/waterdrop/producer/async.rb
         | 
| 166 | 
            +
            - lib/waterdrop/producer/buffer.rb
         | 
| 167 | 
            +
            - lib/waterdrop/producer/builder.rb
         | 
| 168 | 
            +
            - lib/waterdrop/producer/dummy_client.rb
         | 
| 169 | 
            +
            - lib/waterdrop/producer/status.rb
         | 
| 170 | 
            +
            - lib/waterdrop/producer/sync.rb
         | 
| 171 | 
            +
            - lib/waterdrop/version.rb
         | 
| 170 172 | 
             
            - log/.gitkeep
         | 
| 171 173 | 
             
            - waterdrop.gemspec
         | 
| 172 | 
            -
            homepage: https:// | 
| 174 | 
            +
            homepage: https://karafka.io
         | 
| 173 175 | 
             
            licenses:
         | 
| 174 176 | 
             
            - MIT
         | 
| 175 | 
            -
            metadata: | 
| 177 | 
            +
            metadata:
         | 
| 178 | 
            +
              source_code_uri: https://github.com/karafka/waterdrop
         | 
| 179 | 
            +
              rubygems_mfa_required: 'true'
         | 
| 176 180 | 
             
            post_install_message: 
         | 
| 177 181 | 
             
            rdoc_options: []
         | 
| 178 182 | 
             
            require_paths:
         | 
| @@ -181,14 +185,14 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 181 185 | 
             
              requirements:
         | 
| 182 186 | 
             
              - - ">="
         | 
| 183 187 | 
             
                - !ruby/object:Gem::Version
         | 
| 184 | 
            -
                  version: 2. | 
| 188 | 
            +
                  version: '2.7'
         | 
| 185 189 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 186 190 | 
             
              requirements:
         | 
| 187 191 | 
             
              - - ">="
         | 
| 188 192 | 
             
                - !ruby/object:Gem::Version
         | 
| 189 193 | 
             
                  version: '0'
         | 
| 190 194 | 
             
            requirements: []
         | 
| 191 | 
            -
            rubygems_version: 3. | 
| 195 | 
            +
            rubygems_version: 3.3.4
         | 
| 192 196 | 
             
            signing_key: 
         | 
| 193 197 | 
             
            specification_version: 4
         | 
| 194 198 | 
             
            summary: Kafka messaging made easy!
         | 
    
        metadata.gz.sig
    CHANGED
    
    | Binary file | 
    
        data/lib/water_drop.rb
    DELETED
    
    | @@ -1,36 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            # External components
         | 
| 4 | 
            -
            # delegate should be removed because we don't need it, we just add it because of ruby-kafka
         | 
| 5 | 
            -
            %w[
         | 
| 6 | 
            -
              concurrent/array
         | 
| 7 | 
            -
              dry-configurable
         | 
| 8 | 
            -
              dry/monitor/notifications
         | 
| 9 | 
            -
              dry-validation
         | 
| 10 | 
            -
              rdkafka
         | 
| 11 | 
            -
              json
         | 
| 12 | 
            -
              zeitwerk
         | 
| 13 | 
            -
              securerandom
         | 
| 14 | 
            -
            ].each { |lib| require lib }
         | 
| 15 | 
            -
             | 
| 16 | 
            -
            # WaterDrop library
         | 
| 17 | 
            -
            module WaterDrop
         | 
| 18 | 
            -
              class << self
         | 
| 19 | 
            -
                # @return [String] root path of this gem
         | 
| 20 | 
            -
                def gem_root
         | 
| 21 | 
            -
                  Pathname.new(File.expand_path('..', __dir__))
         | 
| 22 | 
            -
                end
         | 
| 23 | 
            -
              end
         | 
| 24 | 
            -
            end
         | 
| 25 | 
            -
             | 
| 26 | 
            -
            Zeitwerk::Loader
         | 
| 27 | 
            -
              .for_gem
         | 
| 28 | 
            -
              .tap { |loader| loader.ignore("#{__dir__}/waterdrop.rb") }
         | 
| 29 | 
            -
              .tap(&:setup)
         | 
| 30 | 
            -
              .tap(&:eager_load)
         | 
| 31 | 
            -
             | 
| 32 | 
            -
            # Rdkafka uses a single global callback for things. We bypass that by injecting a manager for
         | 
| 33 | 
            -
            # each callback type. Callback manager allows us to register more than one callback
         | 
| 34 | 
            -
            # @note Those managers are also used by Karafka for consumer related statistics
         | 
| 35 | 
            -
            Rdkafka::Config.statistics_callback = WaterDrop::Instrumentation.statistics_callbacks
         | 
| 36 | 
            -
            Rdkafka::Config.error_callback = WaterDrop::Instrumentation.error_callbacks
         |