The Wayback Machine - https://web.archive.org/web/20201109232400/https://github.com/fluent/fluentd/pull/1857
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Counter API #1857

Merged
merged 23 commits into from Apr 21, 2018
Merged

Counter API #1857

merged 23 commits into from Apr 21, 2018

Conversation

@repeatedly
Copy link
Member

@repeatedly repeatedly commented Feb 14, 2018

Update version of #1241
We continue to update a patch here.

@repeatedly repeatedly added the v1 label Feb 14, 2018
@repeatedly repeatedly self-assigned this Feb 14, 2018
@repeatedly
Copy link
Member Author

@repeatedly repeatedly commented Feb 14, 2018

@okkez If you want to test counter-api, use this branch instead.

@okkez
Copy link
Contributor

@okkez okkez commented Feb 21, 2018

I've tried to test counter-api but it seems that counter-api is wok in progress.
Fluentd does not call any counter-api (client). So I cannot test counter-api with Fluentd and fluent-plugin-xxx, for now.

I will try to add some ad-hoc patch and test counter-api with Fluentd.

Copy link
Contributor

@okkez okkez left a comment

I've noticed some points.

config_param :scope, :string

desc 'endpoint of counter server'
config_param :endpoint, :string # host:port

This comment has been minimized.

@okkez

okkez Mar 30, 2018
Contributor

How about splitting host and port for consistency with other plugins such as in_forward and in_monitor_agent?
It is useful to set the default value for those parameters.

config_section :counter_server, multi: false do
  config_param :bind, :string
  config_param :port, :integer
end

config_section :counter_client, multi: false do
desc 'endpoint of counter client'
config_param :endpoint, :string # host:port

This comment has been minimized.

@okkez

okkez Mar 30, 2018
Contributor

How about following? It is useful to set the default value for those parameters.

config_sectio :counter_client, multi: false do
  config_param :host, :string
  config_param :port, :integer
end
@port = opt[:port] || DEFAULT_PORT
@addr = opt[:addr] || DEFAULT_ADDR
@log = opt[:log] || $log
@conn = Connection.connect(@addr, @port, method(:on_message))

This comment has been minimized.

@okkez

okkez Mar 30, 2018
Contributor

How about following?
Fluent::Counter::Client is used by plugin developers and Counter API users. Is this right?
opt ={} does not describe details of parameters. Thus users have to read the code to understand this API.
We may also need plugin helper to create Counter API client for plugins.

def initialize(event_loop: Coolio::Loop.new, log: $log, host: '127.0.0.1', port: 4321)
  @event_loop = event_loop
  @host = host
  @port = port
  @log = log
  @conn = Connection.connect(@host, @port, method(:on_message))
  # ...
end
socket_manager_path = ServerEngine::SocketManager::Server.generate_path
ServerEngine::SocketManager::Server.open(socket_manager_path)
ENV['SERVERENGINE_SOCKETMANAGER_PATH'] = socket_manager_path.to_s
end

def after_run
stop_rpc_server if @rpc_endpoint
stop_counter_server if @counter_endpoint

This comment has been minimized.

@okkez

okkez Apr 2, 2018
Contributor

@counter_endpoint is removed in 056a344.

exist_scope!
params = [params] unless params.is_a?(Array)
res = send_request('inc', @scope, params, options)
options[:async] ? res : res.get

This comment has been minimized.

@okkez

okkez Apr 2, 2018
Contributor

How about like following?

      def inc(params, options: {})
        exist_scope!
        params = [params] unless params.is_a?(Array)
        res = send_request('inc', @scope, params, options)
        if options[:async]
          if block_given?
            Thread.start do
              yield res.get
            end
          else
            res
          end
        else
          if block_given?
            yield res.get
          else
            res.get
          end
        end
      end

We can use this as following:

@counter_client = ...
@counter_client.inc({ name: "counter", value: 1}, options: { async: true }) do |response|
   # use response here
end

In the original code, we must handle future instance always when we send request asynchronously.

This comment has been minimized.

@repeatedly

repeatedly Apr 5, 2018
Author Member

Added suggested API.

def get
# Block until `set` method is called and @result is set a value
join if @result.nil?
@result

This comment has been minimized.

@okkez

okkez Apr 2, 2018
Contributor

How about changing the return value to Response object from plain Hash?

class Response
   attr_reader :errors, :data
   def initialize(result)
      @errors = result["errors"]
      @data = result["data"]
      # ...
   end

  def success?
    @errors.nil? || @errors.empty?
  end

  def error?
    !success?
  end
end

It is useful to check Counter API response as following:

@counter_client.inc({ name: "counter", value: 1}, options: { async: true }) do |response|
   if response.success?
     log.debug("Update counter successfully")
   else
     log.warn("Counter API error: #{response.errors}")
   end
end

Original code:

future = @counter_client.inc({ name: "counter", value: 1}, options: { async: true })
Thread.start do
  response = future.get
  if future.errors?
     log.error("failure")
  else
     log.debug("success")
  end
end

This comment has been minimized.

@repeatedly

repeatedly Apr 4, 2018
Author Member

Looks good. I will apply the changes soon.

repeatedly added 4 commits Apr 4, 2018
Signed-off-by: Masahiro Nakagawa <repeatedly@gmail.com>
Signed-off-by: Masahiro Nakagawa <repeatedly@gmail.com>
@repeatedly
Copy link
Member Author

@repeatedly repeatedly commented Apr 16, 2018

@okkez Do you have other suggestion? If not, I have a plan to merge this PR.

@okkez
Copy link
Contributor

@okkez okkez commented Apr 17, 2018

@repeatedly I want a shorthand for @counter_client.inc({ name: "name", value: 1 }, options: { async: true }). It is annoying to specify options: { async: true } for each asynchronous request.

How about that the counter client sends an asynchronous request by default?

Or, how about that plugin helper creates an asynchronous client?

async_client = counter_client_create(scope: "datacounter", async: true)
async_client.inc(name: "name", value: 1) # send an asynchronous request
async_client.inc(name: "name", value: 1, options: { async: false }) # send a synchronous request

Or else...?
Anyway, I want a shorthand to send asynchronous requests.

@repeatedly
Copy link
Member Author

@repeatedly repeatedly commented Apr 17, 2018

How about that the counter client sends an asynchronous request by default?

I see. One idea is removing sync API. Adding .get is low cost and it is not messy in user code.

future = client.inc(name: "name", value: 1)  # async
result = client.inc(name: "name", value: 1).get  # get result in sync

How about this?

@okkez
Copy link
Contributor

@okkez okkez commented Apr 17, 2018

Looks good to me 👍

Signed-off-by: Masahiro Nakagawa <repeatedly@gmail.com>
@repeatedly
Copy link
Member Author

@repeatedly repeatedly commented Apr 17, 2018

Remove sync API

@repeatedly repeatedly mentioned this pull request Apr 17, 2018
@repeatedly repeatedly merged commit ee4a192 into master Apr 21, 2018
1 of 4 checks passed
1 of 4 checks passed
License Compliance 17 issues found.
Details
DCO The sign-off is missing.
Details
continuous-integration/appveyor/pr AppVeyor build failed
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
@repeatedly
Copy link
Member Author

@repeatedly repeatedly commented Apr 21, 2018

Merged. We will improve Counter API with actual plugins.

@ganmacs ganmacs deleted the counter-api branch Jul 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
3 participants
You can’t perform that action at this time.