Giter Site home page Giter Site logo

bigcommerce / gruf Goto Github PK

View Code? Open in Web Editor NEW
613.0 49.0 75.0 660 KB

gRPC Ruby Framework

Home Page: https://github.com/bigcommerce/gruf

License: MIT License

Ruby 99.31% Shell 0.69%
grpc ruby protobuf rails gruf grpc-ruby-framework grpc-services

gruf's People

Contributors

andydangerous avatar bc-amit avatar dorner avatar fxn avatar gbanuel avatar heka1024 avatar j05h avatar jgarber623 avatar juanyifeng avatar kruczjak avatar ledbettj avatar leonid-shevtsov avatar mattolson avatar pathbox avatar pedelman avatar rgrison avatar scoup avatar songhuangcn avatar splittingred avatar tooooolong avatar ximus avatar y-yagi avatar ydah avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gruf's Issues

New Relic support

It seems that gRPC and New Relic dont integrate currently -- is this something Gruf should add support for?

Segmentation fault when use HAProxy

OS Version

macOS 10.13.4

Ruby Version

ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-darwin17]

Rails Version

Rails 4.2.6

Protoc Version

libprotoc 3.5.1

Grpc version

grpc (1.10.0 universal-darwin)

Gruf Version

2.3.0

HAProxy Version

HA-Proxy version 1.8.7 2018/04/07

HAProxy config

global
  log    127.0.0.1 local2 notice

defaults
    log    global      
    timeout connect 10s     
    timeout client 10s  
    timeout server 10s 
    maxconn     600      
    retries     3           

listen grpc
    bind 0.0.0.0:8081
    maxconn 300
    mode tcp

    balance roundrobin
    server srv01 0.0.0.0:9001 maxconn 1000 check

Crash log

/Users/spirit/.rvm/gems/ruby-2.3.0/gems/gruf-2.3.0/lib/gruf/server.rb:88: [BUG] Segmentation fault at 0x00000000000000
ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-darwin17]

-- Crash Report log information --------------------------------------------
   See Crash Report log file under the one of following:
     * ~/Library/Logs/CrashReporter
     * /Library/Logs/CrashReporter
     * ~/Library/Logs/DiagnosticReports
     * /Library/Logs/DiagnosticReports
   for more details.
Don't forget to include the above Crash Report log file in bug reports.

-- Control frame information -----------------------------------------------
c:0024 p:---- s:0117 e:000116 CFUNC  :join
c:0023 p:0074 s:0114 E:0000d0 METHOD /Users/spirit/.rvm/gems/ruby-2.3.0/gems/gruf-2.3.0/lib/gruf/server.rb:88
c:0022 p:0052 s:0109 e:000108 METHOD /Users/spirit/.rvm/gems/ruby-2.3.0/gems/gruf-2.3.0/lib/gruf/cli/executor.rb:38
c:0021 p:0083 s:0102 e:000101 TOP    /Users/spirit/.rvm/gems/ruby-2.3.0/gems/gruf-2.3.0/bin/gruf:29 [FINISH]
c:0020 p:---- s:0099 e:000098 CFUNC  :load
c:0019 p:0152 s:0095 e:000094 TOP    /Users/spirit/.rvm/gems/ruby-2.3.0/bin/gruf:23 [FINISH]
c:0018 p:---- s:0091 e:000090 CFUNC  :load
c:0017 p:0170 s:0087 e:000086 METHOD /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/cli/exec.rb:75
c:0016 p:0089 s:0078 e:000077 METHOD /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/cli/exec.rb:28
c:0015 p:0032 s:0074 e:000073 METHOD /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/cli.rb:424
c:0014 p:0078 s:0070 e:000069 METHOD /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/command.rb:27
c:0013 p:0058 s:0063 e:000062 METHOD /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/invocation.rb:126
c:0012 p:0311 s:0057 e:000056 METHOD /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor.rb:387
c:0011 p:0012 s:0045 e:000044 METHOD /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/cli.rb:27
c:0010 p:0070 s:0041 e:000040 METHOD /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/base.rb:466
c:0009 p:0012 s:0035 e:000034 METHOD /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/cli.rb:18
c:0008 p:0090 s:0030 e:000029 BLOCK  /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/exe/bundle:30
c:0007 p:0006 s:0025 e:000024 METHOD /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/friendly_errors.rb:122
c:0006 p:0056 s:0021 E:0019b0 TOP    /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/exe/bundle:22 [FINISH]
c:0005 p:---- s:0019 e:000018 CFUNC  :load
c:0004 p:0152 s:0015 E:000780 EVAL   /Users/spirit/.rvm/gems/ruby-2.3.0/bin/bundle:23 [FINISH]
c:0003 p:---- s:0011 e:000010 CFUNC  :eval
c:0002 p:0138 s:0005 E:001b08 EVAL   /Users/spirit/.rvm/gems/ruby-2.3.0/bin/ruby_executable_hooks:15 [FINISH]
c:0001 p:0000 s:0002 E:000020 (none) [FINISH]

