Rubyで別ファイルにログを出力する
Railsで開発をしていると、たくさんSQLを実行しているサーバだと development.log
の出力が多すぎて追うのが大変になります。
こういう時、別ファイルに出力させたいのですが、以下のように行えばOKです。
また、log/
以下は gitignore されていることがほとんどだと思うので、log以下にファイルを置くと良いです。
Logger.new('log/out.log').info( "ログ出力したい文言" )
出力例は以下のようになります。
I, [2019-01-15T18:59:25.132692 #6825] INFO -- : ログ出力したい文言
Rails外の場合だと、require が必要です。
require "logger" Logger.new('out.log').info( "ログ出力したい文言" )
size,count,empty? のパフォーマンスを確認する
size,count,empty? のパフォーマンスを確認をしてみる。
require "benchmark" count = 1000_000 ar = [1, 2, 3, 4, 5] Benchmark.bm(10) do |x| # 10はラベルの為に確保する長さ x.report("size") do count.times do ar.empty? end end x.report("count") do count.times do ar.count == 0 end end x.report("length") do count.times do ar.length == 0 end end end
- 実行結果
user system total real size 0.040000 0.000000 0.040000 ( 0.048787) count 0.060000 0.000000 0.060000 ( 0.058087) length 0.040000 0.000000 0.040000 ( 0.045684)
- 1回あたりの実行時間を nano sec に直してみる。
size 48.787[nano sec] count 58.087[nano sec] length 45.684[nano sec]
参考資料のNumbers Everyone Should Know - High Scalability -によると、Send 2K bytes over 1 Gbps network 20,000 ns
すなわち、2K bytes のデータを 1Gbpsのネットワークで送信した場合 20[micro sec] かかるということなので、
普通の web application を作っているのならば、これらのメソッドの速度の違いはあまり気にする必要はなさそうだ。
また、Railsのアプリケーションログを見てみると、ざっくりこんな感じで1リクエスト毎にms単位の時間がかかっている。
I, [2019-01-10T12:30:21.152318 #21603] INFO -- : [2236aa74-e13c-475e-a42c-5a87dc7fba51] Completed 200 OK in 143ms (Views: 0.4ms | ActiveRecord: 12.7ms)
これと比較したらメソッド毎の nano sec 単位の実行速度の違いなど誤差の範囲である。
参考資料
gem のコードを git clone して RubyMine で開くスクリプト
以下を /usr/local/bin
に置いて、 chmod a+x clone_and_open.rb
しておく。
clone_and_open.rb https://github.com/u16suzu/foo
すると ~/src にダウンロードされる。
clone_and_open.rb
#!/usr/bin/env ruby class CodeReader # clone and open # # git repository を ~/src に clone して RubyMine で開くコマンド def clone_and_open(uri=ARGV[0]) dir_name = uri.split("/")[-2] repo_name= uri.split("/")[-1] system "mkdir -p ~/src/#{dir_name}" # password入力を避けるために ssh 形式で clone する system "git clone git@github.com:#{dir_name}/#{repo_name}.git ~/src/#{dir_name}/#{repo_name}" system "mine ~/src/#{dir_name}/#{repo_name}" end end CodeReader.new.clone_and_open
gemのソースを pry-byebug を使ってブレークポイントで止めて読む準備
いつも仕事でもプライベートでも使っている bundler
だけど、中身のコードを把握していないのでどうも雰囲気で使っている感が否めない。
そこで、ソースを読み腹落ち感を得るためにコードを読む準備を進めてみた。
pry-byebug を使ってブレークポイントで止められるようにする
(1). システムに pry-byebugを入れる
毎回 Gemfile 書くのは面倒なのでシステムに入れちゃう
gem install pry-byebug gem install pry-stack_explorer # 超便利なのでこれも
(2). require "pry" して、止めたいところで binding.pryすれば止まる
require "pry" ar = [1,2,3] ar.each do |i| binding.pry # ここで止まる p i end
便利。
bundlerのコードで試してみる
(1). ソースを git cloneする
$ git clone git@github.com:bundler/bundler.git ~/src
/vendor/bundle
に入ったコードだと git blame
できなくて普通に読みづらいので、git clone したり gem-src
を使うなりして git repository を取得した方が良い。
(2). CUI ツールのエントリポイントであるbundler/exe/bundle
でまずは require "pry"する
#!/usr/bin/env ruby # frozen_string_literal: true require 'pry' (略
(3). 実行して止まるか確認
./bundler
で実行すればシステムに入っている方ではなく git clone
した方の bundler が実行できる。
$ cd /Users/suzuki_y/src/bundler/exe/ suzuki_y@MBP:~/s/b/exe$ ./bundle install From: /Users/suzuki_y/src/bundler/exe/bundle @ line 30 : 25: require "bundler/cli" 26: 27: binding.pry 28: 29: # Allow any command to use --help flag to show help for that command => 30: help_flags = %w[--help -h] 31: help_flag_used = ARGV.any? {|a| help_flags.include? a } 32: args = help_flag_used ? Bundler::CLI.reformatted_help_args(ARGV) : ARGV 33: 34: Bundler::CLI.start(args, :debug => true) 35: end [1] pry(main)>
無事止まりました。
show-stackでコールスタックもみれます。
[1] pry(main)> show-stack Showing all accessible frames in stack (9 in total): -- => #0 <main> #1 [block] block in run <Byebug::PryProcessor#run(&_block)> #2 [method] run <Byebug::PryProcessor#run(&_block)> #3 [method] resume_pry <Byebug::PryProcessor#resume_pry()> #4 [method] at_line <Byebug::PryProcessor#at_line()> #5 [method] at_line <Byebug::Context#at_line()> #6 [block] block in <main> #7 [method] with_friendly_errors <Bundler.with_friendly_errors()> #8 [main] <main>
あとは、コードを好きにいじりながら自由にコード読み放題です。
メソッド系のgemの場合
また、 bundlerのようなコマンド系の gem ではなく、tapp
gem のようにコード内で使用するメソッド系の gem は、
gemのルートディレクトリに main.rb
みたいな適当なファイルを作って、そこから対象のgemを require して呼び出しを行ってとっかかりを作ります。
# src/tapp/main.rb require "./lib/tapp" require "pry" binding.pry "123".tapp "123".taputs
From: /Users/suzuki_y/src/tapp/main.rb @ line 6 : 1: require "./lib/tapp" 2: require "pry" 3: 4: binding.pry 5: => 6: "123".tapp 7: "123".taputs [1] pry(main)> step From: /Users/suzuki_y/src/tapp/lib/tapp.rb @ line 13 Tapp.config: 12: def config => 13: @config ||= Tapp::Configuration.new 14: end [1] pry(Tapp):1>
いい感じですね。
RubyMineを使ったやり方もあとで追記したいと思います。
rails console から任意のメソッドのソースコードをRubyMineで開く
設定
.pryrcに以下を追記する。RubyMineのCUIコマンドがない場合は Tools > Create Command-line Launcher...
で作っておく。
Pry.config.editor = proc { |file, line| "/usr/local/bin/mine --line #{line} #{file}" } Pry.commands.alias_command 'mine', 'edit' Pry.commands.alias_command 'mi', 'edit'
実行例
以下のコマンドを実行すると、RubyMine で User.first.label
を定義している部分のコードが開かれる。
pry(main)> mine User.first.label
こちらももちろん呼び出し可能。
pry(main) mine User.first.label=
Rails などの gem のコードも同様に開ける。
pry(main)> mine Rails.cache.read
開かれたコード。dalli_store.rb の 115行目あたり。
def read(name, options=nil) options ||= {} name = expanded_key name instrument(:read, name, options) do |payload| entry = read_entry(name, options) payload[:hit] = !!entry if payload entry end end
自分の小さな「箱」から脱出する方法を読んだ
自分の中で一方的に師と仰いでいる元KLab CTO 仙石さんの投稿をきっかけにして、 以前購入し積読してあった本を読んだ。 とても良い本だった。
> 「私は正しい」という思いに気づくのは、難しいhttps://t.co/kUEFcu3LzM
— 仙石浩明 Hiroaki Sengoku (@gcd_org) 2018年7月9日
世の中で一番重要な真実でしょうね。
> 結論から言うと、経験は買える
昨今では買う必要すらなくて、タダで手に入るんですが、手に入れようとする人は圧倒的に少数派ですね、残念なことに。
- 作者: アービンジャーインスティチュート,金森重樹,冨永星
- 出版社/メーカー: 大和書房
- 発売日: 2006/10/19
- メディア: 単行本(ソフトカバー)
- 購入: 156人 クリック: 3,495回
- この商品を含むブログ (418件) を見る
本書の概要
自分が本来相手のためにすべきだと思ったことをしないことを、心理学の世界では「自己欺瞞」という。 これを本書ではシンプルに「箱に入る」とか自分への裏切りと呼ぶ。
一度この自己欺瞞が始まると、そこから...
1. 他人の欠点を大げさにあげつらう 2. 自分の長所を過大に評価する 3. 自己欺瞞を正当化する。ものの価値を過大に評価する 4. 相手に非があると考える
というような流れで悪化していき、物事を見る目が曇ってしまい、しまいには他人との信頼関係が壊れてしまう。 本書では、これを防ぐには自分が箱の中に入っているかどうかを意識して、 なんとか箱の中から脱出することで、解決を目指しましょうということを述べている。 もちろん、つねに箱から出ているのが理想ではあるけれども、 そうもいかないので、たまには箱に入ることもある。 でも、箱に入っている状態を意識するというのは大事だと思う。
正直、過去現在に自分が周りで観測した人間関係のこじれはこの流れに沿っている。 もちろん自分が当事者になった時もあるし、そうじゃない時もある。 本書では、そのような過去の事柄についても、ことあるごとにその時どうすればベストだったか? を振り返って考えることを勧めている。
最後に
最後に本の最終ページに書いてあったリストを引用しておく。
知っておくべきこと
- 自分への裏切りは、自己欺瞞へ、さらには箱へとつながっていく。
- 箱の中にいると、業績向上に気持ちを集中することができなくなる。
- 自分が人にどのような影響を及ぼすか、成功できるかどうかは、全てはこの外に出ているか否かにかかっている。
- 他の人々に抵抗するのをやめた時、箱の外に出ることができる。
知ったことに即して生きること
- 完璧であろうと思うな。より良くなろうと思え。
- すでにそのことを知っている人以外には、箱などの言葉を使うな。自分自身の生活に、この原則を活かせ。
- 他の人々の箱を見つけようとするのではなく、自分の箱を探せ。
- 箱の中に入っているといって他人を責めるな。自分自身が箱の外に留まるようにしろ。
- 自分が箱の中にいることがわかっても、あきらめるな。努力を続けろ。
- 自分が箱の中にいた場合、箱の中にいたということを否定するな。謝った上で、さらに前へ進め。これから先、もっと他の人の役に立つよう努力しろ。
- 他の人が間違ったことをしているという点に注目するのではなく、どのような正しいことをすればその人に手を貸せるかを、よく考えろ。
- 他の人が手を貸してくれるかどうかを気にやむのはやめろ。自分が他の人に手を貸せているかどうかに気をつけろ。