-- Ruby level backtrace information ----------------------------------------
/Users/spirit/.rvm/gems/ruby-2.3.0/bin/ruby_executable_hooks:15:in `<main>'
/Users/spirit/.rvm/gems/ruby-2.3.0/bin/ruby_executable_hooks:15:in `eval'
/Users/spirit/.rvm/gems/ruby-2.3.0/bin/bundle:23:in `<main>'
/Users/spirit/.rvm/gems/ruby-2.3.0/bin/bundle:23:in `load'
/Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/exe/bundle:22:in `<top (required)>'
/Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/friendly_errors.rb:122:in `with_friendly_errors'
/Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/exe/bundle:30:in `block in <top (required)>'
/Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/cli.rb:18:in `start'
/Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/base.rb:466:in `start'
/Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/cli.rb:27:in `dispatch'
/Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor.rb:387:in `dispatch'
/Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'
/Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
/Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/cli.rb:424:in `exec'
/Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/cli/exec.rb:28:in `run'
/Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/cli/exec.rb:75:in `kernel_load'
/Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/cli/exec.rb:75:in `load'
/Users/spirit/.rvm/gems/ruby-2.3.0/bin/gruf:23:in `<top (required)>'
/Users/spirit/.rvm/gems/ruby-2.3.0/bin/gruf:23:in `load'
/Users/spirit/.rvm/gems/ruby-2.3.0/gems/gruf-2.3.0/bin/gruf:29:in `<top (required)>'
/Users/spirit/.rvm/gems/ruby-2.3.0/gems/gruf-2.3.0/lib/gruf/cli/executor.rb:38:in `run'
/Users/spirit/.rvm/gems/ruby-2.3.0/gems/gruf-2.3.0/lib/gruf/server.rb:88:in `start!'
/Users/spirit/.rvm/gems/ruby-2.3.0/gems/gruf-2.3.0/lib/gruf/server.rb:88:in `join'

-- Machine register context ------------------------------------------------
 rax: 0x00007f82bc27ce40 rbx: 0x00007f82c006ec40 rcx: 0x0000000000000000
 rdx: 0x0000000000000000 rdi: 0x0000000000000000 rsi: 0x0000000000000000
 rbp: 0x000070000c073020 rsp: 0x000070000c073020  r8: 0x0000000000000006
  r9: 0x00007f82bde24bb0 r10: 0x000007f82bdaf53c r11: 0x00006fff03b85f7f
 r12: 0x0000000000000003 r13: 0xcf3d4d12b20f00c2 r14: 0x0000000000000000
 r15: 0x000070000c076fc0 rip: 0x00007fff52dbb232 rfl: 0x0000000000010246

-- C level backtrace information -------------------------------------------
0   libruby.2.3.0.dylib                 0x0000000107562c19 rb_vm_bugreport + 377
1   libruby.2.3.0.dylib                 0x00000001073fc704 rb_bug_context + 452
2   libruby.2.3.0.dylib                 0x00000001074d45d4 sigsegv + 68
3   libsystem_platform.dylib            0x00007fff53079f5a _sigtramp + 26
4   libsystem_c.dylib                   0x00007fff52dbb232 strlen + 18
5   ???                                 0x000070000c0730a0 0x0 + 123145504108704

-- Other runtime information -----------------------------------------------

* Loaded script: /Users/spirit/.rvm/gems/ruby-2.3.0/bin/gruf

* Loaded features:

    0 enumerator.so
    1 thread.rb
    2 rational.so
    3 complex.so
    4 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/x86_64-darwin17/enc/encdb.bundle
    5 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/x86_64-darwin17/enc/trans/transdb.bundle
    6 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/unicode_normalize.rb
    7 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/x86_64-darwin17/rbconfig.rb
    8 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/compatibility.rb
    9 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/defaults.rb
   10 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/deprecate.rb
   11 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/errors.rb
   12 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/version.rb
   13 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/requirement.rb
   14 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/platform.rb
   15 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/basic_specification.rb
   16 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/stub_specification.rb
   17 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/util/list.rb
   18 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/x86_64-darwin17/stringio.bundle
   19 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/specification.rb
   20 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/exceptions.rb
   21 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_gem.rb
   22 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/monitor.rb
   23 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb
   24 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems.rb
   25 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/path_support.rb
   26 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/dependency.rb
   27 /Users/spirit/.rvm/gems/ruby-2.3.0@global/gems/did_you_mean-1.0.0/lib/did_you_mean/version.rb
   28 /Users/spirit/.rvm/gems/ruby-2.3.0@global/gems/did_you_mean-1.0.0/lib/did_you_mean/core_ext/name_error.rb
   29 /Users/spirit/.rvm/gems/ruby-2.3.0@global/gems/did_you_mean-1.0.0/lib/did_you_mean/levenshtein.rb
   30 /Users/spirit/.rvm/gems/ruby-2.3.0@global/gems/did_you_mean-1.0.0/lib/did_you_mean/jaro_winkler.rb
   31 /Users/spirit/.rvm/gems/ruby-2.3.0@global/gems/did_you_mean-1.0.0/lib/did_you_mean/spell_checkable.rb
   32 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/delegate.rb
   33 /Users/spirit/.rvm/gems/ruby-2.3.0@global/gems/did_you_mean-1.0.0/lib/did_you_mean/spell_checkers/name_error_checkers/class_name_checker.rb
   34 /Users/spirit/.rvm/gems/ruby-2.3.0@global/gems/did_you_mean-1.0.0/lib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb
   35 /Users/spirit/.rvm/gems/ruby-2.3.0@global/gems/did_you_mean-1.0.0/lib/did_you_mean/spell_checkers/name_error_checkers.rb
   36 /Users/spirit/.rvm/gems/ruby-2.3.0@global/gems/did_you_mean-1.0.0/lib/did_you_mean/spell_checkers/method_name_checker.rb
   37 /Users/spirit/.rvm/gems/ruby-2.3.0@global/gems/did_you_mean-1.0.0/lib/did_you_mean/spell_checkers/null_checker.rb
   38 /Users/spirit/.rvm/gems/ruby-2.3.0@global/gems/did_you_mean-1.0.0/lib/did_you_mean/formatter.rb
   39 /Users/spirit/.rvm/gems/ruby-2.3.0@global/gems/did_you_mean-1.0.0/lib/did_you_mean.rb
   40 /Users/spirit/.rvm/gems/ruby-2.3.0@global/gems/executable-hooks-1.4.2/lib/executable-hooks/hooks.rb
   41 /Users/spirit/.rvm/gems/ruby-2.3.0@global/gems/rubygems-bundler-1.4.4/lib/rubygems-bundler/noexec.rb
   42 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/version.rb
   43 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/compatibility_guard.rb
   44 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/x86_64-darwin17/etc.bundle
   45 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/fileutils.rb
   46 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendored_fileutils.rb
   47 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/x86_64-darwin17/pathname.bundle
   48 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/pathname.rb
   49 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/errors.rb
   50 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/environment_preserver.rb
   51 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/plugin/api.rb
   52 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/plugin.rb
   53 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/uri/rfc2396_parser.rb
   54 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/uri/rfc3986_parser.rb
   55 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/uri/common.rb
   56 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/uri/generic.rb
   57 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/uri/ftp.rb
   58 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/uri/http.rb
   59 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/uri/https.rb
   60 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/uri/ldap.rb
   61 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/uri/ldaps.rb
   62 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/uri/mailto.rb
   63 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/uri.rb
   64 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/x86_64-darwin17/digest.bundle
   65 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/digest.rb
   66 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/util.rb
   67 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/source/git.rb
   68 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/source/installed.rb
   69 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/source/specific_file.rb
   70 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/source/local.rb
   71 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/source/lock.rb
   72 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/source/vendor.rb
   73 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/source.rb
   74 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/gem_helpers.rb
   75 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/match_platform.rb
   76 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/rubygems_ext.rb
   77 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/x86_64-darwin17/io/console.bundle
   78 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/user_interaction.rb
   79 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/config_file.rb
   80 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/rubygems_integration.rb
   81 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/constants.rb
   82 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/current_ruby.rb
   83 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/build_metadata.rb
   84 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler.rb
   85 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/cgi/core.rb
   86 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/x86_64-darwin17/cgi/escape.bundle
   87 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/cgi/util.rb
   88 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/cgi/cookie.rb
   89 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/cgi.rb
   90 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/set.rb
   91 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/command.rb
   92 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb
   93 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/core_ext/ordered_hash.rb
   94 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/error.rb
   95 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/invocation.rb
   96 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/parser/argument.rb
   97 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb
   98 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/parser/option.rb
   99 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/parser/options.rb
  100 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/parser.rb
  101 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/shell.rb
  102 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/line_editor/basic.rb
  103 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/x86_64-darwin17/readline.bundle
  104 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/line_editor/readline.rb
  105 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/line_editor.rb
  106 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/util.rb
  107 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor/base.rb
  108 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendor/thor/lib/thor.rb
  109 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/vendored_thor.rb
  110 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/friendly_errors.rb
  111 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/cli/common.rb
  112 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/settings.rb
  113 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/feature_flag.rb
  114 /Users/spirit/.rvm/gems/ruby-2.3.0/gems/bundler-1.16.1/lib/bundler/shared_helpers.rb
  115 /Users/spirit/.rvm/rubies/ruby-2.3.0/lib/ruby/site_ruby/2.3.0/rubygems/ext/builder.rb

First start gruf bundle exec gruf, then start HAProxy, so the gruf crashed

DescriptorPool: out of memory

Please describe the issue

After defining many protos the server is unable to start.

How to Reproduce

Steps to reproduce the behavior:

  1. defined many protos
  2. Try starting server

is there a way to increase memory or any configuration or way to debug this issue?

What should happen?

Start gruf server

Anything else we should know?

Sample proto

syntax = "proto3";

import "AddressModel.proto";
import "ClientCreditModel.proto";
import "ContactModel.proto";
import "Filter.proto";

package remote_proto;

service Clients {
  rpc Index(IndexReq) returns (stream ClientModel) {}
  rpc Show(ShowReq) returns (ShowResp) { }
}

// model
message ClientModel {
  uint32 id = 1;
  string name = 2;
  float price = 3;
  repeated Address addresses = 4;
  repeated Contact contacts = 5;
  ClientCredit client_credit = 6;
}

message IndexReq {
  uint32 limit = 1;
  uint32 page = 2;
  Filter filter = 3;
}

message ShowReq {
  uint64 id = 1;
}

message ShowResp {
  ClientModel client = 1;
}

Generated

# Generated by the protocol buffer compiler.  DO NOT EDIT!
# source: Clients.proto

require 'google/protobuf'

require 'app/proto/AddressModel_pb'
require 'app/proto/ClientCreditModel_pb'
require 'app/proto/ContactModel_pb'
require 'app/proto/Filter_pb'
Google::Protobuf::DescriptorPool.generated_pool.build do
  add_file("app/proto/Clients.proto", :syntax => :proto3) do
    add_message "remote_proto.ClientModel" do
      optional :id, :uint32, 1
      optional :name, :string, 2
      optional :price, :float, 3
      repeated :addresses, :message, 4, "remote_proto.Address"
      repeated :contacts, :message, 5, "remote_proto.Contact"
      optional :client_credit, :message, 6, "remote_proto.ClientCredit"
    end
    add_message "remote_proto.IndexReq" do
      optional :limit, :uint32, 1
      optional :page, :uint32, 2
      optional :filter, :message, 3, "remote_proto.Filter"
    end
    add_message "remote_proto.ShowReq" do
      optional :id, :uint64, 1
    end
    add_message "remote_proto.ShowResp" do
      optional :client, :message, 1, "remote_proto.ClientModel"
    end
  end
end

module RemoteProto
  ClientModel = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("remote_proto.ClientModel").msgclass
  IndexReq = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("remote_proto.IndexReq").msgclass
  ShowReq = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("remote_proto.ShowReq").msgclass
  ShowResp = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("remote_proto.ShowResp").msgclass
end
# Generated by the protocol buffer compiler.  DO NOT EDIT!
# Source: Clients.proto for package 'remote_proto'

require 'grpc'
require 'app/proto/Clients_pb'

module RemoteProto
  module Clients
    class Service

      include GRPC::GenericService

      self.marshal_class_method = :encode
      self.unmarshal_class_method = :decode
      self.service_name = 'remote_proto.Clients'

      rpc :Index, ::RemoteProto::IndexReq, stream(::RemoteProto::ClientModel)
      rpc :Show, ::RemoteProto::ShowReq, ::RemoteProto::ShowResp
    end

    Stub = Service.rpc_stub_class
  end
end

Error

bundle exec gruf
bundler: failed to load command: gruf (/home/fusion01/.rbenv/versions/2.6.5/bin/gruf)
Google::Protobuf::TypeError: Unable to add defs to DescriptorPool: out of memory
  /home/fusion01/Documentos/Fusion/Web Cimentao/varejo-api/app/rpc/app/proto/Contacts_pb.rb:9:in `add_file'
  /home/fusion01/Documentos/Fusion/Web Cimentao/varejo-api/app/rpc/app/proto/Contacts_pb.rb:9:in `block in <main>'
  /home/fusion01/Documentos/Fusion/Web Cimentao/varejo-api/app/rpc/app/proto/Contacts_pb.rb:8:in `instance_eval'
  /home/fusion01/Documentos/Fusion/Web Cimentao/varejo-api/app/rpc/app/proto/Contacts_pb.rb:8:in `build'
  /home/fusion01/Documentos/Fusion/Web Cimentao/varejo-api/app/rpc/app/proto/Contacts_pb.rb:8:in `<main>'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.9/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.9/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.9/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.9/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.9/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/zeitwerk-2.4.1/lib/zeitwerk/kernel.rb:33:in `require'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.4/lib/active_support/dependencies.rb:324:in `block in require'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.4/lib/active_support/dependencies.rb:291:in `load_dependency'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.4/lib/active_support/dependencies.rb:324:in `require'
  /home/fusion01/Documentos/Fusion/Web Cimentao/varejo-api/app/rpc/app/proto/Contacts_services_pb.rb:5:in `<main>'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.9/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.9/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.9/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in `register'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.9/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in `require_with_bootsnap_lfi'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.9/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in `require'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/zeitwerk-2.4.1/lib/zeitwerk/kernel.rb:33:in `require'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.4/lib/active_support/dependencies.rb:324:in `block in require'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.4/lib/active_support/dependencies.rb:291:in `load_dependency'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.4/lib/active_support/dependencies.rb:324:in `require'
  /home/fusion01/Documentos/Fusion/Web Cimentao/varejo-api/config/initializers/gruf.rb:4:in `<main>'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.9/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:59:in `load'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.9/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:59:in `load'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.4/lib/active_support/dependencies.rb:318:in `block in load'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.4/lib/active_support/dependencies.rb:291:in `load_dependency'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.4/lib/active_support/dependencies.rb:318:in `load'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/railties-6.0.3.4/lib/rails/engine.rb:666:in `block in load_config_initializer'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.4/lib/active_support/notifications.rb:182:in `instrument'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/railties-6.0.3.4/lib/rails/engine.rb:665:in `load_config_initializer'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/railties-6.0.3.4/lib/rails/engine.rb:625:in `block (2 levels) in <class:Engine>'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/railties-6.0.3.4/lib/rails/engine.rb:624:in `each'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/railties-6.0.3.4/lib/rails/engine.rb:624:in `block in <class:Engine>'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/railties-6.0.3.4/lib/rails/initializable.rb:32:in `instance_exec'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/railties-6.0.3.4/lib/rails/initializable.rb:32:in `run'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/railties-6.0.3.4/lib/rails/initializable.rb:61:in `block in run_initializers'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/2.6.0/tsort.rb:228:in `block in tsort_each'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/2.6.0/tsort.rb:350:in `block (2 levels) in each_strongly_connected_component'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/2.6.0/tsort.rb:422:in `block (2 levels) in each_strongly_connected_component_from'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/2.6.0/tsort.rb:431:in `each_strongly_connected_component_from'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/2.6.0/tsort.rb:421:in `block in each_strongly_connected_component_from'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/railties-6.0.3.4/lib/rails/initializable.rb:50:in `each'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/railties-6.0.3.4/lib/rails/initializable.rb:50:in `tsort_each_child'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/2.6.0/tsort.rb:415:in `call'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/2.6.0/tsort.rb:415:in `each_strongly_connected_component_from'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/2.6.0/tsort.rb:349:in `block in each_strongly_connected_component'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/2.6.0/tsort.rb:347:in `each'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/2.6.0/tsort.rb:347:in `call'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/2.6.0/tsort.rb:347:in `each_strongly_connected_component'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/2.6.0/tsort.rb:226:in `tsort_each'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/2.6.0/tsort.rb:205:in `tsort_each'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/railties-6.0.3.4/lib/rails/initializable.rb:60:in `run_initializers'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/railties-6.0.3.4/lib/rails/application.rb:363:in `initialize!'
  config/environment.rb:5:in `<top (required)>'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.4/lib/active_support/dependencies.rb:318:in `load'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.4/lib/active_support/dependencies.rb:318:in `block in load'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.4/lib/active_support/dependencies.rb:291:in `load_dependency'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.4/lib/active_support/dependencies.rb:318:in `load'
  /home/fusion01/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/gruf-2.8.1/bin/gruf:25:in `<top (required)>'
  /home/fusion01/.rbenv/versions/2.6.5/bin/gruf:23:in `load'
  /home/fusion01/.rbenv/versions/2.6.5/bin/gruf:23:in `<top (required)>'
  • Ruby versions: 2.5.5, 2.6.5 and 2.7.1
  • OS: Ubuntu 19.04

Idea: Refactoring TLS options/configuration/etc.

Hello! I recently came across Gruf and I'm really enjoying using it with some gRPC services we're implementing at work. Thank you for your hard work on this gem!

Background

I started digging in to the build_ssl_credentials to determine how the gem creates instances of GRPC::Core::ChannelCredentials (the relevant lines in client.rb).

Gruf currently supports passing a path to a file (ssl_certificate_file) or a string representing a single certificate (ssl_certificate). Both are coerced and passed to GRPC::Core::ChannelCredentials.new as a single argument.

This behavior maps to one of several cases supported by the GRPC::Core::ChannelCredentials. That class itself is generated on-the-fly (I thinkโ€ฆ), but we can infer what it supports from the class' specs. The cases in the specs show that the class can take no arguments, one argument (as supported by Gruf), and three arguments (PEM-encoded root certificate, client key, and client certificate).

Question/Idea/Feature Request

Would it be reasonable to modify Gruf to support the latter case? Possibly having a new option (e.g. certificate_list) that is an Array that build_ssl_credentials passes as arguments to GRPC::Core::ChannelCredentials?

Or, a broader refactoring that allows for more declarative specification of root certificate, client key, and client certificate could be useful, too.

Edit: Another idea: would it be reasonable to also allow passing an existing GRPC::Core::ChannelCredentials instance?

I'm not terribly familiar with C, but I think these are the relevant lines demonstrating how the GRPC gem handles channel credential creation in grpc/src/ruby/ext/grpc/rb_channel_credentials.h.

If one or more of the above ideas seems reasonable, I'd be happy to put together a PR for feedback. Let me know what y'all think and thanks for your time!

Gruf::Client::Errors::Internal errors

Please describe the issue

Our web service is sending gRPC requests using Gruf::Client and it's returning a lot of Gruf::Client::Errors::Internal errors.

When I send the same request in a rails console, it works fine.

There are no additional messages attached to the exception, and nothing useful in the logs, except a stack trace pointing to

raise @error_factory.from_exception(resp.result) unless resp.success?

How to Reproduce

Hard to give repro steps because it works fine in a rails console, but in our puma web service, it keeps throwing Gruf::Client::Errors::Internal exceptions.

What should happen?

Either the gRPC requests should succeed, or the Gruf::Client::Errors::Internal exceptions should have additional details on why it failed.

Anything else we should know?

  • gRPC version: 1.35.0
  • Ruby version: 2.6.3
  • OS: Linux d221dd419d11 4.19.121-linuxkit #1 SMP Tue Dec 1 17:50:32 UTC 2020 x86_64 GNU/Linux
    • Debian GNU/Linux 10 \n \l
  • Does it occur at certain traffic volumes, payload size, etc: not that I can tell

Configuration to disable gRPC native logging

When running a gRPC server with Gruf I notice logs such as:

deadline is 1969-12-31 23:59:59 +0000; (now=2017-05-04 21:56:58 +0000)

or

schedule another job

When investigating, I see that the logs are coming from the gRPC logger. (https://github.com/grpc/grpc/blob/6ff81e91c9577a52252460fb029fbbf990cfc7b6/src/ruby/lib/grpc/generic/rpc_server.rb#L80)

It would be nice to support a configuration option to disable this kind of logging from configuration in Gruf.

Protobuf wrapper class serialized as nil

Please describe the issue

Apologies in advance if this has nothing to do with gruf. I have a pretty straight-forward server/client setup and I'm serializing proto3 objects in the response. I'm seeing a strange issue where an int wrapper object with a value of 0, i.e. <Google::Protobuf::Int32Value: value: 0>, comes over the wire to the client as nil.

How to Reproduce

Serialize a proto object with a property as described in the issue.

What should happen?

The response on the client side should contain <Google::Protobuf::Int32Value: value: 0> for the particular attribute instead of nil

Anything else we should know?

Server:

  • google-protobuf 3.11
  • grpc 1.24
  • gruf 2.8.0
  • Ruby 2.6.3
  • OS: I think it's a debian docker container

Can not use gruf in a non-rails ruby application

gruf is not rails specific, but I hit the following exception when I try to use gruf in a non-rails application. It complains that it can not load rails.

$ bundle exec gruf
bundler: failed to load command: gruf (/Users/xinchen.shen/.rbenv/versions/2.4.1/bin/gruf)
LoadError: cannot load such file -- rails
  /Users/xinchen.shen/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/gruf-2.0.2/bin/gruf:20:in `require'
  /Users/xinchen.shen/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/gruf-2.0.2/bin/gruf:20:in `<top (required)>'
  /Users/xinchen.shen/.rbenv/versions/2.4.1/bin/gruf:22:in `load'
  /Users/xinchen.shen/.rbenv/versions/2.4.1/bin/gruf:22:in `<top (required)>'

request became nil in heavy traffic situation

We use Gruf in our production env and the throughput is around 38.5k per minute

And we are receiving errors like this occasionally. This error is raised in every services.

GRPC::Internal: 13:undefined method `market_uuid' for nil:NilClass

Our code looks like this. Looks like request.message is a nil.

class Smaug::V2::CandleService < ApplicationService
  bind Peatio::Smaug::V2::Candles::Service

  def list
    candles = Candle.where(
      market_uuid: request.message.market_uuid,
      period: request.message.period.to_s.downcase.to_sym
    )

    candles = build_query(
      candles,
      request.message.pagination,
      permit_order: ["time"],
      permit_where: ["time"]
    )

    Smaug::V2::CandleSerializer.serialize(candles)
  rescue Exception => e
    fail!(:internal, :internal, e.message)
  end
end

the call stack

  /usr/local/bundle/gems/gruf-2.5.0/lib/gruf/
error.rb: 176:in `fail!'
โ€ฆocal/bundle/gems/gruf-2.5.0/lib/gruf/errors/
helpers.rb:  38:in `fail!'
       /opt/app/app/services/smaug/v2/
candle_service.rb:  19:in `rescue in list'
       /opt/app/app/services/smaug/v2/candle_service.rb:   4:in `list'
โ€ฆal/bundle/gems/gruf-2.5.0/lib/gruf/controllers/
base.rb:  71:in `block in call'
โ€ฆundle/gems/gruf-2.5.0/lib/gruf/interceptors/
context.rb:  46:in `block (2 levels) in intercept!'
โ€ฆundle/gems/gruf-2.5.0/lib/gruf/interceptors/
context.rb:  46:in `block (2 levels) in intercept!'
โ€ฆundle/gems/gruf-2.5.0/lib/gruf/interceptors/context.rb:  46:in `block (2 levels) in intercept!'
โ€ฆundle/gems/gruf-2.5.0/lib/gruf/interceptors/
context.rb:  46:in `block (2 levels) in intercept!'
โ€ฆundle/gems/gruf-2.5.0/lib/gruf/interceptors/context.rb:  48:in `block in intercept!'
โ€ฆib/gruf/interceptors/active_record/
connection_reset.rb:   3:in `call'
โ€ฆundle/gems/gruf-2.5.0/lib/gruf/interceptors/context.rb:  44:in `intercept!'
โ€ฆundle/gems/gruf-2.5.0/lib/gruf/interceptors/
context.rb:  46:in `block in intercept!'
โ€ฆ/interceptors/instrumentation/output_metadata_timer.rb:  32:in `block in call'
โ€ฆ/bundle/gems/gruf-2.5.0/lib/gruf/interceptors/timer.rb:  72:in `time'
โ€ฆ/interceptors/instrumentation/output_metadata_timer.rb:  31:in `call'
โ€ฆundle/gems/gruf-2.5.0/lib/gruf/interceptors/context.rb:  44:in `intercept!'
โ€ฆundle/gems/gruf-2.5.0/lib/gruf/interceptors/context.rb:  46:in `block in intercept!'
โ€ฆundle/gems/gruf-2.5.0/lib/gruf/interceptors/context.rb:  44:in `intercept!'
โ€ฆundle/gems/gruf-2.5.0/lib/gruf/interceptors/context.rb:  46:in `block in intercept!'
       /opt/app/app/lib/gruf/interceptors/idempotent.rb:   5:in `call'
โ€ฆundle/gems/gruf-2.5.0/lib/gruf/interceptors/context.rb:  44:in `intercept!'
โ€ฆundle/gems/gruf-2.5.0/lib/gruf/interceptors/context.rb:  46:in `block in intercept!'
โ€ฆceptors/instrumentation/request_logging/interceptor.rb:  65:in `block in call'
โ€ฆ/bundle/gems/gruf-2.5.0/lib/gruf/interceptors/
timer.rb:  72:in `time'
โ€ฆceptors/instrumentation/request_logging/interceptor.rb:  64:in `call'
โ€ฆundle/gems/gruf-2.5.0/lib/gruf/interceptors/context.rb:  44:in `intercept!'
โ€ฆal/bundle/gems/gruf-2.5.0/lib/gruf/controllers/base.rb:  70:in `call'
โ€ฆgems/gruf-2.5.0/lib/gruf/controllers/service_binder.rb:  72:in `block (2 levels) in bind_method'
โ€ฆ5.0-x86_64-linux/src/ruby/lib/grpc/generic/rpc_desc.rb:  94:in `call'
โ€ฆ5.0-x86_64-linux/src/ruby/lib/grpc/generic/rpc_desc.rb:  94:in `block in handle_server_streamer'
โ€ฆx86_64-linux/src/ruby/lib/grpc/generic/interceptors.rb: 170:in `intercept!'
โ€ฆ5.0-x86_64-linux/src/ruby/lib/grpc/generic/rpc_desc.rb:  88:in `handle_server_streamer'
โ€ฆ5.0-x86_64-linux/src/ruby/lib/grpc/generic/rpc_desc.rb: 126:in `run_server_method'
โ€ฆ0-x86_64-linux/src/ruby/lib/grpc/generic/rpc_server.rb: 399:in `block in loop_handle_server_calls'
                          /opt/app/app/lib/grpc/pool.rb:   8:in `block in loop_execute_jobs'
                          /opt/app/app/lib/grpc/pool.rb:   5:in `loop'
                          /opt/app/app/lib/grpc/pool.rb:   5:in `loop_execute_jobs'
โ€ฆ0-x86_64-linux/src/ruby/lib/grpc/generic/rpc_server.rb:  84:in `block (2 levels) in start'
โ€ฆ0-x86_64-linux/src/ruby/lib/grpc/generic/rpc_server.rb:  83:in `catch'
โ€ฆ0-x86_64-linux/src/ruby/lib/grpc/generic/rpc_server.rb:  83:in `block in start'

Anything else we should know?

  • gRPC version 1.15.0 universal-darwin
  • Ruby version 2.5.1
  • OS linux / Ubuntu
  • Does it occur at certain traffic volumes, payload size, etc / NO

Configuration to choose unit for StatsD timings

It seems the timer we are using records the time by subtracting two Time.now calls, resulting in timings being recorded in seconds. Is this expected behavior? Many other tools choose to broadcast in ms.

irb(main):001:0> Time.now
=> 2017-04-28 05:17:58 +0000
irb(main):002:0> Time.now - _
=> 3.680870978

Current timing implementation in: lib/gruf/client.rb#L68-L70

timed = Timer.time do
  self.send(call_signature, req, return_op: true, metadata: md)
end
Gruf::Response.new(timed.result, timed.time)

The timer can be found in rubyworks/facets - lib/standard/facets/timer.rb

Perhaps we can add configuration to broadcast timings in different units?

The request response is not logged

What? Why?

Describe the problem you are occurring and a proposed solution for it.
I'm using Gruf::Interceptors::Instrumentation::RequestLogging::Interceptor with formatter: :plain for request and response logging, but current implementation doesn't log the result value. Is it intended?

Should we add the result to log?

Other Notables

Current source code, it is ignoring the result parameter

https://github.com/bigcommerce/gruf/blob/master/lib/gruf/interceptors/instrumentation/request_logging/formatters/plain.rb#L35-L43
Add any other context or screenshots about the feature request here.

client can not connect

rails start with passenger, Gruf::Client.new can not connect with grpc service.
but run in 'rails c' console is fine.

Zeitwerk conflicts with Rails 6

Please describe the issue

When I place the _pb.rb files in app/proto, the system fails to load them because they don't comply with the filename must match class name policy.

How to Reproduce

Generate some Ruby files from a .proto file. Place them somewhere rails can find them.

What should happen?

Gruf should start up and run.

Anything else we should know?

I got it to at least start by doing this in application.rb:

Rails.autoloaders.main.ignore(Rails.root.join('app/proto/'))

Gruf logs `Grpc::InvalidArgument` as an error rather than info

When utilizing the Gruf request logger, when the service raises a Grpc::InvalidArgument, Gruf is marking that as an error severity.

I consider InvalidArgument to be more of an "allowed" or "expected" behavior, and shouldn't be logged at such a severity. I propose we would handle this error as info level.

fail!(:bad_request, :bad_request, 'Bad Request')

Code that determine the log severity: lib/gruf/interceptors/instrumentation/request_logging/interceptor.rb#L52-L58

Blacklisting params does not support nested structures.

In Gruf 1.2.0 parameter blacklisting was added in order to filter out sensitive or long values from logs.

The current implementation will loop over each of the values in the incoming request object and check if that value is in the blacklist, if so, we will replace with some value (REDACTED by default). See: lib/gruf/instrumentation/request_logging/hook.rb#L126

Say I have a request like the following:

message UpdateUserReq {
  message Data {
    google.protobuf.StringValue sensitive = 1;
    ...
  }
  uint64 user_id = 1;
  Data data = 2;
}

With this structure, the incoming request params will have a shape like the following:

{:user_id=>263606,
 :data=>
  {:sensitive=>{:value=>"dont log me, or else"}}}

If I want to redact sensitive from the logs, I would expect to either define sensitive in the blacklist configuration, or to specify the key structure so that the blacklist knows how to traverse the hash, like data.sensitive.value.

Currently it is not possible to redact fields from within an embedded message.

Question: is it easier to use gruf with rails or not?

Note: this is not an issue per se, it's more of a general question. Let me know if this is not the best place to do this.

Hey guys,

I'm about to implement a gRPC service using ruby. gruf seems to be a great addition to achieve that goal.

I'm pondering whether I should use gruf with rails or not. What would be the main benefit of doing it? My service will be stateless, without a DB and not an http server. I see that gruf is supposed to be framework agnostic but a lot of the documentation is using examples inside rails apps. So I'm wondering if using gruf along with rails might be smoother.

Can I use struct objects instead of Hashes?

If an attribute was defined to be google.protobuf.Struct which is open-struct (allows to define any attribute keys).
I can't input undefined attributes within the hash on the client.call

# messaging_broker_pb.rb
require 'google/protobuf'

require 'google/api/annotations_pb'
require 'google/protobuf/struct_pb'
Google::Protobuf::DescriptorPool.generated_pool.build do
  add_message "messaging_broker.Receiver" do
    optional :type, :string, 1
    repeated :ids, :string, 2
  end
  add_message "messaging_broker.QueueParams" do
    optional :receiver, :message, 1, "messaging_broker.Receiver"
    repeated :messages, :message, 2, "google.protobuf.Struct"
  end
end

module MessagingBroker
  Receiver = Google::Protobuf::DescriptorPool.generated_pool.lookup("messaging_broker.Receiver").msgclass
  QueueParams = Google::Protobuf::DescriptorPool.generated_pool.lookup("messaging_broker.QueueParams").msgclass
end
# messaging_broker_services_pb.rb
require 'grpc'

module MessagingBroker
  module DispatchMessagesService
    class Service

      include GRPC::GenericService

      self.marshal_class_method = :encode
      self.unmarshal_class_method = :decode
      self.service_name = 'messaging_broker.DispatchMessagesService'

      rpc :Queue, QueueParams, QueueParams
    end

    Stub = Service.rpc_stub_class
  end
end
client = ::Gruf::Client.new(service: ::MessagingBroker::DispatchMessagesService, options: {hostname: 'localhost:9090' })
params = {
  receiver: {
    type: "user",
    ids: ["1", "2"]
  },
  messages: [
    { foo: "foo", test: "test" }  
  ]
}
client.call(:Queue, params) # error when mapping params

here's the problem when the messages supposed to be an array of message bodies.
the code line would say ArgumentError: Unknown field name 'foo' in initialization map entry.

Around filters

What? Why?

Can we get hooks like rails controller in this ? Interceptors are good but hooks can help set instance variables kind of thing.

Other Notables

Got this from a gist. But the idea is to do something like this:

module Util
  module ExecutionHooks
  # this method is invoked whenever a new instance method is added to a class
    def method_added(method_name)
      return if hooks.include?(method_name) || after_hooks.include?(method_name) || hooked_methods.include?(method_name)
      add_hooks_to(method_name)
    end

    def before_filter(method_name)
      hooks << method_name
    end

    def after_filter(method_name)
      after_hooks << method_name
    end

    def hooks
      @hooks ||= []
    end
    
    def after_hooks
      @after_hooks ||=[]
    end

    private

    def hooked_methods
      @hooked_methods ||= []
    end

    def add_hooks_to(method_name)

      hooked_methods << method_name

      original_method = instance_method(method_name)

      define_method(method_name) do |*args, &block|

        self.class.hooks.each do |hook|
          method(hook).call
        end

        response = original_method.bind(self).call(*args, &block)

        self.class.after_hooks.each do |hook|
          method(hook).call
        end

        response
        
      end
    end
  end
end

More clear docs needed

The docs are not clear on where relevant files should be put. Does there need to be a specific structure within app/rpc/ or can we order things however we like in there? How does the service file know how to find the foo_services_pb file? Does that need to be in a specific place? What about the .proto file, are they important?

I tried putting my files in various ways but every time I tried to run the server it failed because the module name for my service is not recognised in the gruff controller bind statement. I feel like there should be a require foo_services_pb statement at the top of the gruff controller file, but there isn't in the docs and the example app, so I'm confused how that works.

Support Rails code reloading in Dev env

What? Why?

Rails framework automatically reloads code when it is changed in dev environment. That enables developer to see changes right away without need of restarting the server. It would make development process much faster and easier, if within Rails framework, gruf could use reloaded code.

Other Notables

Starting Rails 5, there are helpers to deal with thread safety and code reloading. Other multi-threaded gems that integrate with Rails, use these helpers to enable code reloading in dev env. Refer to https://guides.rubyonrails.org/threading_and_code_execution.html#reloader and sidekiq/sidekiq@be2d129

When error/exception happens, metadata to be sent got dropped

Please describe the issue

When a GRPC::BadStatus, GRPC::Core::CallError or StandardError happens, the metadata prepared to be sent to client doesn't get combined with the Error response metadata to the client. So the metadata to be sent got drop when there's any error happens.

This is caused by the logic under gruf/controllers/base.rb

  • If gRPC BadStatus happens, it raises the error directly without appending metadata to be send to the error metadata.
  • If other kind of error happens, it return a gRPC BadStatus with status code 'INTERNAL' with no metadata

How to Reproduce

Steps to reproduce the behavior:

  1. Create a server interceptor to inject a key in metadata to be send like:

class TestServerInterceptor < ::Gruf::Interceptors::ServerInterceptor
   def call
ย      metadata = {"test-key" => "test-value"}
ย       request.active_call.merge_metadata_to_send(metadata)
ย       yield
ย  end
end

  1. Make your server use this TestServerInterceptor
  2. Make one of your RPC raise any error, for example:
    raise "Failure is simply the opportunity to begin again
  3. Use a client to make a RPC call to the server and inspect the metadata in the response. You will find the "test-key" get lost and never got send by the server.

Also, I double check in the gRPC ruby library and found even error happen, client will still received the prepared metadata by the interceptor. So this is a bug introduce by Gruf.

What should happen?

When error happen, client will still received the prepared metadata in the error metadata.

Anything else we should know?

  • gRPC version - 2.7.1
  • Ruby version - 2.6.2p47
  • OS - linux
  • Does it occur at certain traffic volumes, payload size, etc - all the time

Modify metadata inside client interceptor

What? Why?

In order to provide a library internally to handle authentication, we would like to implement an interceptor that runs on each client call and appends a JWT to the metadata of the request.

I have not been able to find any examples of modifying the request, just logging based activity. Is an update possible?

:invalid_request doesn't seem to be a valid error type

First of all, thank you for creating and maintaining this gem!

While trying it out myself, I realized that calling fail :invalid_request as explained in the Wiki actually raises an unexpected error GRPC::Internal: 13:undefined method 'new' for nil:NilClass.

I think it should be either fail :invalid_argument or fail :bad_request in this case.

Global exception handler sends along the exception message by default

For global exception handler, the default behavior is to send along the e.message. This behavior was added in PR #10.

See: https://github.com/bigcommerce/gruf/blob/master/lib/gruf/service.rb#L231

Exceptions can contain potentially sensitive server information and we may not want this data to be sent along to clients. We should set up a config to allow for this behavior to more tightly controlled by the service.

Perhaps something like the following.

Gruf.configure do |c|
  c.internal_error_message = 'Server Error'
  # other config setting
end

Either that or we can create a default value and explicitly require the configuration to enable the e.message logging. I personally see the e.message error as an insecure default.

Gruf.configure do |c|
  c.internal_exception_message = true # default is false
  # other config setting
end

We could also go with a combination of the two options. Any other thoughts?

Logging not working, or not well documented

Please describe the issue

I am trying to log information to the log the way I can in a normal rails application

A clear and concise description of what the bug is.
I am trying to add a GRPC service to an existing rails 6 api service. It may be that gruf isnt ready for rails 6.

I have the following in config/initializers/gruf.rb

   Gruf.configure do |c|
        c.server_binding_url = "0.0.0.0:#{grpc_port}"
        c.backtrace_on_error = !Rails.env.production?
        c.use_exception_message = !Rails.env.production?
        c.hooks.use(Gruf::Prometheus::Hook)
        c.rpc_server_options = {
            pool_size: grpc_pool_size,
            pool_keep_alive: grpc_pool_keepalive,
            poll_period: grpc_poll_period
        }
        c.interceptors.use(
            Gruf::Interceptors::Instrumentation::RequestLogging::Interceptor,
            formatter: :logstash
        )
    end

I have tried putting the following in my Controller (which inherits from Gruf::Controllers::Base)

logger.error { "are we there?" }

I also add the following line after the logger.error line to immediately fail the request, which should also log

fail!(:invalid_argument, :jwt_error, "dont get no request with jwt")

This results is a fail response in my client, and nothing is logged

<GRPC::Internal: 13:undefined local variable or method `logger' for #<Authentication::V1::UserInfoServiceController:0x0000563e1bd2e2b8>>

When I ctrl-c the server, the following logs before shutdown:

log writing failed. can't be called from trap context
deadline is 1969-12-31 23:59:59 +0000; (now=2020-01-18 21:31:01 +0000)
schedule another job
Intercepting request with interceptor: Gruf::Interceptors::Instrumentation::RequestLogging::Interceptor
Intercepting request with interceptor: Gruf::Interceptors::Instrumentation::OutputMetadataTimer
Intercepting request with interceptor: Gruf::Interceptors::ActiveRecord::ConnectionReset
app err:#<GRPC::ActiveCall:0x000056369d818e48>, status:13:undefined local variable or method `logger' for #<Authentication::V1::UserInfoServiceController:0x000056369d8185d8>
Sending status  13:undefined local variable or method `logger' for #<Authentication::V1::UserInfoServiceController:0x000056369d8185d8>
[bigcommerce-prometheus][unknown] Prometheus exporter cleanly shut down
Shutting down...
stopping, will wait for all the workers to exit
stopped: #<GRPC::RpcServer:0x000056369c92ce48>
stopped, all workers are shutdown
Goodbye!

I have tried adding the following line to my Controller with the logger.error and fail lines

include Gruf::Loggable

I get the fail response exception in my client

<GRPC::InvalidArgument: 3:dont get no request with jwt>

I do not see anything output in the log until I ctrl-C the server, then I get the following in my log output:

log writing failed. can't be called from trap context
deadline is 1969-12-31 23:59:59 +0000; (now=2020-01-18 21:33:38 +0000)
schedule another job
Intercepting request with interceptor: Gruf::Interceptors::Instrumentation::RequestLogging::Interceptor
Intercepting request with interceptor: Gruf::Interceptors::Instrumentation::OutputMetadataTimer
Intercepting request with interceptor: Gruf::Interceptors::ActiveRecord::ConnectionReset
are we there?
{"message":"[GRPC::InvalidArgument] (authentication.v1.user_info_service.get_user_info) 3:dont get no request with jwt","status":3,"service":"authentication.v1.user_info_service","method":"get_user_info","action":"get_user_info","grpc_status":"GRPC::InvalidArgument","duration":0.48,"thread_id":47097108531520,"time":"2020-01-18 21:33:38 +0000","host":"905332c24f39","format":"json"}
app err:#<GRPC::ActiveCall:0x000055ab4dc6e5c8>, status:3:dont get no request with jwt
Sending status  3:dont get no request with jwt
[bigcommerce-prometheus] Pushing gruf_prometheus_ metrics to type collector: {:type=>"grpc", :pool_jobs_waiting_total=>0, :pool_ready_workers_total=>1, :pool_workers_total=>1, :pool_initial_size=>1, :poll_period=>1}
[bigcommerce-prometheus][unknown] Prometheus exporter cleanly shut down
Shutting down...
stopping, will wait for all the workers to exit
stopped: #<GRPC::RpcServer:0x000055ab4cd93968>
stopped, all workers are shutdown
Goodbye!
Stopping ...
[bigcommerce-prometheus][unknown] Prometheus exporter cleanly shut down

How to Reproduce

Steps to reproduce the behavior:

  1. create the demo application in a rails 6 server
  2. add logging to the demo server code
  3. run the demo client
  4. See error

What should happen?

it should log to the logger output (STDOUT)

Describe what expected behavior should be.

Anything else we should know?

  • gRPC version: libprotoc 3.8.0
  • Ruby version: ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-linux]
  • OS: fedora 31
  • Does it occur at certain traffic volumes, payload size, etc
    no all the time

Question: Timing/performance of consuming request.messages enumerable

Hey folks,

I've been using gruf in production for a quite a bit and first off, thanks for the awesome project!
I'm now digging into some slow production traces and am trying to understand exactly what I'm measuring so I can troubleshoot more effectively.

What I've discovered is that I'm seeing a large amount of time -- 100-200+ ms, occasionally -- in my bi-directional streaming service when consuming the request.messages enumerable via something like Array(request.messages) or request.messages.to_a, etc.

I think I've narrowed my question down to: given a streaming endpoint, Is the controller instantiated and the endpoint invoked before a single request is even received? Is what I'm looking at here TLS/network time in gruf/gRPC gems to send/receive/parse the request payloads?

Here's an example trace showing what I'm looking at, if that helps :)
image

More details:

  • I haven't adjusted the thread pool size (30) but I also haven't seen any thread pool exhausted log messages.
  • I'm running 3 separate instances to handle these messages, which based on requests/second and average trace time shouldn't be anywhere near max capacity.

Cheers!

Support for Request/Response logging

It would be nice for gruf to support a standardized request/response logging similar to what you get with a rails logger. Does this feature belong in the gem or is it something that each app should handle independently?

Ability to generate code automatically with the gruf binary

What? Why?

Would be nice to have gruf regenerate the service code when we run gruf.

Proposed solution: Something like adding this either to the binary, or to the executor:

`rm -rf app/rpc/generated/*`
Dir[File.expand_path "./app/rpc/**/*.proto"].each do |proto|
  absolute_path = Pathname.new(File.expand_path(proto))
  project_path  = Pathname.new(File.join(__dir__, ".."))
  relative_proto = absolute_path.relative_path_from(project_path)
  `grpc_tools_ruby_protoc -I "./app/rpc" --ruby_out="app/rpc/generated" --grpc_out="app/rpc/generated" #{relative_proto}`
end

Gruf::Server doesn't handle signals

It appears that all signal handling logic was removed from GRPC::RpcServer and server now simply crashes when process is killed:

Ctrl+C

I, [2017-10-27T12:59:43.326558 #87078]  INFO -- : Booting gRPC Server...
I, [2017-10-27T12:59:43.329951 #87078]  INFO -- : handling /grpc.health.v1.Health/Check with #<Method: Grpc::Health::V1::Health::Service#check>
^C
bundler: failed to load command: gruf (/Users/user/.rbenv/versions/2.4.1/bin/gruf)
Interrupt:
  /Users/user/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/grpc-1.6.6-universal-darwin/src/ruby/lib/grpc/generic/rpc_server.rb:370:in `request_call'
  /Users/user/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/grpc-1.6.6-universal-darwin/src/ruby/lib/grpc/generic/rpc_server.rb:370:in `loop_handle_server_calls'
  /Users/user/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/grpc-1.6.6-universal-darwin/src/ruby/lib/grpc/generic/rpc_server.rb:331:in `run'
  /Users/user/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/gruf-2.0.1/lib/gruf/server.rb:63:in `start!'
  /Users/user/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/gruf-2.0.1/bin/gruf:27:in `<top (required)>'
  /Users/user/.rbenv/versions/2.4.1/bin/gruf:22:in `load'
  /Users/user/.rbenv/versions/2.4.1/bin/gruf:22:in `<top (required)>

SIGTERM

I, [2017-10-27T12:59:43.326558 #87078]  INFO -- : Booting gRPC Server...
I, [2017-10-27T12:59:43.329951 #87078]  INFO -- : handling /grpc.health.v1.Health/Check with #<Method: Grpc::Health::V1::Health::Service#check>
bundler: failed to load command: gruf (/Users/user/.rbenv/versions/2.4.1/bin/gruf)
SignalException: SIGTERM
  /Users/user/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/grpc-1.6.6-universal-darwin/src/ruby/lib/grpc/generic/rpc_server.rb:370:in `request_call'

With this monkey-patch Ctrl+C and SIGTERM are handled properly.

Gruf::Server.class_eval do
  alias_method :orig_start!, :start!

  def start!
    orig_start!
  rescue Interrupt, SignalException, SystemExit
    logger.info { 'Shutting down gRPC server...' }
    server.stop
  end
end
I, [2017-10-27T12:59:43.326558 #87078]  INFO -- : Booting gRPC Server...
I, [2017-10-27T12:59:43.329951 #87078]  INFO -- : handling /grpc.health.v1.Health/Check with #
^C
I, [2017-10-27T13:01:14.288286 #87184]  INFO -- : Shutting down gRPC server...
I, [2017-10-27T13:01:14.288537 #87184]  INFO -- : stopping, will wait for all the workers to exit
I, [2017-10-27T13:01:14.290172 #87184]  INFO -- : schedule another job
I, [2017-10-27T13:01:14.292240 #87184]  INFO -- : stopped, all workers are shutdown

Can I submit a PR to rescue these exceptions in Gruf::Server so we can remove this patch from all of our services or am I missing something here?

Idea: Support sample rate for request logger

What? Why?

I would like to define a sample rate for the request logger on a per RPC basis. Currently I have a service which has high volume of traffic and my options are to either disable the logger (using ignore_methods) for that RPC or to keep logging the request at high volume.

This could potentially be set up like:

  c.interceptors.use(
    Gruf::Interceptors::Instrumentation::RequestLogging::Interceptor,
    formatter: :logstash,
    ...
    sampled_methods: { 
      'rpc.dummy.high.volume.request' => 0.1
    }
  )

EDIT:
Another interesting idea would be to attach sample rates to the status of the RPC, as an example say I only want to log 1% of successes and 100% of failed (Grpc::BadStatus) requests.

fail! raises "NameError: uninitialized constant ActiveSupport::JSON" if active_support/core_ext is required in application

Please describe the issue

If an application that uses gruf requires active_support/core_ext, the gruf server returns { "error": "2 UNKNOWN: NameError: uninitialized constant ActiveSupport::JSON" } upon fail! :bad_request, implying ActiveSupport::JSON is somehow unloaded.

With require 'active_support/core_ext' commented out, it works just as expected and returns { "error": "3 INVALID_ARGUMENT: " }. Also, requiring active_support/all or active_support/json won't raise NameError and works as expected.

How to Reproduce

Here are the files that reproduce the behaviour.

hello.proto

syntax = "proto3";

package protos.hello;

service Hello {
  rpc SayHello(HelloInput) returns (HelloOutput) {}
}

message HelloInput {}
message HelloOutput {}

app.rb

require 'gruf'
require 'google/protobuf'

# Returns `{ "error": "2 UNKNOWN: NameError: uninitialized constant ActiveSupport::JSON" }`
require 'active_support/core_ext'

# Fails as expected (`{ "error": "3 INVALID_ARGUMENT: " }`)
# require 'active_support/all'

# Fails as expected (`{ "error": "3 INVALID_ARGUMENT: " }`)
# require 'active_support/json'

Google::Protobuf::DescriptorPool.generated_pool.build do
  add_file('hello.proto', syntax: :proto3) do
    add_message('protos.hello.HelloInput') {}
    add_message 'protos.hello.HelloOutput' do
      optional :message, :string, 1
    end
  end
end

HelloInput = ::Google::Protobuf::DescriptorPool.generated_pool.lookup('protos.hello.HelloInput').msgclass
HelloOutput = ::Google::Protobuf::DescriptorPool.generated_pool.lookup('protos.hello.HelloOutput').msgclass

class MyService
  include GRPC::GenericService

  self.marshal_class_method = :encode
  self.unmarshal_class_method = :decode
  self.service_name = 'protos.hello.Hello'

  rpc :SayHello, HelloInput, HelloOutput
end

class MyController < ::Gruf::Controllers::Base
  bind MyService

  def say_hello
    fail! :bad_request
  end
end

server = Gruf::Server.new(Gruf.server_options)
Gruf.services.each { |s| server.add_service(s) }
server.start!

Gemfile

gem 'gruf', '2.8.1'

Gemfile.lock

GEM
  specs:
    activesupport (6.0.3.1)
      concurrent-ruby (~> 1.0, >= 1.0.2)
      i18n (>= 0.7, < 2)
      minitest (~> 5.1)
      tzinfo (~> 1.1)
      zeitwerk (~> 2.2, >= 2.2.2)
    concurrent-ruby (1.1.6)
    google-protobuf (3.12.1)
    googleapis-common-protos-types (1.0.5)
      google-protobuf (~> 3.11)
    grpc (1.28.0)
      google-protobuf (~> 3.11)
      googleapis-common-protos-types (~> 1.0)
    grpc-tools (1.28.0)
    gruf (2.8.1)
      activesupport (> 4)
      concurrent-ruby (> 1)
      grpc (~> 1.10)
      grpc-tools (~> 1.10)
      slop (~> 4.6)
    i18n (1.8.2)
      concurrent-ruby (~> 1.0)
    minitest (5.14.1)
    slop (4.8.1)
    thread_safe (0.3.6)
    tzinfo (1.2.7)
      thread_safe (~> 0.1)
    zeitwerk (2.3.0)

PLATFORMS
  ruby

DEPENDENCIES
  gruf (= 2.8.1)

BUNDLED WITH
   2.1.4

Steps to reproduce the behavior:

  1. bundle then bundle exec ruby app.rb to start the server on port 9001
  2. Call the SayHello rpc with an empty message.

What should happen?

It should return { "error": "3 INVALID_ARGUMENT: " } instead of { "error": "2 UNKNOWN: NameError: uninitialized constant ActiveSupport::JSON" }.

Anything else we should know?

  • Ruby version: 2.6.5
  • OS: macOS 10.15.4

The error is raised at https://github.com/bigcommerce/gruf/blob/master/lib/gruf/serializers/errors/json.rb#L31 .
I'm not 100% sure whether this issue is coming from gruf itself, or Active Support, but at least I can confirm that requiring active_support/json in gruf itself fixes the issue.

Allow custom payload in request logger

What? Why?

My API response has some custom data fields that I'd like to add to the request logs. However, I don't see any way of extending the current request log payload. Would it make sense to provide a way for user to define custom payload that gets merged into the default payload for request logs?

If this makes sense to folks, I'm happy to try and submit a PR on this. I'm also happy to hear any work-around for this.

Not clear how to implement client

It's unclear where to instantiate a client. Not in the initializer apparently, thats just where defaults are set.

Do you instantiate a new client stub for every call you are making to a GRPC service?

Add catchall handler

Should catch exceptions and add debug info + fail!(req, call, :bad_request, :bad_request, e.message)

Exception handler for the controller class

What? Why?

Is there's a way to rescue certain type of exceptions in controller like in Rails rescue_from?
If no, could you please point me to the right direction of adding it?

Thanks

Wiki update in Server::Installation

Please describe the issue

https://github.com/bigcommerce/gruf/wiki/Server:-Installation

GRPC::RpcServer configuration does not work due to Cannot modify Frozen hash error. It should be something like below.

Gruf.configure do |c|
  # The size of the underlying thread pool. No more concurrent requests can be made
  # than the size of the thread pool.
  c.rpc_server_options = c.rpc_server_options.merge({ pool_size: 10 })
end

I can't seem to make a PR to make an update. Can someone on the bigcommerce team update the docs? Thanks.

Question about using TLS

From the documentation,

"We don't recommend using TLS for gRPC, but instead using something like linkerd for TLS encryption between services. If you need it, however, this library supports TLS."

I was wondering why isn't TLS recommended for gRPC? Thanks.

Segmentation fault when using Alpine

How to Reproduce

Steps to reproduce the behavior:

  1. docker run --rm -it ruby:2.6.5-alpine /bin/sh
  2. apk update && apk add --no-cache gcompat
  3. gem install gruf
  4. gruf
/ # gruf
/usr/local/lib/ruby/2.6.0/forwardable.rb:230: [BUG] Segmentation fault at 0x000000000003dda6
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-linux-musl]

-- Control frame information -----------------------------------------------
c:0011 p:---- s:0055 e:000054 CFUNC  :add_http2_port
c:0010 p:0029 s:0049 e:000048 METHOD /usr/local/lib/ruby/2.6.0/forwardable.rb:230
c:0009 p:0235 s:0042 e:000041 BLOCK  /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/server.rb:77
c:0008 p:0022 s:0037 e:000036 METHOD /usr/local/lib/ruby/2.6.0/monitor.rb:235
c:0007 p:0007 s:0033 e:000032 METHOD /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/server.rb:57
c:0006 p:0039 s:0029 E:002540 METHOD /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/server.rb:106
c:0005 p:0030 s:0023 e:000022 METHOD /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/cli/executor.rb:52
c:0004 p:0064 s:0017 e:000016 TOP    /usr/local/bundle/gems/gruf-2.8.0/bin/gruf:29 [FINISH]
c:0003 p:---- s:0013 e:000012 CFUNC  :load
c:0002 p:0109 s:0008 E:001a60 EVAL   /usr/local/bundle/bin/gruf:23 [FINISH]
c:0001 p:0000 s:0003 E:001e70 (none) [FINISH]

-- Ruby level backtrace information ----------------------------------------
/usr/local/bundle/bin/gruf:23:in `<main>'
/usr/local/bundle/bin/gruf:23:in `load'
/usr/local/bundle/gems/gruf-2.8.0/bin/gruf:29:in `<top (required)>'
/usr/local/bundle/gems/gruf-2.8.0/lib/gruf/cli/executor.rb:52:in `run'
/usr/local/bundle/gems/gruf-2.8.0/lib/gruf/server.rb:106:in `start!'
/usr/local/bundle/gems/gruf-2.8.0/lib/gruf/server.rb:57:in `server'
/usr/local/lib/ruby/2.6.0/monitor.rb:235:in `mon_synchronize'
/usr/local/bundle/gems/gruf-2.8.0/lib/gruf/server.rb:77:in `block in server'
/usr/local/lib/ruby/2.6.0/forwardable.rb:230:in `add_http2_port'
/usr/local/lib/ruby/2.6.0/forwardable.rb:230:in `add_http2_port'

-- Machine register context ------------------------------------------------
 RIP: 0x000000000003dda6 RBP: 0x00007f5de9d31cb3 RSP: 0x00007ffcdf9bf738
 RAX: 0x00007ffcdf9bf7c0 RBX: 0x00007ffcdf9bf9a0 RCX: 0x0000000000000040
 RDX: 0x0000000000000001 RDI: 0x00007ffcdf9bf770 RSI: 0x0000000000000040
  R8: 0x00007f5de9d31cb3  R9: 0x00007ffcdf9bf758 R10: 0x00007f5dec639156
 R11: 0x0000000000000000 R12: 0x00007ffcdf9bf758 R13: 0x0000000000000061
 R14: 0x00007ffcdf9bf770 R15: 0x00007ffcdf9bf8c0 EFL: 0x0000000000010246

-- Other runtime information -----------------------------------------------

* Loaded script: /usr/local/bundle/bin/gruf

* Loaded features:

    0 enumerator.so
    1 thread.rb
    2 rational.so
    3 complex.so
    4 /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/enc/encdb.so
    5 /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/enc/trans/transdb.so
    6 /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/rbconfig.rb
    7 /usr/local/lib/ruby/2.6.0/rubygems/compatibility.rb
    8 /usr/local/lib/ruby/2.6.0/rubygems/defaults.rb
    9 /usr/local/lib/ruby/2.6.0/rubygems/deprecate.rb
   10 /usr/local/lib/ruby/2.6.0/rubygems/errors.rb
   11 /usr/local/lib/ruby/2.6.0/rubygems/version.rb
   12 /usr/local/lib/ruby/2.6.0/rubygems/requirement.rb
   13 /usr/local/lib/ruby/2.6.0/rubygems/platform.rb
   14 /usr/local/lib/ruby/2.6.0/rubygems/basic_specification.rb
   15 /usr/local/lib/ruby/2.6.0/rubygems/stub_specification.rb
   16 /usr/local/lib/ruby/2.6.0/delegate.rb
   17 /usr/local/lib/ruby/2.6.0/uri/rfc2396_parser.rb
   18 /usr/local/lib/ruby/2.6.0/uri/rfc3986_parser.rb
   19 /usr/local/lib/ruby/2.6.0/uri/common.rb
   20 /usr/local/lib/ruby/2.6.0/uri/generic.rb
   21 /usr/local/lib/ruby/2.6.0/uri/file.rb
   22 /usr/local/lib/ruby/2.6.0/uri/ftp.rb
   23 /usr/local/lib/ruby/2.6.0/uri/http.rb
   24 /usr/local/lib/ruby/2.6.0/uri/https.rb
   25 /usr/local/lib/ruby/2.6.0/uri/ldap.rb
   26 /usr/local/lib/ruby/2.6.0/uri/ldaps.rb
   27 /usr/local/lib/ruby/2.6.0/uri/mailto.rb
   28 /usr/local/lib/ruby/2.6.0/uri.rb
   29 /usr/local/lib/ruby/2.6.0/rubygems/specification_policy.rb
   30 /usr/local/lib/ruby/2.6.0/rubygems/util/list.rb
   31 /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/stringio.so
   32 /usr/local/lib/ruby/2.6.0/rubygems/specification.rb
   33 /usr/local/lib/ruby/2.6.0/rubygems/exceptions.rb
   34 /usr/local/lib/ruby/2.6.0/rubygems/util.rb
   35 /usr/local/lib/ruby/2.6.0/rubygems/bundler_version_finder.rb
   36 /usr/local/lib/ruby/2.6.0/rubygems/dependency.rb
   37 /usr/local/lib/ruby/2.6.0/rubygems/core_ext/kernel_gem.rb
   38 /usr/local/lib/ruby/2.6.0/monitor.rb
   39 /usr/local/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb
   40 /usr/local/lib/ruby/2.6.0/rubygems/core_ext/kernel_warn.rb
   41 /usr/local/lib/ruby/2.6.0/rubygems.rb
   42 /usr/local/lib/ruby/2.6.0/rubygems/path_support.rb
   43 /usr/local/lib/ruby/gems/2.6.0/gems/did_you_mean-1.3.0/lib/did_you_mean/version.rb
   44 /usr/local/lib/ruby/gems/2.6.0/gems/did_you_mean-1.3.0/lib/did_you_mean/core_ext/name_error.rb
   45 /usr/local/lib/ruby/gems/2.6.0/gems/did_you_mean-1.3.0/lib/did_you_mean/levenshtein.rb
   46 /usr/local/lib/ruby/gems/2.6.0/gems/did_you_mean-1.3.0/lib/did_you_mean/jaro_winkler.rb
   47 /usr/local/lib/ruby/gems/2.6.0/gems/did_you_mean-1.3.0/lib/did_you_mean/spell_checker.rb
   48 /usr/local/lib/ruby/gems/2.6.0/gems/did_you_mean-1.3.0/lib/did_you_mean/spell_checkers/name_error_checkers/class_name_checker.rb
   49 /usr/local/lib/ruby/gems/2.6.0/gems/did_you_mean-1.3.0/lib/did_you_mean/spell_checkers/name_error_checkers/variable_name_checker.rb
   50 /usr/local/lib/ruby/gems/2.6.0/gems/did_you_mean-1.3.0/lib/did_you_mean/spell_checkers/name_error_checkers.rb
   51 /usr/local/lib/ruby/gems/2.6.0/gems/did_you_mean-1.3.0/lib/did_you_mean/spell_checkers/method_name_checker.rb
   52 /usr/local/lib/ruby/gems/2.6.0/gems/did_you_mean-1.3.0/lib/did_you_mean/spell_checkers/key_error_checker.rb
   53 /usr/local/lib/ruby/gems/2.6.0/gems/did_you_mean-1.3.0/lib/did_you_mean/spell_checkers/null_checker.rb
   54 /usr/local/lib/ruby/gems/2.6.0/gems/did_you_mean-1.3.0/lib/did_you_mean/formatters/plain_formatter.rb
   55 /usr/local/lib/ruby/gems/2.6.0/gems/did_you_mean-1.3.0/lib/did_you_mean.rb
   56 /usr/local/lib/ruby/2.6.0/tsort.rb
   57 /usr/local/lib/ruby/2.6.0/rubygems/request_set/gem_dependency_api.rb
   58 /usr/local/lib/ruby/2.6.0/rubygems/request_set/lockfile/parser.rb
   59 /usr/local/lib/ruby/2.6.0/rubygems/request_set/lockfile/tokenizer.rb
   60 /usr/local/lib/ruby/2.6.0/rubygems/request_set/lockfile.rb
   61 /usr/local/lib/ruby/2.6.0/rubygems/request_set.rb
   62 /usr/local/lib/ruby/2.6.0/rubygems/resolver/molinillo/lib/molinillo/gem_metadata.rb
   63 /usr/local/lib/ruby/2.6.0/rubygems/resolver/molinillo/lib/molinillo/errors.rb
   64 /usr/local/lib/ruby/2.6.0/set.rb
   65 /usr/local/lib/ruby/2.6.0/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/action.rb
   66 /usr/local/lib/ruby/2.6.0/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_edge_no_circular.rb
   67 /usr/local/lib/ruby/2.6.0/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/add_vertex.rb
   68 /usr/local/lib/ruby/2.6.0/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/delete_edge.rb
   69 /usr/local/lib/ruby/2.6.0/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/detach_vertex_named.rb
   70 /usr/local/lib/ruby/2.6.0/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/set_payload.rb
   71 /usr/local/lib/ruby/2.6.0/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/tag.rb
   72 /usr/local/lib/ruby/2.6.0/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/log.rb
   73 /usr/local/lib/ruby/2.6.0/rubygems/resolver/molinillo/lib/molinillo/dependency_graph/vertex.rb
   74 /usr/local/lib/ruby/2.6.0/rubygems/resolver/molinillo/lib/molinillo/dependency_graph.rb
   75 /usr/local/lib/ruby/2.6.0/rubygems/resolver/molinillo/lib/molinillo/state.rb
   76 /usr/local/lib/ruby/2.6.0/rubygems/resolver/molinillo/lib/molinillo/modules/specification_provider.rb
   77 /usr/local/lib/ruby/2.6.0/rubygems/resolver/molinillo/lib/molinillo/delegates/resolution_state.rb
   78 /usr/local/lib/ruby/2.6.0/rubygems/resolver/molinillo/lib/molinillo/delegates/specification_provider.rb
   79 /usr/local/lib/ruby/2.6.0/rubygems/resolver/molinillo/lib/molinillo/resolution.rb
   80 /usr/local/lib/ruby/2.6.0/rubygems/resolver/molinillo/lib/molinillo/resolver.rb
   81 /usr/local/lib/ruby/2.6.0/rubygems/resolver/molinillo/lib/molinillo/modules/ui.rb
   82 /usr/local/lib/ruby/2.6.0/rubygems/resolver/molinillo/lib/molinillo.rb
   83 /usr/local/lib/ruby/2.6.0/rubygems/resolver/molinillo.rb
   84 /usr/local/lib/ruby/2.6.0/rubygems/resolver/activation_request.rb
   85 /usr/local/lib/ruby/2.6.0/rubygems/resolver/conflict.rb
   86 /usr/local/lib/ruby/2.6.0/rubygems/resolver/dependency_request.rb
   87 /usr/local/lib/ruby/2.6.0/rubygems/resolver/requirement_list.rb
   88 /usr/local/lib/ruby/2.6.0/rubygems/resolver/stats.rb
   89 /usr/local/lib/ruby/2.6.0/rubygems/resolver/set.rb
   90 /usr/local/lib/ruby/2.6.0/rubygems/resolver/api_set.rb
   91 /usr/local/lib/ruby/2.6.0/rubygems/resolver/composed_set.rb
   92 /usr/local/lib/ruby/2.6.0/rubygems/resolver/best_set.rb
   93 /usr/local/lib/ruby/2.6.0/rubygems/resolver/current_set.rb
   94 /usr/local/lib/ruby/2.6.0/rubygems/resolver/git_set.rb
   95 /usr/local/lib/ruby/2.6.0/rubygems/resolver/index_set.rb
   96 /usr/local/lib/ruby/2.6.0/rubygems/resolver/installer_set.rb
   97 /usr/local/lib/ruby/2.6.0/rubygems/resolver/lock_set.rb
   98 /usr/local/lib/ruby/2.6.0/rubygems/resolver/vendor_set.rb
   99 /usr/local/lib/ruby/2.6.0/rubygems/resolver/source_set.rb
  100 /usr/local/lib/ruby/2.6.0/rubygems/resolver/specification.rb
  101 /usr/local/lib/ruby/2.6.0/rubygems/resolver/spec_specification.rb
  102 /usr/local/lib/ruby/2.6.0/rubygems/resolver/api_specification.rb
  103 /usr/local/lib/ruby/2.6.0/rubygems/resolver/git_specification.rb
  104 /usr/local/lib/ruby/2.6.0/rubygems/resolver/index_specification.rb
  105 /usr/local/lib/ruby/2.6.0/rubygems/resolver/installed_specification.rb
  106 /usr/local/lib/ruby/2.6.0/rubygems/resolver/local_specification.rb
  107 /usr/local/lib/ruby/2.6.0/rubygems/resolver/lock_specification.rb
  108 /usr/local/lib/ruby/2.6.0/rubygems/resolver/vendor_specification.rb
  109 /usr/local/lib/ruby/2.6.0/rubygems/resolver.rb
  110 /usr/local/lib/ruby/2.6.0/rubygems/source/git.rb
  111 /usr/local/lib/ruby/2.6.0/rubygems/source/installed.rb
  112 /usr/local/lib/ruby/2.6.0/rubygems/source/specific_file.rb
  113 /usr/local/lib/ruby/2.6.0/rubygems/source/local.rb
  114 /usr/local/lib/ruby/2.6.0/rubygems/source/lock.rb
  115 /usr/local/lib/ruby/2.6.0/rubygems/source/vendor.rb
  116 /usr/local/lib/ruby/2.6.0/rubygems/source.rb
  117 /usr/local/lib/ruby/2.6.0/bundler/version.rb
  118 /usr/local/lib/ruby/2.6.0/bundler/compatibility_guard.rb
  119 /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/pathname.so
  120 /usr/local/lib/ruby/2.6.0/pathname.rb
  121 /usr/local/lib/ruby/2.6.0/bundler/constants.rb
  122 /usr/local/lib/ruby/2.6.0/rubygems/text.rb
  123 /usr/local/lib/ruby/2.6.0/rubygems/user_interaction.rb
  124 /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/etc.so
  125 /usr/local/lib/ruby/2.6.0/rubygems/config_file.rb
  126 /usr/local/lib/ruby/2.6.0/bundler/rubygems_integration.rb
  127 /usr/local/lib/ruby/2.6.0/bundler/current_ruby.rb
  128 /usr/local/lib/ruby/2.6.0/bundler/shared_helpers.rb
  129 /usr/local/lib/ruby/2.6.0/rubygems/ext/builder.rb
  130 /usr/local/lib/ruby/2.6.0/bundler/setup.rb
  131 /usr/local/bundle/gems/grpc-1.27.0-x86_64-linux/src/ruby/lib/grpc/structs.rb
  132 /usr/local/bundle/gems/grpc-1.27.0-x86_64-linux/src/ruby/lib/grpc/core/status_codes.rb
  133 /usr/local/bundle/gems/grpc-1.27.0-x86_64-linux/src/ruby/lib/grpc/google_rpc_status_utils.rb
  134 /usr/local/bundle/gems/grpc-1.27.0-x86_64-linux/src/ruby/lib/grpc/errors.rb
  135 /usr/local/bundle/gems/grpc-1.27.0-x86_64-linux/src/ruby/lib/grpc/2.6/grpc_c.so
  136 /usr/local/bundle/gems/grpc-1.27.0-x86_64-linux/src/ruby/lib/grpc/grpc.rb
  137 /usr/local/bundle/gems/grpc-1.27.0-x86_64-linux/src/ruby/lib/grpc/logconfig.rb
  138 /usr/local/bundle/gems/grpc-1.27.0-x86_64-linux/src/ruby/lib/grpc/notifier.rb
  139 /usr/local/bundle/gems/grpc-1.27.0-x86_64-linux/src/ruby/lib/grpc/version.rb
  140 /usr/local/bundle/gems/grpc-1.27.0-x86_64-linux/src/ruby/lib/grpc/core/time_consts.rb
  141 /usr/local/lib/ruby/2.6.0/forwardable/impl.rb
  142 /usr/local/lib/ruby/2.6.0/forwardable.rb
  143 /usr/local/lib/ruby/2.6.0/weakref.rb
  144 /usr/local/bundle/gems/grpc-1.27.0-x86_64-linux/src/ruby/lib/grpc/generic/bidi_call.rb
  145 /usr/local/bundle/gems/grpc-1.27.0-x86_64-linux/src/ruby/lib/grpc/generic/active_call.rb
  146 /usr/local/bundle/gems/grpc-1.27.0-x86_64-linux/src/ruby/lib/grpc/generic/client_stub.rb
  147 /usr/local/bundle/gems/grpc-1.27.0-x86_64-linux/src/ruby/lib/grpc/generic/rpc_desc.rb
  148 /usr/local/bundle/gems/grpc-1.27.0-x86_64-linux/src/ruby/lib/grpc/generic/service.rb
  149 /usr/local/bundle/gems/grpc-1.27.0-x86_64-linux/src/ruby/lib/grpc/generic/rpc_server.rb
  150 /usr/local/bundle/gems/grpc-1.27.0-x86_64-linux/src/ruby/lib/grpc/generic/interceptor_registry.rb
  151 /usr/local/bundle/gems/grpc-1.27.0-x86_64-linux/src/ruby/lib/grpc/generic/interceptors.rb
  152 /usr/local/bundle/gems/grpc-1.27.0-x86_64-linux/src/ruby/lib/grpc.rb
  153 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/core_ext/module/delegation.rb
  154 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/concern.rb
  155 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/constants.rb
  156 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/utility/engine.rb
  157 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb
  158 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb
  159 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/synchronization/mri_object.rb
  160 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/synchronization/jruby_object.rb
  161 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/synchronization/rbx_object.rb
  162 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/synchronization/truffleruby_object.rb
  163 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/synchronization/object.rb
  164 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/synchronization/volatile.rb
  165 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb
  166 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb
  167 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/synchronization/jruby_lockable_object.rb
  168 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/synchronization/rbx_lockable_object.rb
  169 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb
  170 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/synchronization/condition.rb
  171 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/synchronization/lock.rb
  172 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/synchronization.rb
  173 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb
  174 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb
  175 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/map.rb
  176 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/core_ext/hash/deep_merge.rb
  177 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/core_ext/hash/except.rb
  178 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/core_ext/hash/slice.rb
  179 /usr/local/bundle/gems/i18n-1.8.2/lib/i18n/version.rb
  180 /usr/local/lib/ruby/2.6.0/cgi/core.rb
  181 /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/cgi/escape.so
  182 /usr/local/lib/ruby/2.6.0/cgi/util.rb
  183 /usr/local/lib/ruby/2.6.0/cgi/cookie.rb
  184 /usr/local/lib/ruby/2.6.0/cgi.rb
  185 /usr/local/bundle/gems/i18n-1.8.2/lib/i18n/exceptions.rb
  186 /usr/local/bundle/gems/i18n-1.8.2/lib/i18n/interpolate/ruby.rb
  187 /usr/local/bundle/gems/i18n-1.8.2/lib/i18n.rb
  188 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/lazy_load_hooks.rb
  189 /usr/local/bundle/gems/i18n-1.8.2/lib/i18n/config.rb
  190 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/i18n.rb
  191 /usr/local/lib/ruby/2.6.0/singleton.rb
  192 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/core_ext/kernel/singleton_class.rb
  193 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/deprecation/instance_delegator.rb
  194 /usr/local/lib/ruby/2.6.0/securerandom.rb
  195 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/notifications/instrumenter.rb
  196 /usr/local/lib/ruby/2.6.0/mutex_m.rb
  197 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/notifications/fanout.rb
  198 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/per_thread_registry.rb
  199 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/notifications.rb
  200 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/deprecation/behaviors.rb
  201 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/deprecation/reporting.rb
  202 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/deprecation/constant_accessor.rb
  203 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/core_ext/array/extract_options.rb
  204 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/core_ext/module/redefine_method.rb
  205 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/deprecation/method_wrappers.rb
  206 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/deprecation/proxy_wrappers.rb
  207 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/core_ext/module/deprecation.rb
  208 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/deprecation.rb
  209 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/inflector/inflections.rb
  210 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/multibyte.rb
  211 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/core_ext/string/multibyte.rb
  212 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/inflector/transliterate.rb
  213 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/inflections.rb
  214 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/inflector/methods.rb
  215 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/core_ext/string/inflections.rb
  216 /usr/local/bundle/gems/activesupport-6.0.2.1/lib/active_support/inflector.rb
  217 /usr/local/lib/ruby/2.6.0/base64.rb
  218 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/version.rb
  219 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/logging.rb
  220 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/loggable.rb
  221 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/configuration.rb
  222 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/errors/helpers.rb
  223 /usr/local/bundle/gems/slop-4.8.0/lib/slop/option.rb
  224 /usr/local/bundle/gems/slop-4.8.0/lib/slop/options.rb
  225 /usr/local/bundle/gems/slop-4.8.0/lib/slop/parser.rb
  226 /usr/local/bundle/gems/slop-4.8.0/lib/slop/result.rb
  227 /usr/local/bundle/gems/slop-4.8.0/lib/slop/types.rb
  228 /usr/local/bundle/gems/slop-4.8.0/lib/slop/error.rb
  229 /usr/local/bundle/gems/slop-4.8.0/lib/slop.rb
  230 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/cli/executor.rb
  231 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/controllers/request.rb
  232 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/controllers/service_binder.rb
  233 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/controllers/base.rb
  234 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/outbound/request_context.rb
  235 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/interceptors/registry.rb
  236 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/interceptors/client_interceptor.rb
  237 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/interceptors/server_interceptor.rb
  238 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/interceptors/context.rb
  239 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/interceptors/timer.rb
  240 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/interceptors/active_record/connection_reset.rb
  241 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/interceptors/authentication/basic.rb
  242 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/interceptors/instrumentation/statsd.rb
  243 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/interceptors/instrumentation/output_metadata_timer.rb
  244 /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/socket.so
  245 /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/io/wait.so
  246 /usr/local/lib/ruby/2.6.0/socket.rb
  247 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/interceptors/instrumentation/request_logging/formatters/base.rb
  248 /usr/local/lib/ruby/2.6.0/json/version.rb
  249 /usr/local/lib/ruby/2.6.0/ostruct.rb
  250 /usr/local/lib/ruby/2.6.0/json/generic_object.rb
  251 /usr/local/lib/ruby/2.6.0/json/common.rb
  252 /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/json/ext/parser.so
  253 /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/json/ext/generator.so
  254 /usr/local/lib/ruby/2.6.0/json/ext.rb
  255 /usr/local/lib/ruby/2.6.0/json.rb
  256 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/interceptors/instrumentation/request_logging/formatters/logstash.rb
  257 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/interceptors/instrumentation/request_logging/formatters/plain.rb
  258 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/interceptors/instrumentation/request_logging/interceptor.rb
  259 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/interceptors/base.rb
  260 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/hooks/registry.rb
  261 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/hooks/executor.rb
  262 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/hooks/base.rb
  263 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/timer.rb
  264 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/response.rb
  265 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/errors/field.rb
  266 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/errors/debug_info.rb
  267 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/serializers/errors/base.rb
  268 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/serializers/errors/json.rb
  269 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/error.rb
  270 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/client/error.rb
  271 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/client/error_factory.rb
  272 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/client.rb
  273 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/version.rb
  274 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/errors.rb
  275 /usr/local/lib/ruby/2.6.0/timeout.rb
  276 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atomic/event.rb
  277 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/concern/dereferenceable.rb
  278 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/concern/obligation.rb
  279 /usr/local/lib/ruby/2.6.0/logger.rb
  280 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/concern/logging.rb
  281 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/concern/deprecation.rb
  282 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/executor_service.rb
  283 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb
  284 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/serial_executor_service.rb
  285 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/immediate_executor.rb
  286 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/delay.rb
  287 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atomic_reference/numeric_cas_wrapper.rb
  288 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb
  289 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb
  290 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb
  291 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb
  292 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb
  293 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/thread_pool_executor.rb
  294 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/cached_thread_pool.rb
  295 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/utility/processor_counter.rb
  296 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/configuration.rb
  297 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb
  298 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb
  299 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/utility/native_integer.rb
  300 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb
  301 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb
  302 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb
  303 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb
  304 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atomic/java_count_down_latch.rb
  305 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atomic/count_down_latch.rb
  306 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb
  307 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atomic/abstract_thread_local_var.rb
  308 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atomic/ruby_thread_local_var.rb
  309 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atomic/java_thread_local_var.rb
  310 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb
  311 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb
  312 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb
  313 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atomic/semaphore.rb
  314 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atomics.rb
  315 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb
  316 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb
  317 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/indirect_immediate_executor.rb
  318 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb
  319 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/java_single_thread_executor.rb
  320 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb
  321 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/ruby_single_thread_executor.rb
  322 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb
  323 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/serialized_execution.rb
  324 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/serialized_execution_delegator.rb
  325 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/single_thread_executor.rb
  326 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb
  327 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb
  328 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/concern/observable.rb
  329 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/ivar.rb
  330 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/options.rb
  331 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/scheduled_task.rb
  332 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/collection/java_non_concurrent_priority_queue.rb
  333 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb
  334 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/collection/non_concurrent_priority_queue.rb
  335 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executor/timer_set.rb
  336 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/executors.rb
  337 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb
  338 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/agent.rb
  339 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/atom.rb
  340 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/thread_safe/util.rb
  341 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/array.rb
  342 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/hash.rb
  343 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/set.rb
  344 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/tuple.rb
  345 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/async.rb
  346 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/future.rb
  347 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/dataflow.rb
  348 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/maybe.rb
  349 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/exchanger.rb
  350 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb
  351 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/immutable_struct.rb
  352 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/mutable_struct.rb
  353 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/mvar.rb
  354 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/promise.rb
  355 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/settable_struct.rb
  356 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/timer_task.rb
  357 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/tvar.rb
  358 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb
  359 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/re_include.rb
  360 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/promises.rb
  361 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb
  362 /usr/local/bundle/gems/concurrent-ruby-1.1.6/lib/concurrent-ruby/concurrent.rb
  363 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/synchronized_client.rb
  364 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/instrumentable_grpc_server.rb
  365 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf/server.rb
  366 /usr/local/bundle/gems/gruf-2.8.0/lib/gruf.rb

* Process memory map:

5618cedcf000-5618cedd0000 r--p 00000000 08:01 3603955                    /usr/local/bin/ruby
5618cedd0000-5618cedd1000 r-xp 00001000 08:01 3603955                    /usr/local/bin/ruby
5618cedd1000-5618cedd2000 r--p 00002000 08:01 3603955                    /usr/local/bin/ruby
5618cedd2000-5618cedd3000 r--p 00002000 08:01 3603955                    /usr/local/bin/ruby
5618cedd3000-5618cedd4000 rw-p 00003000 08:01 3603955                    /usr/local/bin/ruby
5618d010c000-5618d0e23000 rw-p 00000000 00:00 0                          [heap]
7f5de8d90000-7f5de8d92000 ---p 00000000 00:00 0
7f5de8d92000-7f5de8f94000 rw-p 00000000 00:00 0
7f5de8f94000-7f5de8f96000 ---p 00000000 00:00 0
7f5de8f96000-7f5de9198000 rw-p 00000000 00:00 0
7f5de9198000-7f5de919a000 ---p 00000000 00:00 0
7f5de919a000-7f5de91bb000 rw-p 00000000 00:00 0
7f5de91bb000-7f5de91bd000 ---p 00000000 00:00 0
7f5de91bd000-7f5de91de000 rw-p 00000000 00:00 0
7f5de91de000-7f5de91e0000 ---p 00000000 00:00 0
7f5de91e0000-7f5de9201000 rw-p 00000000 00:00 0
7f5de9201000-7f5de9203000 ---p 00000000 00:00 0
7f5de9203000-7f5de9405000 rw-p 00000000 00:00 0
7f5de9405000-7f5de9407000 ---p 00000000 00:00 0
7f5de9407000-7f5de9609000 rw-p 00000000 00:00 0
7f5de9609000-7f5de960b000 ---p 00000000 00:00 0
7f5de960b000-7f5de980d000 rw-p 00000000 00:00 0
7f5de980d000-7f5de980f000 r--p 00000000 08:01 3737841                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/json/ext/generator.so
7f5de980f000-7f5de9815000 r-xp 00002000 08:01 3737841                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/json/ext/generator.so
7f5de9815000-7f5de9817000 r--p 00008000 08:01 3737841                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/json/ext/generator.so
7f5de9817000-7f5de9818000 r--p 00009000 08:01 3737841                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/json/ext/generator.so
7f5de9818000-7f5de9819000 rw-p 0000a000 08:01 3737841                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/json/ext/generator.so
7f5de9819000-7f5de985f000 rw-p 00000000 00:00 0
7f5de9861000-7f5de9863000 r--p 00000000 08:01 3737842                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/json/ext/parser.so
7f5de9863000-7f5de9866000 r-xp 00002000 08:01 3737842                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/json/ext/parser.so
7f5de9866000-7f5de9867000 r--p 00005000 08:01 3737842                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/json/ext/parser.so
7f5de9867000-7f5de9868000 r--p 00006000 08:01 3737842                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/json/ext/parser.so
7f5de9868000-7f5de9869000 r--p 00006000 08:01 3737842                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/json/ext/parser.so
7f5de9869000-7f5de986a000 rw-p 00007000 08:01 3737842                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/json/ext/parser.so
7f5de986a000-7f5de986b000 r--p 00000000 08:01 3737838                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/io/wait.so
7f5de986b000-7f5de986c000 r-xp 00001000 08:01 3737838                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/io/wait.so
7f5de986c000-7f5de986d000 r--p 00002000 08:01 3737838                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/io/wait.so
7f5de986d000-7f5de986e000 r--p 00002000 08:01 3737838                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/io/wait.so
7f5de986e000-7f5de986f000 rw-p 00003000 08:01 3737838                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/io/wait.so
7f5de986f000-7f5de9875000 r--p 00000000 08:01 3605048                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/socket.so
7f5de9875000-7f5de9895000 r-xp 00006000 08:01 3605048                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/socket.so
7f5de9895000-7f5de989c000 r--p 00026000 08:01 3605048                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/socket.so
7f5de989c000-7f5de989d000 r--p 0002d000 08:01 3605048                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/socket.so
7f5de989d000-7f5de989e000 r--p 0002d000 08:01 3605048                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/socket.so
7f5de989e000-7f5de989f000 rw-p 0002e000 08:01 3605048                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/socket.so
7f5de989f000-7f5de98a0000 r--p 00000000 08:01 3737752                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/cgi/escape.so
7f5de98a0000-7f5de98a2000 r-xp 00001000 08:01 3737752                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/cgi/escape.so
7f5de98a2000-7f5de98a3000 r--p 00003000 08:01 3737752                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/cgi/escape.so
7f5de98a3000-7f5de98a4000 r--p 00003000 08:01 3737752                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/cgi/escape.so
7f5de98a4000-7f5de98a5000 rw-p 00004000 08:01 3737752                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/cgi/escape.so
7f5de98a5000-7f5de9a80000 rw-p 00000000 00:00 0
7f5de9a80000-7f5de9a81000 r--p 00000000 08:01 396206                     /lib/ld-linux-x86-64.so.2
7f5de9a81000-7f5de9a83000 r-xp 00001000 08:01 396206                     /lib/ld-linux-x86-64.so.2
7f5de9a83000-7f5de9a84000 r--p 00003000 08:01 396206                     /lib/ld-linux-x86-64.so.2
7f5de9a84000-7f5de9a85000 r--p 00003000 08:01 396206                     /lib/ld-linux-x86-64.so.2
7f5de9a85000-7f5de9a86000 rw-p 00004000 08:01 396206                     /lib/ld-linux-x86-64.so.2
7f5de9a86000-7f5dea010000 r-xp 00000000 08:01 396498                     /usr/local/bundle/gems/grpc-1.27.0-x86_64-linux/src/ruby/lib/grpc/2.6/grpc_c.so
7f5dea010000-7f5dea02e000 r--p 0038a000 08:01 396498                     /usr/local/bundle/gems/grpc-1.27.0-x86_64-linux/src/ruby/lib/grpc/2.6/grpc_c.so
7f5dea02e000-7f5dea031000 rw-p 003a8000 08:01 396498                     /usr/local/bundle/gems/grpc-1.27.0-x86_64-linux/src/ruby/lib/grpc/2.6/grpc_c.so
7f5dea031000-7f5dea039000 rw-p 00000000 00:00 0
7f5dea039000-7f5dea03b000 r--p 00000000 08:01 3605033                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/etc.so
7f5dea03b000-7f5dea03e000 r-xp 00002000 08:01 3605033                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/etc.so
7f5dea03e000-7f5dea040000 r--p 00005000 08:01 3605033                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/etc.so
7f5dea040000-7f5dea041000 r--p 00006000 08:01 3605033                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/etc.so
7f5dea041000-7f5dea042000 rw-p 00007000 08:01 3605033                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/etc.so
7f5dea042000-7f5dea044000 r--p 00000000 08:01 3605041                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/pathname.so
7f5dea044000-7f5dea04a000 r-xp 00002000 08:01 3605041                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/pathname.so
7f5dea04a000-7f5dea04c000 r--p 00008000 08:01 3605041                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/pathname.so
7f5dea04c000-7f5dea04d000 r--p 00009000 08:01 3605041                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/pathname.so
7f5dea04d000-7f5dea04e000 rw-p 0000a000 08:01 3605041                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/pathname.so
7f5dea04e000-7f5dea0af000 rw-p 00000000 00:00 0
7f5dea0af000-7f5dea0b1000 r--p 00000000 08:01 3605049                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/stringio.so
7f5dea0b1000-7f5dea0b6000 r-xp 00002000 08:01 3605049                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/stringio.so
7f5dea0b6000-7f5dea0b8000 r--p 00007000 08:01 3605049                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/stringio.so
7f5dea0b8000-7f5dea0b9000 r--p 00008000 08:01 3605049                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/stringio.so
7f5dea0b9000-7f5dea0ba000 rw-p 00009000 08:01 3605049                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/stringio.so
7f5dea0ba000-7f5dea0bb000 r--p 00000000 08:01 3737821                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/enc/trans/transdb.so
7f5dea0bb000-7f5dea0bd000 r-xp 00001000 08:01 3737821                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/enc/trans/transdb.so
7f5dea0bd000-7f5dea0be000 r--p 00003000 08:01 3737821                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/enc/trans/transdb.so
7f5dea0be000-7f5dea0bf000 r--p 00003000 08:01 3737821                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/enc/trans/transdb.so
7f5dea0bf000-7f5dea0c0000 rw-p 00004000 08:01 3737821                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/enc/trans/transdb.so
7f5dea0c0000-7f5dea0c1000 r--p 00000000 08:01 3737763                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/enc/encdb.so
7f5dea0c1000-7f5dea0c2000 r-xp 00001000 08:01 3737763                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/enc/encdb.so
7f5dea0c2000-7f5dea0c3000 r--p 00002000 08:01 3737763                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/enc/encdb.so
7f5dea0c3000-7f5dea0c4000 r--p 00002000 08:01 3737763                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/enc/encdb.so
7f5dea0c4000-7f5dea0c5000 rw-p 00003000 08:01 3737763                    /usr/local/lib/ruby/2.6.0/x86_64-linux-musl/enc/encdb.so
7f5dea0c5000-7f5dec1cf000 rw-p 00000000 00:00 0
7f5dec1cf000-7f5dec1da000 r--p 00000000 08:01 822819                     /usr/lib/libgmp.so.10.3.2
7f5dec1da000-7f5dec21b000 r-xp 0000b000 08:01 822819                     /usr/lib/libgmp.so.10.3.2
7f5dec21b000-7f5dec231000 r--p 0004c000 08:01 822819                     /usr/lib/libgmp.so.10.3.2
7f5dec231000-7f5dec233000 r--p 00061000 08:01 822819                     /usr/lib/libgmp.so.10.3.2
7f5dec233000-7f5dec234000 rw-p 00063000 08:01 822819                     /usr/lib/libgmp.so.10.3.2
7f5dec234000-7f5dec237000 r--p 00000000 08:01 821052                     /lib/libz.so.1.2.11
7f5dec237000-7f5dec245000 r-xp 00003000 08:01 821052                     /lib/libz.so.1.2.11
7f5dec245000-7f5dec24c000 r--p 00011000 08:01 821052                     /lib/libz.so.1.2.11
7f5dec24c000-7f5dec24d000 r--p 00017000 08:01 821052                     /lib/libz.so.1.2.11
7f5dec24d000-7f5dec24e000 rw-p 00018000 08:01 821052                     /lib/libz.so.1.2.11
7f5dec24e000-7f5dec278000 r--p 00000000 08:01 3603995                    /usr/local/lib/libruby.so.2.6.5
7f5dec278000-7f5dec4ae000 r-xp 0002a000 08:01 3603995                    /usr/local/lib/libruby.so.2.6.5
7f5dec4ae000-7f5dec594000 r--p 00260000 08:01 3603995                    /usr/local/lib/libruby.so.2.6.5
7f5dec594000-7f5dec595000 r--p 00346000 08:01 3603995                    /usr/local/lib/libruby.so.2.6.5
7f5dec595000-7f5dec59d000 r--p 00346000 08:01 3603995                    /usr/local/lib/libruby.so.2.6.5
7f5dec59d000-7f5dec59e000 rw-p 0034e000 08:01 3603995                    /usr/local/lib/libruby.so.2.6.5
7f5dec59e000-7f5dec5ad000 rw-p 00000000 00:00 0
7f5dec5ad000-7f5dec5c2000 r--p 00000000 08:01 821047                     /lib/ld-musl-x86_64.so.1
7f5dec5c2000-7f5dec608000 r-xp 00015000 08:01 821047                     /lib/ld-musl-x86_64.so.1
7f5dec608000-7f5dec63a000 r--p 0005b000 08:01 821047                     /lib/ld-musl-x86_64.so.1
7f5dec63a000-7f5dec63b000 r--p 0008c000 08:01 821047                     /lib/ld-musl-x86_64.so.1
7f5dec63b000-7f5dec63c000 rw-p 0008d000 08:01 821047                     /lib/ld-musl-x86_64.so.1
7f5dec63c000-7f5dec63f000 rw-p 00000000 00:00 0
7ffcdf1c3000-7ffcdf9c2000 rw-p 00000000 00:00 0                          [stack]
7ffcdf9d6000-7ffcdf9d9000 r--p 00000000 00:00 0                          [vvar]
7ffcdf9d9000-7ffcdf9db000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]


[NOTE]
You may have encountered a bug in the Ruby interpreter or extension libraries.
Bug reports are welcome.
For details: https://www.ruby-lang.org/bugreport.html

Aborted

What should happen?

We shouldn't see segmentation fault issue. At least missed service definition exception.

Anything else we should know?

  • gRPC version - 1.27.0 x86_64-linux
  • Ruby version - 2.5.7-alpine, 2.6.5-alpine
  • OS - MacOS 10.15.3
  • Does it occur at certain traffic volumes, payload size, etc

Field errors are persisted in between calls

Have been able to confirm this by creating an RPC method that adds field errors depending on incoming value:

context 'with multiple calls, where the first returns an error, the second doesnt' do
  it 'should not raise a Gruf::Client::Error the second time', run_thing_server: true do
    client = build_client
    expect do
      client.call(:GetContextualFieldErrorFail, id: 1)
    end.to raise_error(Gruf::Client::Error)

    expect do
      client.call(:GetContextualFieldErrorFail, id: 2)
    end.to_not raise_error(Gruf::Client::Error)
  end
end

It will throw an error currently:

expected no Gruf::Client::Error, got #<Gruf::Client::Error: Gruf::Client::Error> with backtrace:

This seems to be due to @error being set memoized on the service class, and not reset in-between calls. This was designed in order to support the add_field_error method without having to pass around an error object. A simple fix is just to unset the @error attribute at the end of every call.

Expose @service from Gruf::Controllers::Request to interceptors

I would like to instrument Gruf endpoints with New Relic. For this I plan to create an interceptor which will utilize the ControllerInstrumentation#perform_action_with_newrelic_trace. http://www.rubydoc.info/github/newrelic/rpm/NewRelic%2FAgent%2FInstrumentation%2FControllerInstrumentation:perform_action_with_newrelic_trace

In order for the requests to show up correctly, I need to pass in the class_name of the controller / service. It seems like the @service is a natural fit for this use case.

https://github.com/bigcommerce/gruf/blob/master/lib/gruf/controllers/request.rb#L54

Herre is an example of the code I wrote which can instrument Gruf endpoints using newrelic, (maybe this is something which can also be brought into Gruf).

require 'new_relic/agent'

module Interceptors
  module Gruf
    ##
    # New Relic transaction tracing for Gruf endpoints
    #
    class NewRelicTracer < ::Gruf::Interceptors::ServerInterceptor
      include ::NewRelic::Agent::Instrumentation::ControllerInstrumentation

      def call
        opts = {
          category: :controller,
          class_name: request.instance_variable_get('@service'),
          name: request.method_key
        }

        perform_action_with_newrelic_trace(opts) do
          yield
        end
      end
    end
  end
end

I would also gladly open a pr to add an attr_reader for the service but figure we may want to have a different approach to expose these values.

Integration testing guide for `Gruf::Client`

What? Why?

It would be great to have some guidance around stubbing out downstream gRPC calls in test code of applications that use Gruf::Client.
In traditional (RESTful) scenarios, tools like vcr or WebMock to prerecord / mock out downstream HTTP requests.

Spelunking in the gruf code itself, it looks like one can always create Gruf::Client instances with mocked-out #call methods for specs, which then return prefabricated Gruf::Response results. That said, it would be great to have a dedicated documentation section somewhere (on the Wiki?) to give guidance and/or example code for a recommended approach.

Explicit render support

Current way of rendering values returned from Gruf controller action makes it impossible to use wisper gem in Gruf controllers.

In order to use wisper it would need some explicit render support, similar to what rails does.
Example from wisper docs

Calling return in wisper callback blocks can't work due to way ruby handles blocks

`uninitialized constant PackageModule::GeneratedModule::Service`

Please describe the issue

I followed the wiki and created a very small proto file with a package, service and Req & Resp messages. Then I generated the stubs and created a controller but no matter what I do, when I run bundle exec gruf and tries to load the controller, it errors on the bind call saying:
NameError: uninitialized constant PackageModule::GeneratedModule::Service

How to Reproduce

Steps to reproduce the behavior:

  1. Follow the Wiki
  2. Run Gruf
  3. See error

What should happen?

Not sure :)

Anything else we should know?

  • gRPC version 1.22.0
  • Ruby version 2.6.2
  • Rails version 5.2.3
  • OS MacOs

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.